-/**/
-
-#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>
-#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);
-
-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;
-}
-
-
-#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";
-
-REIMPLEMENTWRAP(execve,
- (const char *path, char *const oargv[], char *const envp[]),
- (path, oargv, 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;
-}
-
-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 )