/*
* WebCit "system dependent" code.
*
- * Copyright (c) 1996-2011 by the citadel.org team
+ * Copyright (c) 1996-2012 by the citadel.org team
*
* This program is open source software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
+ * it under the terms of the GNU General Public License, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "sysdep.h"
#include <sys/socket.h>
#include <syslog.h>
#include <sys/syslog.h>
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
+#include <time.h>
#include <limits.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <sys/select.h>
#endif
-#ifndef HAVE_SNPRINTF
-#include "snprintf.h"
-#endif
#include "webserver.h"
#include "modules_init.h"
#if HAVE_BACKTRACE
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);
+extern void do_housekeeping(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]="";
+char file_etc_mimelist[PATH_MAX]="";
-const char editor_absolut_dir[PATH_MAX]=EDITORDIR; /* nailed to what configure gives us. */
+char etc_dir[PATH_MAX];
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... */
+ "./static",
+ "./static.local",
+ "./tiny_mce",
+ "./static/webcit_icons"
};
+int ExitPipe[2];
+HashList *GZMimeBlackList = NULL; /* mimetypes which shouldn't be gzip compressed */
+
+void LoadMimeBlacklist(void)
+{
+ StrBuf *MimeBlackLine;
+ IOBuffer IOB;
+ eReadState state;
+
+ memset(&IOB, 0, sizeof(IOBuffer));
+ IOB.fd = open(file_etc_mimelist, O_RDONLY);
+
+ IOB.Buf = NewStrBuf();
+ MimeBlackLine = NewStrBuf();
+ GZMimeBlackList = NewHash(1, NULL);
+
+ do
+ {
+ state = StrBufChunkSipLine(MimeBlackLine, &IOB);
+
+ switch (state)
+ {
+ case eMustReadMore:
+ if (StrBuf_read_one_chunk_callback(IOB.fd, 0, &IOB) <= 0)
+ state = eReadFail;
+ break;
+ case eReadSuccess:
+ if ((StrLength(MimeBlackLine) > 1) &&
+ (*ChrPtr(MimeBlackLine) != '#'))
+ {
+ Put(GZMimeBlackList, SKEY(MimeBlackLine),
+ (void*) 1, reference_free_handler);
+ }
+ FlushStrBuf(MimeBlackLine);
+ break;
+ case eReadFail:
+ break;
+ case eBufferNotEmpty:
+ break;
+ }
+ }
+ while (state != eReadFail);
+
+ close(IOB.fd);
+
+ FreeStrBuf(&IOB.Buf);
+ FreeStrBuf(&MimeBlackLine);
+}
+
+void CheckGZipCompressionAllowed(const char *MimeType, long MLen)
+{
+ void *v;
+ wcsession *WCC = WC;
+
+ if (WCC->Hdr->HR.gzip_ok)
+ WCC->Hdr->HR.gzip_ok = GetHash(GZMimeBlackList, MimeType, MLen, &v) == 0;
+}
+
void InitialiseSemaphores(void)
{
int i;
for (i=0; i<MAX_SEMAPHORES; ++i) {
pthread_mutex_init(&Critters[i], NULL);
}
+
+ if (pipe(ExitPipe))
+ {
+ syslog(LOG_WARNING, "Failed to open exit pipe: %d [%s]\n",
+ errno,
+ strerror(errno));
+
+ exit(-1);
+ }
}
/*
void ShutDownWebcit(void)
{
+
+ DeleteHash(&GZMimeBlackList);
free_zone_directory ();
icaltimezone_release_zone_tab ();
icalmemory_free_ring ();
ssock = -1;
errno = EAGAIN;
do {
+ fd_set wset;
--num_threads_executing;
+ FD_ZERO(&wset);
+ FD_SET(msock, &wset);
+ FD_SET(ExitPipe[1], &wset);
+
+ select(msock + 1, NULL, &wset, NULL, NULL);
+ if (time_to_die)
+ break;
+
ssock = accept(msock, NULL, 0);
++num_threads_executing;
if (ssock < 0) fail_this_transaction = 1;
if (shutdown == 1)
{/* we're the one to cleanup the mess. */
http_destroy_modules(&Hdr);
- syslog(2, "I'm master shutdown: tagging sessions to be killed.\n");
+ syslog(LOG_DEBUG, "I'm master shutdown: tagging sessions to be killed.\n");
shutdown_sessions();
- syslog(2, "master shutdown: waiting for others\n");
+ syslog(LOG_DEBUG, "master shutdown: waiting for others\n");
sleeeeeeeeeep(1); /* wait so some others might finish... */
- syslog(2, "master shutdown: cleaning up sessions\n");
+ syslog(LOG_DEBUG, "master shutdown: cleaning up sessions\n");
do_housekeeping();
- syslog(2, "master shutdown: cleaning up libical\n");
+ syslog(LOG_DEBUG, "master shutdown: cleaning up libical\n");
ShutDownWebcit();
- syslog(2, "master shutdown exiting.\n");
+ syslog(LOG_DEBUG, "master shutdown exiting.\n");
exit(0);
}
break;
/* Now do something. */
if (msock < 0) {
if (ssock > 0) close (ssock);
- syslog(2, "in between.");
+ syslog(LOG_DEBUG, "in between.");
pthread_exit(NULL);
} else {
/* Got it? do some real work! */
int fdflags;
fdflags = fcntl(ssock, F_GETFL);
if (fdflags < 0)
- syslog(1, "unable to get server socket flags! %s \n",
+ syslog(LOG_WARNING, "unable to get server socket flags! %s \n",
strerror(errno));
fdflags = fdflags | O_NONBLOCK;
if (fcntl(ssock, F_SETFL, fdflags) < 0)
- syslog(1, "unable to set server socket nonblocking flags! %s \n",
+ syslog(LOG_WARNING, "unable to set server socket nonblocking flags! %s \n",
strerror(errno));
}
} while (!time_to_die);
http_destroy_modules(&Hdr);
- syslog(1, "Thread exiting.\n");
+ syslog(LOG_DEBUG, "Thread exiting.\n");
pthread_exit(NULL);
}
*/
pid_t current_child;
void graceful_shutdown_watcher(int signum) {
- syslog(1, "Watcher thread exiting.\n");
+ syslog(LOG_INFO, "Watcher thread exiting.\n");
+ write(ExitPipe[0], HKEY(" "));
kill(current_child, signum);
if (signum != SIGHUP)
exit(0);
FILE *FD;
int fd;
- syslog(1, "WebCit is being shut down on signal %d.\n", signum);
+ syslog(LOG_INFO, "WebCit is being shut down on signal %d.\n", signum);
fd = msock;
msock = -1;
time_to_die = 1;
fflush (FD);
fclose (FD);
close(fd);
+ write(ExitPipe[0], HKEY(" "));
}
pid_t child = 0;
FILE *fp;
int do_restart = 0;
- int rv;
- FILE *rvfp = NULL;
current_child = 0;
* We don't just call close() because we don't want these fd's
* to be reused for other files.
*/
- rv = chdir("/");
+ chdir("/");
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
setsid();
umask(0);
- rvfp = freopen("/dev/null", "r", stdin);
- rvfp = freopen("/dev/null", "w", stdout);
- rvfp = freopen("/dev/null", "w", stderr);
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
signal(SIGTERM, graceful_shutdown_watcher);
signal(SIGHUP, graceful_shutdown_watcher);
* otherwise the MIME parser crashes on FreeBSD.
*/
if ((ret = pthread_attr_setstacksize(&attr, 1024 * 1024))) {
- syslog(1, "pthread_attr_setstacksize: %s\n", strerror(ret));
+ syslog(LOG_WARNING, "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) {
- syslog(1, "Can't create thread: %s\n", strerror(errno));
+ syslog(LOG_WARNING, "Can't create thread: %s\n", strerror(errno));
}
/* free up the attributes */
"%s/citadel.cer",
ctdl_key_dir);
+
+ basedir=ETCDIR;
+ COMPUTE_DIRECTORY(etc_dir);
+ StripSlashes(etc_dir, 1);
+ snprintf(file_etc_mimelist,
+ sizeof file_etc_mimelist,
+ "%s/nogz-mimetypes.txt",
+ etc_dir);
+
/* we should go somewhere we can leave our coredump, if enabled... */
- syslog(9, "Changing directory to %s\n", socket_dir);
+ syslog(LOG_INFO, "Changing directory to %s\n", socket_dir);
if (chdir(webcitdir) != 0) {
perror("chdir");
}
void drop_root(uid_t UID)
{
struct passwd pw, *pwp = NULL;
+#ifdef HAVE_GETPWUID_R
+ char pwbuf[SIZ];
+#endif
/*
* Now that we've bound the sockets, change to the Citadel user id and its
#ifdef HAVE_GETPWUID_R
#ifdef SOLARIS_GETPWUID
pwp = getpwuid_r(UID, &pw, pwbuf, sizeof(pwbuf));
-#else // SOLARIS_GETPWUID
+#else /* SOLARIS_GETPWUID */
getpwuid_r(UID, &pw, pwbuf, sizeof(pwbuf), &pwp);
-#endif // SOLARIS_GETPWUID
-#else // HAVE_GETPWUID_R
+#endif /* SOLARIS_GETPWUID */
+#else /* HAVE_GETPWUID_R */
pwp = NULL;
-#endif // HAVE_GETPWUID_R
+#endif /* HAVE_GETPWUID_R */
if (pwp == NULL)
- syslog(LOG_CRIT, "WARNING: getpwuid(%ld): %s\n"
+ syslog(LOG_CRIT, "WARNING: getpwuid(%d): %s\n"
"Group IDs will be incorrect.\n", UID,
strerror(errno));
else {
/*
* print the actual stack frame.
*/
-void wc_backtrace(void)
+void wc_backtrace(long LogLevel)
{
#ifdef HAVE_BACKTRACE
void *stack_frames[50];
strings = backtrace_symbols(stack_frames, size);
for (i = 0; i < size; i++) {
if (strings != NULL)
- syslog(1, "%s\n", strings[i]);
+ syslog(LogLevel, "%s\n", strings[i]);
else
- syslog(1, "%p\n", stack_frames[i]);
+ syslog(LogLevel, "%p\n", stack_frames[i]);
}
free(strings);
#endif