Commit | Line | Data |
---|---|---|
6a580c17 | 1 | /* |
2 | * Usage: as CGI script, but called by userv | |
3 | * environment variables are USERV_U_E_... | |
4 | */ | |
a33962ba | 5 | /* |
711a0748 | 6 | * Copyright (C) 1998-1999,2003 Ian Jackson |
a33962ba | 7 | * |
8 | * This is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with userv-utils; if not, write to the Free Software | |
20 | * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
21 | * | |
22 | * $Id$ | |
23 | */ | |
6a580c17 | 24 | |
25 | #include <stdio.h> | |
26 | #include <string.h> | |
27 | #include <ctype.h> | |
28 | #include <unistd.h> | |
29 | #include <sys/types.h> | |
30 | #include <sys/wait.h> | |
31 | #include <sys/stat.h> | |
32 | ||
33 | #include "ucgi.h" | |
34 | ||
6a580c17 | 35 | int main(int argc, const char **argv) { |
36 | char *uservarn, *scriptpath, *newvar; | |
37 | const char *nextslash, *lastslash, *pathi, *ev, *ev2, *en, *scriptdir, *av; | |
38 | const char *const *ep; | |
39 | const char **arguments; | |
40 | size_t scriptdirlen, scriptpathlen, l, uservarnl; | |
41 | struct stat stab; | |
42 | int r, nargs; | |
43 | ||
44 | ev= getenv("USERV_U_DEBUG"); | |
45 | if (ev && *ev) debugmode= 1; | |
46 | ||
6a3086f1 | 47 | D( if (debugmode) printf(";;; UCGITARGET\n"); ) |
6a580c17 | 48 | if (argc > MAX_ARGS) error("too many arguments"); |
49 | ||
50 | if (!*++argv) error("no script directory argument"); | |
51 | ev= getenv("HOME"); if (!ev) error("no HOME env. var"); | |
52 | l= strlen(*argv)+strlen(ev); | |
53 | newvar= xmalloc(l+2); | |
54 | sprintf(newvar,"%s/%s",ev,*argv); | |
55 | scriptdir= newvar; | |
56 | scriptdirlen= strlen(scriptdir); | |
57 | ||
58 | uservarn= 0; | |
59 | uservarnl= 0; | |
60 | for (ep= envok; (en= *ep); ep++) { | |
61 | l= strlen(en)+11; | |
62 | if (uservarnl<l) { uservarn= xrealloc(uservarn,l); uservarnl= l; } | |
63 | sprintf(uservarn,"USERV_U_E_%s",en); | |
64 | ev= getenv(uservarn); if (!ev) continue; | |
65 | if (strlen(ev) > MAX_ENVVAR_VALUE) error("environment variable too long"); | |
66 | if (setenv(en,ev,1)) syserror("setenv"); | |
67 | unsetenv(uservarn); | |
68 | } | |
69 | ||
70 | scriptpath= 0; | |
71 | pathi= getenv("PATH_INFO"); | |
72 | if (!pathi) error("PATH_INFO not found"); | |
73 | lastslash= pathi; | |
6a3086f1 MW |
74 | D( if (debugmode) { |
75 | printf(";; find script name...\n" | |
76 | ";; PATH_INFO = `%s'\n", | |
77 | pathi); | |
78 | } ) | |
6a580c17 | 79 | for (;;) { |
80 | if (*lastslash != '/') error("PATH_INFO expected slash not found"); | |
81 | if (lastslash[1]=='.' || lastslash[1]=='#' || !lastslash[1]) error("bad char begin"); | |
82 | nextslash= strchr(lastslash+1,'/'); | |
83 | if (!nextslash) nextslash= lastslash+1+strlen(lastslash+1); | |
84 | if (!nextslash) error("insufficient elements in PATH_INFO"); | |
85 | if (nextslash==lastslash+1) error("empty component in PATH_INFO"); | |
86 | if (nextslash-pathi > MAX_SCRIPTPATH_LEN) error("PATH_INFO script path too long"); | |
87 | scriptpathlen= scriptdirlen+(nextslash-pathi); | |
88 | scriptpath= xrealloc(scriptpath,scriptpathlen+1); | |
89 | strcpy(scriptpath,scriptdir); | |
90 | memcpy(scriptpath+scriptdirlen,pathi,nextslash-pathi); | |
91 | scriptpath[scriptpathlen]= 0; | |
92 | if (scriptpath[scriptpathlen-1]=='~') error("bad char end"); | |
6a3086f1 | 93 | D( if (debugmode) printf(";; try `%s'\n", scriptpath); ) |
6a580c17 | 94 | r= stat(scriptpath,&stab); if (r) syserror("stat script"); |
95 | if (S_ISREG(stab.st_mode)) break; | |
1ba0145f | 96 | if (!S_ISDIR(stab.st_mode)) error("script not directory or file"); |
6a580c17 | 97 | lastslash= nextslash; |
98 | } | |
6a3086f1 | 99 | D( if (debugmode) printf(";; found script: tail = `%s'\n", nextslash); ) |
6a580c17 | 100 | if (*nextslash) xsetenv("PATH_INFO",nextslash,1); |
101 | else unsetenv("PATH_INFO"); | |
102 | ||
103 | newvar= xmalloc(scriptpathlen+strlen(nextslash)+3); | |
104 | sprintf(newvar,"%s%s",scriptpath,nextslash); | |
105 | xsetenv("PATH_TRANSLATED",newvar,1); | |
106 | ||
107 | xsetenv("SCRIPT_FILENAME",scriptpath,1); | |
108 | ||
109 | ev= getenv("SCRIPT_NAME"); | |
110 | if (ev) { | |
111 | ev2= getenv("USER"); if (!ev2) error("no USER variable"); | |
112 | newvar= xmalloc(strlen(ev)+2+strlen(ev2)+scriptpathlen-scriptdirlen+2); | |
113 | sprintf(newvar,"%s/~%s%s",ev,ev2,scriptpath+scriptdirlen); | |
114 | xsetenv("SCRIPT_NAME",newvar,1); | |
115 | } | |
116 | ||
117 | arguments= xmalloc(sizeof(const char*)*(argc+5)); | |
118 | nargs= 0; | |
119 | ||
120 | arguments[nargs++]= scriptpath; | |
121 | while ((av= (*++argv))) arguments[nargs++]= av; | |
122 | arguments[nargs++]= 0; | |
123 | ||
6a3086f1 MW |
124 | D( if (debugmode) { |
125 | int i; | |
126 | ||
127 | printf(";; final environment...\n"); | |
128 | for (i = 0; environ[i]; i++) | |
129 | printf(";; %s\n", environ[i]); | |
130 | ||
131 | printf(";; final command line...\n"); | |
132 | for (i = 0; arguments[i]; i++) | |
133 | printf(";; %s\n", arguments[i]); | |
134 | fflush(stdout); | |
135 | } ) | |
136 | ||
6a580c17 | 137 | execvp(scriptpath,(char*const*)arguments); |
138 | syserror("exec script"); | |
139 | return -1; | |
140 | } |