diff --git a/config.def.h b/config.def.h index 35ee857..716fb0d 100644 --- a/config.def.h +++ b/config.def.h @@ -2,6 +2,7 @@ static const char *servername = "127.0.0.1"; static const char *serverport = "80"; +static const char *chrootdir = "."; static const char *docroot = "."; static const char *docindex = "index.html"; static const char *user = "nobody"; diff --git a/quark.1 b/quark.1 index ceee081..35f854c 100644 --- a/quark.1 +++ b/quark.1 @@ -4,6 +4,8 @@ quark \- simple httpd .SH SYNOPSIS .B quark .RB [ \-c ] +.RB [ \-C +.IR chrootdir ] .RB [ \-d .IR cgidir ] .RB [ \-e @@ -29,6 +31,9 @@ Quark is a simple httpd. .B \-c enable CGI-mode, disabled by default. .TP +.B \-C " chrootdir" +chroot into chrootdir, by default ".". +.TP .B \-d " cgidir" change directory to cgidir for CGI-mode, by default ".". .TP @@ -48,7 +53,7 @@ enable directory listing, disabled by default. listen on port, by default "80". .TP .B \-r " docroot" -change directory to docroot, by default ".". +change directory to docroot for static files, by default ".". .TP .B \-s " server" listen on server, by default "127.0.0.1". diff --git a/quark.c b/quark.c index d211abb..575eaa0 100644 --- a/quark.c +++ b/quark.c @@ -93,7 +93,8 @@ static char location[256]; static int running = 1; static int status; static char host[NI_MAXHOST]; -static char reqbuf[MAXBUFLEN]; +static char* reqbuf = NULL; +static char* reqpath = NULL; static char resbuf[MAXBUFLEN]; static char reqhost[256]; static char reqmod[256]; @@ -204,7 +205,7 @@ responsefile(void) { int r, ffd; struct stat st; - if ((r = stat(reqbuf, &st)) == -1 || (ffd = open(reqbuf, O_RDONLY)) == -1) { + if ((r = stat(reqpath, &st)) == -1 || (ffd = open(reqpath, O_RDONLY)) == -1) { /* file not found */ if (putresentry(HEADER, HttpNotFound, tstamp(0)) || putresentry(CONTENTTYPE, texthtml)) @@ -291,8 +292,8 @@ responsedir(void) { return; } if (len + strlen(docindex) + 1 < MAXBUFLEN) - memcpy(reqbuf + len, docindex, strlen(docindex) + 1); - if (access(reqbuf, R_OK) == -1) { /* directory mode */ + memmove(reqbuf + len, docindex, strlen(docindex) + 1); + if (access(reqpath, R_OK) == -1) { /* directory mode */ reqbuf[len] = 0; /* cut off docindex again */ if(!allowdirlist) { if (putresentry(HEADER, HttpForbidden, tstamp(0)) @@ -303,12 +304,12 @@ responsedir(void) { writetext("\r\n"HttpForbidden"\r\n"); return; } - if ((n = scandir(reqbuf, &namelist, NULL, alphasort)) >= 0) { + if ((n = scandir(reqpath, &namelist, NULL, alphasort)) >= 0) { responsedirdata(namelist, n); free(namelist); } else { logerrmsg("client %s requests %s but scandir failed: %s\n", - host, reqbuf, strerror(errno)); + host, reqpath, strerror(errno)); } } else { responsefile(); /* docindex */ @@ -406,7 +407,7 @@ response(void) { } } - r = stat(reqbuf, &st); + r = stat(reqpath, &st); if (cgi_mode) { if(r != -1 && !S_ISDIR(st.st_mode)) responsefile(); @@ -562,9 +563,9 @@ sighandler(int sig) { void usage(void) { - fprintf(stderr, "usage: quark [-c] [-d cgidir] [-e cgiscript] [-g group] " - "[-i index] [-l] [-p port] [-r docroot] [-s server] " - "[-u user] [-v]\n"); + fprintf(stderr, "usage: quark [-c] [-C chrootdir] [-d cgidir] " + "[-e cgiscript] [-g group] [-i index] [-l] [-p port] " + "[-r docroot] [-s server] [-u user] [-v]\n"); exit(EXIT_FAILURE); } @@ -574,12 +575,15 @@ main(int argc, char *argv[]) { struct passwd *upwd = NULL; struct group *gpwd = NULL; struct rlimit rlim; - int i; + int i, docrootlen; ARGBEGIN { case 'c': cgi_mode = 1; break; + case 'C': + chrootdir = EARGF(usage()); + break; case 'd': cgi_dir = EARGF(usage()); break; @@ -619,6 +623,15 @@ main(int argc, char *argv[]) { if (group && *group && !(gpwd = getgrnam(group))) die("error\tinvalid group %s\n", group); + docrootlen = strlen(docroot); + reqpath = malloc(docrootlen + MAXBUFLEN); + if (reqpath == NULL) { + logerrmsg("error\tcannot allocate memory\n"); + goto err; + } + memcpy(reqpath, docroot, docrootlen + 1); + reqbuf = reqpath + docrootlen; + signal(SIGCHLD, sighandler); signal(SIGHUP, sighandler); signal(SIGINT, sighandler); @@ -666,8 +679,8 @@ main(int argc, char *argv[]) { goto err; } - if (chdir(docroot) == -1) { - logerrmsg("error\tchdir %s: %s\n", docroot, strerror(errno)); + if (chdir(chrootdir) == -1) { + logerrmsg("error\tchdir %s: %s\n", chrootdir, strerror(errno)); goto err; } if (chroot(".") == -1) { @@ -693,15 +706,17 @@ main(int argc, char *argv[]) { goto err; } - logmsg("ready\t%s:%s\t%s\n", servername, serverport, docroot); + logmsg("ready\t%s:%s\t%s\n", servername, serverport, chrootdir); serve(listenfd); /* main loop */ close(listenfd); + free(reqpath); freeaddrinfo(ai); return EXIT_SUCCESS; err: if (listenfd != -1) close(listenfd); + free(reqpath); if (ai) freeaddrinfo(ai); return EXIT_FAILURE;