--- /dev/null
+/**/
+
+#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);
+}
+
+int execve(const char *opath, char *const oargv[], char *const oenvp[]) {
+ int oargc;
+ for (oargc=0; oargv[oargc]; oargc++);
+ xassert(oargc);
+ if (strcmp(oargv[oargc-1], "com.threerings.yohoho.client.YoApp"))
+ old_execve(opath, oargv, oenvp);
+
+ /* 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);
+
+ const char path2extdir_rm[]= "/bin/java";
+ int opathlen= strlen(opath);
+ int njvmextdirbaselen= opathlen-sizeof(path2extdir_rm)-1);
+ xassert(opathlen >= sizeof(path2extdir_rm));
+ 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
+}