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; /**< shold we shut down? */
extern void *context_loop(int);
extern void *housekeeping_loop(void);
extern pthread_mutex_t SessionListMutex;
extern pthread_key_t MyConKey;
+
+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 */
static const char editor_absolut_dir[PATH_MAX]=EDITORDIR; /**< nailed to what configure gives us. */
static char static_dir[PATH_MAX]; /**< calculated on startup */
+static char static_local_dir[PATH_MAX]; /**< calculated on startup */
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 */
};
-int ndirs=2; //sizeof(static_content_dirs);//sizeof(char *);
/**
* 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" /** the JS editor */
};
+int ndirs=3;
char *server_cookie = NULL; /**< our Cookie connection to the client */
char *ctdlport = DEFAULT_PORT; /**< our Port */
int setup_wizard = 0; /**< should we run the setup wizard? \todo */
char wizard_filename[PATH_MAX];/**< where's the setup wizard? */
+int running_as_daemon = 0; /**< should we deamonize on startup? */
+
/**
* \brief This is a generic function to set up a master socket for listening on
if (port_number == 0) {
lprintf(1, "Cannot start: no port number specified.\n");
- exit(1);
+ exit(WC_EXIT_BIND);
}
sin.sin_port = htons((u_short) port_number);
s = socket(PF_INET, SOCK_STREAM, (getprotobyname("tcp")->p_proto));
if (s < 0) {
lprintf(1, "Can't create a socket: %s\n", strerror(errno));
- exit(errno);
+ exit(WC_EXIT_BIND);
}
/** Set some socket options that make sense. */
i = 1;
if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
lprintf(1, "Can't bind: %s\n", strerror(errno));
- exit(errno);
+ exit(WC_EXIT_BIND);
}
if (listen(s, queue_len) < 0) {
lprintf(1, "Can't listen: %s\n", strerror(errno));
- exit(errno);
+ exit(WC_EXIT_BIND);
}
return (s);
}
if (i != 0) if (errno != ENOENT) {
lprintf(1, "citserver: can't unlink %s: %s\n",
sockpath, strerror(errno));
- exit(errno);
+ exit(WC_EXIT_BIND);
}
memset(&addr, 0, sizeof(addr));
if (s < 0) {
lprintf(1, "citserver: Can't create a socket: %s\n",
strerror(errno));
- exit(errno);
+ exit(WC_EXIT_BIND);
}
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
lprintf(1, "citserver: Can't bind: %s\n",
strerror(errno));
- exit(errno);
+ exit(WC_EXIT_BIND);
}
if (listen(s, actual_queue_len) < 0) {
lprintf(1, "citserver: Can't listen: %s\n",
strerror(errno));
- exit(errno);
+ exit(WC_EXIT_BIND);
}
chmod(sockpath, 0777);
* Strip any trailing non-printable characters.
*/
buf[i] = 0;
- while ((strlen(buf) > 0) && (!isprint(buf[strlen(buf) - 1]))) {
- buf[strlen(buf) - 1] = 0;
+ while ((i > 0) && (!isprint(buf[i - 1]))) {
+ buf[--i] = 0;
}
return (retval);
}
+/**
+ * \brief shut us down the regular way.
+ * param signum 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);
+ exit(0);
+}
+
+/**
+ * \brief shut us down the regular way.
+ * param signum the signal we want to forward
+ */
+pid_t current_child;
+void graceful_shutdown(int signum) {
+// kill(current_child, signum);
+ lprintf (1, "bye going down gracefull.");
+ time_to_die = 1;
+ exit(0);
+}
+
/**
* \brief Start running as a daemon.
*
* param do_close_stdio Only close stdio if set.
*/
-void start_daemon(int do_close_stdio)
+
+/*
+ * Start running as a daemon.
+ */
+void start_daemon(char *pid_file)
{
- if (do_close_stdio) {
- /* close(0); */
- close(1);
- close(2);
- }
+ int status = 0;
+ pid_t child = 0;
+ FILE *fp;
+ int do_restart = 0;
+
+ 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.
+ */
+ chdir("/");
+
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
- if (fork() != 0) {
+
+ child = fork();
+ if (child != 0) {
exit(0);
}
+
+ setsid();
+ umask(0);
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+ signal(SIGTERM, graceful_shutdown_watcher);
+
+ do {
+ current_child = fork();
+
+
+ if (current_child < 0) {
+ perror("fork");
+ exit(errno);
+ }
+
+ else if (current_child == 0) {
+ signal(SIGTERM, graceful_shutdown);
+ return; /* continue starting webcit. */
+ }
+
+ else {
+ signal(SIGTERM, SIG_IGN);
+ if (pid_file) {
+ fp = fopen(pid_file, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d\n", current_child);
+ 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);
+ }
+ exit(WEXITSTATUS(status));
}
/**
pthread_attr_t attr; /**< Thread attributes */
int a, i; /**< General-purpose variables */
char tracefile[PATH_MAX];
- char ip_addr[256];
+ char ip_addr[256]="0.0.0.0";
char dirbuffer[PATH_MAX]="";
int relh=0;
int home=0;
int home_specified=0;
char relhome[PATH_MAX]="";
char webcitdir[PATH_MAX] = DATADIR;
+ char *pidfile = NULL;
char *hdir;
const char *basedir;
#ifdef ENABLE_NLS
/** Parse command line */
#ifdef HAVE_OPENSSL
- while ((a = getopt(argc, argv, "h:i:p:t:x:cfs")) != EOF)
+ while ((a = getopt(argc, argv, "h:i:p:t:x:dD:cfs")) != EOF)
#else
- while ((a = getopt(argc, argv, "h:i:p:t:x:cf")) != EOF)
+ while ((a = getopt(argc, argv, "h:i:p:t:x:dD:cf")) != EOF)
#endif
switch (a) {
case 'h':
home_specified = 1;
home=1;
break;
+ case 'd':
+ running_as_daemon = 1;
+ break;
+ case 'D':
+ pidfile = strdup(optarg);
+ running_as_daemon = 1;
+ break;
case 'i':
safestrncpy(ip_addr, optarg, sizeof ip_addr);
break;
fprintf(stderr, "usage: webserver "
"[-i ip_addr] [-p http_port] "
"[-t tracefile] [-c] [-f] "
+ "[-d] "
#ifdef HAVE_OPENSSL
"[-s] "
#endif
if (++optind < argc)
ctdlport = argv[optind];
}
+
+ /* daemonize, if we were asked to */
+ if (running_as_daemon) {
+ start_daemon(pidfile);
+ }
+ else {
+ signal(SIGTERM, graceful_shutdown);
+ }
+
/** Tell 'em who's in da house */
lprintf(1, SERVER "\n");
- lprintf(1, "Copyright (C) 1996-2006 by the Citadel development team.\n"
+ lprintf(1, "Copyright (C) 1996-2007 by the Citadel development team.\n"
"This software is distributed under the terms of the "
"GNU General Public License.\n\n"
);
initialize_locales();
locale = setlocale(LC_ALL, "");
mo = malloc(strlen(webcitdir) + 20);
- lprintf(9, "Message catalog directory: %s\n", bindtextdomain("webcit", LOCALEDIR));
+ lprintf(9, "Message catalog directory: %s\n", bindtextdomain("webcit", LOCALEDIR"/locale"));
free(mo);
lprintf(9, "Text domain: %s\n", textdomain("webcit"));
lprintf(9, "Text domain Charset: %s\n", bind_textdomain_codeset("webcit","UTF8"));
(dirbuffer[0]!='\0')?"/":"");
basedir=RUNDIR;
COMPUTE_DIRECTORY(socket_dir);
- basedir=DATADIR;
+ basedir=WWWDIR "/static";
COMPUTE_DIRECTORY(static_dir);
+ basedir=WWWDIR "/static.local";
+ COMPUTE_DIRECTORY(static_local_dir);
+
+ 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) {
* exits if it doesn't succeed.
*/
- if (strlen(uds_listen_path) > 0) {
+ if (!IsEmptyStr(uds_listen_path)) {
lprintf(2, "Attempting to create listener socket at %s...\n", uds_listen_path);
msock = ig_uds_server(uds_listen_path, LISTEN_QUEUE_LENGTH);
}
{
int ssock;
int i = 0;
- int time_to_die = 0;
int fail_this_transaction = 0;
do {
} while (!time_to_die);
+ lprintf (1, "bye");
pthread_exit(NULL);
}