chiark / gitweb /
Before try different approach since ldpreload does not work apparently
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sun, 1 Nov 2009 21:56:50 +0000 (21:56 +0000)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sun, 1 Nov 2009 21:56:50 +0000 (21:56 +0000)
jwrap-script-jpctb
libjwrap.c

index 117e720..72aa83e 100755 (executable)
@@ -1,9 +1,9 @@
 #!/bin/bash
 set -e$JWRAP_SCRIPT_X
 
-exec 4>&2
-exec 2>>/home/ian/u
-date >&2
+#exec 4>&2
+#exec 2>>/home/ian/u
+#date >&2
 
 unwire () {
        ldp="$LD_PRELOAD:"
@@ -57,4 +57,5 @@ if [ x"$lastarg" = x"com.threerings.yohoho.client.YoApp" ]; then
        unwire
 fi
 
-exec -a "$arg0" /dev/jwrap/bypass "$path" "$@" 2>&4
+exec -a "$arg0" /dev/jwrap/bypass "$path" "$@"
+#2>&4
index b74a99a..23ee7d6 100644 (file)
@@ -8,6 +8,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdarg.h>
 
 #define STDERRSTR_CONST(m) write(2,m,sizeof(m)-1)
 #define STDERRSTR_STRING(m) write(2,m,strlen(m))
 #define QUIS "libjwrap"
 
 typedef void anyfn_type(void);
-typedef int
-execvefn_type(const char *path, char *const argv[], char *const envp[]);
-
-static execvefn_type find_execve, *old_execve= find_execve;
 
 static anyfn_type *find_any(const char *name) {
   static const char *dlerr;
@@ -35,17 +32,29 @@ static anyfn_type *find_any(const char *name) {
   return 0;
 }
 
-static int find_execve(const char *path,
-                      char *const argv[], char *const envp[]) {
-  anyfn_type *anyfn;
-  anyfn= find_any("execve"); if (!anyfn) return -1;
-  old_execve= (execvefn_type*)anyfn;
-  return old_execve(path, argv, envp);
-}
+
+#define REIMPLEMENTWRAP(FN, ARGS_DECL, ARGS_USE)       \
+                                                       \
+  typedef int FN##_type ARGS_DECL;                     \
+                                                       \
+  static FN##_type find_##FN, *old_##FN= find_##FN;    \
+                                                       \
+  static int find_##FN ARGS_DECL {                     \
+    anyfn_type *anyfn;                                 \
+    anyfn= find_any(# FN);  if (!anyfn) return -1;     \
+    old_##FN= (FN##_type*)anyfn;                       \
+    return old_##FN ARGS_USE;                          \
+  }                                                    \
+                                                       \
+  int FN ARGS_DECL
+
+
 
 static const char javatail[]= "/bin/java";
 
-int execve(const char *path, char *const oargv[], char *const envp[]) {
+REIMPLEMENTWRAP(execve,
+               (const char *path, char *const oargv[], char *const envp[]),
+               (path, oargv, envp)) {
   int oargc;
   for (oargc=0; oargv[oargc]; oargc++);
 
@@ -98,3 +107,88 @@ int execve(const char *path, char *const oargv[], char *const envp[]) {
   errno= e;
   return -1;
 }
+
+int execv(const char *path, char *const argv[]) {
+  return execve(path, argv, environ);
+}
+
+
+static int execvep(const char *path, char *const argv[], char *const envp[]) {
+  /* How tiresome.
+   * libc binds strongly to its own execve.
+   * That means we need to reimplement exec*p.
+   * (Also for some mysterious reason there is no standard execvep
+   *  and no standard execlep)
+   */
+  if (strchr(path,'/')) return execve(path,argv,envp);
+
+  int pathlen= strlen(path);
+  int buflen= 0;
+  char *buf= 0;
+
+  const char *searchpath= getenv("PATH");
+  for (;;) {
+    const char *colon= strchr(searchpath,':');
+    int entrylen= colon ? colon - searchpath : strlen(searchpath);
+    const char *try;
+    if (entrylen) {
+      try= path;
+    } else {
+      int trylen= entrylen + 1 + pathlen + 1;
+      if (trylen > buflen) {
+       free(buf);
+       buf= malloc(trylen);
+       if (!buf) return -1;
+       buflen= trylen;
+      }
+      memcpy(buf, searchpath, entrylen);
+      buf[entrylen]= '/';
+      strcpy(buf+entrylen+1, path);
+      try= buf;
+    }
+    execve(try, argv, envp);
+    if (errno != ENOENT)
+      return -1;
+  }
+  errno= ENOENT;
+  return -1;
+}
+
+
+static int execl_corev(int e, int p,
+                      const char *path, const char *arg0, va_list al) {
+  char *arg;
+  va_list countal;
+
+  va_copy(countal,al);
+  int argc=1;
+  while ((arg= va_arg(countal, char*)))
+    argc++;
+  va_end(countal);
+
+  char **argv= malloc(sizeof(*argv) * (argc+1));
+  argc=0;
+  argv[argc++]= (char*)arg0;
+  while ((arg= va_arg(al, char*)))
+    argv[argc++]= arg;
+  argv[argc]= 0;
+
+  char **envp= e ? va_arg(al, char**) : environ;
+
+  if (p) return execvep(path, argv, envp);
+  else return execve(path, argv, envp);
+}   
+
+
+#define REIMPLEMENTLCOREV(FN,E,P)                      \
+  int FN(const char *path, const char *arg, ...) {     \
+    va_list al;                                                \
+    va_start(al,arg);                                  \
+    execl_corev(E,P,path,arg,al);                      \
+    va_end(al);                                                \
+    return -1;                                         \
+  }
+
+REIMPLEMENTLCOREV( execl,  0,0 )
+REIMPLEMENTLCOREV( execle, 1,0 )
+REIMPLEMENTLCOREV( execlp, 0,1 )