From e376f2f26c84111e1e06f2368a7111b818550456 Mon Sep 17 00:00:00 2001 From: Dave West Date: Thu, 17 Jul 2008 19:03:00 +0000 Subject: [PATCH] Added code to provide a preliminary single user mode. CtdlTrySingleUser() - Try to go single user CtdlEndSingleUser() - End single user CtdlIsSingleUser() - True is system is single user CtdlWantSingleUser() - True if system is trying to go single user The system is said to be in single user mode when there is only one session active. Which should be the one that asked it to go single user. When trying to go single user new connections are refused as per the nologin mechanism and scheduled threads are prevented. --- citadel/citserver.c | 2 +- citadel/include/ctdl_module.h | 4 +++ citadel/modules/vandelay/serv_vandelay.c | 36 ++++++++++--------- citadel/sysdep.c | 46 ++++++++++++++++++++++++ citadel/threads.c | 4 +++ 5 files changed, 74 insertions(+), 18 deletions(-) diff --git a/citadel/citserver.c b/citadel/citserver.c index ca612b0b0..dbed6366a 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -984,7 +984,7 @@ void begin_session(struct CitContext *con) con->dl_is_net = 0; con->nologin = 0; - if ((config.c_maxsessions > 0)&&(num_sessions > config.c_maxsessions)) { + if (((config.c_maxsessions > 0)&&(num_sessions > config.c_maxsessions)) || CtdlWantSingleUser()) { con->nologin = 1; } diff --git a/citadel/include/ctdl_module.h b/citadel/include/ctdl_module.h index 90932ca82..754b2e146 100644 --- a/citadel/include/ctdl_module.h +++ b/citadel/include/ctdl_module.h @@ -149,6 +149,10 @@ void CtdlThreadAllocTSD(void); struct CitContext *CtdlGetContextArray (int *count); void CtdlFillSystemContext(struct CitContext *context, char *name); +int CtdlTrySingleUser(void); +void CtdlEndSingleUser(void); +int CtdlWantSingleUser(void); +int CtdlIsSingleUser(void); /* diff --git a/citadel/modules/vandelay/serv_vandelay.c b/citadel/modules/vandelay/serv_vandelay.c index 138a5e5c4..79533aa2f 100644 --- a/citadel/modules/vandelay/serv_vandelay.c +++ b/citadel/modules/vandelay/serv_vandelay.c @@ -904,26 +904,28 @@ void cmd_artv(char *cmdbuf) { static int is_running = 0; if (CtdlAccessCheck(ac_internal)) return; - if (is_running) { + + if (CtdlTrySingleUser()) + { + CtdlMakeTempFileName(artv_tempfilename1, sizeof artv_tempfilename1); + CtdlMakeTempFileName(artv_tempfilename2, sizeof artv_tempfilename2); + + extract_token(cmd, cmdbuf, 0, '|', sizeof cmd); + if (!strcasecmp(cmd, "export")) artv_do_export(); + else if (!strcasecmp(cmd, "import")) artv_do_import(); + else if (!strcasecmp(cmd, "dump")) artv_do_dump(); + else cprintf("%d illegal command\n", ERROR + ILLEGAL_VALUE); + + unlink(artv_tempfilename1); + unlink(artv_tempfilename2); + + CtdlEndSingleUser(); + } + else + { cprintf("%d The importer/exporter is already running.\n", ERROR + RESOURCE_BUSY); - return; } - is_running = 1; - - CtdlMakeTempFileName(artv_tempfilename1, sizeof artv_tempfilename1); - CtdlMakeTempFileName(artv_tempfilename2, sizeof artv_tempfilename2); - - extract_token(cmd, cmdbuf, 0, '|', sizeof cmd); - if (!strcasecmp(cmd, "export")) artv_do_export(); - else if (!strcasecmp(cmd, "import")) artv_do_import(); - else if (!strcasecmp(cmd, "dump")) artv_do_dump(); - else cprintf("%d illegal command\n", ERROR + ILLEGAL_VALUE); - - unlink(artv_tempfilename1); - unlink(artv_tempfilename2); - - is_running = 0; } diff --git a/citadel/sysdep.c b/citadel/sysdep.c index c09fd2a06..2114fb0e1 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -99,6 +99,52 @@ int syslog_facility = LOG_DAEMON; int enable_syslog = 0; +/* Flag for single user mode */ +static int want_single_user = 0; + +/* Try to go single user */ + +int CtdlTrySingleUser(void) +{ + int can_do = 0; + + begin_critical_section(S_SINGLE_USER); + if (want_single_user) + can_do = 0; + else + { + can_do = 1; + want_single_user = 1; + } + end_critical_section(S_SINGLE_USER); + return can_do; +} + +void CtdlEndSingleUser(void) +{ + begin_critical_section(S_SINGLE_USER); + want_single_user = 0; + end_critical_section(S_SINGLE_USER); +} + + +int CtdlWantSingleUser(void) +{ + return want_single_user; +} + +int CtdlIsSingleUser(void) +{ + if (want_single_user) + { + /* check for only one context here */ + if (num_sessions == 1) + return TRUE; + } + return FALSE; +} + + /* * CtdlLogPrintf() ... Write logging information */ diff --git a/citadel/threads.c b/citadel/threads.c index 2d8576e1d..63e6ba072 100644 --- a/citadel/threads.c +++ b/citadel/threads.c @@ -1101,6 +1101,10 @@ void ctdl_thread_internal_check_scheduled(void) CtdlThreadNode *this_thread, *that_thread; time_t now; + /* Don't start scheduled threads if the system wants single user mode */ + if (CtdlWantSingleUser()) + return; + if (try_critical_section(S_SCHEDULE_LIST)) return; /* If this list is locked we wait till the next chance */ -- 2.30.2