$Log$
+Revision 1.109 1999/12/03 05:09:54 ajc
+* Rewrote the HTTP engine and application coupling to run in a worker thread
+ model and to run as a single multithreaded program (eliminated helper
+ processes and pipes). It currently runs but has many large bugs.
+
Revision 1.108 1999/12/03 00:18:20 ajc
* Added ".c.o" rule to Makefile
1998-12-03 Nathan Bryant <bryant@cs.usm.maine.edu>
* webserver.c: warning fix
-
# End of configuration section
-all: webserver webcit
+all: webserver
.SUFFIXES: .c .o
webserver: webserver.o context_loop.o tools.o \
- cookie_conversion.o locate_host.o $(LIBOBJS)
+ cookie_conversion.o locate_host.o \
+ webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \
+ roomops.o messages.o userlist.o paging.o sysmsgs.o \
+ mime_parser.o graphics.o netconf.o siteconfig.o $(LIBOBJS)
$(CC) webserver.o context_loop.o tools.o cookie_conversion.o \
- locate_host.o $(LIBOBJS) $(LIBS) -o webserver
+ webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \
+ roomops.o messages.o userlist.o paging.o sysmsgs.o \
+ locate_host.o siteconfig.o \
+ mime_parser.o graphics.o netconf.o \
+ $(LIBOBJS) $(LIBS) -o webserver
.c.o:
$(CC) $(CFLAGS) $(DEFS) -c -D_REENTRANT -DWEBCITDIR=\"`pwd`\" $<
-
-webcit: webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \
- roomops.o tools.o messages.o userlist.o paging.o sysmsgs.o \
- mime_parser.o graphics.o netconf.o cookie_conversion.o siteconfig.o \
- wildmat.o braindamage.o
- $(CC) webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \
- tools.o roomops.o messages.o userlist.o paging.o sysmsgs.o siteconfig.o \
- mime_parser.o graphics.o netconf.o cookie_conversion.o \
- wildmat.o braindamage.o -o webcit
-
Makefile: $(srcdir)/Makefile.in config.status
CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
* $Id$
*/
+
+#include <ctype.h>
#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
-#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
char *axdefs[] =
{
{
char buf[256];
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(3);
/* Da banner */
strcpy(WC->wc_password, "");
strcpy(WC->wc_roomname, "");
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(2); /* note "2" causes cookies to be unset */
wprintf("<CENTER>");
char buf[256];
int a;
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
strcpy(buf, bstr("user"));
char buf[256];
int a;
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=007700><TR><TD>");
{
char buf[256];
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
+++ /dev/null
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <stdarg.h>
-#include "webcit.h"
-#include "child.h"
-
-/*
- * browser_braindamage_check()
- *
- * Given the value of the HTTP "User-agent:" directive supplied by
- * a web browser, determine using a local configuration file whether
- * the browser is capable of handling JavaScript.
- *
- * This function returns one of the following values:
- * B_YES (Yes, it's ok to use JavaScript)
- * B_NO (No, fall back to HTML)
- * B_ASK (We don't know; ask the user)
- */
-
-int browser_braindamage_check(char *browser)
-{
- FILE *fp;
- char buf[256];
- int thisval;
-
- fp = fopen("static/braindamage", "r");
- if (fp == NULL)
- return (B_ASK);
-
- while (fgets(buf, 256, fp) != NULL) {
- buf[strlen(buf)-1] = 0;
- thisval = (-1);
- if (!strncasecmp(buf, "YES", 3)) {
- thisval = B_YES;
- strcpy(buf, &buf[3]);
- } else if (!strncasecmp(buf, "NO", 2)) {
- thisval = B_NO;
- strcpy(buf, &buf[2]);
- } else if (!strncasecmp(buf, "ASK", 3)) {
- thisval = B_ASK;
- strcpy(buf, &buf[3]);
- }
- if (thisval >= 0) {
- while (isspace(buf[0])) strcpy(buf, &buf[1]);
- if (wildmat(buf, browser)) {
- return(thisval);
- }
- }
- }
-
- fclose(fp);
- return (B_ASK);
-}
+++ /dev/null
-/*
- * child.h: prototypes for the `webcit' child process
- *
- * $Id$
- */
-
-void become_logged_in(char *, char *, char *);
-void do_login(void);
-void display_login(char *mesg);
-void do_welcome(void);
-void do_logout(void);
-void display_main_menu(void);
-void display_advanced_menu(void);
-void list_all_rooms_by_floor(void);
-void slrp_highest(void);
-void gotonext(void);
-void ungoto(void);
-void get_serv_info(char *, char *);
-int connectsock(char *host, char *service, char *protocol);
-void serv_gets(char *strbuf);
-void serv_puts(char *string);
-void whobbs(void);
-void fmout(FILE * fp);
-void wDumpContent(int);
-void serv_printf(const char *format,...);
-char *bstr(char *key);
-char *urlesc(char *);
-void urlescputs(char *);
-void output_headers(int);
-void wprintf(const char *format,...);
-void extract(char *dest, char *source, int parmnum);
-int extract_int(char *source, int parmnum);
-void output_static(char *what);
-void escputs(char *strbuf);
-void url(char *buf);
-void escputs1(char *strbuf, int nbsp);
-long extract_long(char *source, long int parmnum);
-void dump_vars(void);
-void embed_main_menu(void);
-void serv_read(char *buf, int bytes);
-int haschar(char *st, char ch);
-void readloop(char *oper);
-void text_to_server(char *ptr);
-void display_enter(void);
-void post_message(void);
-void confirm_delete_msg(void);
-void delete_msg(void);
-void confirm_move_msg(void);
-void move_msg(void);
-void userlist(void);
-void showuser(void);
-void display_page(void);
-void page_user(void);
-void do_chat(void);
-void display_private(char *rname, int req_pass);
-void goto_private(void);
-void zapped_list(void);
-void display_zap(void);
-void zap(void);
-void display_error(char *);
-void display_success(char *);
-void display_entroom(void);
-void entroom(void);
-void display_editroom(void);
-void editroom(void);
-void server_to_text(void);
-void save_edit(char *description, char *enter_cmd, int regoto);
-void display_edit(char *description, char *check_cmd,
- char *read_cmd, char *save_cmd);
-void gotoroom(char *gname, int display_name);
-void confirm_delete_room(void);
-void delete_room(void);
-void validate(void);
-void display_graphics_upload(char *, char *, char *);
-void do_graphics_upload(char *upl_cmd);
-void serv_read(char *buf, int bytes);
-void serv_gets(char *strbuf);
-void serv_write(char *buf, int nbytes);
-void serv_puts(char *string);
-void serv_printf(const char *format,...);
-void load_floorlist(void);
-void select_floor_to_edit_pic(void);
-void display_reg(int);
-void register_user(void);
-void display_changepw(void);
-void changepw(void);
-void display_edit_node(void);
-void display_netconf(void);
-void display_confirm_unshare(void);
-void display_confirm_delete_node(void);
-void delete_node(void);
-void unshare(void);
-void display_add_node(void);
-void add_node(void);
-void display_share(void);
-void share(void);
-void terminate_session(void);
-void edit_me(void);
-void display_siteconfig(void);
-void siteconfig(void);
-void display_generic(void);
-void do_generic(void);
-int browser_braindamage_check(char *);
-void display_menubar(int);
-void embed_room_banner(char *);
-void smart_goto(char *);
-void ExpressMessageCat(char *);
#include "webcit.h"
#include "webserver.h"
-/*
- * We keep one of these around for each active session
- */
-struct wc_session {
- struct wc_session *next; /* Next session in list */
- int session_id; /* Session ID */
- pid_t webcit_pid; /* PID of the webcit process */
- int inpipe[2]; /* Data from webserver to session */
- int outpipe[2]; /* Data from session to webserver */
- pthread_mutex_t critter; /* Critical section uses pipes */
- time_t lastreq; /* Timestamp of most recent http */
-};
-
-struct wc_session *SessionList = NULL;
-extern const char *defaulthost;
-extern const char *defaultport;
-
/* Only one thread may manipulate SessionList at a time... */
-pthread_mutex_t MasterCritter;
-
-
-/*
- * Grab a lock on the session, so other threads don't try to access
- * the pipes at the same time.
- */
-static void lock_session(struct wc_session *session)
-{
- printf("Locking session %d...\n", session->session_id);
- pthread_mutex_lock(&session->critter);
- printf(" ...got lock\n");
-}
-
-/*
- * Let go of the lock.
- */
-static void unlock_session(struct wc_session *session)
-{
- printf("Unlocking.\n");
- pthread_mutex_unlock(&session->critter);
-}
-
-/*
- * Remove a session context from the list.
- * Set do_lock to 1, to lock the list while manipulating it. The ONLY
- * situation in which this should _not_ be done is when it's already locked
- * by the caller.
- */
-void remove_session(struct wc_session *TheSession, int do_lock)
-{
- struct wc_session *sptr;
-
- printf("Removing session.\n");
-
- /* Lock the list while manipulating it */
- if (do_lock)
- pthread_mutex_lock(&MasterCritter);
-
- if (SessionList == TheSession) {
- SessionList = SessionList->next;
- } else {
- for (sptr = SessionList; sptr != NULL; sptr = sptr->next) {
- if (sptr->next == TheSession) {
- sptr->next = TheSession->next;
- }
- }
- }
-
- if (do_lock)
- pthread_mutex_unlock(&MasterCritter);
-
- /* Now finish destroying the session */
- close(TheSession->inpipe[1]);
- close(TheSession->outpipe[0]);
- if (do_lock)
- unlock_session(TheSession);
- free(TheSession);
-
-}
-
+pthread_mutex_t SessionListMutex;
+struct wcsession *SessionList = NULL;
+pthread_key_t MyConKey; /* TSD key for MySession() */
void do_housekeeping(void)
{
- struct wc_session *sptr;
+ struct wcsession *sptr;
- pthread_mutex_lock(&MasterCritter);
+ pthread_mutex_lock(&SessionListMutex);
/* Kill idle sessions */
for (sptr = SessionList; sptr != NULL; sptr = sptr->next) {
if ((time(NULL) - (sptr->lastreq)) > (time_t) WEBCIT_TIMEOUT) {
- kill(sptr->webcit_pid, 15);
+ /* FIX do something here */
}
}
- /* Remove dead sessions */
- for (sptr = SessionList; sptr != NULL; sptr = sptr->next) {
- if (kill(sptr->webcit_pid, 0)) {
- remove_session(sptr, 0);
- }
- }
-
- pthread_mutex_unlock(&MasterCritter);
+ pthread_mutex_unlock(&SessionListMutex);
}
}
-
-
-
+/*
+ * Generate a unique WebCit session ID (which is not the same thing as the
+ * Citadel session ID).
+ *
+ * FIX ... we really should check to make sure we're generating a truly
+ * unique session ID by traversing the SessionList.
+ *
+ */
int GenerateSessionID(void)
{
- return getpid();
+ static int seq = (-1);
+
+ if (seq < 0) {
+ seq = (int) time(NULL);
+ }
+
+ return ++seq;
}
return close(fd);
}
+
+
+
/*
- * This loop gets called once for every HTTP connection made to WebCit.
+ * This loop gets called once for every HTTP connection made to WebCit. At
+ * this entry point we have an HTTP socket with a browser allegedly on the
+ * other end, but we have not yet bound to a WebCit session.
+ *
+ * The job of this function is to locate the correct session and bind to it,
+ * or create a session if necessary and bind to it, then run the WebCit
+ * transaction loop. Afterwards, we unbind from the session. When this
+ * function returns, the worker thread is then free to handle another
+ * transaction.
*/
-void *context_loop(int sock)
+void context_loop(int sock)
{
- char (*req)[256];
+ struct httprequest *req = NULL;
+ struct httprequest *last = NULL;
+ struct httprequest *hptr;
char buf[256], hold[256];
- char browser_host[256];
- char browser[256];
- int num_lines = 0;
- int a;
- int f;
int desired_session = 0;
int got_cookie = 0;
- char str_session[256];
- struct wc_session *sptr;
- struct wc_session *TheSession;
- int ContentLength;
+ struct wcsession *TheSession, *sptr;
int CloseSession = 0;
- if ((req = malloc((long) sizeof(char[256][256]))) == NULL) {
- sprintf(buf, "Can't malloc buffers; dropping connection.\n");
- fprintf(stderr, "%s", buf);
- write(sock, buf, strlen(buf));
- close(sock);
- pthread_exit(NULL);
- }
- bzero(req, sizeof(char[256][256])); /* clear it out */
- strcpy(browser, "unknown");
- printf("Reading request from socket %d\n", sock);
+ fprintf(stderr, "Reading request from socket %d\n", sock);
/*
* Find out what it is that the web browser is asking for
*/
- ContentLength = 0;
do {
req_gets(sock, buf, hold);
if (!strncasecmp(buf, "Cookie: webcit=", 15)) {
NULL, NULL, NULL);
got_cookie = 1;
}
- else if (!strncasecmp(buf, "Content-length: ", 16)) {
- ContentLength = atoi(&buf[16]);
- }
- else if (!strncasecmp(buf, "User-agent: ", 12)) {
- strcpy(browser, &buf[12]);
- }
- strcpy(&req[num_lines++][0], buf);
+
+ hptr = (struct httprequest *)
+ malloc(sizeof(struct httprequest));
+ if (req == NULL)
+ req = hptr;
+ else
+ last->next = hptr;
+ hptr->next = NULL;
+ last = hptr;
+
+ strcpy(hptr->line, buf);
+
} while (strlen(buf) > 0);
* set. If there isn't, the client browser has cookies turned off
* (or doesn't support them) and we have to barf & bail.
*/
- strcpy(buf, &req[0][0]);
+ strcpy(buf, req->line);
if (!strncasecmp(buf, "GET ", 4)) strcpy(buf, &buf[4]);
else if (!strncasecmp(buf, "HEAD ", 5)) strcpy(buf, &buf[5]);
if (buf[1]==' ') buf[1]=0;
* robots.txt file...
*/
if (!strncasecmp(buf, "/robots.txt", 11)) {
- strcpy(&req[0][0], "GET /static/robots.txt HTTP/1.0");
+ strcpy(req->line, "GET /static/robots.txt HTTP/1.0");
}
/* Do the non-root-cookie check now. */
else if ( (strcmp(buf, "/")) && (got_cookie == 0)) {
- strcpy(&req[0][0], "GET /static/nocookies.html HTTP/1.0");
+ strcpy(req->line, "GET /static/nocookies.html HTTP/1.0");
}
*/
TheSession = NULL;
if (desired_session != 0) {
- pthread_mutex_lock(&MasterCritter);
+ pthread_mutex_lock(&SessionListMutex);
for (sptr = SessionList; sptr != NULL; sptr = sptr->next) {
- if (sptr->session_id == desired_session) {
+ if (sptr->wc_session == desired_session) {
TheSession = sptr;
}
}
- pthread_mutex_unlock(&MasterCritter);
- }
-
- /*
- * Before we trumpet to the universe that the session we're looking
- * for actually exists, check first to make sure it's still there.
- */
- if (TheSession != NULL) {
- if (kill(TheSession->webcit_pid, 0)) {
- printf(" Session is *DEAD* !!\n");
- remove_session(TheSession, 1);
- TheSession = NULL;
- }
+ pthread_mutex_unlock(&SessionListMutex);
}
/*
*/
if (TheSession == NULL) {
printf("Creating a new session\n");
- locate_host(browser_host, sock);
- TheSession = (struct wc_session *)
- malloc(sizeof(struct wc_session));
- TheSession->session_id = GenerateSessionID();
- pipe(TheSession->inpipe);
- pipe(TheSession->outpipe);
- pthread_mutex_init(&TheSession->critter, NULL);
-
- pthread_mutex_lock(&MasterCritter);
+ TheSession = (struct wcsession *)
+ malloc(sizeof(struct wcsession));
+ memset(TheSession, 0, sizeof(struct wcsession));
+ TheSession->wc_session = GenerateSessionID();
+ pthread_mutex_init(&TheSession->SessionMutex, NULL);
+
+ pthread_mutex_lock(&SessionListMutex);
TheSession->next = SessionList;
SessionList = TheSession;
- pthread_mutex_unlock(&MasterCritter);
-
- sprintf(str_session, "%d", TheSession->session_id);
- f = fork();
- if (f > 0)
- TheSession->webcit_pid = f;
-
- fflush(stdout);
- fflush(stdin);
- if (f == 0) {
-
- /* Hook stdio to the ends of the pipe we're using */
- dup2(TheSession->inpipe[0], 0);
- dup2(TheSession->outpipe[1], 1);
-
- /* Close the ends of the pipes that we're not using */
- close(TheSession->inpipe[1]);
- close(TheSession->outpipe[0]);
-
- /* Close the HTTP socket in this pid; don't need it */
- close(sock);
-
- /* Run the actual WebCit session */
- execlp("./webcit", "webcit", str_session, defaulthost,
- defaultport, browser_host, browser, NULL);
-
- /* Simple page to display if exec fails */
- printf("HTTP/1.0 404 WebCit Failure\n\n");
- printf("Server: %s\n", SERVER);
- printf("X-WebCit-Session: close\n");
- printf("Content-type: text/html\n");
- printf("Content-length: 76\n");
- printf("\n");
- printf("<HTML><HEAD><TITLE>Error</TITLE></HEAD><BODY>\n");
- printf("execlp() failed: %s</BODY></HTML>\n", strerror(errno));
- exit(0);
- } else {
- /* Close the ends of the pipes that we're not using */
- close(TheSession->inpipe[0]);
- close(TheSession->outpipe[1]);
- }
+ pthread_mutex_unlock(&SessionListMutex);
}
- /*
- * Send the request to the appropriate session...
- */
- lock_session(TheSession);
- TheSession->lastreq = time(NULL);
- printf(" Writing %d lines of command\n", num_lines);
- printf("%s\n", &req[0][0]);
- for (a = 0; a < num_lines; ++a) {
- write(TheSession->inpipe[1], &req[a][0], strlen(&req[a][0]));
- write(TheSession->inpipe[1], "\n", 1);
- }
- printf(" Writing %d bytes of content\n", ContentLength);
- while (ContentLength > 0) {
- a = ContentLength;
- if (a > sizeof buf)
- a = sizeof buf;
- if (!client_read(sock, buf, a))
- goto end;
- if (write(TheSession->inpipe[1], buf, a) != a)
- goto end;
- ContentLength -= a;
- }
/*
- * ...and get the response.
+ *
+ * FIX ... check session integrity here before continuing
+ *
*/
- printf(" Reading response\n");
- ContentLength = 0;
- do {
- gets0(TheSession->outpipe[0], buf);
- write(sock, buf, strlen(buf));
- write(sock, "\n", 1);
- if (!strncasecmp(buf, "Content-length: ", 16))
- ContentLength = atoi(&buf[16]);
- if (!strcasecmp(buf, "X-WebCit-Session: close")) {
- CloseSession = 1;
- }
- } while (strlen(buf) > 0);
- printf(" Reading %d bytes of content\n", ContentLength);
- while (ContentLength--) {
- read(TheSession->outpipe[0], buf, 1);
- write(sock, buf, 1);
- }
+
+ /*
+ * Bind to the session
+ */
+ pthread_mutex_lock(&TheSession->SessionMutex);
+ pthread_setspecific(MyConKey, (void *)TheSession);
+ TheSession->lastreq = time(NULL);
+ TheSession->http_sock = sock;
+
+ /*
+ * Perform the WebCit transaction
+ */
+ fprintf(stderr, "Transaction: %s\n", req->line);
+ session_loop(req);
+ fprintf(stderr, "Returned from transaction loop\n");
/*
* If the last response included a "close session" directive,
* remove the context now.
*/
if (CloseSession) {
- remove_session(TheSession, 1);
+ /* FIX remove_session(TheSession, 1); */
} else {
-end: unlock_session(TheSession);
+
+ pthread_mutex_unlock(&TheSession->SessionMutex);
}
- free(req);
+ /* Free the request buffer */
+ while (req != NULL) {
+ hptr = req->next;
+ free(req);
+ req = hptr;
+ }
/*
- * Now our HTTP connection is done. It would be relatively easy
- * to support HTTP/1.1 "persistent" connections by looping back to
- * the top of this function. For now, we'll just close.
+ * Now our HTTP connection is done. Close the socket and exit this
+ * function, so the worker thread can handle a new HTTP connection.
*/
printf(" Closing socket %d ... ret=%d\n", sock,
lingering_close(sock));
-
- /*
- * The thread handling this HTTP connection is now finished.
- * Instead of calling pthread_exit(), just return. It does the same
- * thing, and supresses a compiler warning.
- */
- return NULL;
+ return;
}
+
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
/*
* Pack all session info into one easy-to-digest cookie. Healthy and delicious!
+
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
-#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
#include <errno.h>
-#include <time.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
-
void display_graphics_upload(char *description, char *check_cmd, char *uplurl)
{
display_error(&buf[4]);
return;
}
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
{
int a;
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
* locate the originating host
*/
+
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/socket.h>
-#include <netinet/in.h>
+#include <sys/time.h>
#include <limits.h>
+#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
+#include "webcit.h"
+
+
+
void locate_host(char *tbuf, int client_socket)
{
/* $Id$ */
+
+
+
+#include <ctype.h>
#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
-#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
/*
*/
void display_main_menu(void)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
embed_main_menu();
wDumpContent(2);
void display_advanced_menu(void)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
embed_advanced_menu();
embed_main_menu();
*/
void display_generic(void)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770077><TR><TD>");
return;
}
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
serv_printf("%s", bstr("g_cmd"));
char buf[256];
if (as_single_page) {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(0);
wprintf("<HTML>\n"
"<HEAD>\n"
+
+
+
+
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
-#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
#include <errno.h>
-#include <time.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
+
char reply_to[512];
long msgarr[1024];
int a;
int nummsgs;
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\"><CENTER><B>%s - ", WC->wc_roomname);
char buf[256];
static long dont_post = (-1L);
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\">");
long now;
struct tm *tm;
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<FACE=\"Arial,Helvetica,sans-serif\">");
msgid = atol(bstr("msgid"));
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
msgid = atol(bstr("msgid"));
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
if (!strcasecmp(bstr("yesno"), "Yes")) {
msgid = atol(bstr("msgid"));
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
msgid = atol(bstr("msgid"));
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
if (!strcasecmp(bstr("yesno"), "Move")) {
* messages -- in the case of WebCit, a form containing uploaded files.
*/
+
+
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
-#include "mime_parser.h"
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
+
+
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
+
+
struct sharelist {
struct sharelist *next;
strcpy(node, bstr("node"));
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
char buf[256];
char node[256];
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
char node[256];
char sroom[256];
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
{
char node[256];
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
serv_puts(buf);
serv_gets(buf);
if (buf[0] == '1') {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
server_to_text();
wprintf("<A HREF=\"/display_netconf\">Back to menu</A>\n");
serv_puts(buf);
serv_gets(buf);
if (buf[0] == '1') {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
server_to_text();
wprintf("<A HREF=\"/display_netconf\">Back to menu</A>\n");
void display_add_node(void)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=007700><TR><TD>");
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
serv_puts(buf);
serv_gets(buf);
if (buf[0] == '1') {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
server_to_text();
wprintf("<A HREF=\"/display_netconf\">Back to menu</A>\n");
strcpy(node, bstr("node"));
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=007700><TR><TD>");
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
serv_puts(buf);
serv_gets(buf);
if (buf[0] == '1') {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
server_to_text();
wprintf("<A HREF=\"/display_netconf\">Back to menu</A>\n");
/* $Id$ */
+#include <ctype.h>
#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
/*
* display the form for paging (x-messaging) another user
char buf[256];
char user[256];
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=007700><TR><TD>");
char sc[256];
char buf[256];
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
strcpy(recp, bstr("recp"));
void do_chat(void)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
/* $Id$ */
+
+#include <ctype.h>
#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
+
+
+
+
/*
* This struct holds a list of rooms for <G>oto operations.
load_floorlist();
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE width=100% border><TR><TH>Floor</TH>");
*/
void zapped_list(void)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\" SIZE=+1 COLOR=\"FFFFFF\"");
if (display_name) {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
printf("Pragma: no-cache\n");
printf("Cache-Control: no-store\n");
output_headers(0);
er_floor = extract_int(&buf[4], 4);
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
display_error(&buf[4]);
return;
}
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
void display_private(char *rname, int req_pass)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
display_private(bstr("gr_name"), 1);
return;
}
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("%s\n", &buf[4]);
wDumpContent(1);
*/
void display_zap(void)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
display_error(&buf[4]);
return;
}
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
/* $Id$ */
+
+
#include <ctype.h>
#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
+
+
+
struct serv_info serv_info;
*
*/
+
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
void display_siteconfig(void)
char buf[256];
int i;
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
serv_printf("CONF get");
+
+
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
+
+
+
+
/*
* display the form for editing something (room info, bio, etc)
display_error(&buf[4]);
return;
}
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=007700><TR><TD>");
char buf[256];
if (strcmp(bstr("sc"), "Save")) {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("Cancelled. %s was not saved.<BR>\n", description);
wDumpContent(1);
if (regoto) {
smart_goto(WC->wc_roomname);
} else {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("%s has been saved.\n", description);
wDumpContent(1);
* $Id$
*/
+
+#include <ctype.h>
#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
#include <netinet/in.h>
-#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
+
+
+
+
char server_is_local = 0;
#ifndef INADDR_NONE
* tools.c -- Miscellaneous routines
*/
-#include <stdio.h>
+
+
+#include <ctype.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
+
+
+
char *safestrncpy(char *dest, const char *src, size_t n)
{
if (dest == NULL || src == NULL) {
*/
int haschar(st, ch)
char st[];
-int ch;
+char ch;
{
int a, b;
b = 0;
+#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
-#include <time.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
struct namelist {
struct namelist *next;
strcpy(bptr->name, buf);
bio = bptr;
}
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
serv_puts("LIST");
char buf[256];
int have_pic;
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
* $Id$
*/
+#include <ctype.h>
#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
-#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
#include <errno.h>
-#include <sys/stat.h>
#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
-#include "mime_parser.h"
+
+
int TransactionCount = 0;
char *ExpressMessages = NULL;
*/
int fake_frames = 0;
-struct webcontent *wlist = NULL;
-struct webcontent *wlast = NULL;
-
struct urlcontent *urlstrings = NULL;
static const char *defaulthost = DEFAULT_HOST;
-struct wcsession *WC = NULL; /* FIX take this out when multithreaded */
-
void unescape_input(char *buf)
{
int a, b;
void wprintf(const char *format,...)
{
va_list arg_ptr;
- struct webcontent *wptr;
-
- wptr = (struct webcontent *) malloc(sizeof(struct webcontent));
- wptr->next = NULL;
- if (wlist == NULL) {
- wlist = wptr;
- wlast = wptr;
- } else {
- wlast->next = wptr;
- wlast = wptr;
- }
+ char wbuf[1024];
va_start(arg_ptr, format);
- vsprintf(wptr->w_data, format, arg_ptr);
+ vsprintf(wbuf, format, arg_ptr);
va_end(arg_ptr);
-}
-
-int wContentLength(void)
-{
- struct webcontent *wptr;
- int len = 0;
-
- for (wptr = wlist; wptr != NULL; wptr = wptr->next) {
- len = len + strlen(wptr->w_data);
- }
- return (len);
+ write(WC->http_sock, wbuf, strlen(wbuf));
}
+
/*
- * wDumpContent() takes all the stuff that's been queued up using
- * the wprintf() and escputs() functions, and sends it out to the browser.
- * By queuing instead of transmitting as it's generated, we're able to
- * calculate a Content-length: header.
+ * wDumpContent() wraps up an HTTP session, closes tags, etc.
*
* print_standard_html_footer should be set to 0 to transmit only, 1 to
* append the main menu and closing tags, or 2 to
*/
void wDumpContent(int print_standard_html_footer)
{
- struct webcontent *wptr;
-
if (fake_frames) {
wprintf("<CENTER><FONT SIZE=-1>"
"<TABLE border=0 width=100%><TR>"
}
wprintf("</BODY></HTML>\n");
}
- printf("Content-type: text/html\n");
- printf("Content-length: %d\n", wContentLength());
- printf("\n");
-
- while (wlist != NULL) {
- fwrite(wlist->w_data, strlen(wlist->w_data), 1, stdout);
- wptr = wlist->next;
- free(wlist);
- wlist = wptr;
- }
- wlast = NULL;
+
+
}
-/*
- * Get a line of text from the webserver (which originally came from the
- * user's browser), checking for sanity etc.
- */
-char *getz(char *buf)
-{
- int e = 0;
-
- bzero(buf, 256);
-
- /* If fgets() fails, it's because the webserver crashed, so kill off
- * the session too.
- */
- if (fgets(buf, 256, stdin) == NULL) {
- e = errno;
- fprintf(stderr, "webcit: exit code %d (%s)\n",
- e, strerror(e));
- fflush(stderr);
- exit(e);
-
- /* Otherwise, strip out nonprintables and resume our happy day.
- */
- } else {
- while ((strlen(buf) > 0) && (!isprint(buf[strlen(buf) - 1])))
- buf[strlen(buf) - 1] = 0;
- return buf;
- }
-}
-
-
-
/*
* Output all that important stuff that the browser will want to see
*
static char *unset = "; expires=28-May-1971 18:10:00 GMT";
char cookie[256];
- printf("Server: %s\n", SERVER);
- printf("Connection: close\n");
+ wprintf("Content-type: text/html\n");
+ wprintf("Server: %s\n", SERVER);
+ wprintf("Connection: close\n");
if (print_standard_html_head > 0) {
- printf("Pragma: no-cache\n");
- printf("Cache-Control: no-store\n");
+ wprintf("Pragma: no-cache\n");
+ wprintf("Cache-Control: no-store\n");
}
stuff_to_cookie(cookie, WC->wc_session, WC->wc_username,
WC->wc_password, WC->wc_roomname);
if (print_standard_html_head == 2) {
- printf("X-WebCit-Session: close\n");
- printf("Set-cookie: webcit=%s\n", unset);
+ wprintf("X-WebCit-Session: close\n");
+ wprintf("Set-cookie: webcit=%s\n", unset);
} else {
- printf("Set-cookie: webcit=%s\n", cookie);
+ wprintf("Set-cookie: webcit=%s\n", cookie);
}
+ wprintf("\n");
+
if (print_standard_html_head > 0) {
wprintf("<HTML><HEAD><TITLE>");
escputs(serv_info.serv_humannode);
sprintf(buf, "static/%s", what);
fp = fopen(buf, "rb");
if (fp == NULL) {
- printf("HTTP/1.0 404 %s\n", strerror(errno));
- output_headers(0);
- printf("Content-Type: text/plain\n");
- sprintf(buf, "%s: %s\n", what, strerror(errno));
- printf("Content-length: %d\n", strlen(buf));
- printf("\n");
- fwrite(buf, strlen(buf), 1, stdout);
+ wprintf("HTTP/1.0 404 %s\n", strerror(errno));
+ wprintf("Content-Type: text/plain\n");
+ wprintf("\n");
+ wprintf("Cannot open %s: %s\n", what, strerror(errno));
} else {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(0);
if (!strncasecmp(&what[strlen(what) - 4], ".gif", 4))
- printf("Content-type: image/gif\n");
+ wprintf("Content-type: image/gif\n");
else if (!strncasecmp(&what[strlen(what) - 4], ".txt", 4))
- printf("Content-type: text/plain\n");
+ wprintf("Content-type: text/plain\n");
else if (!strncasecmp(&what[strlen(what) - 4], ".jpg", 4))
- printf("Content-type: image/jpeg\n");
+ wprintf("Content-type: image/jpeg\n");
else if (!strncasecmp(&what[strlen(what) - 5], ".html", 5))
- printf("Content-type: text/html\n");
+ wprintf("Content-type: text/html\n");
else
- printf("Content-type: application/octet-stream\n");
+ wprintf("Content-type: application/octet-stream\n");
fstat(fileno(fp), &statbuf);
bytes = statbuf.st_size;
- printf("Content-length: %ld\n", (long) bytes);
+ wprintf("Content-length: %ld\n", (long) bytes);
printf("\n");
while (bytes--) {
- putc(getc(fp), stdout);
+ wprintf("%c", getc(fp) );
}
- fflush(stdout);
fclose(fp);
}
}
serv_gets(buf);
if (buf[0] == '2') {
bytes = extract_long(&buf[4], 0);
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(0);
- printf("Content-type: image/gif\n");
- printf("Content-length: %ld\n", (long) bytes);
- printf("\n");
+ wprintf("Content-type: image/gif\n");
+ wprintf("Content-length: %ld\n", (long) bytes);
+ wprintf("\n");
while (bytes > (off_t) 0) {
thisblock = (off_t) sizeof(xferbuf);
if (buf[0] == '6')
thisblock = extract_long(&buf[4], 0);
serv_read(xferbuf, (int) thisblock);
- fwrite(xferbuf, thisblock, 1, stdout);
+ write(WC->http_sock, xferbuf, thisblock);
bytes = bytes - thisblock;
accomplished = accomplished + thisblock;
}
serv_puts("CLOS");
serv_gets(buf);
} else {
- printf("HTTP/1.0 404 %s\n", strerror(errno));
+ wprintf("HTTP/1.0 404 %s\n", strerror(errno));
output_headers(0);
- printf("Content-Type: text/plain\n");
- sprintf(buf, "Error retrieving image\n");
- printf("Content-length: %d\n", strlen(buf));
- printf("\n");
- fwrite(buf, strlen(buf), 1, stdout);
+ wprintf("Content-Type: text/plain\n");
+ wprintf("\n");
+ wprintf("Error retrieving image\n");
}
}
*/
void convenience_page(char *titlebarcolor, char *titlebarmsg, char *messagetext)
{
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=%s><TR><TD>", titlebarcolor);
wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
}
-void session_loop(char *browser_host, char *user_agent)
+/*
+ * Entry point for WebCit transaction
+ */
+void session_loop(struct httprequest *req)
{
char cmd[256];
char action[256];
int ContentLength = 0;
char ContentType[512];
char *content;
+ struct httprequest *hptr;
+ char browser_host[256];
+ char user_agent[256];
/* We stuff these with the values coming from the client cookies,
* so we can use them to reconnect a timed out session if we have to.
WC->upload_length = 0;
WC->upload = NULL;
- if (getz(cmd) == NULL)
- return;
+ hptr = req;
+ if (hptr == NULL) return;
+
+ strcpy(cmd, hptr->line);
+ hptr = hptr->next;
extract_action(action, cmd);
- do {
- if (getz(buf) == NULL)
- return;
+ while (hptr != NULL) {
+ strcpy(buf, hptr->line);
+ hptr = hptr->next;
if (!strncasecmp(buf, "Cookie: webcit=", 15)) {
strcpy(cookie, &buf[15]);
cookie_to_stuff(cookie, NULL,
c_username, c_password, c_roomname);
}
- if (!strncasecmp(buf, "Content-length: ", 16)) {
+ else if (!strncasecmp(buf, "Content-length: ", 16)) {
ContentLength = atoi(&buf[16]);
}
- if (!strncasecmp(buf, "Content-type: ", 14)) {
+ else if (!strncasecmp(buf, "Content-type: ", 14)) {
strcpy(ContentType, &buf[14]);
}
- } while (strlen(buf) > 0);
+ else if (!strncasecmp(buf, "User-agent: ", 12)) {
+ strcpy(user_agent, &buf[12]);
+ }
+ }
++TransactionCount;
if (ContentLength > 0) {
content = malloc(ContentLength + 1);
- fread(content, ContentLength, 1, stdin);
+ read(WC->http_sock, content, ContentLength);
content[ContentLength] = 0;
cmd[a] = 0;
}
/*
- * If we're not WC->connected to a Citadel server, try to hook up the
+ * If we're not connected to a Citadel server, try to hook up the
* connection now. Preference is given to the host and port specified
* by browser cookies, if cookies have been supplied.
*/
WC->connected = 1;
serv_gets(buf); /* get the server welcome message */
+ locate_host(browser_host, WC->http_sock);
get_serv_info(browser_host, user_agent);
}
check_for_express_messages();
} else if (!strcasecmp(action, "display_menubar")) {
display_menubar(1);
} else if (!strcasecmp(action, "diagnostics")) {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("TransactionCount is %d<BR>\n", TransactionCount);
WC->upload_length = 0;
}
}
-
-int main(int argc, char *argv[])
-{
-
- char browser[256];
- int bd;
-
- if (argc != 6) {
- fprintf(stderr,
- "webcit: usage error (argc must be 6, not %d)\n",
- argc);
- return 1;
- }
-
- WC = (struct wcsession *) malloc(sizeof(struct wcsession));
- memset(WC, 0, sizeof(struct wcsession));
-
-
-
- WC->wc_session = atoi(argv[1]);
- defaulthost = argv[2];
- defaultport = argv[3];
-
- strcpy(WC->wc_username, "");
- strcpy(WC->wc_password, "");
- strcpy(WC->wc_roomname, "");
-
- /* Clear out serv_info and temporarily set the value of serv_humannode
- * to a default value, because it'll be used in HTML page titles
- */
- memset(&serv_info, 0, sizeof(serv_info));
- strcpy(serv_info.serv_humannode, "WebCit");
-
- strcpy(browser, argv[5]);
- bd = browser_braindamage_check(browser);
-
- while (1) {
- session_loop(argv[4], browser);
- }
-}
#define SLEEPING 180 /* TCP connection timeout */
#define WEBCIT_TIMEOUT 900 /* WebCit session timeout */
#define PORT_NUM 2000 /* port number to listen on */
-#define SERVER "WebCit v2.01" /* who's in da house */
+#define SERVER "WebCit v2.50" /* who's in da house */
#define DEVELOPER_ID 0
#define CLIENT_ID 4
-#define CLIENT_VERSION 201
+#define CLIENT_VERSION 250
#define DEFAULT_HOST "localhost"
#define DEFAULT_PORT "504"
#define LB (1)
#define QR_MAILBOX 16384 /* Set if this is a private mailbox */
-/* Browser braindamage check values */
-enum {
- B_NO,
- B_YES,
- B_ASK
-};
-
-
-struct webcontent {
- struct webcontent *next;
- char w_data[256];
+struct httprequest {
+ struct httprequest *next;
+ char line[256];
};
struct urlcontent {
int serv_ok_floors;
};
+
+
+/*
+ * One of these is kept for each active Citadel session.
+ * HTTP transactions are bound to one at a time.
+ */
struct wcsession {
- int wc_session;
+ struct wcsession *next; /* Linked list */
+ int wc_session; /* WebCit session ID */
char wc_username[256];
char wc_password[256];
char wc_roomname[256];
int axlevel;
int is_aide;
int is_room_aide;
+ int http_sock;
int serv_sock;
- struct serv_info serv_info;
unsigned room_flags;
char ugname[128];
long uglsn;
char *upload;
int new_mail;
int need_vali;
+ pthread_mutex_t SessionMutex; /* mutex for exclusive access */
+ time_t lastreq; /* Timestamp of most recent HTTP */
};
-extern struct wcsession *WC;
+
+
+#define WC ((struct wcsession *)pthread_getspecific(MyConKey))
+extern pthread_key_t MyConKey;
struct serv_info serv_info;
extern char floorlist[128][256];
extern char *axdefs[];
-void stuff_to_cookie(char *, int, char *, char *, char *);
-void cookie_to_stuff(char *, int *, char *, char *, char *);
+
+void stuff_to_cookie(char *cookie, int session,
+ char *user, char *pass, char *room);
+void cookie_to_stuff(char *cookie, int *session,
+ char *user, char *pass, char *room);
void locate_host(char *, int);
+void become_logged_in(char *, char *, char *);
+void do_login(void);
+void display_login(char *mesg);
+void do_welcome(void);
+void do_logout(void);
+void display_main_menu(void);
+void display_advanced_menu(void);
+void list_all_rooms_by_floor(void);
+void slrp_highest(void);
+void gotonext(void);
+void ungoto(void);
+void get_serv_info(char *, char *);
+int connectsock(char *host, char *service, char *protocol);
+void serv_gets(char *strbuf);
+void serv_puts(char *string);
+void whobbs(void);
+void fmout(FILE * fp);
+void wDumpContent(int);
+void serv_printf(const char *format,...);
+char *bstr(char *key);
+char *urlesc(char *);
+void urlescputs(char *);
+void output_headers(int);
+void wprintf(const char *format,...);
+void extract(char *dest, char *source, int parmnum);
+int extract_int(char *source, int parmnum);
+void output_static(char *what);
+void escputs(char *strbuf);
+void url(char *buf);
+void escputs1(char *strbuf, int nbsp);
+long extract_long(char *source, long int parmnum);
+void dump_vars(void);
+void embed_main_menu(void);
+void serv_read(char *buf, int bytes);
+int haschar(char *, char);
+void readloop(char *oper);
+void text_to_server(char *ptr);
+void display_enter(void);
+void post_message(void);
+void confirm_delete_msg(void);
+void delete_msg(void);
+void confirm_move_msg(void);
+void move_msg(void);
+void userlist(void);
+void showuser(void);
+void display_page(void);
+void page_user(void);
+void do_chat(void);
+void display_private(char *rname, int req_pass);
+void goto_private(void);
+void zapped_list(void);
+void display_zap(void);
+void zap(void);
+void display_error(char *);
+void display_success(char *);
+void display_entroom(void);
+void entroom(void);
+void display_editroom(void);
+void editroom(void);
+void server_to_text(void);
+void save_edit(char *description, char *enter_cmd, int regoto);
+void display_edit(char *description, char *check_cmd,
+ char *read_cmd, char *save_cmd);
+void gotoroom(char *gname, int display_name);
+void confirm_delete_room(void);
+void delete_room(void);
+void validate(void);
+void display_graphics_upload(char *, char *, char *);
+void do_graphics_upload(char *upl_cmd);
+void serv_read(char *buf, int bytes);
+void serv_gets(char *strbuf);
+void serv_write(char *buf, int nbytes);
+void serv_puts(char *string);
+void serv_printf(const char *format,...);
+void load_floorlist(void);
+void select_floor_to_edit_pic(void);
+void display_reg(int);
+void register_user(void);
+void display_changepw(void);
+void changepw(void);
+void display_edit_node(void);
+void display_netconf(void);
+void display_confirm_unshare(void);
+void display_confirm_delete_node(void);
+void delete_node(void);
+void unshare(void);
+void display_add_node(void);
+void add_node(void);
+void display_share(void);
+void share(void);
+void terminate_session(void);
+void edit_me(void);
+void display_siteconfig(void);
+void siteconfig(void);
+void display_generic(void);
+void do_generic(void);
+void display_menubar(int);
+void embed_room_banner(char *);
+void smart_goto(char *);
+void ExpressMessageCat(char *);
+void worker_entry(void);
+void session_loop(struct httprequest *);
+void mime_parser(char *content,
+ int ContentLength,
+ char *ContentType,
+ void (*CallBack)
+ (char *cbname,
+ char *cbfilename,
+ char *cbencoding,
+ void *cbcontent, char *cbtype, size_t cblength)
+);
int msock; /* master listening socket */
extern void *context_loop(int);
extern void *housekeeping_loop(void);
-extern pthread_mutex_t MasterCritter;
+extern pthread_mutex_t SessionListMutex;
+extern pthread_key_t MyConKey;
+
+
+
+
const char *defaulthost = DEFAULT_HOST;
const char *defaultport = DEFAULT_PORT;
+pthread_mutex_t AcceptQueue;
+
/*
* This is a generic function to set up a master socket for listening on
* a TCP port. The server shuts down if the bind fails.
*/
int main(int argc, char **argv)
{
- struct sockaddr_in fsin; /* Data for master socket */
- int alen; /* Data for master socket */
- int ssock; /* Descriptor for master socket */
pthread_t SessThread; /* Thread descriptor */
pthread_attr_t attr; /* Thread attributes */
int a, i; /* General-purpose variables */
defaultport = argv[optind];
}
/* Tell 'em who's in da house */
- printf("WebCit version 2.01\n");
- printf("Copyright (C) 1996-1999. All rights reserved.\n\n");
+ fprintf(stderr, SERVER "\n"
+ "Copyright (C) 1996-1999. All rights reserved.\n\n");
if (chdir(WEBCITDIR) != 0)
perror("chdir");
+ /*
+ * Set up a place to put thread-specific data.
+ * We only need a single pointer per thread - it points to the
+ * wcsession struct to which the thread is currently bound.
+ */
+ if (pthread_key_create(&MyConKey, NULL) != 0) {
+ fprintf(stderr, "Can't create TSD key: %s\n", strerror(errno));
+ }
+
/*
* Bind the server to our favorite port.
* There is no need to check for errors, because ig_tcp_server()
printf("Listening on socket %d\n", msock);
signal(SIGPIPE, SIG_IGN);
- pthread_mutex_init(&MasterCritter, NULL);
-
-
+ pthread_mutex_init(&SessionListMutex, NULL);
+ pthread_mutex_init(&AcceptQueue, NULL);
/*
* Start up the housekeeping thread
- /*
- * Endless loop. Listen on the master socket. When a connection
- * comes in, create a socket, a context, and a thread.
- */
- while (1) {
+ /* FIX make this variable */
+ for (i=0; i<10; ++i) {
+
+ /* set attributes for the new thread */
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ /* now create the thread */
+ if (pthread_create(&SessThread, &attr,
+ (void *(*)(void *)) worker_entry, NULL)
+ != 0) {
+ printf("webcit: can't create thread: %s\n",
+ strerror(errno));
+ }
+ }
+
+ /* now become a worker thread too */
+ worker_entry();
+ pthread_exit(NULL);
+}
+
+
+/*
+ * Entry point for worker threads
+ */
+void worker_entry(void) {
+ int ssock;
+ struct sockaddr_in fsin;
+ int alen;
+ int i = 0;
+ int time_to_die = 0;
+
+ do {
+ /* Only one thread can accept at a time */
+ pthread_mutex_lock(&AcceptQueue);
ssock = accept(msock, (struct sockaddr *) &fsin, &alen);
+ pthread_mutex_unlock(&AcceptQueue);
+
printf("New connection on socket %d\n", ssock);
if (ssock < 0) {
printf("webcit: accept() failed: %s\n",
- strerror(errno));
+ strerror(errno));
} else {
/* Set the SO_REUSEADDR socket option */
i = 1;
setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
- &i, sizeof(i));
-
- /* set attributes for the new thread */
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr,
- PTHREAD_CREATE_DETACHED);
-
- /* now create the thread */
- if (pthread_create(&SessThread, &attr,
- (void *(*)(void *)) context_loop,
- (void *) ssock)
- != 0) {
- printf("webcit: can't create thread: %s\n",
- strerror(errno));
- }
+ &i, sizeof(i));
+ context_loop(ssock);
}
- }
+
+ } while (!time_to_die);
+
+ pthread_exit(NULL);
}
/* $Id$ */
+
+
+
+#include <ctype.h>
#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif
#include <stdio.h>
+#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <netinet/in.h>
+#include <netdb.h>
#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
#include "webcit.h"
-#include "child.h"
+
+
+
+
+
+
struct whouser {
struct whouser *next;
char buf[256], sess, user[256], room[256], host[256];
int foundit;
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=007700><TR><TD>");
display_error(&buf[4]);
}
} else {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\" SIZE=+1 COLOR=\"FFFFFF\"<B>Confirm session termination");
whobbs();
} else {
- printf("HTTP/1.0 200 OK\n");
+ wprintf("HTTP/1.0 200 OK\n");
output_headers(1);
wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=000077><TR><TD>");
+++ /dev/null
-/* $Source$
-
- * $Revision$
- *
- * wildmat.c - simple regular expression pattern matching routines
- *
- * DESCRIPTION
- *
- * These routines provide simple UNIX style regular expression matching.
- * They were originally written by Rich Salz, the comp.sources.unix
- * moderator for inclusion in some of his software. These routines
- * were released into the public domain and used by John Gilmore in
- * USTAR.
- *
- * AUTHORS
- *
- * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- * John Gilmore (gnu@hoptoad)
- * Rich Salz (rs@uunet.uu.net)
- *
- *
- * Sponsored by The USENIX Association for public distribution.
- *
- * Copyright (c) 1989 Mark H. Colburn.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice is duplicated in all such
- * forms and that any documentation, advertising materials, and other
- * materials related to such distribution and use acknowledge that the
- * software was developed * by Mark H. Colburn and sponsored by The
- * USENIX Association.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Log$
- * Revision 1.3 1999/06/08 02:01:29 ajc
- * * Session no longer locks up when an express message is cancelled
- * * The default Citadel server is now "localhost" instead of uncnsrd
- * * Added some documentation
- *
- * Revision 1.2 1999/06/03 03:48:52 ajc
- * * Ditched the frames mode completely. It wasn't working properly in,
- * among other places, IE 5. Die, Bill, Die.
- *
- * Revision 1.1 1999/03/07 03:09:55 ajc
- * * wildmat.c, braindamage.c: added
- *
- * Revision 1.1 88/12/23 18:02:41 mark
- * Initial revision
- *
- */
-
-/* Includes */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-
-
-
-/* Function Prototypes */
-
-#ifdef __STDC__
-static int star(char *, char *);
-#else /* !__STDC__ */
-static int star();
-#endif /* __STDC__ */
-
-
-/*
- * star - handle trailing * in a regular expression
- *
- * DESCRIPTION
- *
- * Star is used to match filename expansions containing a trailing
- * asterisk ('*'). Star call wildmat() to determine if the substring
- * passed to it is matches the regular expression.
- *
- * PARAMETERS
- *
- * char *source - The source string which is to be compared to the
- * regular expression pattern.
- * char *pattern - The regular expression which we are supposed to
- * match to.
- *
- * RETURNS
- *
- * Returns non-zero if the entire source string is completely matched by
- * the regular expression pattern, returns 0 otherwise. This is used to
- * see if *'s in a pattern matched the entire source string.
- *
- */
-
-#ifdef __STDC__
-
-static int star(char *source, char *pattern)
-#else
-
-static int star(source, pattern)
-char *source; /* source operand */
-char *pattern; /* regular expression to match */
-
-#endif
-{
- while (!wildmat(source, pattern)) {
- if (*++source == '\0') {
- return (0);
- }
- }
- return (1);
-}
-
-
-/*
- * wildmat - match a regular expression
- *
- * DESCRIPTION
- *
- * Wildmat attempts to match the string pointed to by source to the
- * regular expression pointed to by pattern. The subset of regular
- * expression syntax which is supported is defined by POSIX P1003.2
- * FILENAME EXPANSION rules.
- *
- * PARAMETERS
- *
- * char *source - The source string which is to be compared to the
- * regular expression pattern.
- * char *pattern - The regular expression which we are supposed to
- * match to.
- *
- * RETURNS
- *
- * Returns non-zero if the source string matches the regular expression
- * pattern specified, returns 0 otherwise.
- *
- */
-
-#ifdef __STDC__
-
-int wildmat(char *pattern, char *source)
-#else
-
-int wildmat(pattern, source)
-char *pattern; /* regular expression to match */
-char *source; /* source operand */
-
-#endif
-{
- int last; /* last character matched */
- int matched; /* !0 if a match occurred */
- int reverse; /* !0 if sense of match is reversed */
-
- for (; *pattern; source++, pattern++) {
- switch (*pattern) {
- case '\\':
- /* Literal match with following character */
- pattern++;
- /* FALLTHRU */
- default:
- if (*source != *pattern) {
- return (0);
- }
- continue;
- case '?':
- /* Match anything. */
- if (*source == '\0') {
- return (0);
- }
- continue;
- case '*':
- /* Trailing star matches everything. */
- return (*++pattern ? star(source, pattern) : 1);
- case '[':
- /* [^....] means inverse character class. */
- if ((reverse = pattern[1]) == '^') {
- pattern++;
- }
- for (last = 0400, matched = 0;
- *++pattern && *pattern != ']'; last = *pattern) {
- /* This next line requires a good C compiler. */
- if (*pattern == '-'
- ? *source <= *++pattern && *source >= last
- : *source == *pattern) {
- matched = 1;
- }
- }
- if (matched == reverse) {
- return (0);
- }
- continue;
- }
- }
-
- /*
- * For "tar" use, matches that end at a slash also work. --hoptoad!gnu
- */
- return (*source == '\0' || *source == '/');
-}