From c2c1aa8b94024803f623575c5f9ea89d9317f1e0 Mon Sep 17 00:00:00 2001 From: Dave West Date: Tue, 10 Nov 2009 19:27:46 +0000 Subject: [PATCH] Grabbed another chunk of code out of user_ops.c, purge_user() This chunk checked if a user was logged in by testing the user numbers It is now a function and exposed to the API as int CtdlIsUserLoggedInByNum(int num) Also marked the code with a FIXME since it is unsafe, a user could log in after the test but before the delete and realy mess things up. --- citadel/context.c | 26 ++++++++++++++++++++++++++ citadel/include/ctdl_module.h | 1 + citadel/user_ops.c | 22 +++++++++++----------- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/citadel/context.c b/citadel/context.c index 3122e5c06..478ed03ad 100644 --- a/citadel/context.c +++ b/citadel/context.c @@ -151,6 +151,32 @@ int CtdlIsUserLoggedIn (char *user_name) return ret; } + + +/* + * Check to see if a user is currently logged in. + * Basically same as CtdlIsUserLoggedIn() but uses the user number instead. + * Take care with what you do as a result of this test. + * The user may not have been logged in when this function was called BUT + * because of threading the user might be logged in before you test the result. + */ +int CtdlIsUserLoggedInByNum (int usernum) +{ + CitContext *cptr; + int ret = 0; + + begin_critical_section(S_SESSION_TABLE); + for (cptr = ContextList; cptr != NULL; cptr = cptr->next) { + if (cptr->user.usernum == usernum) { + ret = 1; + } + } + end_critical_section(S_SESSION_TABLE); + return ret; +} + + + /* * Return a pointer to the CitContext structure bound to the thread which * called this function. If there's no such binding (for example, if it's diff --git a/citadel/include/ctdl_module.h b/citadel/include/ctdl_module.h index 5e7488794..5ec05ab08 100644 --- a/citadel/include/ctdl_module.h +++ b/citadel/include/ctdl_module.h @@ -190,6 +190,7 @@ int CtdlIsSingleUser(void); int CtdlIsUserLoggedIn (char *user_name); +int CtdlIsUserLoggedInByNum (int usernum); /* diff --git a/citadel/user_ops.c b/citadel/user_ops.c index 965cec625..67935a34f 100644 --- a/citadel/user_ops.c +++ b/citadel/user_ops.c @@ -1027,8 +1027,6 @@ int purge_user(char pname[]) char filename[64]; struct ctdluser usbuf; char usernamekey[USERNAME_SIZE]; - CitContext *ccptr; - int user_is_logged_in = 0; makeuserkey(usernamekey, pname); @@ -1044,15 +1042,7 @@ int purge_user(char pname[]) * set the access level to 0, and let the account get swept up * during the next purge. */ - user_is_logged_in = 0; - begin_critical_section(S_SESSION_TABLE); - for (ccptr = ContextList; ccptr != NULL; ccptr = ccptr->next) { - if (ccptr->user.usernum == usbuf.usernum) { - user_is_logged_in = 1; - } - } - end_critical_section(S_SESSION_TABLE); - if (user_is_logged_in == 1) { + if (CtdlIsUserLoggedInByNum(usbuf.usernum)) { CtdlLogPrintf(CTDL_WARNING, "User <%s> is logged in; not deleting.\n", pname); usbuf.axlevel = 0; CtdlPutUser(&usbuf); @@ -1060,6 +1050,16 @@ int purge_user(char pname[]) } CtdlLogPrintf(CTDL_NOTICE, "Deleting user <%s>\n", pname); +/* + * FIXME: + * This should all be wrapped in a S_USERS mutex. + * Without the mutex the user could log in before we get to the next function + * That would truly mess things up :-( + * I would like to see the S_USERS start before the CtdlIsUserLoggedInByNum() above + * and end after the user has been deleted from the database, below. + * Question is should we enter the EVT_PURGEUSER whilst S_USERS is active? + */ + /* Perform any purge functions registered by server extensions */ PerformUserHooks(&usbuf, EVT_PURGEUSER); -- 2.30.2