X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fserver_main.c;h=9dad4d756ae51602d73882e8ec15acb9752bee5e;hb=b826c3117bb7ddf1386a4811cb2eb47ea4e1097c;hp=3e94a8ab124fa6e66d38fb3f37bd58434f1105c9;hpb=7395c7c662ad7e40a99aef8937e8f90d9e9a729a;p=citadel.git diff --git a/citadel/server_main.c b/citadel/server_main.c index 3e94a8ab1..9dad4d756 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -1,7 +1,7 @@ /* * citserver's main() function lives here. * - * Copyright (c) 1987-2018 by the citadel.org team + * Copyright (c) 1987-2021 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 version 3. @@ -19,7 +19,6 @@ #include #include #include - #include "citserver.h" #include "svn_revision.h" #include "modules_init.h" @@ -32,18 +31,18 @@ uid_t ctdluid = 0; const char *CitadelServiceUDS="citadel-UDS"; const char *CitadelServiceTCP="citadel-TCP"; -void go_threading(void); int sanity_diag_mode = 0; /* * Create or remove a lock file, so we only have one Citadel Server running at a time. + * Set 'op' to nonzero to lock, zero to unlock. */ -void ctdl_lockfile(int yo) { - static char lockfilename[SIZ]; +void ctdl_lockfile(int op) { + static char lockfilename[PATH_MAX]; static FILE *fp; - if (yo) { + if (op) { syslog(LOG_DEBUG, "main: creating lockfile"); snprintf(lockfilename, sizeof lockfilename, "%s/citadel.lock", ctdl_run_dir); fp = fopen(lockfilename, "w"); @@ -68,20 +67,15 @@ void ctdl_lockfile(int yo) { /* * Here's where it all begins. */ -int main(int argc, char **argv) -{ - size_t basesize = 64; +int main(int argc, char **argv) { + char facility[32]; int a; /* General-purpose variables */ struct passwd pw, *pwp = NULL; char pwbuf[SIZ]; int drop_root_perms = 1; - int relh=0; - int home=0; - int dbg=0; int max_log_level = LOG_INFO; - char relhome[PATH_MAX]=""; - char ctdldir[PATH_MAX]=CTDLDIR; + char *ctdldir = CTDLDIR; int syslog_facility = LOG_DAEMON; uid_t u = 0; struct passwd *p = NULL; @@ -89,56 +83,72 @@ int main(int argc, char **argv) struct stat filestats; #endif - /* initialize the master context */ - InitializeMasterCC(); - InitializeMasterTSD(); + /* Tell 'em who's in da house */ + syslog(LOG_INFO, " "); + syslog(LOG_INFO, " "); + syslog(LOG_INFO, "*** Citadel server engine ***\n"); + syslog(LOG_INFO, "Version %d (build %s) ***", REV_LEVEL, svn_revision()); + syslog(LOG_INFO, "Copyright (C) 1987-2021 by the Citadel development team."); + syslog(LOG_INFO, " "); + syslog(LOG_INFO, "This program is open source software: you can redistribute it and/or"); + syslog(LOG_INFO, "modify it under the terms of the GNU General Public License, version 3."); + syslog(LOG_INFO, " "); + syslog(LOG_INFO, "This program is distributed in the hope that it will be useful,"); + syslog(LOG_INFO, "but WITHOUT ANY WARRANTY; without even the implied warranty of"); + syslog(LOG_INFO, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"); + syslog(LOG_INFO, "GNU General Public License for more details."); + syslog(LOG_INFO, " "); + syslog(LOG_INFO, "%s", libcitadel_version_string()); /* parse command-line arguments */ - while ((a=getopt(argc, argv, "l:dh:x:t:B:Dru:s:")) != EOF) switch(a) { + while ((a=getopt(argc, argv, "cl:dh:x:t:B:Dru:s:")) != EOF) switch(a) { + + // test this binary for compatibility and exit + case 'c': + fprintf(stderr, "%s: binary compatibility confirmed\n", argv[0]); + exit(0); + break; + // identify the desired syslog facility case 'l': safestrncpy(facility, optarg, sizeof(facility)); syslog_facility = SyslogFacility(facility); break; - /* run in the background if -d was specified */ + // run in the background if -d was specified case 'd': running_as_daemon = 1; break; + // specify the data directory case 'h': - relh = optarg[0] != '/'; - if (!relh) { - safestrncpy(ctdl_home_directory, optarg, sizeof ctdl_home_directory); - } - else { - safestrncpy(relhome, optarg, sizeof relhome); - } - home=1; + ctdldir = optarg; break; + // identify the desired logging severity level case 'x': max_log_level = atoi(optarg); break; - case 't': /* deprecated */ + // deprecated + case 't': break; - case 'B': /* Basesize */ - basesize = atoi(optarg); + + // deprecated + case 'B': break; + // deprecated case 'D': - dbg = 1; break; - /* -r tells the server not to drop root permissions. - * Don't use this unless you know what you're doing. - */ + // -r tells the server not to drop root permissions. + // Don't use this unless you know what you're doing. case 'r': drop_root_perms = 0; break; - /* -u tells the server what uid to run under... */ + // -u tells the server what uid to run under... case 'u': u = atoi(optarg); if (u > 0) { @@ -155,24 +165,37 @@ int main(int argc, char **argv) } break; - /* -s tells the server to behave differently during sanity checks */ + // -s tells the server to behave differently during sanity checks case 's': sanity_diag_mode = atoi(optarg); break; + // any other parameter makes it crash and burn default: - /* any other parameter makes it crash and burn */ fprintf(stderr, "citserver: usage: " "citserver " "[-l LogFacility] " "[-x MaxLogLevel] " - "[-d] [-D] [-r] " + "[-d] [-r] " "[-u user] " "[-h HomeDir]\n" ); exit(1); } + if (chdir(ctdldir) != 0) { + syslog(LOG_ERR, "main: unable to change directory to [%s]: %m", ctdldir); + exit(CTDLEXIT_HOME); + } + else { + syslog(LOG_INFO, "main: running in data directory %s", ctdldir); + } + + if ((ctdluid == 0) && (drop_root_perms == 0)) { + fprintf(stderr, "citserver: cannot determine user to run as; please specify -r or -u options\n"); + exit(CTDLEXIT_UNUSER); + } + /* Last ditch effort to determine the user name ... if there's a user called "citadel" then use that */ if (ctdluid == 0) { p = getpwnam("citadel"); @@ -190,96 +213,45 @@ int main(int argc, char **argv) } } - if ((ctdluid == 0) && (drop_root_perms == 0)) { - fprintf(stderr, "citserver: cannot determine user to run as; please specify -r or -u options\n"); - exit(CTDLEXIT_UNUSER); - } + /* initialize the master context */ + InitializeMasterCC(); + InitializeMasterTSD(); - StartLibCitadel(basesize); setlogmask(LOG_UPTO(max_log_level)); 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); drop_root_perms = 1; } - /* Tell 'em who's in da house */ - syslog(LOG_INFO, " "); - syslog(LOG_INFO, " "); - syslog(LOG_INFO, "*** Citadel server engine ***\n"); - syslog(LOG_INFO, "Version %d (build %s) ***", REV_LEVEL, svn_revision()); - syslog(LOG_INFO, "Copyright (C) 1987-2018 by the Citadel development team."); - syslog(LOG_INFO, " "); - syslog(LOG_INFO, "This program is open source software: you can redistribute it and/or"); - syslog(LOG_INFO, "modify it under the terms of the GNU General Public License, version 3."); - syslog(LOG_INFO, " "); - syslog(LOG_INFO, "This program is distributed in the hope that it will be useful,"); - syslog(LOG_INFO, "but WITHOUT ANY WARRANTY; without even the implied warranty of"); - syslog(LOG_INFO, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"); - syslog(LOG_INFO, "GNU General Public License for more details."); - syslog(LOG_INFO, " "); - syslog(LOG_INFO, "%s", libcitadel_version_string()); - -#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(ctdluid, &pw, pwbuf, sizeof(pwbuf)); -#else // SOLARIS_GETPWUID - getpwuid_r(ctdluid, &pw, pwbuf, sizeof(pwbuf), &pwp); -#endif // SOLARIS_GETPWUID -#else // HAVE_GETPWUID_R - pwp = NULL; -#endif // HAVE_GETPWUID_R - - if ((mkdir(ctdl_run_dir, 0755) != 0) && (errno != EEXIST)) { - syslog(LOG_ERR, "main: unable to create run directory [%s]: %m", ctdl_run_dir); - } + if ((mkdir(ctdl_run_dir, 0755) != 0) && (errno != EEXIST)) { + syslog(LOG_ERR, "main: unable to create run directory [%s]: %m", ctdl_run_dir); + } - if (chown(ctdl_run_dir, ctdluid, (pwp==NULL)?-1:pw.pw_gid) != 0) { - syslog(LOG_ERR, "main: unable to set the access rights for [%s]: %m", ctdl_run_dir); - } + if (chown(ctdl_run_dir, ctdluid, (pwp==NULL)?-1:pw.pw_gid) != 0) { + syslog(LOG_ERR, "main: unable to set the access rights for [%s]: %m", ctdl_run_dir); } -#endif ctdl_lockfile(1); - - /* Initialize... */ - init_sysdep(); - - /* - * Do non system dependent startup functions. - */ - master_startup(); + init_sysdep(); // Initialize... + master_startup(); // Do non system dependent startup functions + check_control(); // Check/sanitize/initialize control record, fix user indexes + syslog(LOG_INFO, "main: upgrading modules"); // Run any upgrade entry points + upgrade_modules(); /* - * Check that the control record is correct and place sensible values if it isn't + * Load the user for the masterCC or create them if they don't exist */ - check_control(); - - /* - * Run any upgrade entry points - */ - syslog(LOG_INFO, "main: upgrading modules"); - upgrade_modules(); - -/* - * Load the user for the masterCC or create them if they don't exist - */ - if (CtdlGetUser(&masterCC.user, "SYS_Citadel")) - { + 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 */ + CtdlGetUser(&masterCC.user, "SYS_Citadel"); /* Just to be safe */ } /* @@ -313,14 +285,10 @@ int main(int argc, char **argv) do_async_loop, CitadelServiceTCP); - - - /* * Load any server-side extensions available here. */ syslog(LOG_INFO, "main: initializing server extensions"); - initialise_modules(0); /* @@ -337,28 +305,18 @@ int main(int argc, char **argv) checkcrash(); /* - * Now that we've bound the sockets, change to the Citadel user id and its - * corresponding group ids + * Now that we've bound the sockets, change to the Citadel user id and its corresponding group ids */ if (drop_root_perms) { cdb_chmod_data(); /* make sure we own our data files */ - -#ifdef HAVE_GETPWUID_R -#ifdef SOLARIS_GETPWUID - pwp = getpwuid_r(ctdluid, &pw, pwbuf, sizeof(pwbuf)); -#else // SOLARIS_GETPWUID getpwuid_r(ctdluid, &pw, pwbuf, sizeof(pwbuf), &pwp); -#endif // SOLARIS_GETPWUID -#else // HAVE_GETPWUID_R - pwp = NULL; -#endif // HAVE_GETPWUID_R - if (pwp == NULL) syslog(LOG_ERR, "main: WARNING, getpwuid(%ld): %m Group IDs will be incorrect.", (long)CTDLUID); else { initgroups(pw.pw_name, pw.pw_gid); - if (setgid(pw.pw_gid)) + if (setgid(pw.pw_gid)) { syslog(LOG_ERR, "main: setgid(%ld): %m", (long)pw.pw_gid); + } } syslog(LOG_INFO, "main: changing uid to %ld", (long)CTDLUID); if (setuid(CTDLUID) != 0) { @@ -372,9 +330,15 @@ int main(int argc, char **argv) /* We want to check for idle sessions once per minute */ CtdlRegisterSessionHook(terminate_idle_sessions, EVT_TIMER, PRIO_CLEANUP + 1); + /* Go into multithreaded mode. When this call exits, the server is stopping. */ go_threading(); + /* Get ready to shut down the server. */ int exit_code = master_cleanup(exit_signal); ctdl_lockfile(0); + if (restart_server) { + syslog(LOG_INFO, "main: *** CITADEL SERVER IS RESTARTING ***"); + execv(argv[0], argv); + } return(exit_code); }