X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fserver_main.c;h=f13a77361275d59f30c74137d8a239049fdf9a3f;hb=b2e29e3d33f3eda3a3eb3f7be959cf841a393fb0;hp=4a7206ec2a1a8c7be7dbcce3af86da121d998317;hpb=1f677e979d4817890c3a33961273456bebb5bf1b;p=citadel.git diff --git a/citadel/server_main.c b/citadel/server_main.c index 4a7206ec2..f13a77361 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -15,6 +15,7 @@ #include #include #include +#include #if TIME_WITH_SYS_TIME # include @@ -35,11 +36,14 @@ #include #include #include -#include #include +#include #ifdef HAVE_PTHREAD_H #include #endif +#ifdef HAVE_SYS_PRCTL_H +#include +#endif #include "citadel.h" #include "server.h" #include "serv_extensions.h" @@ -47,9 +51,15 @@ #include "citserver.h" #include "support.h" #include "config.h" +#include "control.h" #include "database.h" +#include "user_ops.h" #include "housekeeping.h" #include "tools.h" +#include "citadel_dirs.c" + +#include "modules_init.h" +#include "ecrash.h" #ifdef HAVE_SYS_SELECT_H #include @@ -58,41 +68,51 @@ #ifndef HAVE_SNPRINTF #include "snprintf.h" #endif +const char *CitadelServiceUDS="citadel-UDS"; +const char *CitadelServiceTCP="citadel-TCP"; /* * Here's where it all begins. */ int main(int argc, char **argv) { - char tracefile[128]; /* Name of file to log traces to */ + char facility[32]; int a, i; /* General-purpose variables */ - struct passwd *pw; + struct passwd pw, *pwp = NULL; + char pwbuf[SIZ]; int drop_root_perms = 1; - struct worker_node *wnp; size_t size; - - /* specify default port name and trace file */ - strcpy(tracefile, ""); - + int relh=0; + int home=0; + char relhome[PATH_MAX]=""; + char ctdldir[PATH_MAX]=CTDLDIR; +#ifdef HAVE_RUN_DIR + struct stat filestats; +#endif +#ifdef HAVE_BACKTRACE + eCrashParameters params; +// eCrashSymbolTable symbol_table; +#endif + /* initialise semaphores here. Patch by Matt and davew + * its called here as they are needed by lprintf for thread safety + */ + InitialiseSemaphores(); + /* initialize the master context */ InitializeMasterCC(); /* parse command-line arguments */ for (a=1; a 0) ? 0 : 1 ) ; + running_as_daemon = 1; } /* -x specifies the desired logging level */ @@ -101,9 +121,18 @@ int main(int argc, char **argv) } else if (!strncmp(argv[a], "-h", 2)) { - safestrncpy(bbs_home_directory, &argv[a][2], - sizeof bbs_home_directory); + relh=argv[a][2]!='/'; + if (!relh) safestrncpy(ctdl_home_directory, &argv[a][2], + sizeof ctdl_home_directory); + else + safestrncpy(relhome, &argv[a][2], + sizeof relhome); home_specified = 1; + home=1; + } + + else if (!strncmp(argv[a], "-t", 2)) { + freopen(&argv[a][2], "w", stderr); } else if (!strncmp(argv[a], "-f", 2)) { @@ -118,46 +147,111 @@ int main(int argc, char **argv) /* any other parameter makes it crash and burn */ else { - lprintf(1, "citserver: usage: " - "citserver [-tTraceFile] [-d] [-f]" + lprintf(CTDL_EMERG, "citserver: usage: " + "citserver " + "[-lLogFacility] " + "[-d] [-f]" + " [-tTraceFile]" " [-xLogLevel] [-hHomeDir]\n"); exit(1); } } + calc_dirs_n_files(relh, home, relhome, ctdldir); + /* daemonize, if we were asked to */ + if (running_as_daemon) { + start_daemon(0); + drop_root_perms = 1; + } + +#ifdef HAVE_BACKTRACE + bzero(¶ms, sizeof(params)); + params.filename = file_pid_paniclog; + panic_fd=open(file_pid_paniclog, O_APPEND|O_CREAT|O_DIRECT); + params.filep = fopen(file_pid_paniclog, "a+"); + params.debugLevel = ECRASH_DEBUG_VERBOSE; + params.dumpAllThreads = TRUE; + params.useBacktraceSymbols = 1; +/// BuildSymbolTable(&symbol_table); +// params.symbolTable = &symbol_table; + params.signals[0]=SIGSEGV; + params.signals[1]=SIGILL; + params.signals[2]=SIGBUS; + params.signals[3]=SIGABRT; + + eCrash_Init(¶ms); + + eCrash_RegisterThread("MasterThread", 0); + +/// signal(SIGSEGV, cit_panic_backtrace); +#endif + /* Initialize the syslogger. Yes, we are really using 0 as the + * facility, because we are going to bitwise-OR the facility to + * the severity of each message, allowing us to write to other + * facilities when we need to... + */ + if (enable_syslog) { + openlog("citadel", LOG_NDELAY, 0); + setlogmask(LOG_UPTO(verbosity)); + } + /* Tell 'em who's in da house */ - lprintf(1, - "\n*** Citadel/UX messaging server engine v%d.%02d ***\n" - "Copyright (C) 1987-2003 by the Citadel/UX development team.\n" + lprintf(CTDL_NOTICE, "\n"); + lprintf(CTDL_NOTICE, "\n"); + lprintf(CTDL_NOTICE, + "*** Citadel server engine v%d.%02d ***\n", + (REV_LEVEL/100), (REV_LEVEL%100)); + lprintf(CTDL_NOTICE, + "Copyright (C) 1987-2007 by the Citadel development team.\n"); + lprintf(CTDL_NOTICE, "This program is distributed under the terms of the GNU " - "General Public License.\n\n", - (REV_LEVEL/100), - (REV_LEVEL%100) - ); - - /* Initialize... */ - init_sysdep(); - openlog("citserver", LOG_PID, LOG_USER); + "General Public License.\n"); + lprintf(CTDL_NOTICE, "\n"); + lprintf(CTDL_DEBUG, "Called as: %s\n", argv[0]); /* Load site-specific parameters, and set the ipgm secret */ - lprintf(7, "Loading citadel.config\n"); + lprintf(CTDL_INFO, "Loading citadel.config\n"); get_config(); config.c_ipgm_secret = rand(); put_config(); +#ifdef HAVE_RUN_DIR + /* on some dists rundir gets purged on startup. so we need to recreate it. */ + + if (stat(ctdl_run_dir, &filestats)==-1){ +#ifdef SOLARIS_GETPWUID + pwp = getpwuid_r(config.c_ctdluid, &pw, pwbuf, sizeof(pwbuf)); +#else + getpwuid_r(config.c_ctdluid, &pw, pwbuf, sizeof(pwbuf), &pwp); +#endif + mkdir(ctdl_run_dir, 0755); + chown(ctdl_run_dir, config.c_ctdluid, (pwp==NULL)?-1:pw.pw_gid); + } + + +#endif + + /* Initialize... */ + init_sysdep(); + /* * Do non system dependent startup functions. */ master_startup(); + lprintf(CTDL_INFO, "Acquiring control record\n"); + get_control(); + /* * Bind the server to a Unix-domain socket. */ CtdlRegisterServiceHook(0, - "citadel.socket", + file_citadel_socket, citproto_begin_session, - do_command_loop); + do_command_loop, + do_async_loop, + CitadelServiceUDS); /* * Bind the server to our favorite TCP port (usually 504). @@ -165,47 +259,60 @@ int main(int argc, char **argv) CtdlRegisterServiceHook(config.c_port_number, NULL, citproto_begin_session, - do_command_loop); + do_command_loop, + do_async_loop, + CitadelServiceTCP); /* * Load any server-side extensions available here. */ - lprintf(7, "Initializing server extensions\n"); - size = strlen(bbs_home_directory) + 9; + lprintf(CTDL_INFO, "Initializing server extensions\n"); + size = strlen(ctdl_home_directory) + 9; + +/* initialize_server_extensions(); +*/ + + initialise_modules(); + + /* - * The rescan pipe exists so that worker threads can be woken up and - * told to re-scan the context list for fd's to listen on. This is - * necessary, for example, when a context is about to go idle and needs - * to get back on that list. + * If we need host auth, start our chkpwd daemon. */ - if (pipe(rescan)) { - lprintf(1, "Can't create rescan pipe!\n"); - exit(errno); + if (config.c_auth_mode == 1) { + start_chkpwd_daemon(); } - init_master_fdset(); - /* - * Now that we've bound the sockets, change to the BBS user id and its + * Now that we've bound the sockets, change to the Citadel user id and its * corresponding group ids */ if (drop_root_perms) { - if ((pw = getpwuid(BBSUID)) == NULL) - lprintf(1, "WARNING: getpwuid(%ld): %s\n" - "Group IDs will be incorrect.\n", (long)BBSUID, + cdb_chmod_data(); /* make sure we own our data files */ + +#ifdef SOLARIS_GETPWUID + pwp = getpwuid_r(config.c_ctdluid, &pw, pwbuf, sizeof(pwbuf)); +#else + getpwuid_r(config.c_ctdluid, &pw, pwbuf, sizeof(pwbuf), &pwp); +#endif + if (pwp == NULL) + lprintf(CTDL_CRIT, "WARNING: getpwuid(%ld): %s\n" + "Group IDs will be incorrect.\n", (long)CTDLUID, strerror(errno)); else { - initgroups(pw->pw_name, pw->pw_gid); - if (setgid(pw->pw_gid)) - lprintf(3, "setgid(%ld): %s\n", (long)pw->pw_gid, + initgroups(pw.pw_name, pw.pw_gid); + if (setgid(pw.pw_gid)) + lprintf(CTDL_CRIT, "setgid(%ld): %s\n", (long)pw.pw_gid, strerror(errno)); } - lprintf(7, "Changing uid to %ld\n", (long)BBSUID); - if (setuid(BBSUID) != 0) { - lprintf(3, "setuid() failed: %s\n", strerror(errno)); + lprintf(CTDL_INFO, "Changing uid to %ld\n", (long)CTDLUID); + if (setuid(CTDLUID) != 0) { + lprintf(CTDL_CRIT, "setuid() failed: %s\n", strerror(errno)); } +#if defined (HAVE_SYS_PRCTL_H) && defined (PR_SET_DUMPABLE) + prctl(PR_SET_DUMPABLE, 1); +#endif } /* We want to check for idle sessions once per minute */ @@ -214,35 +321,23 @@ int main(int argc, char **argv) /* * Now create a bunch of worker threads. */ - lprintf(9, "Starting %d worker threads\n", config.c_min_workers-1); + lprintf(CTDL_DEBUG, "Starting %d worker threads\n", + config.c_min_workers-1); begin_critical_section(S_WORKER_LIST); for (i=0; i<(config.c_min_workers-1); ++i) { create_worker(); } end_critical_section(S_WORKER_LIST); - /* Now this thread can become a worker as well. */ - initial_thread = pthread_self(); - worker_thread(NULL); - - /* Server is exiting. Wait for workers to shutdown. */ - lprintf(7, "Waiting for worker threads to shut down\n"); - - begin_critical_section(S_WORKER_LIST); - while (worker_list != NULL) { - wnp = worker_list; - worker_list = wnp->next; - - /* avoid deadlock with an exiting thread */ - end_critical_section(S_WORKER_LIST); - if ((i = pthread_join(wnp->tid, NULL))) - lprintf(1, "pthread_join: %s\n", strerror(i)); - phree(wnp); - begin_critical_section(S_WORKER_LIST); - } - end_critical_section(S_WORKER_LIST); - - master_cleanup(); + /* Create the maintenance threads. */ + create_maintenance_threads(); + /* This thread is now useless. It can't be turned into a worker + * thread because its stack is too small, but it can't be killed + * either because the whole server process would exit. So we just + * join to the first worker thread and exit when it exits. + */ + pthread_join(worker_list->tid, NULL); + master_cleanup(0); return(0); }