chiark / gitweb /
WIP jpctb wrapper
[jarrg-ian.git] / libjwrap.c
1 /**/
2
3 #define _GNU_SOURCE
4 #include <dlfcn.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11
12 #define STDERRSTR_CONST(m) write(2,m,sizeof(m)-1)
13 #define STDERRSTR_STRING(m) write(2,m,strlen(m))
14
15 #define QUIS "libjwrap"
16
17 typedef void anyfn_type(void);
18 typedef int
19 execvefn_type(const char *path, char *const argv[], char *const envp[]);
20
21 static execvefn_type find_execve, *old_execve= find_execve;
22
23 static anyfn_type *find_any(const char *name) {
24   static const char *dlerr;
25   anyfn_type *kv;
26
27   kv= dlsym(RTLD_NEXT,name); if (kv) return kv;
28   dlerr= dlerror(); if (!dlerr) dlerr= "dlsym() failed for no reason";
29   STDERRSTR_CONST(QUIS ": error finding original version of ");
30   STDERRSTR_STRING(name);
31   STDERRSTR_CONST(": ");
32   STDERRSTR_STRING(dlerr);
33   STDERRSTR_CONST("\n");
34   errno= ENOSYS;
35   return 0;
36 }
37
38 static int find_execve(const char *path,
39                        char *const argv[], char *const envp[]) {
40   anyfn_type *anyfn;
41   anyfn= find_any("execve"); if (!anyfn) return -1;
42   old_execve= (execvefn_type*)anyfn;
43   return old_execve(path, argv, envp);
44 }
45
46 static const char javatail[]= "/bin/java";
47
48 int execve(const char *path, char *const oargv[], char *const envp[]) {
49   int oargc;
50   for (oargc=0; oargv[oargc]; oargc++);
51
52   if (!strcmp(path,"/dev/jwrap/bypass")) {
53     //STDERRSTR_CONST(QUIS ": bypass\n");
54     int nargc= oargc-1;
55     char **nargv= malloc(sizeof(*nargv) * nargc);  if (!nargv) return -1;
56     nargv[0]= oargv[0];
57     memcpy(nargv+1, oargv+2, sizeof(*nargv) * nargc-1);
58     return old_execve(oargv[1], nargv, envp);
59   }
60
61   int pathlen= strlen(path);
62   if (!oargc ||
63       pathlen < (sizeof(javatail)-1) ||
64       strcmp(javatail, path + pathlen-(sizeof(javatail)-1))) {
65     //STDERRSTR_CONST(QUIS ": non-java\n");
66     return old_execve(path, oargv, envp);
67   }
68
69   //STDERRSTR_CONST(QUIS ": ours\n");
70
71   struct stat stab;
72   if (stat(path,&stab)) return -1;
73
74   int nargc= oargc+2;
75   char **nargv= malloc(sizeof(*nargv) * nargc);  if (!nargv) return -1;
76
77   const char *jwrap_script= getenv("JWRAP_SCRIPT");
78   if (!jwrap_script) {
79     STDERRSTR_CONST(QUIS ": no JWRAP_SCRIPT specified!\n");
80     errno= ENOENT;
81     return -1;
82   }
83
84   nargv[0]= (char*)jwrap_script;
85   nargv[1]= (char*)path;
86   memcpy(nargv+2, oargv, sizeof(*nargv) * (oargc+1));
87
88   old_execve(nargv[0], nargv, envp);
89   int e= errno;
90
91   const char *errstr= strerror(e);
92   STDERRSTR_CONST(QUIS ": failed to execute ");
93   STDERRSTR_STRING(jwrap_script);
94   STDERRSTR_CONST(": ");
95   STDERRSTR_STRING(errstr);
96   STDERRSTR_CONST("\n");
97   
98   errno= e;
99   return -1;
100 }