X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fserver_main.c;h=86cf5b0b031eb7d1c0dc2792ac9d6bda00f6336c;hb=f1ee61891901850ebbdee1e9440b363dc6df540a;hp=a2bc2b4ef5c325e72e7485148160b6628a90c082;hpb=591b04f1fcb1d91c8da29a1bee0b3182da96f9f7;p=citadel.git diff --git a/citadel/server_main.c b/citadel/server_main.c index a2bc2b4ef..86cf5b0b0 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -1,7 +1,21 @@ /* * citserver's main() function lives here. + * + * Copyright (c) 1987-2011 by the citadel.org team * - * $Id$ + * 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. + * + * 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" @@ -38,16 +52,15 @@ #include #include #include -#ifdef HAVE_PTHREAD_H -#include -#endif #ifdef HAVE_SYS_PRCTL_H #include #endif +#include #include "citadel.h" #include "server.h" #include "serv_extensions.h" #include "sysdep_decls.h" +#include "threads.h" #include "citserver.h" #include "support.h" #include "config.h" @@ -55,8 +68,10 @@ #include "database.h" #include "user_ops.h" #include "housekeeping.h" -#include "tools.h" -#include "citadel_dirs.c" +#include "svn_revision.h" +#include "citadel_dirs.h" + +#include "context.h" #include "modules_init.h" #include "ecrash.h" @@ -71,21 +86,28 @@ const char *CitadelServiceUDS="citadel-UDS"; const char *CitadelServiceTCP="citadel-TCP"; + + +void go_threading(void); + /* * Here's where it all begins. */ int main(int argc, char **argv) { char facility[32]; - int a, i; /* General-purpose variables */ + int a; /* General-purpose variables */ struct passwd pw, *pwp = NULL; char pwbuf[SIZ]; int drop_root_perms = 1; size_t size; int relh=0; int home=0; + int dbg=0; + int have_log=0; char relhome[PATH_MAX]=""; char ctdldir[PATH_MAX]=CTDLDIR; + int syslog_facility = LOG_DAEMON; #ifdef HAVE_RUN_DIR struct stat filestats; #endif @@ -93,8 +115,15 @@ int main(int argc, char **argv) eCrashParameters params; // eCrashSymbolTable symbol_table; #endif + +#ifdef HAVE_GC + GC_INIT(); + GC_find_leak = 1; +#endif + + /* initialise semaphores here. Patch by Matt and davew - * its called here as they are needed by lprintf for thread safety + * its called here as they are needed by syslog for thread safety */ InitialiseSemaphores(); @@ -107,7 +136,6 @@ int main(int argc, char **argv) if (!strncmp(argv[a], "-l", 2)) { safestrncpy(facility, &argv[a][2], sizeof(facility)); syslog_facility = SyslogFacility(facility); - enable_syslog = 1; } /* run in the background if -d was specified */ @@ -115,9 +143,9 @@ int main(int argc, char **argv) running_as_daemon = 1; } - /* -x specifies the desired logging level */ - else if (!strncmp(argv[a], "-x", 2)) { - verbosity = atoi(&argv[a][2]); + /* run a few stats if -s was specified */ + else if (!strncmp(argv[a], "-s", 2)) { + statcount = atoi(&argv[a][2]); } else if (!strncmp(argv[a], "-h", 2)) { @@ -127,16 +155,27 @@ int main(int argc, char **argv) else safestrncpy(relhome, &argv[a][2], sizeof relhome); - home_specified = 1; home=1; } + else if (!strncmp(argv[a], "-x", 2)) { + /* deprecated */ + } + else if (!strncmp(argv[a], "-t", 2)) { - freopen(&argv[a][2], "w", stderr); + if (freopen(&argv[a][2], "w", stderr) != stderr) + { + syslog(LOG_EMERG, + "unable to open your trace log [%s]: %s", + &argv[a][2], + strerror(errno)); + exit(1); + } + have_log = 1; } - else if (!strncmp(argv[a], "-f", 2)) { - do_defrag = 1; + else if (!strncmp(argv[a], "-D", 2)) { + dbg = 1; } /* -r tells the server not to drop root permissions. don't use @@ -147,18 +186,24 @@ int main(int argc, char **argv) /* any other parameter makes it crash and burn */ else { - lprintf(CTDL_EMERG, "citserver: usage: " + fprintf(stderr, "citserver: usage: " "citserver " "[-lLogFacility] " - "[-d] [-f]" - " [-tTraceFile]" - " [-xLogLevel] [-hHomeDir]\n"); + "[-d] [-D] [-s] " + "[-tTraceFile] " + "[-hHomeDir]\n" + ); exit(1); } } - calc_dirs_n_files(relh, home, relhome, ctdldir); + openlog("citserver", + ( running_as_daemon ? (LOG_PID) : (LOG_PID | LOG_PERROR) ), + syslog_facility + ); + + calc_dirs_n_files(relh, home, relhome, ctdldir, dbg); /* daemonize, if we were asked to */ if (running_as_daemon) { start_daemon(0); @@ -173,63 +218,61 @@ int main(int argc, char **argv) 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(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"); - lprintf(CTDL_NOTICE, "\n"); - lprintf(CTDL_DEBUG, "Called as: %s\n", argv[0]); + syslog(LOG_NOTICE, "\n"); + syslog(LOG_NOTICE, "\n"); + syslog(LOG_NOTICE, + "*** Citadel server engine v%d.%02d (build %s) ***\n", + (REV_LEVEL/100), (REV_LEVEL%100), svn_revision()); + syslog(LOG_NOTICE, "Copyright (C) 1987-2010 by the Citadel development team.\n"); + syslog(LOG_NOTICE, "This program is distributed under the terms of the GNU " + "General Public License.\n"); + syslog(LOG_NOTICE, "\n"); + syslog(LOG_DEBUG, "Called as: %s\n", argv[0]); + syslog(LOG_INFO, "%s\n", libcitadel_version_string()); /* Load site-specific parameters, and set the ipgm secret */ - lprintf(CTDL_INFO, "Loading citadel.config\n"); + syslog(LOG_INFO, "Loading citadel.config\n"); get_config(); config.c_ipgm_secret = rand(); - put_config(); - lprintf(CTDL_INFO, "Acquiring control record\n"); + /* get_control() MUST MUST MUST be called BEFORE the databases are opened!! */ + syslog(LOG_INFO, "Acquiring control record\n"); get_control(); + 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 HAVE_GETPWUID_R #ifdef SOLARIS_GETPWUID pwp = getpwuid_r(config.c_ctdluid, &pw, pwbuf, sizeof(pwbuf)); -#else +#else // SOLARIS_GETPWUID 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 // SOLARIS_GETPWUID +#else // HAVE_GETPWUID_R + pwp = NULL; +#endif // HAVE_GETPWUID_R + + if ((mkdir(ctdl_run_dir, 0755) != 0) && (errno != EEXIST)) + syslog(LOG_EMERG, + "unable to create run directory [%s]: %s", + ctdl_run_dir, strerror(errno)); + + if (chown(ctdl_run_dir, config.c_ctdluid, (pwp==NULL)?-1:pw.pw_gid) != 0) + syslog(LOG_EMERG, + "unable to set the access rights for [%s]: %s", + ctdl_run_dir, strerror(errno)); } @@ -243,6 +286,28 @@ int main(int argc, char **argv) */ master_startup(); + /* + * Check that the control record is correct and place sensible values if it isn't + */ + check_control(); + + /* + * Run any upgrade entry points + */ + syslog(LOG_INFO, "Upgrading modules.\n"); + upgrade_modules(); + +/** + * Load the user for the masterCC or create them if they don't exist + */ + if (CtdlGetUser(&masterCC.user, "SYS_Citadel")) + { + /** User doesn't exist. We can't use create user here as the user number needs to be 0 */ + strcpy (masterCC.user.fullname, "SYS_Citadel") ; + CtdlPutUser(&masterCC.user); + CtdlGetUser(&masterCC.user, "SYS_Citadel"); /** Just to be safe */ + } + /* * Bind the server to a Unix-domain socket. */ @@ -263,27 +328,34 @@ int main(int argc, char **argv) do_async_loop, CitadelServiceTCP); + + + /* * Load any server-side extensions available here. */ - lprintf(CTDL_INFO, "Initializing server extensions\n"); + syslog(LOG_INFO, "Initializing server extensions\n"); size = strlen(ctdl_home_directory) + 9; -/* - initialize_server_extensions(); -*/ - - initialise_modules(); + initialise_modules(0); /* * If we need host auth, start our chkpwd daemon. */ - if (config.c_auth_mode == 1) { + if (config.c_auth_mode == AUTHMODE_HOST) { start_chkpwd_daemon(); } + + /* + * check, whether we're fired up another time after a crash. + * if, post an aide message, so the admin has a chance to react. + */ + checkcrash (); + + /* * Now that we've bound the sockets, change to the Citadel user id and its * corresponding group ids @@ -291,24 +363,29 @@ int main(int argc, char **argv) if (drop_root_perms) { cdb_chmod_data(); /* make sure we own our data files */ +#ifdef HAVE_GETPWUID_R #ifdef SOLARIS_GETPWUID pwp = getpwuid_r(config.c_ctdluid, &pw, pwbuf, sizeof(pwbuf)); -#else +#else // SOLARIS_GETPWUID getpwuid_r(config.c_ctdluid, &pw, pwbuf, sizeof(pwbuf), &pwp); -#endif +#endif // SOLARIS_GETPWUID +#else // HAVE_GETPWUID_R + pwp = NULL; +#endif // HAVE_GETPWUID_R + if (pwp == NULL) - lprintf(CTDL_CRIT, "WARNING: getpwuid(%ld): %s\n" + syslog(LOG_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(CTDL_CRIT, "setgid(%ld): %s\n", (long)pw.pw_gid, + syslog(LOG_CRIT, "setgid(%ld): %s\n", (long)pw.pw_gid, strerror(errno)); } - lprintf(CTDL_INFO, "Changing uid to %ld\n", (long)CTDLUID); + syslog(LOG_INFO, "Changing uid to %ld\n", (long)CTDLUID); if (setuid(CTDLUID) != 0) { - lprintf(CTDL_CRIT, "setuid() failed: %s\n", strerror(errno)); + syslog(LOG_CRIT, "setuid() failed: %s\n", strerror(errno)); } #if defined (HAVE_SYS_PRCTL_H) && defined (PR_SET_DUMPABLE) prctl(PR_SET_DUMPABLE, 1); @@ -318,26 +395,9 @@ int main(int argc, char **argv) /* We want to check for idle sessions once per minute */ CtdlRegisterSessionHook(terminate_idle_sessions, EVT_TIMER); - /* - * Now create a bunch of worker threads. - */ - 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); - - /* 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); + go_threading(); + + + master_cleanup(exit_signal); return(0); }