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;
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));
+ 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))) {
+ name = sprintf2("%.*s", (int)(strlen(url) - strlen(rest)), 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"))
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;
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;
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);