AC_TYPE_SIGNAL
dnl AC_FUNC_VPRINTF
AC_REPLACE_FUNCS(snprintf)
+AC_CHECK_HEADER(CUnit/CUnit.h, [AC_DEFINE(ENABLE_TESTS, [], [whether we should compile the test-suite])])
+
AC_CHECK_HEADERS(fcntl.h limits.h sys/time.h unistd.h iconv.h xlocale.h)
dnl Checks for the zlib compression library.
CFLAGS="$CFLAGS -I $abs_builddir"
fi
AC_CONFIG_HEADER(sysdep.h)
-AC_OUTPUT(Makefile po/Makefile )
+AC_OUTPUT(Makefile po/Makefile tests/Makefile)
if test "$abs_srcdir" != "$abs_builddir"; then
ln -s $abs_srcdir/static $abs_builddir
void DeleteFloor(void *vFloor)
{
- floor *Floor;
- Floor = (floor*) vFloor;
- FreeStrBuf(&Floor->Name);
- free(Floor);
+ Floor *pFloor;
+ pFloor = (Floor*) vFloor;
+ FreeStrBuf(&pFloor->Name);
+ free(pFloor);
}
int SortFloorsByNameOrder(const void *vfloor1, const void *vfloor2)
{
- floor *f1 = (floor*) GetSearchPayload(vfloor1);
- floor *f2 = (floor*) GetSearchPayload(vfloor2);
+ Floor *f1 = (Floor*) GetSearchPayload(vfloor1);
+ Floor *f2 = (Floor*) GetSearchPayload(vfloor2);
/* prefer My floor over alpabetical sort */
if (f1->ID == VIRTUAL_MY_FLOOR)
StrBuf *Buf;
HashList *floors;
HashPos *it;
- floor *Floor;
+ Floor *pFloor;
void *vFloor;
const char *Pos;
int i;
WCC->Floors = floors = NewHash(1, Flathash);
Buf = NewStrBuf();
- Floor = malloc(sizeof(floor));
- Floor->ID = VIRTUAL_MY_FLOOR;
- Floor->Name = NewStrBufPlain(_("My Folders"), -1);
- Floor->NRooms = 0;
+ pFloor = (Floor*) malloc(sizeof(Floor));
+ pFloor->ID = VIRTUAL_MY_FLOOR;
+ pFloor->Name = NewStrBufPlain(_("My Folders"), -1);
+ pFloor->NRooms = 0;
- Put(floors, IKEY(Floor->ID), Floor, DeleteFloor);
+ Put(floors, IKEY(pFloor->ID), pFloor, DeleteFloor);
serv_puts("LFLR"); /* get floors */
StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err); /* '100', we hope */
Pos = NULL;
- Floor = malloc(sizeof(floor));
- Floor->ID = StrBufExtractNext_int(Buf, &Pos, '|');
- Floor->Name = NewStrBufPlain(NULL, StrLength(Buf));
- StrBufExtract_NextToken(Floor->Name, Buf, &Pos, '|');
- Floor->NRooms = StrBufExtractNext_long(Buf, &Pos, '|');
+ pFloor = (Floor*) malloc(sizeof(Floor));
+ pFloor->ID = StrBufExtractNext_int(Buf, &Pos, '|');
+ pFloor->Name = NewStrBufPlain(NULL, StrLength(Buf));
+ StrBufExtract_NextToken(pFloor->Name, Buf, &Pos, '|');
+ pFloor->NRooms = StrBufExtractNext_long(Buf, &Pos, '|');
- Put(floors, IKEY(Floor->ID), Floor, DeleteFloor);
+ Put(floors, IKEY(pFloor->ID), pFloor, DeleteFloor);
}
}
FreeStrBuf(&Buf);
SortByPayload(floors, SortFloorsByNameOrder);
it = GetNewHashPos(floors, 0);
while ( GetNextHashPos(floors, it, &HKLen, &HashKey, &vFloor))
- ((floor*) vFloor)->AlphaN = i++;
+ ((Floor*) vFloor)->AlphaN = i++;
DeleteHashPos(&it);
SortByHashKeyStr(floors);
void tmplput_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP)
{
- floor *Floor = (floor *)(TP->Context);
+ Floor *pFloor = (Floor *)(TP->Context);
- StrBufAppendPrintf(Target, "%d", Floor->ID);
+ StrBufAppendPrintf(Target, "%d", pFloor->ID);
}
void tmplput_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP)
{
- floor *Floor = (floor *)(TP->Context);
+ Floor *pFloor = (Floor *)(TP->Context);
- StrBufAppendTemplate(Target, TP, Floor->Name, 0);
+ StrBufAppendTemplate(Target, TP, pFloor->Name, 0);
}
void tmplput_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP)
{
- floor *Floor = (floor *)(TP->Context);
+ Floor *pFloor = (Floor *)(TP->Context);
- StrBufAppendPrintf(Target, "%d", Floor->NRooms);
+ StrBufAppendPrintf(Target, "%d", pFloor->NRooms);
}
HashList *GetRoomListHashLKRA(StrBuf *Target, WCTemplputParams *TP)
{
}
/* get a pointer to the floor we're on: */
GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
- room->Floor = (const floor*) vFloor;
+ room->Floor = (const Floor*) vFloor;
void tmplput_ROOM_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP)
{
folder *Folder = (folder *)(TP->Context);
- const floor *Floor = Folder->Floor;
+ const Floor *pFloor = Folder->Floor;
- if (Floor == NULL)
+ if (pFloor == NULL)
return;
- StrBufAppendPrintf(Target, "%d", Floor->ID);
+ StrBufAppendPrintf(Target, "%d", pFloor->ID);
}
void tmplput_ROOM_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP)
{
folder *Folder = (folder *)(TP->Context);
- const floor *Floor = Folder->Floor;
+ const Floor *pFloor = Folder->Floor;
- if (Floor == NULL)
+ if (pFloor == NULL)
return;
- StrBufAppendTemplate(Target, TP, Floor->Name, 0);
+ StrBufAppendTemplate(Target, TP, pFloor->Name, 0);
}
void tmplput_ROOM_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP)
{
folder *Folder = (folder *)(TP->Context);
- const floor *Floor = Folder->Floor;
+ const Floor *pFloor = Folder->Floor;
- if (Floor == NULL)
+ if (pFloor == NULL)
return;
- StrBufAppendPrintf(Target, "%d", Floor->NRooms);
+ StrBufAppendPrintf(Target, "%d", pFloor->NRooms);
}
}
/* get a pointer to the floor we're on: */
GetHash(WCC->Floors, IKEY(room->floorid), &vFloor);
- room->Floor = (const floor*) vFloor;
+ room->Floor = (const Floor*) vFloor;
}
StrBuf *Name;
long NRooms;
long AlphaN;
-} floor;
+} Floor;
/**
* \brief Data structure for roomlist-to-folderlist conversion
long nRoomNameParts;
StrBuf **RoomNameParts;
- const floor *Floor; /* pint to the floor we're on.. */
+ const Floor *Floor; /* pint to the floor we're on.. */
int hasnewmsgs; /* are there unread messages inside */
int is_inbox; /* is it a mailbox? */
* variants of this file or simply load it up with #ifdefs.
*
*/
-
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#ifndef HAVE_SNPRINTF
#include "snprintf.h"
#endif
-
#include "webserver.h"
+#include "modules_init.h"
+#if HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
pthread_mutex_t Critters[MAX_SEMAPHORES]; /* Things needing locking */
pthread_key_t MyConKey; /* TSD key for MyContext() */
pthread_key_t MyReq; /* TSD key for MyReq() */
+int msock; /* master listening socket */
+int time_to_die = 0; /* Nonzero if server is shutting down */
+int verbosity = 9; /* Logging level */
+
+extern void *context_loop(ParsedHttpHdrs *Hdr);
+extern void *housekeeping_loop(void);
+
+char ctdl_key_dir[PATH_MAX]=SSL_DIR;
+char file_crpt_file_key[PATH_MAX]="";
+char file_crpt_file_csr[PATH_MAX]="";
+char file_crpt_file_cer[PATH_MAX]="";
+
+const char editor_absolut_dir[PATH_MAX]=EDITORDIR; /* nailed to what configure gives us. */
+char static_dir[PATH_MAX]; /* calculated on startup */
+char static_local_dir[PATH_MAX]; /* calculated on startup */
+char static_icon_dir[PATH_MAX]; /* where should we find our mime icons? */
+char *static_dirs[]={ /* needs same sort order as the web mapping */
+ (char*)static_dir, /* our templates on disk */
+ (char*)static_local_dir, /* user provided templates disk */
+ (char*)editor_absolut_dir, /* the editor on disk */
+ (char*)static_icon_dir /* our icons... */
+};
void InitialiseSemaphores(void)
{
pthread_mutex_unlock(&Critters[which_one]);
}
+
+void ShutDownWebcit(void)
+{
+ free_zone_directory ();
+ icaltimezone_release_zone_tab ();
+ icalmemory_free_ring ();
+ ShutDownLibCitadel ();
+ shutdown_modules ();
+#ifdef HAVE_OPENSSL
+ if (is_https) {
+ shutdown_ssl();
+ }
+#endif
+}
+
+/*
+ * Entry point for worker threads
+ */
+void worker_entry(void)
+{
+ int ssock;
+ int i = 0;
+ int fail_this_transaction = 0;
+ int ret;
+ struct timeval tv;
+ fd_set readset, tempset;
+ ParsedHttpHdrs Hdr;
+
+ memset(&Hdr, 0, sizeof(ParsedHttpHdrs));
+ Hdr.HR.eReqType = eGET;
+ http_new_modules(&Hdr);
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ FD_ZERO(&readset);
+ FD_SET(msock, &readset);
+
+ do {
+ /* Only one thread can accept at a time */
+ fail_this_transaction = 0;
+ ssock = -1;
+ errno = EAGAIN;
+ do {
+ ret = -1; /* just one at once should select... */
+ begin_critical_section(S_SELECT);
+
+ FD_ZERO(&tempset);
+ if (msock > 0) FD_SET(msock, &tempset);
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ if (msock > 0) ret = select(msock+1, &tempset, NULL, NULL, &tv);
+ end_critical_section(S_SELECT);
+ if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN))
+ {/* EINTR and EAGAIN are thrown but not of interest. */
+ lprintf(2, "accept() failed:%d %s\n",
+ errno, strerror(errno));
+ }
+ else if ((ret > 0) && (msock > 0) && FD_ISSET(msock, &tempset))
+ {/* Successfully selected, and still not shutting down? Accept! */
+ ssock = accept(msock, NULL, 0);
+ }
+
+ } while ((msock > 0) && (ssock < 0) && (time_to_die == 0));
+
+ if ((msock == -1)||(time_to_die))
+ {/* ok, we're going down. */
+ int shutdown = 0;
+
+ /* the first to come here will have to do the cleanup.
+ * make shure its realy just one.
+ */
+ begin_critical_section(S_SHUTDOWN);
+ if (msock == -1)
+ {
+ msock = -2;
+ shutdown = 1;
+ }
+ end_critical_section(S_SHUTDOWN);
+ if (shutdown == 1)
+ {/* we're the one to cleanup the mess. */
+ http_destroy_modules(&Hdr);
+ lprintf(2, "I'm master shutdown: tagging sessions to be killed.\n");
+ shutdown_sessions();
+ lprintf(2, "master shutdown: waiting for others\n");
+ sleeeeeeeeeep(1); /* wait so some others might finish... */
+ lprintf(2, "master shutdown: cleaning up sessions\n");
+ do_housekeeping();
+ lprintf(2, "master shutdown: cleaning up libical\n");
+
+ ShutDownWebcit();
+
+ lprintf(2, "master shutdown exiting!.\n");
+ exit(0);
+ }
+ break;
+ }
+ if (ssock < 0 ) continue;
+
+ if (msock < 0) {
+ if (ssock > 0) close (ssock);
+ lprintf(2, "inbetween.");
+ pthread_exit(NULL);
+ } else { /* Got it? do some real work! */
+ /* Set the SO_REUSEADDR socket option */
+ i = 1;
+ setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
+ &i, sizeof(i));
+
+ /* If we are an HTTPS server, go crypto now. */
+#ifdef HAVE_OPENSSL
+ if (is_https) {
+ if (starttls(ssock) != 0) {
+ fail_this_transaction = 1;
+ close(ssock);
+ }
+ }
+ else
+#endif
+ {
+ int fdflags;
+ fdflags = fcntl(ssock, F_GETFL);
+ if (fdflags < 0)
+ lprintf(1, "unable to get server socket flags! %s \n",
+ strerror(errno));
+ fdflags = fdflags | O_NONBLOCK;
+ if (fcntl(ssock, F_SETFL, fdflags) < 0)
+ lprintf(1, "unable to set server socket nonblocking flags! %s \n",
+ strerror(errno));
+ }
+
+ if (fail_this_transaction == 0) {
+ Hdr.http_sock = ssock;
+
+ /* Perform an HTTP transaction... */
+ context_loop(&Hdr);
+
+ /* Shut down SSL/TLS if required... */
+#ifdef HAVE_OPENSSL
+ if (is_https) {
+ endtls();
+ }
+#endif
+
+ /* ...and close the socket. */
+ if (Hdr.http_sock > 0)
+ lingering_close(ssock);
+ http_detach_modules(&Hdr);
+
+ }
+
+ }
+
+ } while (!time_to_die);
+
+ http_destroy_modules(&Hdr);
+ lprintf (1, "bye\n");
+ pthread_exit(NULL);
+}
+
+/*
+ * print log messages
+ * logs to stderr if loglevel is lower than the verbosity set at startup
+ *
+ * loglevel level of the message
+ * format the printf like format string
+ * ... the strings to put into format
+ */
+int lprintf(int loglevel, const char *format, ...)
+{
+ va_list ap;
+
+ if (loglevel <= verbosity) {
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fflush(stderr);
+ }
+ return 1;
+}
+
+/*
+ * Shut us down the regular way.
+ * signum is the signal we want to forward
+ */
+pid_t current_child;
+void graceful_shutdown_watcher(int signum) {
+ lprintf (1, "bye; shutting down watcher.");
+ kill(current_child, signum);
+ if (signum != SIGHUP)
+ exit(0);
+}
+
+
+
+
+/*
+ * Shut us down the regular way.
+ * signum is the signal we want to forward
+ */
+pid_t current_child;
+void graceful_shutdown(int signum) {
+ FILE *FD;
+ int fd;
+
+ lprintf (1, "WebCit is being shut down on signal %d.\n", signum);
+ fd = msock;
+ msock = -1;
+ time_to_die = 1;
+ FD=fdopen(fd, "a+");
+ fflush (FD);
+ fclose (FD);
+ close(fd);
+}
+
+
+/*
+ * Start running as a daemon.
+ */
+void start_daemon(char *pid_file)
+{
+ int status = 0;
+ pid_t child = 0;
+ FILE *fp;
+ int do_restart = 0;
+ int rv;
+ FILE *rvfp = NULL;
+
+ current_child = 0;
+
+ /* Close stdin/stdout/stderr and replace them with /dev/null.
+ * We don't just call close() because we don't want these fd's
+ * to be reused for other files.
+ */
+ rv = chdir("/");
+
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+
+ child = fork();
+ if (child != 0) {
+ exit(0);
+ }
+
+ setsid();
+ umask(0);
+ rvfp = freopen("/dev/null", "r", stdin);
+ rvfp = freopen("/dev/null", "w", stdout);
+ rvfp = freopen("/dev/null", "w", stderr);
+ signal(SIGTERM, graceful_shutdown_watcher);
+ signal(SIGHUP, graceful_shutdown_watcher);
+
+ do {
+ current_child = fork();
+
+
+ if (current_child < 0) {
+ perror("fork");
+ ShutDownLibCitadel ();
+ exit(errno);
+ }
+
+ else if (current_child == 0) { /* child process */
+ signal(SIGHUP, graceful_shutdown);
+
+ return; /* continue starting webcit. */
+ }
+ else { /* watcher process */
+ if (pid_file) {
+ fp = fopen(pid_file, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d\n", getpid());
+ fclose(fp);
+ }
+ }
+ waitpid(current_child, &status, 0);
+ }
+
+ do_restart = 0;
+
+ /* Did the main process exit with an actual exit code? */
+ if (WIFEXITED(status)) {
+
+ /* Exit code 0 means the watcher should exit */
+ if (WEXITSTATUS(status) == 0) {
+ do_restart = 0;
+ }
+
+ /* Exit code 101-109 means the watcher should exit */
+ else if ( (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109) ) {
+ do_restart = 0;
+ }
+
+ /* Any other exit code means we should restart. */
+ else {
+ do_restart = 1;
+ }
+ }
+
+ /* Any other type of termination (signals, etc.) should also restart. */
+ else {
+ do_restart = 1;
+ }
+
+ } while (do_restart);
+
+ if (pid_file) {
+ unlink(pid_file);
+ }
+ ShutDownLibCitadel ();
+ exit(WEXITSTATUS(status));
+}
+
+/*
+ * Spawn an additional worker thread into the pool.
+ */
+void spawn_another_worker_thread()
+{
+ pthread_t SessThread; /* Thread descriptor */
+ pthread_attr_t attr; /* Thread attributes */
+ int ret;
+
+ lprintf(3, "Creating a new thread. Pool size is now %d\n", ++num_threads);
+
+ /* set attributes for the new thread */
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ /*
+ * Our per-thread stacks need to be bigger than the default size,
+ * otherwise the MIME parser crashes on FreeBSD.
+ */
+ if ((ret = pthread_attr_setstacksize(&attr, 1024 * 1024))) {
+ lprintf(1, "pthread_attr_setstacksize: %s\n",
+ strerror(ret));
+ pthread_attr_destroy(&attr);
+ }
+
+ /* now create the thread */
+ if (pthread_create(&SessThread, &attr,
+ (void *(*)(void *)) worker_entry, NULL)
+ != 0) {
+ lprintf(1, "Can't create thread: %s\n", strerror(errno));
+ }
+
+ /* free up the attributes */
+ pthread_attr_destroy(&attr);
+}
+
+
+void
+webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdir, char *relhome)
+{
+ char dirbuffer[PATH_MAX]="";
+ /* calculate all our path on a central place */
+ /* where to keep our config */
+
+#define COMPUTE_DIRECTORY(SUBDIR) memcpy(dirbuffer,SUBDIR, sizeof dirbuffer);\
+ snprintf(SUBDIR,sizeof SUBDIR, "%s%s%s%s%s%s%s", \
+ (home&!relh)?webcitdir:basedir, \
+ ((basedir!=webcitdir)&(home&!relh))?basedir:"/", \
+ ((basedir!=webcitdir)&(home&!relh))?"/":"", \
+ relhome, \
+ (relhome[0]!='\0')?"/":"",\
+ dirbuffer,\
+ (dirbuffer[0]!='\0')?"/":"");
+ basedir=RUNDIR;
+ COMPUTE_DIRECTORY(socket_dir);
+ basedir=WWWDIR "/static";
+ COMPUTE_DIRECTORY(static_dir);
+ basedir=WWWDIR "/static/icons";
+ COMPUTE_DIRECTORY(static_icon_dir);
+ basedir=WWWDIR "/static.local";
+ COMPUTE_DIRECTORY(static_local_dir);
+ StripSlashes(static_dir, 1);
+ StripSlashes(static_icon_dir, 1);
+ StripSlashes(static_local_dir, 1);
+
+ snprintf(file_crpt_file_key,
+ sizeof file_crpt_file_key,
+ "%s/citadel.key",
+ ctdl_key_dir);
+ snprintf(file_crpt_file_csr,
+ sizeof file_crpt_file_csr,
+ "%s/citadel.csr",
+ ctdl_key_dir);
+ snprintf(file_crpt_file_cer,
+ sizeof file_crpt_file_cer,
+ "%s/citadel.cer",
+ ctdl_key_dir);
+
+ /* we should go somewhere we can leave our coredump, if enabled... */
+ lprintf(9, "Changing directory to %s\n", socket_dir);
+ if (chdir(webcitdir) != 0) {
+ perror("chdir");
+ }
+}
void drop_root(uid_t UID)
{
struct passwd pw, *pwp = NULL;
#endif
}
}
+
+
+/*
+ * print the actual stack frame.
+ */
+void wc_backtrace(void)
+{
+#ifdef HAVE_BACKTRACE
+ void *stack_frames[50];
+ size_t size, i;
+ char **strings;
+
+
+ size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
+ strings = backtrace_symbols(stack_frames, size);
+ for (i = 0; i < size; i++) {
+ if (strings != NULL)
+ lprintf(1, "%s\n", strings[i]);
+ else
+ lprintf(1, "%p\n", stack_frames[i]);
+ }
+ free(strings);
+#endif
+}
--- /dev/null
+# $Id: Makefile.in 7860 2009-10-05 20:25:07Z dothebart $
+
+prefix=@prefix@
+srcdir=@srcdir@/../
+VPATH=$(srcdir)
+
+AUTOCONF=@AUTOCONF@
+CC=@CC@
+CFLAGS=@CFLAGS@
+DEFS=@DEFS@
+INSTALL=@INSTALL@
+LIBOBJS=@LIBOBJS@
+LIBS=@LIBS@ -lcunit
+LDFLAGS=@LDFLAGS@
+SED=@SED@
+SETUP_LIBS=@SETUP_LIBS@
+PTHREAD_DEFS=@PTHREAD_DEFS@
+LIB_SUBDIRS=
+PROG_SUBDIRS=@PROG_SUBDIRS@
+SUBDIRS=$(LIB_SUBDIRS) $(PROG_SUBDIRS)
+LOCALEDIR=@LOCALEDIR@
+WWWDIR=@WWWDIR@
+
+TEST_OBJECTS= \
+ ../webcit.o \
+ ../context_loop.o \
+ ../modules_init.o \
+ \
+ ../cookie_conversion.o \
+ \
+ ../locate_host.o \
+ ../sysdep.o \
+ ../utils.o \
+ ../decode.o \
+ ../html2html.o \
+ ../http_datestring.o \
+ ../fmt_date.o \
+ \
+ ../subst.o \
+ ../preferences.o \
+ ../paramhandling.o \
+ ../serv_func.o \
+ ../tcp_sockets.o \
+ ../crypto.o \
+ ../gettext.o \
+ ../tabs.o \
+ \
+ ../netconf.o \
+ ../inetconf.o \
+ ../siteconfig.o \
+ ../smtpqueue.o \
+ ../pushemail.o \
+ ../sieve.o \
+ \
+ ../static.o \
+ ../graphics.o \
+ ../downloads.o \
+ \
+ ../auth.o \
+ ../openid.o \
+ ../who.o \
+ ../userlist.o \
+ ../useredit.o \
+ ../sysmsgs.o \
+ \
+ ../listsub.o \
+ \
+ ../setup_wizard.o \
+ ../summary.o \
+ ../mainmenu.o \
+ ../iconbar.o \
+ \
+ ../floors.o \
+ ../roomops.o \
+ ../roomlist.o \
+ ../marchlist.o \
+ \
+ ../messages.o \
+ ../msg_renderers.o \
+ ../bbsview_renderer.o \
+ ../wiki.o \
+ \
+ ../paging.o \
+ \
+ ../vcard_edit.o \
+ ../addressbook_popup.o \
+ ../autocompletion.o \
+ \
+ ../ical_maps.o \
+ ../ical_subst.o \
+ ../ical_dezonify.o \
+ ../calendar.o \
+ ../calendar_tools.o \
+ ../calendar_view.o \
+ ../tasks.o \
+ ../event.o \
+ ../availability.o \
+ ../notes.o \
+ \
+ ../groupdav_main.o \
+ ../groupdav_get.o \
+ ../groupdav_propfind.o \
+ ../groupdav_options.o \
+ ../groupdav_delete.o \
+ ../groupdav_put.o
+
+TEST_COMMON_OBJECTS = \
+ test_tools.o
+
+# End of configuration section
+
+all: test
+
+.SUFFIXES: .cpp .c .o
+
+clean:
+ rm -f $(WEBCIT_OBJECTS)
+
+
+test: $(TEST_OBJECTS) $(TEST_COMMON_OBJECTS) $(LIBOBJS) test_main.o
+ $(CC) $(LDFLAGS) -o test $(LIBOBJS) test_main.o \
+ $(TEST_OBJECTS) $(TEST_COMMON_OBJECTS) $(LIBS)
+
+.c.o:
+ $(CC) $(CFLAGS) -I ../ $(DEFS) -c $(PTHREAD_DEFS) $<
+
+.cpp.o:
+ $(CC) $(CFLAGS) -I ../ $(DEFS) -c $(PTHREAD_DEFS) $<
+
+Makefile: $(srcdir)/Makefile.in $(srcdir)/config.status
+ CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) $(srcdir)/config.status
+
+config.status: $(srcdir)/configure
+ $(SHELL) $(srcdir)/config.status --recheck
+
+$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/aclocal.m4
+ cd $(srcdir) && $(AUTOCONF)
+
+$(srcdir)/aclocal.m4: $(srcdir)/acinclude.m4
+ cd $(srcdir) && $(ACLOCAL)
--- /dev/null
+/*
+ * $Id: webserver.c 7847 2009-10-03 17:57:14Z dothebart $
+ *
+ * This contains a simple multithreaded TCP server manager. It sits around
+ * waiting on the specified port for incoming HTTP connections. When a
+ * connection is established, it calls context_loop() from context_loop.c.
+ *
+ * Copyright (c) 1996-2009 by the citadel.org developers.
+ * This program is released under the terms of the GNU General Public License v3.
+ *
+ */
+
+#include "../webcit.h"
+#include "../webserver.h"
+#include "../modules_init.h"
+
+
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+
+CU_EXPORT void CU_automated_run_tests(void);
+CU_EXPORT CU_ErrorCode CU_list_tests_to_file(void);
+CU_EXPORT void CU_set_output_filename(const char* szFilenameRoot);
+
+extern int msock; /* master listening socket */
+extern int verbosity; /* Logging level */
+extern char static_icon_dir[PATH_MAX]; /* where should we find our mime icons */
+
+int is_https = 0; /* Nonzero if I am an HTTPS service */
+int follow_xff = 0; /* Follow X-Forwarded-For: header */
+int home_specified = 0; /* did the user specify a homedir? */
+int DisableGzip = 0;
+extern pthread_mutex_t SessionListMutex;
+extern pthread_key_t MyConKey;
+
+extern void run_tests(void);
+extern int ig_tcp_server(char *ip_addr, int port_number, int queue_len);
+extern int ig_uds_server(char *sockpath, int queue_len);
+extern void webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdir, char *relhome);
+
+
+char socket_dir[PATH_MAX]; /* where to talk to our citadel server */
+
+char *server_cookie = NULL; /* our Cookie connection to the client */
+int http_port = PORT_NUM; /* Port to listen on */
+char *ctdlhost = DEFAULT_HOST; /* our name */
+char *ctdlport = DEFAULT_PORT; /* our Port */
+int running_as_daemon = 0; /* should we deamonize on startup? */
+char wizard_filename[PATH_MAX];
+
+StrBuf *Username = NULL; /* the test user... */
+StrBuf *Passvoid = NULL; /* the test user... */
+
+
+extern int dbg_analyze_msg;
+extern int dbg_bactrace_template_errors;
+extern int DumpTemplateI18NStrings;
+extern StrBuf *I18nDump;
+void InitTemplateCache(void);
+extern int LoadTemplates;
+
+
+
+/*
+ * Here's where it all begins.
+ */
+int main(int argc, char **argv)
+{
+ size_t basesize = 2; /* how big should strbufs be on creation? */
+ pthread_attr_t attr; /* Thread attributes */
+ int a; /* General-purpose variables */
+ char tracefile[PATH_MAX];
+ char ip_addr[256]="0.0.0.0";
+ int relh=0;
+ int home=0;
+ int home_specified=0;
+ char relhome[PATH_MAX]="";
+ char webcitdir[PATH_MAX] = DATADIR;
+ char *hdir;
+ const char *basedir = NULL;
+ char uds_listen_path[PATH_MAX]; /* listen on a unix domain socket? */
+ FILE *rvfp = NULL;
+
+ WildFireInitBacktrace(argv[0], 2);
+
+ start_modules ();
+
+ /* Ensure that we are linked to the correct version of libcitadel */
+ if (libcitadel_version_number() < LIBCITADEL_VERSION_NUMBER) {
+ fprintf(stderr, " You are running libcitadel version %d.%02d\n",
+ (libcitadel_version_number() / 100), (libcitadel_version_number() % 100));
+ fprintf(stderr, "WebCit was compiled against version %d.%02d\n",
+ (LIBCITADEL_VERSION_NUMBER / 100), (LIBCITADEL_VERSION_NUMBER % 100));
+ return(1);
+ }
+
+ strcpy(uds_listen_path, "");
+
+ /* Parse command line */
+ while ((a = getopt(argc, argv, "h:i:p:t:T:B:x:U:P:cf:Z")) != EOF)
+ switch (a) {
+ case 'U':
+ Username = NewStrBufPlain(optarg, -1);
+ break;
+ case 'P':
+ Passvoid = NewStrBufPlain(optarg, -1);
+ break;
+ case 'h':
+ hdir = strdup(optarg);
+ relh=hdir[0]!='/';
+ if (!relh) {
+ safestrncpy(webcitdir, hdir, sizeof webcitdir);
+ }
+ else {
+ safestrncpy(relhome, relhome, sizeof relhome);
+ }
+ /* free(hdir); TODO: SHOULD WE DO THIS? */
+ home_specified = 1;
+ home=1;
+ break;
+ case 'B': /* Basesize */
+ basesize = atoi(optarg);
+ if (basesize > 2)
+ StartLibCitadel(basesize);
+ break;
+ case 'i':
+ safestrncpy(ip_addr, optarg, sizeof ip_addr);
+ break;
+ case 'p':
+ http_port = atoi(optarg);
+ if (http_port == 0) {
+ safestrncpy(uds_listen_path, optarg, sizeof uds_listen_path);
+ }
+ break;
+ case 't':
+ safestrncpy(tracefile, optarg, sizeof tracefile);
+ rvfp = freopen(tracefile, "w", stdout);
+ rvfp = freopen(tracefile, "w", stderr);
+ rvfp = freopen(tracefile, "r", stdin);
+ break;
+ case 'T':
+ LoadTemplates = atoi(optarg);
+ dbg_analyze_msg = (LoadTemplates && (1<<1)) != 0;
+ dbg_bactrace_template_errors = (LoadTemplates && (1<<2)) != 0;
+ break;
+ case 'Z':
+ DisableGzip = 1;
+ break;
+ case 'x':
+ verbosity = atoi(optarg);
+ break;
+ case 'f':
+ follow_xff = 1;
+ break;
+ case 'c':
+ server_cookie = malloc(256);
+ if (server_cookie != NULL) {
+ safestrncpy(server_cookie,
+ "Set-cookie: wcserver=",
+ 256);
+ if (gethostname
+ (&server_cookie[strlen(server_cookie)],
+ 200) != 0) {
+ lprintf(2, "gethostname: %s\n",
+ strerror(errno));
+ free(server_cookie);
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "usage: webcit "
+ "[-i ip_addr] [-p http_port] "
+ "[-t tracefile] [-c] [-f] "
+ "[-T Templatedebuglevel] "
+ "[-Z] [-G i18ndumpfile] "
+#ifdef HAVE_OPENSSL
+ "[-s] [-S cipher_suites]"
+#endif
+ "[-U Username -P Password]"
+ ""
+ "[remotehost [remoteport]]\n");
+ return 1;
+ }
+
+ if (optind < argc) {
+ ctdlhost = argv[optind];
+ if (++optind < argc)
+ ctdlport = argv[optind];
+ }
+
+ webcit_calc_dirs_n_files(relh, basedir, home, webcitdir, relhome);
+ LoadIconDir(static_icon_dir);
+
+ /* Tell 'em who's in da house */
+ lprintf(1, PACKAGE_STRING "\n");
+ lprintf(1, "Copyright (C) 1996-2009 by the Citadel development team.\n"
+ "This software is distributed under the terms of the "
+ "GNU General Public License.\n\n"
+ );
+
+
+ /* initialize the International Bright Young Thing */
+
+ initialise_modules();
+ initialize_viewdefs();
+ initialize_axdefs();
+
+ InitTemplateCache();
+
+ /* Use our own prefix on tzid's generated from system tzdata */
+ icaltimezone_set_tzid_prefix("/citadel.org/");
+
+ /*
+ * 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) {
+ lprintf(1, "Can't create TSD key: %s\n", strerror(errno));
+ }
+ InitialiseSemaphores ();
+
+
+ /*
+ * Start up the housekeeping thread
+ */
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ run_tests();
+
+ ShutDownWebcit();
+ FreeStrBuf(&Username);
+ FreeStrBuf(&Passvoid);
+
+ return 0;
+}
+
+
--- /dev/null
+#include <CUnit/CUnit.h>
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+
+#include "webcit.h"
+#include "webserver.h"
+#include "modules_init.h"
+#include <stdio.h>
+
+
+wcsession *TestSessionList = NULL;
+
+
+ParsedHttpHdrs Hdr;
+wcsession *TheSession;
+
+extern StrBuf *Username;
+extern StrBuf *Passvoid;
+
+
+extern int ReadHttpSubject(ParsedHttpHdrs *Hdr, StrBuf *Line, StrBuf *Buf);
+extern wcsession *CreateSession(int Lockable, wcsession **wclist, ParsedHttpHdrs *Hdr, pthread_mutex_t *ListMutex);
+
+
+
+void SetUpContext(void)
+{
+ memset(&Hdr, 0, sizeof(ParsedHttpHdrs));
+ Hdr.HR.eReqType = eGET;
+ http_new_modules(&Hdr);
+
+
+ Hdr.http_sock = 1; /* STDOUT */
+/* Context loop */
+ Hdr.HR.dav_depth = 32767; /* TODO: find a general way to have non-0 defaults */
+ TheSession = CreateSession(1, &TestSessionList, &Hdr, NULL);
+ TheSession->lastreq = time(NULL); /* log */
+ TheSession->Hdr = &Hdr;
+ Hdr.HTTPHeaders = NewHash(1, NULL);
+ session_attach_modules(TheSession);
+}
+
+int SetUpConnection(void)
+{
+ StrBuf *Response;
+ if (!GetConnected ())
+ {
+ Response = NewStrBuf();
+ become_logged_in(Username, Passvoid, Response);
+ return 1;
+
+ }
+ else {
+ CU_FAIL("Establishing session failed!");
+ return 0;
+ }
+}
+
+void SetHttpURL(ParsedHttpHdrs *Hdr, const char *Title, long tlen, StrBuf *Buf)
+{
+ StrBuf *Line = NewStrBufPlain (Title, tlen);
+ FreeStrBuf(&Line);
+}
+
+/* from context_loop.c: */
+extern void DestroyHttpHeaderHandler(void *V);
+extern int ReadHttpSubject(ParsedHttpHdrs *Hdr, StrBuf *Line, StrBuf *Buf);
+void SetUpRequest(const char *UrlPath)
+{
+ OneHttpHeader *pHdr;
+ wcsession *WCC = WC;
+ StrBuf *Buf;
+ StrBuf *Line, *HeaderName;
+
+ HeaderName = NewStrBuf();
+ Buf = NewStrBuf();
+ Line = NewStrBuf();
+ StrBufPrintf(Line, "GET %s HTTP/1.0\r\n", UrlPath);
+
+ WCC->Hdr->HTTPHeaders = NewHash(1, NULL);
+ pHdr = (OneHttpHeader*) malloc(sizeof(OneHttpHeader));
+ memset(pHdr, 0, sizeof(OneHttpHeader));
+ pHdr->Val = Line;
+ Put(Hdr.HTTPHeaders, HKEY("GET /"), pHdr, DestroyHttpHeaderHandler);
+ lprintf(9, "%s\n", ChrPtr(Line));
+
+ if (ReadHttpSubject(&Hdr, Line, HeaderName))
+ CU_FAIL("Failed to parse Request line / me is bogus!");
+
+ FreeStrBuf(&Buf);
+}
+
+
+
+void TearDownRequest(void)
+{
+/* End Context loop */
+ http_detach_modules(&Hdr);
+}
+
+void TearDownContext(void)
+{
+ http_destroy_modules(&Hdr);
+/* End Session Loop */
+ session_detach_modules(TheSession);
+ session_destroy_modules(&TheSession);
+
+/* End Session loop */
+/* now shut it down clean. */
+// shutdown_sessions();
+ do_housekeeping();
+}
+
+void test_worker_entry(StrBuf *UrlPath)
+{
+
+
+}
+
+
+void SetGroupdavHeaders(int DavDepth)
+{
+ Hdr.HR.dav_depth = DavDepth;
+}
+
+void FlushHeaders(void)
+{
+
+}
+
+void test_groupdav_directorycommands(void)
+{
+ SetUpContext();
+ if (SetUpConnection())
+ {
+ SetUpRequest("/");
+ SetGroupdavHeaders(0);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/");
+ SetGroupdavHeaders(1);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+
+ SetUpRequest("/groupdav");
+ SetGroupdavHeaders(0);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav");
+ SetGroupdavHeaders(1);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/");
+ SetGroupdavHeaders(0);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/");
+ SetGroupdavHeaders(1);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+
+ SetUpRequest("/groupdav/My%20Folders");
+ SetGroupdavHeaders(0);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/My%20Folders");
+ SetGroupdavHeaders(1);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/My%20Folders/");
+ SetGroupdavHeaders(0);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/My%20Folders/");
+ SetGroupdavHeaders(1);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/My%20Folders/Calendar");
+ SetGroupdavHeaders(0);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/My%20Folders/Calendar");
+ SetGroupdavHeaders(1);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/My%20Folders/Calendar/");
+ SetGroupdavHeaders(0);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/groupdav/My%20Folders/Calendar/");
+ SetGroupdavHeaders(1);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+
+ SetUpRequest("/");
+ SetGroupdavHeaders(0);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+
+ SetUpRequest("/");
+ SetGroupdavHeaders(1);
+ groupdav_main();
+ FlushHeaders();
+ TearDownRequest();
+ }
+
+
+ TearDownContext();
+}
+
+extern void httplang_to_locale(StrBuf *LocaleString, wcsession *sess);
+
+static void test_gettext(const char *str, long len)
+{
+ StrBuf *Test = NewStrBufPlain(str, len);
+
+ SetUpContext();
+ httplang_to_locale(Test, TheSession);
+ TearDownContext();
+
+ FreeStrBuf(&Test);
+}
+
+void test_gettext_headerevaluation_Opera(void)
+{
+ test_gettext(HKEY("sq;q=1.0,de;q=0.9,as;q=0.8,ar;q=0.7,bn;q=0.6,zh-cn;q=0.5,kn;q=0.4,ch;q=0.3,fo;q=0.2,gn;q=0.1,ce;q=0.1,ie;q=0.1"));
+}
+
+void test_gettext_headerevaluation_firefox1(void)
+{
+ test_gettext(HKEY("de-de,en-us;q=0.7,en;q=0.3"));
+}
+
+void test_gettext_headerevaluation_firefox2(void)
+{
+ test_gettext(HKEY("de,en-ph;q=0.8,en-us;q=0.5,de-at;q=0.3"));
+}
+
+void test_gettext_headerevaluation_firefox3(void)
+{
+ test_gettext(HKEY("de,en-us;q=0.9,it;q=0.9,de-de;q=0.8,en-ph;q=0.7,de-at;q=0.7,zh-cn;q=0.6,cy;q=0.5,ar-om;q=0.5,en-tt;q=0.4,xh;q=0.3,nl-be;q=0.3,cs;q=0.2,sv;q=0.1,tk;q=0.1"));
+}
+
+void test_gettext_headerevaluation_ie7(void)
+{
+// ie7????
+// User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; FunWebProducts; FBSMTWB; GTB6.3; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; Seekmo 10.3.86.0)
+
+ test_gettext(HKEY("en-us,x-ns1MvoLpRxbNhu,x-ns2F0f0NnyPOPN"));
+}
+
+static void AddTests(void)
+{
+ CU_pSuite pGroup = NULL;
+ CU_pTest pTest = NULL;
+/*
+ pGroup = CU_add_suite("TestLocaleEvaluator", NULL, NULL);
+ pTest = CU_add_test(pGroup, "Test ie7", test_gettext_headerevaluation_ie7);
+ pTest = CU_add_test(pGroup, "Test Opera", test_gettext_headerevaluation_Opera);
+ pTest = CU_add_test(pGroup, "Test firefox1", test_gettext_headerevaluation_firefox1);
+ pTest = CU_add_test(pGroup, "Test firefox2", test_gettext_headerevaluation_firefox2);
+ pTest = CU_add_test(pGroup, "Test firefox3", test_gettext_headerevaluation_firefox3);
+*/
+ pGroup = CU_add_suite("TestUrlPatterns", NULL, NULL);
+ pTest = CU_add_test(pGroup, "Test", test_groupdav_directorycommands);
+
+
+}
+
+
+
+
+
+
+
+void run_tests(void)
+{
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ CU_set_output_filename("TestAutomated");
+ if (CU_initialize_registry()) {
+ printf("\nInitialize of test Registry failed.");
+ }
+
+ AddTests();
+
+ printf("\nTests completed with return value %d.\n", CU_basic_run_tests());
+ CU_cleanup_registry();
+
+}
if (Floors != NULL)
{
if (GetHash(Floors, SKEY(pFloor), &vFloor))
- WCC->CurrentFloor = (floor*) vFloor;
+ WCC->CurrentFloor = (Floor*) vFloor;
}
}
}
char ImportantMessage[SIZ];
StrBuf *ImportantMsg;
HashList *Directory; /* Parts of the directory URL in snippets */
- const floor *CurrentFloor; /**< when Parsing REST, which floor are we on? */
+ const Floor *CurrentFloor; /**< when Parsing REST, which floor are we on? */
/* accounting */
StrBuf *wc_username; /* login name of current user */
#include "webcit.h"
#include "webserver.h"
-#if HAVE_BACKTRACE
-#include <execinfo.h>
-#endif
#include "modules_init.h"
#ifndef HAVE_SNPRINTF
int vsnprintf(char *buf, size_t max, const char *fmt, va_list argp);
#endif
-int verbosity = 9; /* Logging level */
-int msock; /* master listening socket */
+
+extern int msock; /* master listening socket */
+extern int verbosity; /* Logging level */
+extern char static_icon_dir[PATH_MAX]; /* where should we find our mime icons */
+
int is_https = 0; /* Nonzero if I am an HTTPS service */
int follow_xff = 0; /* Follow X-Forwarded-For: header */
int home_specified = 0; /* did the user specify a homedir? */
-int time_to_die = 0; /* Nonzero if server is shutting down */
int DisableGzip = 0;
-extern void *context_loop(ParsedHttpHdrs *Hdr);
-extern void *housekeeping_loop(void);
extern pthread_mutex_t SessionListMutex;
extern pthread_key_t MyConKey;
+extern void *housekeeping_loop(void);
extern int ig_tcp_server(char *ip_addr, int port_number, int queue_len);
extern int ig_uds_server(char *sockpath, int queue_len);
+extern void graceful_shutdown_watcher(int signum);
+extern void graceful_shutdown(int signum);
+extern void start_daemon(char *pid_file);
+extern void webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdir, char *relhome);
extern void drop_root(uid_t UID);
-char ctdl_key_dir[PATH_MAX]=SSL_DIR;
-char file_crpt_file_key[PATH_MAX]="";
-char file_crpt_file_csr[PATH_MAX]="";
-char file_crpt_file_cer[PATH_MAX]="";
-
char socket_dir[PATH_MAX]; /* where to talk to our citadel server */
-const char editor_absolut_dir[PATH_MAX]=EDITORDIR; /* nailed to what configure gives us. */
-char static_dir[PATH_MAX]; /* calculated on startup */
-char static_local_dir[PATH_MAX]; /* calculated on startup */
-char static_icon_dir[PATH_MAX]; /* where should we find our mime icons? */
-char *static_dirs[]={ /* needs same sort order as the web mapping */
- (char*)static_dir, /* our templates on disk */
- (char*)static_local_dir, /* user provided templates disk */
- (char*)editor_absolut_dir, /* the editor on disk */
- (char*)static_icon_dir /* our icons... */
-};
-
-/*
- * Subdirectories from which the client may request static content
- *
- * (If you add more, remember to increment 'ndirs' below)
- */
-char *static_content_dirs[] = {
- "static", /* static templates */
- "static.local", /* site local static templates */
- "tiny_mce" /* rich text editor */
-};
-
-int ndirs=3;
-
char *server_cookie = NULL; /* our Cookie connection to the client */
int http_port = PORT_NUM; /* Port to listen on */
-/*
- * Shut us down the regular way.
- * signum is the signal we want to forward
- */
-pid_t current_child;
-void graceful_shutdown_watcher(int signum) {
- lprintf (1, "bye; shutting down watcher.");
- kill(current_child, signum);
- if (signum != SIGHUP)
- exit(0);
-}
-
-
-
-
-/*
- * Shut us down the regular way.
- * signum is the signal we want to forward
- */
-pid_t current_child;
-void graceful_shutdown(int signum) {
- FILE *FD;
- int fd;
-
- lprintf (1, "WebCit is being shut down on signal %d.\n", signum);
- fd = msock;
- msock = -1;
- time_to_die = 1;
- FD=fdopen(fd, "a+");
- fflush (FD);
- fclose (FD);
- close(fd);
-}
-
-
-/*
- * Start running as a daemon.
- */
-void start_daemon(char *pid_file)
-{
- int status = 0;
- pid_t child = 0;
- FILE *fp;
- int do_restart = 0;
- int rv;
- FILE *rvfp = NULL;
-
- current_child = 0;
-
- /* Close stdin/stdout/stderr and replace them with /dev/null.
- * We don't just call close() because we don't want these fd's
- * to be reused for other files.
- */
- rv = chdir("/");
-
- signal(SIGHUP, SIG_IGN);
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
-
- child = fork();
- if (child != 0) {
- exit(0);
- }
-
- setsid();
- umask(0);
- rvfp = freopen("/dev/null", "r", stdin);
- rvfp = freopen("/dev/null", "w", stdout);
- rvfp = freopen("/dev/null", "w", stderr);
- signal(SIGTERM, graceful_shutdown_watcher);
- signal(SIGHUP, graceful_shutdown_watcher);
-
- do {
- current_child = fork();
-
-
- if (current_child < 0) {
- perror("fork");
- ShutDownLibCitadel ();
- exit(errno);
- }
-
- else if (current_child == 0) { /* child process */
- signal(SIGHUP, graceful_shutdown);
-
- return; /* continue starting webcit. */
- }
- else { /* watcher process */
- if (pid_file) {
- fp = fopen(pid_file, "w");
- if (fp != NULL) {
- fprintf(fp, "%d\n", getpid());
- fclose(fp);
- }
- }
- waitpid(current_child, &status, 0);
- }
-
- do_restart = 0;
-
- /* Did the main process exit with an actual exit code? */
- if (WIFEXITED(status)) {
-
- /* Exit code 0 means the watcher should exit */
- if (WEXITSTATUS(status) == 0) {
- do_restart = 0;
- }
-
- /* Exit code 101-109 means the watcher should exit */
- else if ( (WEXITSTATUS(status) >= 101) && (WEXITSTATUS(status) <= 109) ) {
- do_restart = 0;
- }
-
- /* Any other exit code means we should restart. */
- else {
- do_restart = 1;
- }
- }
-
- /* Any other type of termination (signals, etc.) should also restart. */
- else {
- do_restart = 1;
- }
-
- } while (do_restart);
-
- if (pid_file) {
- unlink(pid_file);
- }
- ShutDownLibCitadel ();
- exit(WEXITSTATUS(status));
-}
-
-/*
- * Spawn an additional worker thread into the pool.
- */
-void spawn_another_worker_thread()
-{
- pthread_t SessThread; /* Thread descriptor */
- pthread_attr_t attr; /* Thread attributes */
- int ret;
-
- lprintf(3, "Creating a new thread. Pool size is now %d\n", ++num_threads);
-
- /* set attributes for the new thread */
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- /*
- * Our per-thread stacks need to be bigger than the default size,
- * otherwise the MIME parser crashes on FreeBSD.
- */
- if ((ret = pthread_attr_setstacksize(&attr, 1024 * 1024))) {
- lprintf(1, "pthread_attr_setstacksize: %s\n",
- strerror(ret));
- pthread_attr_destroy(&attr);
- }
-
- /* now create the thread */
- if (pthread_create(&SessThread, &attr,
- (void *(*)(void *)) worker_entry, NULL)
- != 0) {
- lprintf(1, "Can't create thread: %s\n", strerror(errno));
- }
-
- /* free up the attributes */
- pthread_attr_destroy(&attr);
-}
-
/* #define DBG_PRINNT_HOOKS_AT_START */
#ifdef DBG_PRINNT_HOOKS_AT_START
+extern HashList *HandlerHash;
const char foobuf[32];
const char *nix(void *vptr) {snprintf(foobuf, 32, "%0x", (long) vptr); return foobuf;}
#endif
void InitTemplateCache(void);
extern int LoadTemplates;
-extern HashList *HandlerHash;
-void
-webcit_calc_dirs_n_files(int relh, const char *basedir, int home, char *webcitdir, char *relhome)
-{
- char dirbuffer[PATH_MAX]="";
- /* calculate all our path on a central place */
- /* where to keep our config */
-
-#define COMPUTE_DIRECTORY(SUBDIR) memcpy(dirbuffer,SUBDIR, sizeof dirbuffer);\
- snprintf(SUBDIR,sizeof SUBDIR, "%s%s%s%s%s%s%s", \
- (home&!relh)?webcitdir:basedir, \
- ((basedir!=webcitdir)&(home&!relh))?basedir:"/", \
- ((basedir!=webcitdir)&(home&!relh))?"/":"", \
- relhome, \
- (relhome[0]!='\0')?"/":"",\
- dirbuffer,\
- (dirbuffer[0]!='\0')?"/":"");
- basedir=RUNDIR;
- COMPUTE_DIRECTORY(socket_dir);
- basedir=WWWDIR "/static";
- COMPUTE_DIRECTORY(static_dir);
- basedir=WWWDIR "/static/icons";
- COMPUTE_DIRECTORY(static_icon_dir);
- basedir=WWWDIR "/static.local";
- COMPUTE_DIRECTORY(static_local_dir);
- StripSlashes(static_dir, 1);
- StripSlashes(static_icon_dir, 1);
- StripSlashes(static_local_dir, 1);
-
- snprintf(file_crpt_file_key,
- sizeof file_crpt_file_key,
- "%s/citadel.key",
- ctdl_key_dir);
- snprintf(file_crpt_file_csr,
- sizeof file_crpt_file_csr,
- "%s/citadel.csr",
- ctdl_key_dir);
- snprintf(file_crpt_file_cer,
- sizeof file_crpt_file_cer,
- "%s/citadel.cer",
- ctdl_key_dir);
-
- /* we should go somewhere we can leave our coredump, if enabled... */
- lprintf(9, "Changing directory to %s\n", socket_dir);
- if (chdir(webcitdir) != 0) {
- perror("chdir");
- }
-}
/*
* Here's where it all begins.
*/
}
-void ShutDownWebcit(void)
-{
- free_zone_directory ();
- icaltimezone_release_zone_tab ();
- icalmemory_free_ring ();
- ShutDownLibCitadel ();
- shutdown_modules ();
-#ifdef HAVE_OPENSSL
- if (is_https) {
- shutdown_ssl();
- }
-#endif
-}
-
-/*
- * Entry point for worker threads
- */
-void worker_entry(void)
-{
- int ssock;
- int i = 0;
- int fail_this_transaction = 0;
- int ret;
- struct timeval tv;
- fd_set readset, tempset;
- ParsedHttpHdrs Hdr;
-
- memset(&Hdr, 0, sizeof(ParsedHttpHdrs));
- Hdr.HR.eReqType = eGET;
- http_new_modules(&Hdr);
- tv.tv_sec = 0;
- tv.tv_usec = 10000;
- FD_ZERO(&readset);
- FD_SET(msock, &readset);
-
- do {
- /* Only one thread can accept at a time */
- fail_this_transaction = 0;
- ssock = -1;
- errno = EAGAIN;
- do {
- ret = -1; /* just one at once should select... */
- begin_critical_section(S_SELECT);
-
- FD_ZERO(&tempset);
- if (msock > 0) FD_SET(msock, &tempset);
- tv.tv_sec = 0;
- tv.tv_usec = 10000;
- if (msock > 0) ret = select(msock+1, &tempset, NULL, NULL, &tv);
- end_critical_section(S_SELECT);
- if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN))
- {/* EINTR and EAGAIN are thrown but not of interest. */
- lprintf(2, "accept() failed:%d %s\n",
- errno, strerror(errno));
- }
- else if ((ret > 0) && (msock > 0) && FD_ISSET(msock, &tempset))
- {/* Successfully selected, and still not shutting down? Accept! */
- ssock = accept(msock, NULL, 0);
- }
-
- } while ((msock > 0) && (ssock < 0) && (time_to_die == 0));
-
- if ((msock == -1)||(time_to_die))
- {/* ok, we're going down. */
- int shutdown = 0;
-
- /* the first to come here will have to do the cleanup.
- * make shure its realy just one.
- */
- begin_critical_section(S_SHUTDOWN);
- if (msock == -1)
- {
- msock = -2;
- shutdown = 1;
- }
- end_critical_section(S_SHUTDOWN);
- if (shutdown == 1)
- {/* we're the one to cleanup the mess. */
- http_destroy_modules(&Hdr);
- lprintf(2, "I'm master shutdown: tagging sessions to be killed.\n");
- shutdown_sessions();
- lprintf(2, "master shutdown: waiting for others\n");
- sleeeeeeeeeep(1); /* wait so some others might finish... */
- lprintf(2, "master shutdown: cleaning up sessions\n");
- do_housekeeping();
- lprintf(2, "master shutdown: cleaning up libical\n");
-
- ShutDownWebcit();
-
- lprintf(2, "master shutdown exiting!.\n");
- exit(0);
- }
- break;
- }
- if (ssock < 0 ) continue;
-
- if (msock < 0) {
- if (ssock > 0) close (ssock);
- lprintf(2, "inbetween.");
- pthread_exit(NULL);
- } else { /* Got it? do some real work! */
- /* Set the SO_REUSEADDR socket option */
- i = 1;
- setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR,
- &i, sizeof(i));
-
- /* If we are an HTTPS server, go crypto now. */
-#ifdef HAVE_OPENSSL
- if (is_https) {
- if (starttls(ssock) != 0) {
- fail_this_transaction = 1;
- close(ssock);
- }
- }
- else
-#endif
- {
- int fdflags;
- fdflags = fcntl(ssock, F_GETFL);
- if (fdflags < 0)
- lprintf(1, "unable to get server socket flags! %s \n",
- strerror(errno));
- fdflags = fdflags | O_NONBLOCK;
- if (fcntl(ssock, F_SETFL, fdflags) < 0)
- lprintf(1, "unable to set server socket nonblocking flags! %s \n",
- strerror(errno));
- }
-
- if (fail_this_transaction == 0) {
- Hdr.http_sock = ssock;
-
- /* Perform an HTTP transaction... */
- context_loop(&Hdr);
-
- /* Shut down SSL/TLS if required... */
-#ifdef HAVE_OPENSSL
- if (is_https) {
- endtls();
- }
-#endif
-
- /* ...and close the socket. */
- if (Hdr.http_sock > 0)
- lingering_close(ssock);
- http_detach_modules(&Hdr);
-
- }
-
- }
-
- } while (!time_to_die);
-
- http_destroy_modules(&Hdr);
- lprintf (1, "bye\n");
- pthread_exit(NULL);
-}
-
-/*
- * print log messages
- * logs to stderr if loglevel is lower than the verbosity set at startup
- *
- * loglevel level of the message
- * format the printf like format string
- * ... the strings to put into format
- */
-int lprintf(int loglevel, const char *format, ...)
-{
- va_list ap;
-
- if (loglevel <= verbosity) {
- va_start(ap, format);
- vfprintf(stderr, format, ap);
- va_end(ap);
- fflush(stderr);
- }
- return 1;
-}
-
-/*
- * print the actual stack frame.
- */
-void wc_backtrace(void)
-{
-#ifdef HAVE_BACKTRACE
- void *stack_frames[50];
- size_t size, i;
- char **strings;
-
-
- size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
- strings = backtrace_symbols(stack_frames, size);
- for (i = 0; i < size; i++) {
- if (strings != NULL)
- lprintf(1, "%s\n", strings[i]);
- else
- lprintf(1, "%p\n", stack_frames[i]);
- }
- free(strings);
-#endif
-}
/* $Id$ */
extern char *static_dirs[PATH_MAX]; /**< Web representation */
-extern char *static_content_dirs[PATH_MAX]; /**< Disk representation */
extern int ndirs;
extern char socket_dir[PATH_MAX];