chiark / gitweb /
Sort of works ...
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sun, 1 Nov 2009 20:10:46 +0000 (20:10 +0000)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sun, 1 Nov 2009 20:10:46 +0000 (20:10 +0000)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
jwrap-script [new file with mode: 0755]
libjava-wrap [new file with mode: 0644]
libjava-wrap.c [new file with mode: 0644]
libjwrap.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..b1e012f
--- /dev/null
@@ -0,0 +1,4 @@
+*~
+*.o
+*.so
+*.so.*
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..cce8b95
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,23 @@
+OPTIMISE=      -O2
+LDFLAGS=       -g
+LIBS=          -ldl -lc
+CFLAGS=                -g $(OPTIMISE) \
+               -Wall -Wwrite-strings -Wpointer-arith -Wimplicit \
+               -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes
+CPPFLAGS=
+
+MAJOR=1
+MINOR=0
+LIBCANON=      libjwrap.so.$(MAJOR)
+LIBTARGET=     $(LIBCANON).$(MINOR)
+
+TARGETS=                $(LIBTARGET)
+
+all:                    $(TARGETS)
+
+
+$(LIBTARGET):          libjwrap.o
+               ld -shared -soname $(LIBCANON) -o $@ $< $(LIBS)
+
+libjwrap.o:          libjwrap.c
+               $(CC) -D_REENTRANT $(CFLAGS) $(CPPFLAGS) -c -o $@ -fPIC $<
diff --git a/jwrap-script b/jwrap-script
new file mode 100755 (executable)
index 0000000..f6fe699
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/bash
+set -e$JWRAP_SCRIPT_X
+
+unwire () {
+       ldp="$LD_PRELOAD:"
+       ldp2=''
+
+       while [ "x$ldp" != x ]; do
+               this="${ldp%%:*}"
+               ldp="${ldp#*:}"
+               case "$this" in
+               *libjwrap*.so.*)                                ;;
+               *)                      ldp2="$ldp2$this:"      ;;
+               esac
+       done
+
+       if [ "x$ldp2" != x ]; then
+               LD_PRELOAD="${ldp2%:}"
+       else
+               unset LD_PRELOAD
+       fi
+
+       unset JWRAP_SCRIPT
+}
+
+echo ":$*"
+
+path="$1"; shift
+arg0="$1"; shift
+
+args=( "$@" )
+nargs=${#args[*]}
+lastarg="${args[$(( $nargs - 1 ))]}"
+
+fail () {
+       echo >&2 "jwrap-script: $*"
+       exit 127
+}
+
+if [ x"$lastarg" = x"com.threerings.yohoho.client.YoApp" ]; then
+       case "$path" in
+       */bin/java) ;;
+       *)      fail "unexpected path format $path" ;;
+       esac
+       [ x"$JWRAP_EXTDIR" != x ] || fail 'JWRAP_EXTDIR not set'
+       extdirs="$JWRAP_EXTDIR:${path%/bin/java}/lib/ext"
+
+       set     -e$JWRAP_SCRIPT_X -- \
+               -Djavax.accessibility.assistive_technologies=com.tedpearson.ypp.market.MarketUploader \
+               -Djava.ext.dirs="$extdirs" \
+               "$@"
+
+       unwire
+fi
+
+exec -a "$arg0" /dev/jwrap/bypass "$path" "$@"
diff --git a/libjava-wrap b/libjava-wrap
new file mode 100644 (file)
index 0000000..9b904ed
--- /dev/null
@@ -0,0 +1,119 @@
+/**/
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define STDERRSTR_CONST(m) write(2,m,sizeof(m)-1)
+#define STDERRSTR_STRING(m) write(2,m,strlen(m))
+
+static anyfn_type *find_any(const char *name) {
+  static const char *dlerr;
+  anyfn_type *kv;
+
+  kv= dlsym(RTLD_NEXT,name); if (kv) return kv;
+  dlerr= dlerror(); if (!dlerr) dlerr= "dlsym() failed for no reason";
+  STDERRSTR_CONST("pctb-preload-wrap: error finding original version of ");
+  STDERRSTR_STRING(name);
+  STDERRSTR_CONST(": ");
+  STDERRSTR_STRING(dlerr);
+  STDERRSTR_STRING("\n");
+  errno= ENOSYS;
+  return 0;
+}
+
+typedef int
+execvefn_type(const char *path, char *const argv[], char *const envp[]);
+
+static execvefn_type find_execve, *old_execve= find_execve;
+
+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);
+}
+
+static const char javatail[]= "/bin/java";
+
+int execve(const char *path, char *const argv[], char *const envp[]) {
+  int pathlen= strlen(path);
+  if (pathlen < (sizeof(path2extdir_rm)-1) ||
+      strcmp(javatail, path + pathlen-(sizeof(path2extdir_rm)-1)))
+    old_execve(opath, oargv, oenvp);
+  
+
+  
+
+  int oargc;
+
+
+
+  xassert(opathlen >= 
+  
+
+  for (oargc=0; oargv[oargc]; oargc++);
+  xassert(oargc);
+  if (strcmp(oargv[oargc-1], "com.threerings.yohoho.client.YoApp"))
+
+  /* Remove ourselves from LD_PRELOAD */
+  int ipreloadenv=-1;
+  const char ldpreload[]= "LD_PRELOAD=";
+  for (oenvc=0; oenvp[oenvc]; oenvc++) {
+    if (memcmp(oenvp[oenvc], ldpreload, sizeof(ldpreload)-1)) continue;
+    xassert(ipreloadenv==-1);
+    ipreloadenv= oenvc;
+  }
+  xassert(ipreloadenv>=0);
+  xassert(!strchr(':',oenvp[ipreloadenv]));
+  
+
+  int nargc= oargc+2;
+  char **nargv= xmalloc(sizeof(*nargv) * (nargc+1));
+
+  /* Add argument for accessibility assistive tech. */
+  int iargc= oargc-1;
+  memcpy(nargv, oargv, iargc);
+  nargv[iargc++]= "-Djavax.accessibility.assistive_technologies="
+    "com.tedpearson.ypp.market.MarketUploader";
+
+  /* Calculate and add argument for ext dirs containing our jars */
+  const char *nextdir;
+  xassert((nextdir= getenv("JPCTB_EXTDIR")));
+  int nextdirlen= strlen(nextdir);
+
+  int njvmextdirbaselen= opathlen-sizeof(path2extdir_rm)-1);
+  xassert(!strcmp(path2extdir_rm, opath+njvmextdirbaselen);
+
+  const char path2extdir_pfx[]= "-Djava.ext.dirs=";
+  const char path2extdir_sfx[]= "/lib/ext";
+
+#define STRS(STR,DL)                                           \
+      STR( path2extdir_pfx, sizeof(path2extdir_pfx)-1 )        DL      \
+      STR( nextdir,         nextdirlen                )        DL      \
+      STR( ":",             1                         )        DL      \
+      STR( opath,           njvmextdirbaselen         )        DL      \
+      STR( path2extdir_sfx, sizeof(path2extdir_sfx)-1 )        DL      \
+      STR( "",              1                         )
+
+#define STR_LEN(str,len) (len)
+  char *nextdirarg= xmalloc(STRS(STR_LEN, +));
+  char *p= nextdirarg;
+
+#define STR_ADD(str,len) \
+  memcpy(p,(str),(len)); p += (len);
+  STRS(STR_ADD, ;);
+
+  nargv[iargc++]= nextdirarg;
+
+  /* Remaining argument: the class */
+  nargv[iargc++]= oargv[oargc-1];
+
+
+
+
+    if (arg
+}
diff --git a/libjava-wrap.c b/libjava-wrap.c
new file mode 100644 (file)
index 0000000..4bafa41
--- /dev/null
@@ -0,0 +1,118 @@
+/**/
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define STDERRSTR_CONST(m) write(2,m,sizeof(m)-1)
+#define STDERRSTR_STRING(m) write(2,m,strlen(m))
+
+static anyfn_type *find_any(const char *name) {
+  static const char *dlerr;
+  anyfn_type *kv;
+
+  kv= dlsym(RTLD_NEXT,name); if (kv) return kv;
+  dlerr= dlerror(); if (!dlerr) dlerr= "dlsym() failed for no reason";
+  STDERRSTR_CONST("pctb-preload-wrap: error finding original version of ");
+  STDERRSTR_STRING(name);
+  STDERRSTR_CONST(": ");
+  STDERRSTR_STRING(dlerr);
+  STDERRSTR_STRING("\n");
+  errno= ENOSYS;
+  return 0;
+}
+
+typedef int
+execvefn_type(const char *path, char *const argv[], char *const envp[]);
+
+static execvefn_type find_execve, *old_execve= find_execve;
+
+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);
+}
+
+static const char javatail[]= "/bin/java";
+
+int execve(const char *path, char *const argv[], char *const envp[]) {
+  int pathlen= strlen(path);
+  if (pathlen < (sizeof(path2extdir_rm)-1) ||
+      strcmp(javatail, path + pathlen-(sizeof(path2extdir_rm)-1)))
+    old_execve(opath, oargv, oenvp);
+  
+
+  
+
+  int oargc;
+
+
+
+  xassert(opathlen >= 
+  
+
+  for (oargc=0; oargv[oargc]; oargc++);
+  xassert(oargc);
+  if (strcmp(oargv[oargc-1], "com.threerings.yohoho.client.YoApp"))
+
+  /* Remove ourselves from LD_PRELOAD */
+  int ipreloadenv=-1;
+  const char ldpreload[]= "LD_PRELOAD=";
+  for (oenvc=0; oenvp[oenvc]; oenvc++) {
+    if (memcmp(oenvp[oenvc], ldpreload, sizeof(ldpreload)-1)) continue;
+    xassert(ipreloadenv==-1);
+    ipreloadenv= oenvc;
+  }
+  xassert(ipreloadenv>=0);
+  xassert(!strchr(':',oenvp[ipreloadenv]));
+  
+
+  int nargc= oargc+2;
+  char **nargv= xmalloc(sizeof(*nargv) * (nargc+1));
+
+  /* Add argument for accessibility assistive tech. */
+  int iargc= oargc-1;
+  memcpy(nargv, oargv, iargc);
+  nargv[iargc++]= "
+    "";
+
+  /* Calculate and add argument for ext dirs containing our jars */
+  const char *nextdir;
+  xassert((nextdir= getenv("JPCTB_EXTDIR")));
+  int nextdirlen= strlen(nextdir);
+
+  int njvmextdirbaselen= opathlen-sizeof(path2extdir_rm)-1);
+  xassert(!strcmp(path2extdir_rm, opath+njvmextdirbaselen);
+
+  const char path2extdir_pfx[]= "
+
+#define STRS(STR,DL)                                           \
+      STR( path2extdir_pfx, sizeof(path2extdir_pfx)-1 )        DL      \
+      STR( nextdir,         nextdirlen                )        DL      \
+      STR( ":",             1                         )        DL      \
+      STR( opath,           njvmextdirbaselen         )        DL      \
+      STR( path2extdir_sfx, sizeof(path2extdir_sfx)-1 )        DL      \
+      STR( "",              1                         )
+
+#define STR_LEN(str,len) (len)
+  char *nextdirarg= xmalloc(STRS(STR_LEN, +));
+  char *p= nextdirarg;
+
+#define STR_ADD(str,len) \
+  memcpy(p,(str),(len)); p += (len);
+  STRS(STR_ADD, ;);
+
+  nargv[iargc++]= nextdirarg;
+
+  /* Remaining argument: the class */
+  nargv[iargc++]= oargv[oargc-1];
+
+
+
+
+    if (arg
+}
diff --git a/libjwrap.c b/libjwrap.c
new file mode 100644 (file)
index 0000000..b74a99a
--- /dev/null
@@ -0,0 +1,100 @@
+/**/
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.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;
+  anyfn_type *kv;
+
+  kv= dlsym(RTLD_NEXT,name); if (kv) return kv;
+  dlerr= dlerror(); if (!dlerr) dlerr= "dlsym() failed for no reason";
+  STDERRSTR_CONST(QUIS ": error finding original version of ");
+  STDERRSTR_STRING(name);
+  STDERRSTR_CONST(": ");
+  STDERRSTR_STRING(dlerr);
+  STDERRSTR_CONST("\n");
+  errno= ENOSYS;
+  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);
+}
+
+static const char javatail[]= "/bin/java";
+
+int execve(const char *path, char *const oargv[], char *const envp[]) {
+  int oargc;
+  for (oargc=0; oargv[oargc]; oargc++);
+
+  if (!strcmp(path,"/dev/jwrap/bypass")) {
+    //STDERRSTR_CONST(QUIS ": bypass\n");
+    int nargc= oargc-1;
+    char **nargv= malloc(sizeof(*nargv) * nargc);  if (!nargv) return -1;
+    nargv[0]= oargv[0];
+    memcpy(nargv+1, oargv+2, sizeof(*nargv) * nargc-1);
+    return old_execve(oargv[1], nargv, envp);
+  }
+
+  int pathlen= strlen(path);
+  if (!oargc ||
+      pathlen < (sizeof(javatail)-1) ||
+      strcmp(javatail, path + pathlen-(sizeof(javatail)-1))) {
+    //STDERRSTR_CONST(QUIS ": non-java\n");
+    return old_execve(path, oargv, envp);
+  }
+
+  //STDERRSTR_CONST(QUIS ": ours\n");
+
+  struct stat stab;
+  if (stat(path,&stab)) return -1;
+
+  int nargc= oargc+2;
+  char **nargv= malloc(sizeof(*nargv) * nargc);  if (!nargv) return -1;
+
+  const char *jwrap_script= getenv("JWRAP_SCRIPT");
+  if (!jwrap_script) {
+    STDERRSTR_CONST(QUIS ": no JWRAP_SCRIPT specified!\n");
+    errno= ENOENT;
+    return -1;
+  }
+
+  nargv[0]= (char*)jwrap_script;
+  nargv[1]= (char*)path;
+  memcpy(nargv+2, oargv, sizeof(*nargv) * (oargc+1));
+
+  old_execve(nargv[0], nargv, envp);
+  int e= errno;
+
+  const char *errstr= strerror(e);
+  STDERRSTR_CONST(QUIS ": failed to execute ");
+  STDERRSTR_STRING(jwrap_script);
+  STDERRSTR_CONST(": ");
+  STDERRSTR_STRING(errstr);
+  STDERRSTR_CONST("\n");
+  
+  errno= e;
+  return -1;
+}