X-Git-Url: http://www.dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fcallcgi.c;h=9e7c21b4c7e76851991e31624312c3a84da65713;hb=d245c327ec854a63b6c6a6c90bd26c88d1a7ddaf;hp=1713a4fef0940f81ecb26dc520370a772f11b303;hpb=8cc516344932495129e25d03d5f0850830f3387f;p=ashd.git diff --git a/src/callcgi.c b/src/callcgi.c index 1713a4f..9e7c21b 100644 --- a/src/callcgi.c +++ b/src/callcgi.c @@ -52,7 +52,18 @@ static void passdata(FILE *in, FILE *out) free(buf); } -static void forkchild(char *prog, char *file, char *method, char *url, char *rest, int *infd, int *outfd) +static char *absolutify(char *file) +{ + char cwd[1024]; + + if(*file != '/') { + getcwd(cwd, sizeof(cwd)); + return(sprintf2("%s/%s", cwd, file)); + } + return(sstrdup(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; @@ -103,8 +114,11 @@ static void forkchild(char *prog, char *file, char *method, char *url, char *res * This is (understandably) missing from the CGI * specification, but PHP seems to require it. */ - putenv(sprintf2("SCRIPT_FILENAME=%s", file)); - execlp(prog, prog, file, NULL); + putenv(sprintf2("SCRIPT_FILENAME=%s", absolutify(file))); + if(inpath) + execlp(prog, prog, file, NULL); + else + execl(prog, prog, file, NULL); exit(127); } close(inp[0]); @@ -183,6 +197,46 @@ fail: return(NULL); } +static char *defstatus(int code) +{ + if(code == 200) + return("OK"); + else if(code == 201) + return("Created"); + else if(code == 202) + return("Accepted"); + else if(code == 204) + return("No Content"); + else if(code == 300) + return("Multiple Choices"); + else if(code == 301) + return("Moved Permanently"); + else if(code == 302) + return("Found"); + else if(code == 303) + return("See Other"); + else if(code == 304) + return("Not Modified"); + else if(code == 307) + return("Moved Temporarily"); + else if(code == 400) + return("Bad Request"); + else if(code == 401) + return("Unauthorized"); + else if(code == 403) + return("Forbidden"); + else if(code == 404) + return("Not Found"); + else if(code == 500) + return("Internal Server Error"); + else if(code == 501) + return("Not Implemented"); + else if(code == 503) + return("Service Unavailable"); + else + return("Unknown status"); +} + static void sendstatus(char **headers, FILE *out) { char **hp; @@ -197,16 +251,20 @@ static void sendstatus(char **headers, FILE *out) **hp = 0; } else if(!strcasecmp(hp[0], "location")) { location = hp[1]; + hp += 2; } else { hp += 2; } } if(status) { - fprintf(out, "HTTP/1.1 %s\r\n", status); + if(strchr(status, ' ')) + fprintf(out, "HTTP/1.1 %s\n", status); + else + fprintf(out, "HTTP/1.1 %i %s\n", atoi(status), defstatus(atoi(status))); } else if(location) { - fprintf(out, "HTTP/1.1 303 See Other\r\n"); + fprintf(out, "HTTP/1.1 303 See Other\n"); } else { - fprintf(out, "HTTP/1.1 200 OK\r\n"); + fprintf(out, "HTTP/1.1 200 OK\n"); } } @@ -214,40 +272,64 @@ static void sendheaders(char **headers, FILE *out) { while(*headers) { if(**headers) - fprintf(out, "%s: %s\r\n", headers[0], headers[1]); + fprintf(out, "%s: %s\n", headers[0], headers[1]); headers += 2; } } +static void usage(void) +{ + flog(LOG_ERR, "usage: callcgi [-p PROGRAM] METHOD URL REST"); +} + int main(int argc, char **argv, char **envp) { - char *file; - int in, out; - FILE *ins, *outs; + int c; + char *file, *prog; + int inpath; + int infd, outfd; + FILE *in, *out; char **headers; environ = envp; signal(SIGPIPE, SIG_IGN); - if(argc < 5) { - flog(LOG_ERR, "usage: callcgi PROGRAM METHOD URL REST"); + + prog = NULL; + inpath = 0; + while((c = getopt(argc, argv, "p:")) >= 0) { + switch(c) { + case 'p': + prog = optarg; + inpath = 1; + break; + default: + usage(); + exit(1); + } + } + + if(argc - optind < 3) { + usage(); exit(1); } if((file = getenv("REQ_X_ASH_FILE")) == NULL) { flog(LOG_ERR, "callcgi: needs to be called with the X-Ash-File header"); exit(1); } - forkchild(argv[1], file, argv[2], argv[3], argv[4], &in, &out); - ins = fdopen(in, "w"); - passdata(stdin, ins); - fclose(ins); - outs = fdopen(out, "r"); - if((headers = parseheaders(outs)) == NULL) { + if(prog == NULL) + prog = file; + forkchild(inpath, prog, file, argv[optind], argv[optind + 1], argv[optind + 2], &infd, &outfd); + in = fdopen(infd, "w"); + passdata(stdin, in); + fclose(in); + out = fdopen(outfd, "r"); + if((headers = parseheaders(out)) == NULL) { flog(LOG_WARNING, "CGI handler returned invalid headers"); exit(1); } sendstatus(headers, stdout); sendheaders(headers, stdout); - printf("\r\n"); - passdata(outs, stdout); + printf("\n"); + passdata(out, stdout); return(0); }