X-Git-Url: https://git.distorted.org.uk/~mdw/userv-utils/blobdiff_plain/1ba0145fe6fe72f63af15e12716c13071523eaa4..0cd9d59dfadf1a9abbef4428ff4f90bf32c01bd4:/www-cgi/ucgitarget.c diff --git a/www-cgi/ucgitarget.c b/www-cgi/ucgitarget.c index 4228951..866a2d5 100644 --- a/www-cgi/ucgitarget.c +++ b/www-cgi/ucgitarget.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -32,71 +33,144 @@ #include "ucgi.h" -static void *xrealloc(void *ptr, size_t sz) { - void *r; +static const char *const default_envok[]= { + "AUTH_TYPE", + "CONTENT_LENGTH", + "CONTENT_TYPE", + "DOCUMENT_ROOT", + "GATEWAY_INTERFACE", + "HTTP_ACCEPT", + "HTTP_ACCEPT_CHARSET", + "HTTP_ACCEPT_ENCODING", + "HTTP_ACCEPT_LANGUAGE", + "HTTP_CACHE_CONTROL", + "HTTP_CONNECTION", + "HTTP_CONTENT_ENCODING", + "HTTP_COOKIE", + "HTTP_DNT", + "HTTP_HOST", + "HTTP_KEEP_ALIVE", + "HTTP_NEGOTIATE", + "HTTP_PRAGMA", + "HTTP_REFERER", + "HTTP_USER_AGENT", + "HTTP_VIA", + "HTTP_X_FORWARDED_FOR", + "HTTPS", + "PATH_INFO", + "PATH_TRANSLATED", + "QUERY_STRING", + "REDIRECT_HANDLER", + "REDIRECT_SCRIPT_URI", + "REDIRECT_SCRIPT_URL", + "REDIRECT_STATUS", + "REDIRECT_URL", + "REMOTE_ADDR", + "REMOTE_HOST", + "REMOTE_USER", + "REMOTE_IDENT", + "REQUEST_METHOD", + "REQUEST_URI", + "SCRIPT_FILENAME", + "SCRIPT_NAME", + "SCRIPT_URI", + "SCRIPT_URL", + "SERVER_ADDR", + "SERVER_ADMIN", + "SERVER_NAME", + "SERVER_PORT", + "SERVER_PROTOCOL", + "SERVER_SIGNATURE", + "SERVER_SOFTWARE", + "SSL_CIPHER", + "SSL_CLIENT_S_DN", + "SSL_CLIENT_VERIFY", + "SSL_PROTOCOL", + 0 +}; - r= realloc(ptr,sz); - if (!r) syserror("realloc failed"); - return r; +static void setenvar(const char *fulln, + const char *en, const char *ep, void *p) { + xsetenv(en, ep, 1); + unsetenv(fulln); } -int main(int argc, const char **argv) { - char *uservarn, *scriptpath, *newvar; - const char *nextslash, *lastslash, *pathi, *ev, *ev2, *en, *scriptdir, *av; - const char *const *ep; +int main(int argc, char **argv) { + char *scriptpath, *newvar; + const char *nextslash, *lastslash, *pathi, *ev, *ev2, *scriptdir, *av; + const char *const *envok; const char **arguments; - size_t scriptdirlen, scriptpathlen, l, uservarnl; + size_t scriptdirlen, scriptpathlen, l; struct stat stab; - int r, nargs; + int i, r, nargs; + const char *filters= 0; ev= getenv("USERV_U_DEBUG"); if (ev && *ev) debugmode= 1; - if (argc > MAX_ARGS) error("too many arguments"); + D( if (debugmode) printf(";;; UCGITARGET\n"); ) + if (argc > MAX_ARGS) error("too many arguments", 500); - if (!*++argv) error("no script directory argument"); - ev= getenv("HOME"); if (!ev) error("no HOME env. var"); + for (;;) { + i= getopt(argc, argv, "+e:"); if (i < 0) break; + switch (i) { + case 'e': filters= optarg; break; + default: error("bad command line", 500); break; + } + } + argc -= optind; argv += optind; + + if (!*argv) error("no script directory argument", 500); + ev= getenv("HOME"); if (!ev) error("no HOME env. var", 500); l= strlen(*argv)+strlen(ev); newvar= xmalloc(l+2); sprintf(newvar,"%s/%s",ev,*argv); scriptdir= newvar; scriptdirlen= strlen(scriptdir); - uservarn= 0; - uservarnl= 0; - for (ep= envok; (en= *ep); ep++) { - l= strlen(en)+11; - if (uservarnl MAX_ENVVAR_VALUE) error("environment variable too long"); - if (setenv(en,ev,1)) syserror("setenv"); - unsetenv(uservarn); + if (filters) + envok= load_filters(LOADF_MUST, filters, LF_END); + else { + envok= load_filters(0, + ".userv/ucgitarget.env-filter", + "/etc/userv/ucgitarget.env-filter", + LF_END); } + filter_environment(0, "USERV_U_E_", envok, default_envok, setenvar, 0); + scriptpath= 0; pathi= getenv("PATH_INFO"); - if (!pathi) error("PATH_INFO not found"); + if (!pathi) error("PATH_INFO not found", 500); lastslash= pathi; + D( if (debugmode) { + printf(";; find script name...\n" + ";; PATH_INFO = `%s'\n", + pathi); + } ) for (;;) { - if (*lastslash != '/') error("PATH_INFO expected slash not found"); - if (lastslash[1]=='.' || lastslash[1]=='#' || !lastslash[1]) error("bad char begin"); + if (*lastslash != '/') error("PATH_INFO expected slash not found", 400); + if (lastslash[1]=='.' || lastslash[1]=='#' || !lastslash[1]) + error("bad char begin", 400); nextslash= strchr(lastslash+1,'/'); if (!nextslash) nextslash= lastslash+1+strlen(lastslash+1); - if (!nextslash) error("insufficient elements in PATH_INFO"); - if (nextslash==lastslash+1) error("empty component in PATH_INFO"); - if (nextslash-pathi > MAX_SCRIPTPATH_LEN) error("PATH_INFO script path too long"); + if (!nextslash) error("insufficient elements in PATH_INFO", 400); + if (nextslash==lastslash+1) error("empty component in PATH_INFO", 400); + if (nextslash-pathi > MAX_SCRIPTPATH_LEN) + error("PATH_INFO script path too long", 400); scriptpathlen= scriptdirlen+(nextslash-pathi); scriptpath= xrealloc(scriptpath,scriptpathlen+1); strcpy(scriptpath,scriptdir); memcpy(scriptpath+scriptdirlen,pathi,nextslash-pathi); scriptpath[scriptpathlen]= 0; - if (scriptpath[scriptpathlen-1]=='~') error("bad char end"); + if (scriptpath[scriptpathlen-1]=='~') error("bad char end", 400); + D( if (debugmode) printf(";; try `%s'\n", scriptpath); ) r= stat(scriptpath,&stab); if (r) syserror("stat script"); if (S_ISREG(stab.st_mode)) break; - if (!S_ISDIR(stab.st_mode)) error("script not directory or file"); + if (!S_ISDIR(stab.st_mode)) error("script not directory or file", 500); lastslash= nextslash; } + D( if (debugmode) printf(";; found script: tail = `%s'\n", nextslash); ) if (*nextslash) xsetenv("PATH_INFO",nextslash,1); else unsetenv("PATH_INFO"); @@ -108,7 +182,7 @@ int main(int argc, const char **argv) { ev= getenv("SCRIPT_NAME"); if (ev) { - ev2= getenv("USER"); if (!ev2) error("no USER variable"); + ev2= getenv("USER"); if (!ev2) error("no USER variable", 500); newvar= xmalloc(strlen(ev)+2+strlen(ev2)+scriptpathlen-scriptdirlen+2); sprintf(newvar,"%s/~%s%s",ev,ev2,scriptpath+scriptdirlen); xsetenv("SCRIPT_NAME",newvar,1); @@ -121,6 +195,19 @@ int main(int argc, const char **argv) { while ((av= (*++argv))) arguments[nargs++]= av; arguments[nargs++]= 0; + D( if (debugmode) { + int i; + + printf(";; final environment...\n"); + for (i = 0; environ[i]; i++) + printf(";; %s\n", environ[i]); + + printf(";; final command line...\n"); + for (i = 0; arguments[i]; i++) + printf(";; %s\n", arguments[i]); + fflush(stdout); + } ) + execvp(scriptpath,(char*const*)arguments); syserror("exec script"); return -1;