* USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Log: wcgi.c,v $
- * Revision 1.4 1995/11/02 16:35:37 adam
+ * Revision 1.5 1995/11/06 10:51:15 adam
+ * End of response marker in response from wsh/wproto to wcgi.
+ * Shells are respawned when necessary.
+ *
+ * Revision 1.4 1995/11/02 16:35:37 adam
* Bug fixes and select on FIFOs in wcgi - doesn't really work!
*
* Revision 1.3 1995/10/31 16:56:24 adam
#define DEADSTRING "Your database server has terminated. To reactivate \
the server, please reload the server's 'front page'."
+#include <gw-db.h>
#include "wproto.h"
#define CGIDIR "/usr/local/etc/httpd/cgi-bin"
static char *prog = "cgi";
static char serverp[256] = {'\0'};
+static GW_DB gw_db = NULL;
static void fatal(char *p)
{
printf("Content-type: text/html\n\n<HTML><HEAD><TITLE>Server Failure</TITLE></HEAD>\n");
printf("<BODY>%s</BODY>\n", p);
+ if (gw_db)
+ gw_db_close (gw_db);
if (*serverp)
unlink(serverp);
exit(0);
}
-static int spawn(char *sprog)
+static int spawn (char *sprog, int id)
{
int r;
char path[256];
+ char envstr[80];
+ sprintf (envstr, "GWID=%d", id);
+ putenv (envstr);
sprintf(path, "%s/%s", CGIDIR, sprog);
switch(r = fork())
{
}
}
-
/*
* NOTE: In the (perhaps odd) terminology used within this software,
* the 'server' is the present program, which is executed by the httpd
{
char clientp[256], tmp[256], *path_info, *p, *operation, *t;
char combuf[COMBUF];
- int linein = -1, lineout, data, childpid;
+ int linein = -1, lineout, data, gw_id;
gw_log_init ("egw");
gw_log_file (GW_LOG_ALL, "/usr/local/etc/httpd/logs/egwcgi_log");
path_info++;
if (*path_info)
*(path_info++) = '\0';
- if ((childpid = atoi(operation)) <= 0)
+ if (!(gw_db = gw_db_open ("user.db", 1)))
{
- childpid = spawn(operation);
- /* synchronize with client. */
- gw_log (GW_LOG_DEBUG, prog, "Synchronizing with client.");
+ gw_log (GW_LOG_FATAL, prog, "gw_db_open");
+ exit (1);
+ }
+ if ((gw_id = atoi(operation)) <= 0)
+ {
+ int r;
+ char gw_id_str[16];
+
+ gw_id = gw_db_seq_no (gw_db);
+ sprintf (gw_id_str, "%d", gw_id);
+
+ spawn(operation, gw_id);
+ r = gw_db_insert (gw_db, gw_id_str, strlen(gw_id_str)+1,
+ operation, strlen(operation)+1);
+ if (r)
+ {
+ gw_log (GW_LOG_FATAL, prog, "gw_db_insert: %d", r);
+ gw_db_close (gw_db);
+ exit (1);
+ }
+ gw_log (GW_LOG_DEBUG, prog, "Synchronizing with client");
if ((linein = open(serverp, O_RDONLY)) < 0)
{
gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "open server %s", serverp);
}
gw_log (GW_LOG_DEBUG, prog, "Synchronized.");
}
- sprintf(clientp, "%s/clt%d", tmp, childpid);
+ sprintf(clientp, "%s/clt%d", tmp, gw_id);
gw_log (GW_LOG_DEBUG, prog, "Opening %s", clientp);
if ((lineout = open(clientp, O_WRONLY)) < 0)
{
- gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "%s", clientp);
- fatal(DEADSTRING);
+ char gw_id_str[16];
+ void *sprog;
+ size_t sprog_size;
+ int r;
+
+ sprintf (gw_id_str, "%d", gw_id);
+ r = gw_db_lookup (gw_db, gw_id_str, strlen(gw_id_str)+1,
+ &sprog, &sprog_size);
+ if (r != 1)
+ {
+ gw_log (GW_LOG_FATAL, prog, "gw_db_lookup %s", gw_id_str);
+ fatal("Internal error in server");
+ }
+ gw_log (GW_LOG_DEBUG|GW_LOG_ERRNO, prog, "open %s restart", clientp);
+ spawn (sprog, gw_id);
+ gw_log (GW_LOG_DEBUG, prog, "Synchronizing with client");
+ if ((linein = open(serverp, O_RDONLY)) < 0)
+ {
+ gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "open server %s", serverp);
+ fatal("Internal error in server");
+ }
+ if (read(linein, combuf, 2) < 2 || strcmp(combuf, "OK"))
+ {
+ gw_log (GW_LOG_FATAL, prog, "Failed to synchronize with client.");
+ fatal("Internal error in server");
+ }
+ gw_log (GW_LOG_DEBUG, prog, "Synchronized.");
+ if ((lineout = open(clientp, O_WRONLY)) < 0)
+ {
+ gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "%s", clientp);
+ gw_db_close (gw_db);
+ exit (1);
+ }
}
+ gw_db_close (gw_db);
gw_log (GW_LOG_DEBUG, prog, "Decoding user data.");
p = combuf + sizeof(data);
strcpy(p, serverp);
exit (1);
}
}
+ if (data < 0)
+ {
+ gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "read");
+ exit (1);
+ }
#else
-# if 1
+# if 0
fcntl (linein, F_SETFL, O_NONBLOCK);
# endif
while (1)
{
fd_set s_input;
struct timeval t;
- int r;
+ int r, eof_flag = 0;
- t.tv_sec = 5;
+ t.tv_sec = 10;
t.tv_usec = 0;
FD_ZERO(&s_input);
FD_SET(linein, &s_input);
# if 0
- FD_SET(1, &s_output);
+ FD_SET(1, &s_input);
# endif
gw_log (GW_LOG_DEBUG, prog, "select");
- r = select (linein + 1, &s_input, NULL, NULL, NULL);
+ r = select (linein + 1, &s_input, NULL, NULL, &t);
if (r < 0)
{
gw_log (GW_LOG_ERRNO|GW_LOG_FATAL, prog, "select");
exit(1);
}
- if (r == 0)
+ if (r == 0 || FD_ISSET (linein, &s_input))
{
- gw_log (GW_LOG_DEBUG, prog, "poll");
+ if (r == 0)
+ gw_log (GW_LOG_DEBUG, prog, "poll");
if ((data = read (linein, combuf, COMBUF)) > 0)
{
+ if (combuf[data-1] == '\0')
+ {
+ --data;
+ eof_flag = 1;
+ }
gw_log (GW_LOG_DEBUG, prog, "Got %d bytes", data);
- if (write(1, combuf, data) < data)
+ if (data > 0 && write(1, combuf, data) < data)
{
gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "write");
exit (1);
}
else if (data == -1)
{
- gw_log (GW_LOG_DEBUG, prog, "No data");
+ if (r > 0)
+ {
+ gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "read");
+ exit (1);
+ }
+ gw_log (GW_LOG_DEBUG, prog, "poll read");
}
else
- {
- gw_log (GW_LOG_DEBUG, prog, "No more");
break;
- }
- continue;
- }
- if (FD_ISSET (linein, &s_input))
- {
- data = read (linein, combuf, COMBUF);
- if (data == 0)
- break;
- else if (data < 0)
- {
- gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "read");
- exit (1);
- }
- gw_log (GW_LOG_DEBUG, prog, "Got %d bytes", data);
- if (write(1, combuf, data) < data)
- {
- gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "write");
- exit (1);
- }
}
- if (FD_ISSET (1, &s_input))
+ if (eof_flag)
+ break;
+ if (r > 0 && FD_ISSET (1, &s_input))
{
gw_log (GW_LOG_DEBUG, prog, "stdout closed");
break;
}
}
#endif
- if (data < 0)
- {
- gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, prog, "read");
- exit (1);
- }
gw_log (GW_LOG_DEBUG, prog, "Cleaning up.");
close(linein);
unlink(serverp);
* USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $Log: wproto.c,v $
- * Revision 1.5 1995/11/02 16:35:37 adam
+ * Revision 1.6 1995/11/06 10:51:17 adam
+ * End of response marker in response from wsh/wproto to wcgi.
+ * Shells are respawned when necessary.
+ *
+ * Revision 1.5 1995/11/02 16:35:37 adam
* Bug fixes and select on FIFOs in wcgi - doesn't really work!
*
* Revision 1.4 1995/10/31 16:56:25 adam
static char *mod = "wproto";
-void wo_puts(WCLIENT wc, char *s)
+void wo_write (WCLIENT wc, const char *s, size_t len)
{
- int len;
-
- if (wc->outbuffer_offset + (len = strlen(s)) + 1 > wc->outbuffer_size)
+ if (wc->outbuffer_offset + len >= wc->outbuffer_size)
wc->outbuffer = realloc(wc->outbuffer, wc->outbuffer_size +=
OUTBUFFER_CHUNK);
- memcpy(wc->outbuffer + wc->outbuffer_offset, s, len + 1);
+ memcpy(wc->outbuffer + wc->outbuffer_offset, s, len);
wc->outbuffer_offset += len;
}
-void wo_printf(WCLIENT wc, const char *fmt, ...)
+void wo_puts (WCLIENT wc, const char *s)
+{
+ wo_write (wc, s, strlen(s));
+}
+
+void wo_printf (WCLIENT wc, const char *fmt, ...)
{
va_list ap;
char tmpbuf[4048];
va_end(ap);
}
-void wo_clear(WCLIENT wc, char *type)
+void wo_clear (WCLIENT wc, char *type)
{
if (!wc->outbuffer)
wc->outbuffer = malloc(wc->outbuffer_size = OUTBUFFER_CHUNK);
wo_printf(wc, "Content-type: %s\n\n", type);
}
-int wo_puthtml(WCLIENT wc, char *name)
+int wo_puthtml (WCLIENT wc, char *name)
{
FILE *f;
char ch;
wc->outbuffer_offset = 0;
for (;;)
{
+ int w_chunk;
+
+ w_chunk = towrite;
wrote = write(wc->lineout, wc->outbuffer + wc->outbuffer_offset,
- towrite);
+ w_chunk);
if (wrote <= 0)
{
gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "write response");
int wo_finish(WCLIENT wc)
{
gw_log (GW_LOG_DEBUG, mod, "wo_finish");
+
+ wo_putc (wc, 0);
if (wo_flush(wc) < 0)
return -1;
close(wc->lineout);
}
else
{
- unlink (wc->wf_serverp);
return 1;
}
}
WCLIENT wproto_init(void)
{
- char path2[256];
+ char *val, path2[256];
wclient_data *new;
gw_log (GW_LOG_DEBUG, mod, "wproto_init");
close(1); /* release us from the wserver */
- new = malloc(sizeof(*new));
- new->id = getpid();
+ if (!(new = malloc(sizeof(*new))))
+ {
+ gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "malloc");
+ exit (1);
+ }
+ if (!(val = getenv ("GWID")))
+ {
+ gw_log (GW_LOG_FATAL, mod, "GWID not set");
+ exit (1);
+ }
+ new->id = atoi (val);
sprintf(new->path, "%s/%s/clt%d", FIFOROOT, FIFODIR, new->id);
if (mkfifo(new->path, 0666 | S_IFIFO) < 0)
{