[hackers] [quark] implemented very basic cgi support || Anselm R Garbe

From: <hg_AT_suckless.org>
Date: Sun, 28 Mar 2010 02:14:33 +0000 (UTC)

changeset: 9:e6663aa4978c
user: Anselm R Garbe <anselm_AT_garbe.us>
date: Sun Mar 28 01:09:14 2010 +0000
files: Makefile config.def.h config.h quark.c
description:
implemented very basic cgi support

diff -r acec1806580b -r e6663aa4978c Makefile
--- a/Makefile Sun Aug 16 13:33:02 2009 +0100
+++ b/Makefile Sun Mar 28 01:09:14 2010 +0000
@@ -17,7 +17,11 @@
         @echo CC $<
         @${CC} -c ${CFLAGS} $<
 
-${OBJ}: config.mk
+${OBJ}: config.mk config.h
+
+config.h:
+ @echo creating $@ from config.def.h
+ @cp config.def.h $@
 
 quark: ${OBJ}
         @echo CC -o $@
diff -r acec1806580b -r e6663aa4978c config.def.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/config.def.h Sun Mar 28 01:09:14 2010 +0000
@@ -0,0 +1,25 @@
+/* quark configuration */
+
+static const char servername[] = "192.168.1.66";
+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_script[] = "/var/www/werc-dev/bin/werc.rc";
+static const int cgi_mode = 0;
+
+static const MimeType servermimes[] = {
+ { "html", "text/html; charset=UTF-8" },
+ { "htm", "text/html; charset=UTF-8" },
+ { "css", "text/css" },
+ { "txt", "text/plain" },
+ { "text", "text/plain" },
+ { "png", "image/png" },
+ { "gif", "image/gif" },
+ { "jpg", "image/jpg" },
+ { "iso", "application/x-iso9660-image" },
+ { "gz", "application/x-gtar" },
+ { "pdf", "application/x-pdf" },
+ { "tar", "application/tar" },
+};
diff -r acec1806580b -r e6663aa4978c config.h
--- a/config.h Sun Aug 16 13:33:02 2009 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-/* quark configuration */
-
-static const char servername[] = "192.168.1.66";
-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 MimeType servermimes[] = {
- { "html", "text/html; charset=UTF-8" },
- { "htm", "text/html; charset=UTF-8" },
- { "css", "text/css" },
- { "txt", "text/plain" },
- { "text", "text/plain" },
- { "png", "image/png" },
- { "gif", "image/gif" },
- { "jpg", "image/jpg" },
- { "iso", "application/x-iso9660-image" },
- { "gz", "application/x-gtar" },
- { "pdf", "application/x-pdf" },
- { "tar", "application/tar" },
-};
diff -r acec1806580b -r e6663aa4978c quark.c
--- a/quark.c Sun Aug 16 13:33:02 2009 +0100
+++ b/quark.c Sun Mar 28 01:09:14 2010 +0000
@@ -18,7 +18,7 @@
 #include <unistd.h>
 
 #define LENGTH(x) (sizeof x / sizeof x[0])
-#define MAXREQLEN 256
+#define MAXREQLEN 255
 
 typedef struct {
         const char *extension;
@@ -34,6 +34,7 @@
 static ssize_t writedata(const char *buf);
 static void die(const char *errstr, ...);
 static void response(void);
+static void responsecgi(void);
 static void responsedir(void);
 static void responsedirdata(DIR *d);
 static void responsefile(void);
@@ -48,7 +49,7 @@
 static char location[256];
 static int running = 1;
 static char name[128];
-static char reqbuf[MAXREQLEN];
+static char reqbuf[MAXREQLEN+1];
 static char respbuf[1024];
 static int fd, cfd;
 
@@ -221,7 +222,7 @@
         ssize_t len = strlen(reqbuf);
         DIR *d;
 
- if((reqbuf[len - 1] != '/') && (len + 1 < MAXREQLEN - 1)) {
+ if((reqbuf[len - 1] != '/') && (len + 1 < MAXREQLEN)) {
                 /* add directory terminator if necessary */
                 reqbuf[len++] = '/';
                 reqbuf[len] = 0;
@@ -232,7 +233,7 @@
                 && writedata("\r\n<html><body>301 Moved Permanently</a></body></html>\r\n") != -1);
                 return;
         }
- if(len + strlen(docindex) + 1 < MAXREQLEN - 1)
+ if(len + strlen(docindex) + 1 < MAXREQLEN)
                 memcpy(reqbuf + len, docindex, strlen(docindex) + 1);
         if(access(reqbuf, R_OK) == -1) { /* directory mode */
                 reqbuf[len] = 0; /* cut off docindex again */
@@ -243,7 +244,34 @@
         }
         else
                 responsefile(); /* docindex */
+}
 
