X-Git-Url: http://www.dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fcallcgi.c;h=e6e909b9c3ce31d1c89be62d055c6ccc55b68e46;hb=c703cd40b144284a46eb4a59294b4b1757b8faa6;hp=84d4c6916db069b8bd4e7ea6d181960c505f7928;hpb=8626e489ae471e4842aecef363bfb9e8b3eaa246;p=ashd.git diff --git a/src/callcgi.c b/src/callcgi.c index 84d4c69..e6e909b 100644 --- a/src/callcgi.c +++ b/src/callcgi.c @@ -66,7 +66,7 @@ static char *absolutify(char *file) static void forkchild(int inpath, char *prog, char *file, char *method, char *url, char *rest, int *infd, int *outfd) { int i; - char *qp, **env; + char *qp, **env, *name; int inp[2], outp[2]; pid_t pid; @@ -90,15 +90,26 @@ static void forkchild(int inpath, char *prog, char *file, char *method, char *ur if(getenv("HTTP_VERSION")) putenv(sprintf2("SERVER_PROTOCOL=%s", getenv("HTTP_VERSION"))); putenv(sprintf2("REQUEST_METHOD=%s", method)); - putenv(sprintf2("PATH_INFO=%s", rest)); - putenv(sprintf2("SCRIPT_NAME=%s", url)); + if(*rest) + putenv(sprintf2("PATH_INFO=/%s", rest)); + else + putenv("PATH_INFO="); + name = url; + /* XXX: This is an ugly hack (I think), but though I can think + * of several alternatives, none seem to be better. */ + if(*rest && (strlen(url) > strlen(rest)) && + !strcmp(rest, url + strlen(url) - strlen(rest)) && + (url[strlen(url) - strlen(rest) - 1] == '/')) { + name = sprintf2("%.*s", (int)(strlen(url) - strlen(rest) - 1), url); + } + putenv(sprintf2("SCRIPT_NAME=%s", name)); putenv(sprintf2("QUERY_STRING=%s", qp?qp:"")); if(getenv("REQ_HOST")) putenv(sprintf2("SERVER_NAME=%s", getenv("REQ_HOST"))); if(getenv("REQ_X_ASH_SERVER_PORT")) putenv(sprintf2("SERVER_PORT=%s", getenv("REQ_X_ASH_SERVER_PORT"))); if(getenv("REQ_X_ASH_PROTOCOL") && !strcmp(getenv("REQ_X_ASH_PROTOCOL"), "https")) - putenv("HTTPS=ON"); + putenv("HTTPS=on"); if(getenv("REQ_X_ASH_ADDRESS")) putenv(sprintf2("REMOTE_ADDR=%s", getenv("REQ_X_ASH_ADDRESS"))); if(getenv("REQ_CONTENT_TYPE")) @@ -278,14 +289,14 @@ static void sendheaders(char **headers, FILE *out) static void usage(void) { - flog(LOG_ERR, "usage: callcgi [-p PROGRAM] METHOD URL REST"); + flog(LOG_ERR, "usage: callcgi [-c] [-p PROGRAM] METHOD URL REST"); } int main(int argc, char **argv, char **envp) { int c; - char *file, *prog; - int inpath; + char *file, *prog, *sp; + int inpath, cd; int infd, outfd; FILE *in, *out; char **headers; @@ -295,8 +306,12 @@ int main(int argc, char **argv, char **envp) prog = NULL; inpath = 0; - while((c = getopt(argc, argv, "p:")) >= 0) { + cd = 0; + while((c = getopt(argc, argv, "cp:")) >= 0) { switch(c) { + case 'c': + cd = 1; + break; case 'p': prog = optarg; inpath = 1; @@ -315,6 +330,21 @@ int main(int argc, char **argv, char **envp) flog(LOG_ERR, "callcgi: needs to be called with the X-Ash-File header"); exit(1); } + + if(cd) { + /* This behavior is encouraged by the CGI specification (RFC 3875, 7.2), + * but not strictly required, and I get the feeling it might break some + * relative paths here or there, so it's not the default for now. */ + if((sp = strrchr(file, '/')) != NULL) { + *sp = 0; + if(chdir(file)) { + *sp = '/'; + } else { + file = sp + 1; + } + } + } + if(prog == NULL) prog = file; forkchild(inpath, prog, file, argv[optind], argv[optind + 1], argv[optind + 2], &infd, &outfd);