#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;
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++);
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 )