chiark / gitweb /
www-cgi: Add support for virtual hosts and known CGI scripts.
authorMark Wooding <mdw@metalzone.distorted.org.uk>
Mon, 6 Feb 2006 19:01:09 +0000 (19:01 +0000)
committerMark Wooding <mdw@metalzone.distorted.org.uk>
Mon, 6 Feb 2006 19:01:09 +0000 (19:01 +0000)
There's now a CDB mapping virtual host names and CGI script names to the
users who are meant to run things for them.

www-cgi/.gitignore [new file with mode: 0644]
www-cgi/Makefile
www-cgi/ucgi.c
www-cgi/ucgi.h

diff --git a/www-cgi/.gitignore b/www-cgi/.gitignore
new file mode 100644 (file)
index 0000000..79f731a
--- /dev/null
@@ -0,0 +1,2 @@
+ucgi
+ucgitarget
index 69d4566..8092368 100644 (file)
@@ -28,7 +28,7 @@ all:          $(TARGETS)
 
 OBJS=          ucgi.o ucgitarget.o ucgicommon.o
 
-ucgi:          ucgi.o ucgicommon.o
+ucgi:          ucgi.o ucgicommon.o -lcdb
 ucgitarget:    ucgitarget.o ucgicommon.o
 
 $(OBJS):       ucgi.h
index 2993ecf..bea1e28 100644 (file)
  * $Id: ucgi.c,v 1.3 2003/07/06 20:47:12 ian Exp $
  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <cdb.h>
 
 #include "ucgi.h"
 
+int conf = -1;
+
+static char *lookup(int prefix, const char *label, int len)
+{
+  char *p = 0;
+  unsigned nn;
+  int rc;
+
+  if (conf < 0 || !label) return (0);
+  if (len < 0) len = strlen(label);
+  p = xmalloc(len + 2);
+  p[0] = prefix;
+  memcpy(p + 1, label, len);
+  p[len + 1] = 0;
+  if ((rc = cdb_seek(conf, p, len + 1, &nn)) < 0)
+    error("error seeking in `" CONFIG_CDB "'");
+  free(p);
+  if (!rc) return (0);
+  p = xmalloc(nn + 1);
+  if (read(conf, p, nn) < nn)
+    error("error reading `" CONFIG_CDB "'");
+  p[nn] = 0;
+  return (p);
+}
+
 int main(int argc, const char **argv) {
   char *defarg, *username;
   const char *slash2, *pathi, *ev, *en, *av;
@@ -50,17 +78,29 @@ int main(int argc, const char **argv) {
   
   if (argc > MAX_ARGS) error("too many arguments");
 
+  if ((conf = open(CONFIG_CDB, O_RDONLY)) < 0 && errno != ENOENT)
+    error("failed to open `" CONFIG_CDB "'");
+
   pathi= getenv("PATH_INFO");
   if (!pathi) error("PATH_INFO not found");
-  if (pathi[0] != '/' || pathi[1] != '~') error("PATH_INFO must start with /~");
-  slash2= strchr(pathi+2,'/'); if (!slash2) error("PATH_INFO must have more than one /");
-  usernamelen= slash2-(pathi+2);
-  if (usernamelen > MAX_USERNAME_LEN) error("PATH_INFO username too long");
-  username= xmalloc(usernamelen+1);
-  memcpy(username,pathi+2,usernamelen); username[usernamelen]= 0;
+  if (pathi[0] != '/') error("PATH_INFO must start with /");
+  if ((username = lookup('H', getenv("HTTP_HOST"), -1)) != 0)
+    /* cool! */;
+  else if (pathi[1] == '~') {
+    slash2= strchr(pathi+2,'/'); if (!slash2) error("PATH_INFO must have more than one /");
+    usernamelen= slash2-(pathi+2);
+    if (usernamelen > MAX_USERNAME_LEN) error("PATH_INFO username too long");
+    username= xmalloc(usernamelen+1);
+    memcpy(username,pathi+2,usernamelen); username[usernamelen]= 0;
+    xsetenv("PATH_INFO",slash2,1);
+  } else {
+    slash2 = strchr(pathi+1,'/');
+    if ((username = lookup('S', pathi + 1,
+                          slash2 ? slash2 - pathi - 1 : -1)) == 0)
+      error("unknown CGI service");
+  }
+
   if (!isalpha(username[0])) error("username 1st character is not alphabetic");
-  xsetenv("PATH_INFO",slash2,1);
-  
   arguments= xmalloc(sizeof(const char*)*(nenvok+argc+10));
   nargs= 0;
   
index 5c94122..99fc9d1 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <stdlib.h>
 
+#define CONFIG_CDB "/etc/ucgi/ucgi.cdb"
 #define MAX_ARGS 1024
 #define MAX_USERNAME_LEN 1024
 #define MAX_SCRIPTPATH_LEN 1024