X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=jarrg-owen.git;a=blobdiff_plain;f=libjwrap.c;h=23ee7d6ec16eddb83f93cee5408c721ae0fd0e10;hp=b74a99a19709c9f55c0154c92f43302b4bccbab3;hb=801ee8fc524bfda06f4bbfbec51caf228258d3fe;hpb=63e60c613ba89505965f2958a3c75c3b507eeb74 diff --git a/libjwrap.c b/libjwrap.c index b74a99a..23ee7d6 100644 --- a/libjwrap.c +++ b/libjwrap.c @@ -8,6 +8,7 @@ #include #include #include +#include #define STDERRSTR_CONST(m) write(2,m,sizeof(m)-1) #define STDERRSTR_STRING(m) write(2,m,strlen(m)) @@ -15,10 +16,6 @@ #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 )