On Mon, Aug 25, 2008 at 02:37:18PM -0700, Michel Lespinasse wrote:
> Attached is a small proof-of-concept patch to start up the discussion.
> I'm not sure if majordomo likes attachments, so if it gets eaten please
> get it at http://www.lespinasse.org/mathopd-scgi.diff instead.

And I, of course, forgot to attach it. Here it is, hope it'll make it to
the list.

Cheers,

-- 
Michel "Walken" Lespinasse
A program is never fully debugged until the last user dies.
diff -rdu mathopd-1.5p5/src/cgi.c mathopd-1.5p5-scgi/src/cgi.c
--- mathopd-1.5p5/src/cgi.c	2003-12-22 12:38:18.000000000 -0800
+++ mathopd-1.5p5-scgi/src/cgi.c	2008-08-25 13:53:43.000000000 -0700
@@ -47,6 +47,8 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <sys/un.h>
+#include <errno.h>
 #include "mathopd.h"
 
 struct cgi_parameters {
@@ -338,18 +340,45 @@
 	}
 }
 
-int process_cgi(struct request *r)
+static int process_scgi(struct request *r, struct cgi_parameters *c);
+static int process_cgi(struct request *r, struct cgi_parameters *c);
+
+int process_cgi_scgi(struct request *r, int scgi)
 {
 	struct cgi_parameters c;
-	uid_t u;
-	gid_t g;
-	int p[2], efd;
-	pid_t pid;
+	int ok;
 
+	c.cgi_envc = 0;
+	c.cgi_envp = 0;
+	c.cgi_argc = 0;
+	c.cgi_argv = 0;
+	if ((scgi && add ("SCGI", "1", 0, &c) == -1) ||
+	    init_cgi_env(r, &c) == -1) {
+		log_d("process_cgi_scgi: out of memory");
+		destroy_parameters(&c);
+		r->status = 500;
+		return 0;
+	}
 	if (r->curdir[0] == 0) {
 		r->status = 500;
 		return 0;
 	}
+	if (scgi) {
+	    ok = process_scgi (r, &c);
+	} else {
+	    ok = process_cgi (r, &c);
+	}
+	destroy_parameters(&c);
+	return ok;
+}
+
+int process_cgi(struct request *r, struct cgi_parameters *c)
+{
+	uid_t u;
+	gid_t g;
+	int p[2], efd;
+	pid_t pid;
+
 	switch (r->c->script_identity) {
 	case SI_CHANGETOFIXED:
 		u = r->c->script_uid;
@@ -380,19 +409,8 @@
 		r->status = 500;
 		return 0;
 	}
-	c.cgi_envc = 0;
-	c.cgi_envp = 0;
-	c.cgi_argc = 0;
-	c.cgi_argv = 0;
-	if (init_cgi_env(r, &c) == -1) {
-		log_d("process_cgi: out of memory");
-		destroy_parameters(&c);
-		r->status = 500;
-		return 0;
-	}
 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, p) == -1) {
 		lerror("socketpair");
-		destroy_parameters(&c);
 		r->status = 500;
 		return 0;
 	}
@@ -403,29 +421,74 @@
 		if (efd == -1) {
 			close(p[0]);
 			close(p[1]);
-			destroy_parameters(&c);
 			r->status = 500;
 			return 0;
 		}
 		fcntl(efd, F_SETFD, FD_CLOEXEC);
 	} else
 		efd = -1;
-	pid = spawn(c.cgi_argv[0], c.cgi_argv, c.cgi_envp, p[1], efd, u, g, r->curdir);
+	pid = spawn(c->cgi_argv[0], c->cgi_argv, c->cgi_envp, p[1], efd, u, g, r->curdir);
 	if (efd != -1)
 		close(efd);
 	close(p[1]);
 	if (pid == -1) {
 		close(p[0]);
-		destroy_parameters(&c);
 		r->cn->keepalive = 0;
 		r->status = 503;
 		return 0;
 	}
 	fcntl(p[0], F_SETFL, O_NONBLOCK);
 	init_child(r->cn, p[0]);
-	destroy_parameters(&c);
 	if (debug)
 		log_d("process_cgi: %d", p[0]);
 	r->forked = 1;
 	return -1;
 }
