6c8e44a5 |
1 | /* |
2 | * Usage: as CGI script, but called by userv |
3 | * environment variables are USERV_U_E_... |
4 | */ |
5 | |
6 | #include <stdio.h> |
7 | #include <string.h> |
8 | #include <ctype.h> |
9 | #include <unistd.h> |
10 | #include <sys/types.h> |
11 | #include <sys/wait.h> |
12 | #include <stat.h> |
13 | |
14 | #include "ucgi.h" |
15 | |
16 | void *xrealloc(void *ptr, size_t sz) { |
17 | void *r; |
18 | |
19 | r= realloc(ptr,sz); |
20 | if (!r) syserror("realloc failed"); |
21 | return r; |
22 | } |
23 | |
24 | int main(int argc, const char **argv) { |
25 | char *uservar, *scriptpath; |
26 | const char *nextslash, *lastslash, *pathi, *ev, *en, *scriptdir; |
27 | const char *const *ep; |
28 | const char **arguments; |
29 | size_t scriptdirlen, scriptpathlen, l, uservarnl; |
30 | struct stat stab; |
31 | |
32 | ev= getenv("USERV_U_DEBUG"); |
33 | if (ev && *ev) debugmode= 1; |
34 | |
35 | if (argc > MAX_ARGS) error("too many arguments"); |
36 | |
37 | scriptdir= *++argv; |
38 | if (!scriptdir) error("no argv[1] (script directory)"); |
39 | scriptdirlen= strlen(scriptdir); |
40 | |
41 | for (ep= envok; (en= *ep); ep++) { |
42 | l= strlen(en)+11; |
43 | if (uservarnl<l) { uservarn= xrealloc(uservarn,l); uservarnl= l; } |
44 | sprintf(uservarn,"USERV_U_E_%s",en); |
45 | ev= getenv(uservarn); if (!ev) continue; |
46 | if (strlen(ev) > MAX_ENVVAR_VALUE) error("environment variable too long"); |
47 | if (setenv(en,ev,1)) syserror("setenv"); |
48 | if (unsetenv(uservarn)) syserror("unsetenv"); |
49 | } |
50 | |
51 | pathi= getenv("PATH_INFO"); |
52 | if (!pathi) error("PATH_INFO not found"); |
53 | if (pathi[0] != '/') error("PATH_INFO must start with /"); |
54 | lastslash= pathi; |
55 | for (;;) { |
56 | nextslash= strchr(lastslash+1,'/'); |
57 | if (!nextslash) error("insufficient slashes in PATH_INFO beyond directory"); |
58 | if (nextslash[1]=='.' || nextslash[1]=='#' || !nextslash[1]) error("bad char begin"); |
59 | if (nextslash-pathi > MAX_SCRIPTPATH_LEN) error("PATH_INFO script dir too long"); |
60 | scriptpathlen= scriptdirlen+(nextslash-pathi); |
61 | scriptpath= xrealloc(scriptpath,scriptpathlen); |
62 | memcpy(scriptpath,pathi,scriptpathlen); scriptpath[scriptpathlen]= 0; |
63 | if (scriptpath[scriptpathlen-1]=='~') error("bad char end"); |
64 | r= stat(scriptpath,&stab); if (r) syserror("stat script"); |
65 | if (S_ISREG(stab.st_mode)) break; |
66 | if (!S_ISDIR(stab.st_mode)) syserror("script not directory or file"); |
67 | lastlash= nextslash; |
68 | } |
69 | if (setenv("PATH_INFO",nextslash,1)) syserror("setenv PATH_INFO"); |
70 | |
71 | arguments= xmalloc(sizeof(const char*)*(argc+5)); |
72 | nargs= 0; |
73 | |
74 | arguments[nargs++]= scriptpath; |
75 | while ((av= (*++argv))) arguments[nargs++]= av; |
76 | arguments[nargs++]= 0; |
77 | |
78 | execvp(scriptpath,(char*const*)arguments); |
79 | syserror("exec script"); |
80 | return -1; |
81 | } |