[hackers] [quark] made simple CGI working, quark can be used to run werc || Anselm R Garbe

From: <hg_AT_suckless.org>
Date: Sun, 28 Mar 2010 11:31:55 +0000 (UTC)

changeset: 13:f777a085fc72
tag: tip
user: Anselm R Garbe <anselm_AT_garbe.us>
date: Sun Mar 28 11:31:30 2010 +0000
files: config.def.h quark.c
description:
made simple CGI working, quark can be used to run werc

diff -r 62d56df19b0b -r f777a085fc72 config.def.h
--- a/config.def.h Sun Mar 28 02:18:34 2010 +0000
+++ b/config.def.h Sun Mar 28 11:31:30 2010 +0000
@@ -1,14 +1,14 @@
 /* quark configuration */
 
-static char *servername = "127.0.0.1";
-static char *serverport = "80";
-static char *docroot = ".";
-static char *docindex = "index.html";
-static char *user = "nobody";
-static char *group = "nobody";
-static char *cgi_dir = "/var/www/werc-dev/bin";
-static char *cgi_script = "./werc.rc";
-static int cgi_mode = 0;
+static const char servername[] = "127.0.0.1";
+static const char serverport[] = "80";
+static const char docroot[] = ".";
+static const char docindex[] = "index.html";
+static const char user[] = "nobody";
+static const char group[] = "nobody";
+static const char cgi_dir[] = "/var/www/werc-dev/bin";
+static const char cgi_script[] = "./werc.rc";
+static const int cgi_mode = 0;
 
 static const MimeType servermimes[] = {
         { "html", "text/html; charset=UTF-8" },
diff -r 62d56df19b0b -r f777a085fc72 quark.c
--- a/quark.c Sun Mar 28 02:18:34 2010 +0000
+++ b/quark.c Sun Mar 28 11:31:30 2010 +0000
@@ -18,7 +18,7 @@
 #include <unistd.h>
 
 #define LENGTH(x) (sizeof x / sizeof x[0])
-#define MAXREQLEN 255
+#define MAXBUFLEN 1024
 
 enum {
         GET = 4,
@@ -39,6 +39,8 @@
 static ssize_t writetext(const char *buf);
 static ssize_t writedata(const char *buf, size_t buflen);
 static void die(const char *errstr, ...);
+void logmsg(const char *errstr, ...);
+void logerrmsg(const char *errstr, ...);
 static void response(void);
 static void responsecgi(void);
 static void responsedir(void);
@@ -54,9 +56,10 @@
 
 static char location[256];
 static int running = 1;
-static char name[128];
-static char reqbuf[MAXREQLEN+1];
-static char respbuf[1024];
+static char host[NI_MAXHOST];
+static char reqbuf[MAXBUFLEN+1];
+static char resbuf[MAXBUFLEN+1];
+static char reqhost[256];
 static int fd, cfd, reqtype;
 
 ssize_t
@@ -65,7 +68,7 @@
 
         while(offset < buf_len) {
                 if((r = write(cfd, buf + offset, buf_len - offset)) == -1) {
- fprintf(stderr, "%s: client %s closed connection\n", tstamp(), name);
+ logerrmsg("%s: client %s closed connection\n", tstamp(), host);
                         return -1;
                 }
                 offset += r;
@@ -111,53 +114,53 @@
 
 int
 responsehdr(const char *status) {
- if(snprintf(respbuf, sizeof respbuf,
+ if(snprintf(resbuf, MAXBUFLEN,
                 "HTTP/1.1 %s\r\n"
                 "Connection: close\r\n"
                 "Date: %s\r\n"
                 "Server: quark-"VERSION"\r\n",
- status, tstamp()) >= sizeof respbuf)
+ status, tstamp()) >= MAXBUFLEN)
         {
                 logerrmsg("snprintf failed, buffer size exceeded");
                 return -1;
         }
- return writetext(respbuf);
+ return writetext(resbuf);
 }
 
 int
 responsecontentlen(off_t size) {
- if(snprintf(respbuf, sizeof respbuf,
+ if(snprintf(resbuf, MAXBUFLEN,
                 "Content-Length: %lu\r\n",
- size) >= sizeof respbuf)
+ size) >= MAXBUFLEN)
         {
                 logerrmsg("snprintf failed, buffer sizeof exceeded");
                 return -1;
         }
- return writetext(respbuf);
+ return writetext(resbuf);
 }
 
 int
 responselocation(const char *location, const char *pathinfo) {
- if(snprintf(respbuf, sizeof respbuf,
+ if(snprintf(resbuf, MAXBUFLEN,
                 "Location: %s%s\r\n",
- location, pathinfo) >= sizeof respbuf)
+ location, pathinfo) >= MAXBUFLEN)
         {
                 logerrmsg("snprintf failed, buffer sizeof exceeded");
                 return -1;
         }
- return writetext(respbuf);
+ return writetext(resbuf);
 }
 
 int
 responsecontenttype(const char *mimetype) {
- if(snprintf(respbuf, sizeof respbuf,
+ if(snprintf(resbuf, MAXBUFLEN,
                 "Content-Type: %s\r\n",
- mimetype) >= sizeof respbuf)
+ mimetype) >= MAXBUFLEN)
         {
                 logerrmsg("snprintf failed, buffer sizeof exceeded");
                 return -1;
         }
- return writetext(respbuf);
+ return writetext(resbuf);
 }
 
 void
@@ -166,7 +169,7 @@
 
         while(offset < size)
                 if(sendfile(cfd, fd, &offset, size - offset) == -1) {
- fprintf(stderr, "%s: sendfile failed on client %s: %s\n", tstamp(), name, strerror(errno));
+ logerrmsg("sendfile failed on client %s: %s\n", host, strerror(errno));
                         return;
                 }
 }
@@ -180,7 +183,7 @@
 
         stat(reqbuf, &st);
         if((ffd = open(reqbuf, O_RDONLY)) == -1) {
- fprintf(stderr, "%s: %s requests unknown path %s\n", tstamp(), name, reqbuf);
+ logerrmsg("%s requests unknown path %s\n", host, reqbuf);
                 if(responsehdr(HttpNotFound) != -1
                 && responsecontenttype(texthtml) != -1)
                         ;
@@ -225,13 +228,13 @@
                 while((e = readdir(d))) {
                         if(e->d_name[0] == '.') /* ignore hidden files, ., .. */
                                 continue;
- if(snprintf(respbuf, sizeof respbuf, "<a href='%s%s'>%s</a><br>\r\n",
- reqbuf, e->d_name, e->d_name) >= sizeof respbuf)
+ if(snprintf(resbuf, MAXBUFLEN, "<a href='%s%s'>%s</a><br>\r\n",
+ reqbuf, e->d_name, e->d_name) >= MAXBUFLEN)
                         {
                                 logerrmsg("snprintf failed, buffer sizeof exceeded");
                                 return;
                         }
- if(writetext(respbuf) == -1)
+ if(writetext(resbuf) == -1)
                                 return;
                 }
                 writetext("</body></html>\r\n");
@@ -243,11 +246,11 @@
         ssize_t len = strlen(reqbuf);
         DIR *d;
 
- if((reqbuf[len - 1] != '/') && (len + 1 < MAXREQLEN)) {
+ if((reqbuf[len - 1] != '/') && (len + 1 < MAXBUFLEN)) {
                 /* add directory terminator if necessary */
                 reqbuf[len++] = '/';
                 reqbuf[len] = 0;
- fprintf(stdout, "%s: redirecting %s to %s%s\n", tstamp(), name, location, reqbuf);
+ logmsg("redirecting %s to %s%s\n", host, location, reqbuf);
                 if(responsehdr(HttpMoved) != -1
                 && responselocation(location, reqbuf) != -1
                 && responsecontenttype(texthtml) != -1)
@@ -258,7 +261,7 @@
                         writetext("\r\n<html><body>301 Moved Permanently</a></body></html>\r\n");
                 return;
         }
- if(len + strlen(docindex) + 1 < MAXREQLEN)
+ if(len + strlen(docindex) + 1 < MAXBUFLEN)
                 memcpy(reqbuf + len, docindex, strlen(docindex) + 1);
         if(access(reqbuf, R_OK) == -1) { /* directory mode */
                 reqbuf[len] = 0; /* cut off docindex again */
@@ -282,15 +285,17 @@
                 setenv("REQUEST_METHOD", "HEAD", 1);
         else
                 return;
- setenv("SERVER_NAME", servername, 1);
+ if(*reqhost)
+ setenv("SERVER_NAME", reqhost, 1);
         setenv("SCRIPT_NAME", cgi_script, 1);
         setenv("REQUEST_URI", reqbuf, 1);
+ logmsg("CGI SERVER_NAME=%s SCRIPT_NAME=%s REQUEST_URI=%s\n", reqhost, cgi_script, reqbuf);
         chdir(cgi_dir);
         if((cgi = popen(cgi_script, "r"))) {
                 if(responsehdr(HttpOk) == -1)
                         return;
- while((r = fread(respbuf, 1, sizeof respbuf - 1, cgi)) > 0) {
- if(writedata(respbuf, r) == -1) {
+ while((r = fread(resbuf, 1, MAXBUFLEN, cgi)) > 0) {
+ if(writedata(resbuf, r) == -1) {
                                 pclose(cgi);
                                 return;
                         }
@@ -298,7 +303,7 @@
                 pclose(cgi);
         }
         else {
- fprintf(stderr, "%s: %s requests %s, but cannot run cgi script %s\n", tstamp(), name, cgi_script, reqbuf);
+ logerrmsg("%s requests %s, but cannot run cgi script %s\n", host, cgi_script, reqbuf);
                 if(responsehdr(HttpNotFound) != -1
                 && responsecontenttype(texthtml) != -1)
                         ;
@@ -315,8 +320,8 @@
         struct stat st;
 
         for(p = reqbuf; *p; p++)
- if(*p == '\\' || *p == '?' || *p == '%' || *p == '&' || (*p == '/' && *(p + 1) == '.')) { /* don't serve bogus or hidden files */
- fprintf(stderr, "%s: %s requests bogus or hidden file %s\n", tstamp(), name, reqbuf);
+ if(*p == '\\' || (*p == '/' && *(p + 1) == '.')) { /* don't serve bogus or hidden files */
+ logerrmsg("%s requests bogus or hidden file %s\n", host, reqbuf);
                         if(responsehdr(HttpUnauthorized) != -1
                         && responsecontenttype(texthtml) != -1)
                                 ;
@@ -326,7 +331,7 @@
                                 writetext("\r\n<html><body>401 Unauthorized</body></html>\r\n");
                         return;
                 }
- fprintf(stdout, "%s: %s requests: %s\n", tstamp(), name, reqbuf);
+ logmsg("%s requests: %s\n", host, reqbuf);
         if(cgi_mode)
                 responsecgi();
         else {
@@ -344,24 +349,37 @@
         int r;
         size_t offset = 0;
 
- do { /* MAXREQLEN byte of reqbuf is emergency 0 terminator */
- if((r = read(cfd, reqbuf + offset, MAXREQLEN - offset)) < 0) {
- fprintf(stderr, "%s: read: %s\n", tstamp(), strerror(errno));
+ do { /* MAXBUFLEN byte of reqbuf is emergency 0 terminator */
+ if((r = read(cfd, reqbuf + offset, MAXBUFLEN - offset)) < 0) {
+ logerrmsg("read: %s\n", strerror(errno));
                         return -1;
                 }
                 offset += r;
                 reqbuf[offset] = 0;
         }
- while(offset < MAXREQLEN && !strstr(reqbuf, "\r\n\r\n") && !strstr(reqbuf, "\n\n"));
+ while(r > 0 && offset < MAXBUFLEN && (!strstr(reqbuf, "\r\n") || !strstr(reqbuf, "\n")));
+ if((res = strstr(reqbuf, "Host:"))) {
+ for(res = res + 5; *res && (*res == ' ' || *res == '\t'); res++);
+ if(!*res)
+ goto invalid_request;
+ for(p = res; *p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\t'; p++);
+ if(!*p)
+ goto invalid_request;
+ *p = 0;
+ if(p - res > sizeof reqhost)
+ goto invalid_request;
+ memcpy(reqhost, res, p - res);
+ reqhost[p - res] = 0;
+ }
         for(p = reqbuf; *p && *p != '\r' && *p != '\n'; p++);
- if(p >= reqbuf + MAXREQLEN)
+ if(!*p)
                 goto invalid_request;
         if(*p == '\r' || *p == '\n') {
                 *p = 0;
                 /* check command */
                 if(!strncmp(reqbuf, "GET ", 4) && reqbuf[4] == '/')
                         reqtype = GET;
- else if(!strncmp(reqbuf, "HEAD ", 5) && reqbuf[5] != '/')
+ else if(!strncmp(reqbuf, "HEAD ", 5) && reqbuf[5] == '/')
                         reqtype = HEAD;
                 else
                         goto invalid_request;
@@ -370,16 +388,16 @@
                 goto invalid_request;
         /* determine path */
         for(res = reqbuf + reqtype; *res && *(res + 1) == '/'; res++); /* strip '/' */
- if(res >= reqbuf + MAXREQLEN)
+ if(!*res)
                 goto invalid_request;
         for(p = res; *p && *p != ' ' && *p != '\t'; p++);
- if(p >= reqbuf + MAXREQLEN)
+ if(!*p)
                 goto invalid_request;
         *p = 0;
         memmove(reqbuf, res, (p - res) + 1);
         return 0;
 invalid_request:
- fprintf(stderr, "%s: %s performs invalid request %s\n", tstamp(), name, reqbuf);
+ logerrmsg("%s performs invalid request %s\n", host, reqbuf);
         return -1;
 }
 
@@ -393,14 +411,14 @@
         while(running) {
                 if((cfd = accept(fd, &sa, &salen)) == -1) {
                         /* el cheapo socket release */
- fprintf(stderr, "%s: cannot accept: %s, sleep a second...\n", tstamp(), strerror(errno));
+ logerrmsg("cannot accept: %s, sleep a second...\n", strerror(errno));
                         sleep(1);
                         continue;
                 }
                 if(fork() == 0) {
                         close(fd);
- name[0] = 0;
- getnameinfo(&sa, salen, name, sizeof name, NULL, 0, NI_NOFQDN);
+ host[0] = 0;
+ getnameinfo(&sa, salen, host, sizeof host, NULL, 0, NI_NOFQDN);
                         result = request();
                         shutdown(cfd, SHUT_RD);
                         if(result == 0)
@@ -411,7 +429,7 @@
                 }
                 close(cfd);
         }
- fprintf(stdout, "%s: shutting down\n", tstamp());
+ logmsg("shutting down\n");
 }
 
 void
@@ -431,7 +449,7 @@
         case SIGQUIT:
         case SIGABRT:
         case SIGTERM:
- fprintf(stderr, "%s: received signal %s, closing down\n", tstamp(), signame[sig] ? signame[sig] : "");
+ logerrmsg("received signal %s, closing down\n", signame[sig] ? signame[sig] : "");
                 close(fd);
                 running = 0;
                 break;
@@ -459,42 +477,10 @@
 
         /* arguments */
         for(i = 1; i < argc; i++)
- if(!strcmp(argv[i], "-n")) {
- if(++i < argc) servername = argv[i];
- }
- else if(!strcmp(argv[i], "-p")) {
- if(++i < argc) serverport = argv[i];
- }
- else if(!strcmp(argv[i], "-r")) {
- if(++i < argc) docroot = argv[i];
- }
- else if(!strcmp(argv[i], "-i")) {
- if(++i < argc) docindex = argv[i];
- }
- else if(!strcmp(argv[i], "-u")) {
- if(++i < argc) user = argv[i];
- }
- else if(!strcmp(argv[i], "-g")) {
- if(++i < argc) group = argv[i];
- }
- else if(!strcmp(argv[i], "-c")) {
- if(++i < argc) cgi_dir = argv[i];
- if(++i < argc) {
- cgi_script = argv[i];
- cgi_mode = 1;
- }
- }
- else if(!strcmp(argv[i], "-v"))
+ if(!strcmp(argv[i], "-v"))
                         die("quark-"VERSION", © 2009-2010 Anselm R Garbe\n");
                 else
- die("\nusage: quark [-n <server-name>]\n"
- " [-p <port>]\n"
- " [-r <doc root>]\n"
- " [-i <doc index>]\n"
- " [-u <user>]\n"
- " [-g <group>]\n"
- " [-c <cgi dir> <cgi script>]\n"
- " [-v]\n");
+ die("usage: quark [-v]\n");
 
         /* sanity checks */
         if(!(upwd = getpwnam(user)))
@@ -556,7 +542,7 @@
         if(getgid() == 0)
                 die("error: won't run with root permissions, choose another group\n");
 
- fprintf(stdout, "%s: listening on %s:%s using %s as root directory\n", tstamp(), servername, serverport, docroot);
+ logmsg("listening on %s:%s using %s as root directory\n", servername, serverport, docroot);
 
         serve(fd); /* main loop */
         freeaddrinfo(ai);
Received on Sun Mar 28 2010 - 11:31:55 UTC

This archive was generated by hypermail 2.2.0 : Sun Mar 28 2010 - 11:36:07 UTC