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;