/* * Usage: as CGI script, but called by userv * environment variables are USERV_U_E_... */ #include #include #include #include #include #include #include #include "ucgi.h" void *xrealloc(void *ptr, size_t sz) { void *r; r= realloc(ptr,sz); if (!r) syserror("realloc failed"); return r; } int main(int argc, const char **argv) { char *uservar, *scriptpath; const char *nextslash, *lastslash, *pathi, *ev, *en, *scriptdir; const char *const *ep; const char **arguments; size_t scriptdirlen, scriptpathlen, l, uservarnl; struct stat stab; ev= getenv("USERV_U_DEBUG"); if (ev && *ev) debugmode= 1; if (argc > MAX_ARGS) error("too many arguments"); scriptdir= *++argv; if (!scriptdir) error("no argv[1] (script directory)"); scriptdirlen= strlen(scriptdir); 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"); if (unsetenv(uservarn)) syserror("unsetenv"); } pathi= getenv("PATH_INFO"); if (!pathi) error("PATH_INFO not found"); if (pathi[0] != '/') error("PATH_INFO must start with /"); lastslash= pathi; for (;;) { nextslash= strchr(lastslash+1,'/'); if (!nextslash) error("insufficient slashes in PATH_INFO beyond directory"); if (nextslash[1]=='.' || nextslash[1]=='#' || !nextslash[1]) error("bad char begin"); if (nextslash-pathi > MAX_SCRIPTPATH_LEN) error("PATH_INFO script dir too long"); scriptpathlen= scriptdirlen+(nextslash-pathi); scriptpath= xrealloc(scriptpath,scriptpathlen); memcpy(scriptpath,pathi,scriptpathlen); scriptpath[scriptpathlen]= 0; if (scriptpath[scriptpathlen-1]=='~') error("bad char end"); r= stat(scriptpath,&stab); if (r) syserror("stat script"); if (S_ISREG(stab.st_mode)) break; if (!S_ISDIR(stab.st_mode)) syserror("script not directory or file"); lastlash= nextslash; } if (setenv("PATH_INFO",nextslash,1)) syserror("setenv PATH_INFO"); arguments= xmalloc(sizeof(const char*)*(argc+5)); nargs= 0; arguments[nargs++]= scriptpath; while ((av= (*++argv))) arguments[nargs++]= av; arguments[nargs++]= 0; execvp(scriptpath,(char*const*)arguments); syserror("exec script"); return -1; }