+void
+responsecgi(void) {
+ FILE *cgi;
+ int r;
+
+ setenv("REQUEST_METHOD", "GET", 1);
+ setenv("SERVER_NAME", servername, 1);
+ setenv("SCRIPT_NAME", cgi_script, 1);
+ if((cgi = popen(cgi_script, "r"))) {
+ if(responsehdr(HttpOk) == -1)
+ return;
+ while((r = fread(respbuf, 1, sizeof respbuf - 1, cgi) > 0)) {
+ respbuf[r] = 0;
+ if(writedata(respbuf) == -1) {
+ pclose(cgi);
+ return;
+ }
+ }
+ pclose(cgi);
+ }
+ else {
+ fprintf(stderr, "%s: %s requests %s, but cannot run cgi script %s\n", tstamp(), name, cgi_script, reqbuf);
+ if(responsehdr(HttpNotFound) != -1
+ && responsecontenttype(texthtml) != -1
+ && writedata("\r\n<html><body>404 Not Found</body></html>\r\n") != -1);
+ }
 }
 
 void
@@ -252,7 +280,7 @@
         struct stat st;
 
         for(p = reqbuf; *p; p++)
- if(*p == '\\' || (*p == '/' && *(p + 1) == '.')) { /* don't serve bogus or hidden files */
+ 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(responsehdr(HttpUnauthorized) != -1
                         && responsecontenttype(texthtml) != -1
@@ -260,23 +288,35 @@
                         return;
                 }
         fprintf(stdout, "%s: %s requests: %s\n", tstamp(), name, reqbuf);
- stat(reqbuf, &st);
- if(S_ISDIR(st.st_mode))
- responsedir();
- else
- responsefile();
+ if(cgi_mode)
+ responsecgi();
+ else {
+ stat(reqbuf, &st);
+ if(S_ISDIR(st.st_mode))
+ responsedir();
+ else
+ responsefile();
+ }
 }
 
 int
 request(void) {
         char *p, *res;
         int r;
+ size_t offset = 0;
 
- if((r = read(cfd, reqbuf, (MAXREQLEN - 1))) < 0) {
- fprintf(stderr, "%s: read: %s\n", tstamp(), strerror(errno));
- return -1;
+ 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));
+ return -1;
+ }
+ offset += r;
+ reqbuf[offset] = 0;
         }
- for(p = reqbuf; p < reqbuf + MAXREQLEN && *p != '\r' && *p != '\n'; p++);
+ while(offset < MAXREQLEN && (!strstr(reqbuf, "\r\n\r\n") || !strstr(reqbuf, "\n\n")));
+ for(p = reqbuf; *p && *p != '\r' && *p != '\n'; p++);
+ if(p >= reqbuf + MAXREQLEN)
+ goto invalid_request;
         if(*p == '\r' || *p == '\n') {
                 *p = 0;
                 /* check command */
@@ -286,8 +326,12 @@
         else
                 goto invalid_request;
         /* determine path */
- for(res = reqbuf + 4; *res && *(res + 1) == '/'; res++);
- for(p = res; *p && *p != ' '; p++);
+ for(res = reqbuf + 4; *res && *(res + 1) == '/'; res++); /* strip '/' */
+ if(res >= reqbuf + MAXREQLEN)
+ goto invalid_request;
+ for(p = res; *p && *p != ' ' && *p != '\t'; p++);
+ if(p >= reqbuf + MAXREQLEN)
+ goto invalid_request;
         *p = 0;
         memmove(reqbuf, res, (p - res) + 1);
         return 0;
@@ -373,7 +417,7 @@
         /* arguments */
         for(i = 1; i < argc; i++)
                 if(!strcmp(argv[i], "-v"))
- die("quark-"VERSION", © 2009 Anselm R Garbe\n");
+ die("quark-"VERSION", © 2009-2010 Anselm R Garbe\n");
                 else
                         die("usage: quark [-v]\n");
 
Received on Sun Mar 28 2010 - 02:14:33 UTC

This archive was generated by hypermail 2.2.0 : Sun Mar 28 2010 - 02:24:07 UTC