+
+int process_scgi(struct request *r, struct cgi_parameters *c)
+{
+	int sock;
+	struct sockaddr_un addr;
+	char **p;
+	int n = 0;
+	struct pool *scgi = &r->cn->client_input;
+
+	sock = socket(PF_UNIX, SOCK_STREAM, 0);
+	fcntl(sock, F_SETFL, O_NONBLOCK);
+
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, "/var/www/pygall/devel/scgi/pygall.sock",
+		sizeof(addr.sun_path));
+	if (connect(sock, (struct sockaddr *)&addr, sizeof addr) == -1) {
+		/* EAGAIN when server socket's listen queue is full. */
+		log_d("could not connect, errno %d", errno);
+		r->status = 500;
+		return 0;
+	}
+
+	for (p = c->cgi_envp; *p != NULL; p++) {
+		if (strchr(*p, '='))
+			n += strlen (*p) + 1;
+	}
+	if (scgi->floor + n + 16 > scgi->ceiling) {
+		log_d("scgi: ScriptBufSize is too small");
+		r->status = 500;
+		return 0;
+	}
+
+	init_child(r->cn, sock);
+
+	pool_print (scgi, "%u:", n);
+	for (p = c->cgi_envp; *p != NULL; p++) {
+		char * eq = strchr(*p, '=');
+		if (eq) {
+			*eq = 0;
+			pool_print (scgi, "%s%c%s%c", *p, 0, eq+1, 0);
+		}
+	}
+	pool_print (scgi, ",");
+	writetochild (r->cn);
+
+	r->forked = 1;
+	return -1;
+}
diff -rdu mathopd-1.5p5/src/mathopd.h mathopd-1.5p5-scgi/src/mathopd.h
--- mathopd-1.5p5/src/mathopd.h	2004-02-23 07:01:13.000000000 -0800
+++ mathopd-1.5p5-scgi/src/mathopd.h	2008-08-25 05:28:47.000000000 -0700
@@ -45,6 +45,7 @@
 #include <signal.h>
 
 #define CGI_MAGIC_TYPE "CGI"
+#define SCGI_MAGIC_TYPE "SCGI"
 #define IMAP_MAGIC_TYPE "Imagemap"
 #define REDIRECT_MAGIC_TYPE "Redirect"
 #define DUMP_MAGIC_TYPE "Dump"
@@ -398,7 +399,7 @@
 
 /* cgi */
 
-extern int process_cgi(struct request *);
+extern int process_cgi_scgi(struct request *, int scgi);
 
 /* dump */
 
@@ -433,6 +434,7 @@
 extern int init_cgi_headers(void);
 extern void pipe_run(struct connection *);
 extern void init_child(struct connection *, int);
+extern int writetochild(struct connection *p);
 extern int setup_child_pollfds(int, struct connection *);
 
 #if defined LINUX_SENDFILE || defined FREEBSD_SENDFILE
diff -rdu mathopd-1.5p5/src/request.c mathopd-1.5p5-scgi/src/request.c
--- mathopd-1.5p5/src/request.c	2005-03-22 23:16:18.000000000 -0800
+++ mathopd-1.5p5-scgi/src/request.c	2008-08-25 13:51:22.000000000 -0700
@@ -520,7 +520,7 @@
 static int process_external(struct request *r)
 {
 	r->num_content = -1;
-	return process_cgi(r);
+	return process_cgi_scgi(r, 0);
 }
 
 static int process_special(struct request *r)
@@ -530,7 +530,9 @@
 	ct = r->content_type;
 	r->num_content = -1;
 	if (!strcasecmp(ct, CGI_MAGIC_TYPE))
-		return process_cgi(r);
+		return process_cgi_scgi(r, 0);
+	if (!strcasecmp(ct, SCGI_MAGIC_TYPE))
+		return process_cgi_scgi(r, 1);
 	if (r->status)
 		return 0;
 	if (r->method == M_POST) {
diff -rdu mathopd-1.5p5/src/stub.c mathopd-1.5p5-scgi/src/stub.c
--- mathopd-1.5p5/src/stub.c	2003-12-23 02:21:26.000000000 -0800
+++ mathopd-1.5p5-scgi/src/stub.c	2008-08-25 05:25:42.000000000 -0700
@@ -406,7 +406,7 @@
 	return 0;
 }
 
-static int writetochild(struct connection *p)
+int writetochild(struct connection *p)
 {
 	size_t bytestowrite;
 	ssize_t r;

Reply via email to