Did away with lprintf all together now its called CtdlLogPrintf()
[citadel.git] / citadel / modules / expire / serv_expire.c
index 4902af16b0a4d0aad4c3e74f6a2d99f930a95082..b494d9755495cd513c6ca5856464cd9f2a0a6047 100644 (file)
@@ -62,7 +62,7 @@
 #include "user_ops.h"
 #include "control.h"
 #include "serv_network.h"      /* Needed for defenition of UseTable */
-
+#include "threads.h"
 
 #include "ctdl_module.h"
 
@@ -114,6 +114,7 @@ struct ValidRoom *ValidRoomList = NULL;
 struct ValidUser *ValidUserList = NULL;
 int messages_purged;
 int users_not_purged;
+char *users_corrupt_msg = NULL;
 
 struct ctdlroomref *rr = NULL;
 
@@ -224,12 +225,12 @@ void DoPurgeMessages(FILE *purgelist) {
 void PurgeMessages(void) {
        FILE *purgelist;
 
-       lprintf(CTDL_DEBUG, "PurgeMessages() called\n");
+       CtdlLogPrintf(CTDL_DEBUG, "PurgeMessages() called\n");
        messages_purged = 0;
 
        purgelist = tmpfile();
        if (purgelist == NULL) {
-               lprintf(CTDL_CRIT, "Can't create purgelist temp file: %s\n",
+               CtdlLogPrintf(CTDL_CRIT, "Can't create purgelist temp file: %s\n",
                        strerror(errno));
                return;
        }
@@ -296,7 +297,7 @@ void DoPurgeRooms(struct ctdlroom *qrbuf, void *data) {
                age = time(NULL) - (qrbuf->QRmtime);
                purge_secs = (time_t)config.c_roompurge * (time_t)86400;
                if (purge_secs <= (time_t)0) return;
-               lprintf(CTDL_DEBUG, "<%s> is <%ld> seconds old\n", qrbuf->QRname, (long)age);
+               CtdlLogPrintf(CTDL_DEBUG, "<%s> is <%ld> seconds old\n", qrbuf->QRname, (long)age);
                if (age > purge_secs) do_purge = 1;
        } /* !QR_MAILBOX */
 
@@ -318,7 +319,7 @@ int PurgeRooms(void) {
        struct ValidUser *vuptr;
        char *transcript = NULL;
 
-       lprintf(CTDL_DEBUG, "PurgeRooms() called\n");
+       CtdlLogPrintf(CTDL_DEBUG, "PurgeRooms() called\n");
 
 
        /* Load up a table full of valid user numbers so we can delete
@@ -355,7 +356,7 @@ int PurgeRooms(void) {
        if (num_rooms_purged > 0) aide_message(transcript, "Room Autopurger Message");
        free(transcript);
 
-       lprintf(CTDL_DEBUG, "Purged %d rooms.\n", num_rooms_purged);
+       CtdlLogPrintf(CTDL_DEBUG, "Purged %d rooms.\n", num_rooms_purged);
        return(num_rooms_purged);
 }
 
@@ -383,6 +384,7 @@ void do_uid_user_purge(struct ctdluser *us, void *data) {
 
 
 
+
 /*
  * Back end function to check user accounts for expiration.
  */
@@ -403,16 +405,14 @@ void do_user_purge(struct ctdluser *us, void *data) {
        /* The default rule is to not purge. */
        purge = 0;
 
-       /* If the user hasn't called in two months, his/her account
+       /* If the user hasn't called in two months and expiring of accounts is turned on, his/her account
         * has expired, so purge the record.
         */
-       now = time(NULL);
-       if ((now - us->lastcall) > purge_time) purge = 1;
-
-       /* If the user set his/her password to 'deleteme', he/she
-        * wishes to be deleted, so purge the record.
-        */
-       if (!strcasecmp(us->password, "deleteme")) purge = 1;
+       if (config.c_userpurge > 0)
+       {
+               now = time(NULL);
+               if ((now - us->lastcall) > purge_time) purge = 1;
+       }
 
        /* If the record is marked as permanent, don't purge it.
         */
@@ -428,15 +428,44 @@ void do_user_purge(struct ctdluser *us, void *data) {
         */
        if (us->axlevel == 0) purge = 1;
 
+       /* If the user set his/her password to 'deleteme', he/she
+        * wishes to be deleted, so purge the record.
+        * Moved this lower down so that aides and permanent users get purged if they ask to be.
+        */
+       if (!strcasecmp(us->password, "deleteme")) purge = 1;
+       
        /* 0 calls is impossible.  If there are 0 calls, it must
         * be a corrupted record, so purge it.
+        * Actually it is possible if an Aide created the user so now we check for less than 0 (DRW)
         */
-       if (us->timescalled == 0) purge = 1;
+       if (us->timescalled < 0) purge = 1;
 
        /* User number 0, as well as any negative user number, is
         * also impossible.
         */
        if (us->usernum < 1L) purge = 1;
+       
+       /* If the user has no full name entry then we can't purge them
+        * since the actual purge can't find them.
+        * This shouldn't happen but does somehow.
+        * So we make an Aide message to alert to it but don't add it to the purge list
+        */
+       if (IsEmptyStr(us->fullname))
+       {
+               purge=0;
+               if (users_corrupt_msg == NULL)
+               {
+                       users_corrupt_msg = malloc(SIZ);
+                       strcpy(users_corrupt_msg, "The auto-purger found the following user numbers with no name.\n"
+                       "Unfortunately the auto-purger is not yet able to fix this problem.\n"
+                       "This problem is not considered serious since a user with no name can\n"
+                       "not log in.\n");
+               }
+               
+               users_corrupt_msg=realloc(users_corrupt_msg, strlen(users_corrupt_msg)+SIZ);
+               snprintf(&users_corrupt_msg[strlen(users_corrupt_msg)], SIZ, " %ld\n", us->usernum);
+       }
+
 
        if (purge == 1) {
                pptr = (struct PurgeList *) malloc(sizeof(struct PurgeList));
@@ -457,18 +486,19 @@ int PurgeUsers(void) {
        int num_users_purged = 0;
        char *transcript = NULL;
 
-       lprintf(CTDL_DEBUG, "PurgeUsers() called\n");
+       CtdlLogPrintf(CTDL_DEBUG, "PurgeUsers() called\n");
        users_not_purged = 0;
 
-       if (config.c_auth_mode == 1) {
-               /* host auth mode */
-               ForEachUser(do_uid_user_purge, NULL);
-       }
-       else {
-               /* native auth mode */
-               if (config.c_userpurge > 0) {
+       switch(config.c_auth_mode) {
+               case AUTHMODE_NATIVE:
                        ForEachUser(do_user_purge, NULL);
-               }
+                       break;
+               case AUTHMODE_HOST:
+                       ForEachUser(do_uid_user_purge, NULL);
+                       break;
+               default:
+                       CtdlLogPrintf(CTDL_DEBUG, "Unknown authentication mode!\n");
+                       break;
        }
 
        transcript = malloc(SIZ);
@@ -503,7 +533,15 @@ int PurgeUsers(void) {
        if (num_users_purged > 0) aide_message(transcript, "User Purge Message");
        free(transcript);
 
-       lprintf(CTDL_DEBUG, "Purged %d users.\n", num_users_purged);
+       if(users_corrupt_msg)
+       {
+               aide_message(users_corrupt_msg, "User Corruption Message");
+               free (users_corrupt_msg);
+               users_corrupt_msg = NULL;
+       }
+       
+               
+       CtdlLogPrintf(CTDL_DEBUG, "Purged %d users.\n", num_users_purged);
        return(num_users_purged);
 }
 
@@ -618,7 +656,7 @@ int PurgeUseTable(void) {
        struct UPurgeList *uptr; 
 
        /* Phase 1: traverse through the table, discovering old records... */
-       lprintf(CTDL_DEBUG, "Purge use table: phase 1\n");
+       CtdlLogPrintf(CTDL_DEBUG, "Purge use table: phase 1\n");
        cdb_rewind(CDB_USETABLE);
        while(cdbut = cdb_next_item(CDB_USETABLE), cdbut != NULL) {
 
@@ -645,7 +683,7 @@ int PurgeUseTable(void) {
        }
 
        /* Phase 2: delete the records */
-       lprintf(CTDL_DEBUG, "Purge use table: phase 2\n");
+       CtdlLogPrintf(CTDL_DEBUG, "Purge use table: phase 2\n");
        while (ul != NULL) {
                cdb_delete(CDB_USETABLE, ul->up_key, strlen(ul->up_key));
                uptr = ul->next;
@@ -653,7 +691,7 @@ int PurgeUseTable(void) {
                ul = uptr;
        }
 
-       lprintf(CTDL_DEBUG, "Purge use table: finished (purged %d records)\n", purged);
+       CtdlLogPrintf(CTDL_DEBUG, "Purge use table: finished (purged %d records)\n", purged);
        return(purged);
 }
 
@@ -672,7 +710,7 @@ int PurgeEuidIndexTable(void) {
        struct CtdlMessage *msg = NULL;
 
        /* Phase 1: traverse through the table, discovering old records... */
-       lprintf(CTDL_DEBUG, "Purge EUID index: phase 1\n");
+       CtdlLogPrintf(CTDL_DEBUG, "Purge EUID index: phase 1\n");
        cdb_rewind(CDB_EUIDINDEX);
        while(cdbei = cdb_next_item(CDB_EUIDINDEX), cdbei != NULL) {
 
@@ -699,7 +737,7 @@ int PurgeEuidIndexTable(void) {
        }
 
        /* Phase 2: delete the records */
-       lprintf(CTDL_DEBUG, "Purge euid index: phase 2\n");
+       CtdlLogPrintf(CTDL_DEBUG, "Purge euid index: phase 2\n");
        while (el != NULL) {
                cdb_delete(CDB_EUIDINDEX, el->ep_key, el->ep_keylen);
                free(el->ep_key);
@@ -708,54 +746,94 @@ int PurgeEuidIndexTable(void) {
                el = eptr;
        }
 
-       lprintf(CTDL_DEBUG, "Purge euid index: finished (purged %d records)\n", purged);
+       CtdlLogPrintf(CTDL_DEBUG, "Purge euid index: finished (purged %d records)\n", purged);
        return(purged);
 }
 
 
-void purge_databases(void) {
-       int retval;
-       static time_t last_purge = 0;
-       time_t now;
-       struct tm tm;
-
-       /* Do the auto-purge if the current hour equals the purge hour,
-        * but not if the operation has already been performed in the
-        * last twelve hours.  This is usually enough granularity.
-        */
-       now = time(NULL);
-       localtime_r(&now, &tm);
-       if (tm.tm_hour != config.c_purge_hour) return;
-       if ((now - last_purge) < 43200) return;
-
-       lprintf(CTDL_INFO, "Auto-purger: starting.\n");
-
-       retval = PurgeUsers();
-       lprintf(CTDL_NOTICE, "Purged %d users.\n", retval);
-
-       PurgeMessages();
-       lprintf(CTDL_NOTICE, "Expired %d messages.\n", messages_purged);
+void *purge_databases(void *args)
+{
+        int retval;
+        static time_t last_purge = 0;
+        time_t now;
+        struct tm tm;
+       struct CitContext purgerCC;
+
+       CtdlLogPrintf(CTDL_DEBUG, "Auto-purger_thread() initializing\n");
+
+       memset(&purgerCC, 0, sizeof(struct CitContext));
+       purgerCC.internal_pgm = 1;
+       purgerCC.cs_pid = 0;
+       pthread_setspecific(MyConKey, (void *)&purgerCC );
+
+        while (!CtdlThreadCheckStop()) {
+                /* Do the auto-purge if the current hour equals the purge hour,
+                 * but not if the operation has already been performed in the
+                 * last twelve hours.  This is usually enough granularity.
+                 */
+                now = time(NULL);
+                localtime_r(&now, &tm);
+                if ((tm.tm_hour != config.c_purge_hour) || ((now - last_purge) < 43200)) {
+                        CtdlThreadSleep(60);
+                        continue;
+                }
+
+
+                CtdlLogPrintf(CTDL_INFO, "Auto-purger: starting.\n");
+
+               if (!CtdlThreadCheckStop())
+               {
+                       retval = PurgeUsers();
+                       CtdlLogPrintf(CTDL_NOTICE, "Purged %d users.\n", retval);
+               }
+               
+               if (!CtdlThreadCheckStop())
+               {
+                       PurgeMessages();
+                       CtdlLogPrintf(CTDL_NOTICE, "Expired %d messages.\n", messages_purged);
+               }
 
-       retval = PurgeRooms();
-       lprintf(CTDL_NOTICE, "Expired %d rooms.\n", retval);
+               if (!CtdlThreadCheckStop())
+               {
+                       retval = PurgeRooms();
+                       CtdlLogPrintf(CTDL_NOTICE, "Expired %d rooms.\n", retval);
+               }
 
-       retval = PurgeVisits();
-       lprintf(CTDL_NOTICE, "Purged %d visits.\n", retval);
+               if (!CtdlThreadCheckStop())
+               {
+                       retval = PurgeVisits();
+                       CtdlLogPrintf(CTDL_NOTICE, "Purged %d visits.\n", retval);
+               }
 
-       retval = PurgeUseTable();
-       lprintf(CTDL_NOTICE, "Purged %d entries from the use table.\n", retval);
+               if (!CtdlThreadCheckStop())
+               {
+                       retval = PurgeUseTable();
+                       CtdlLogPrintf(CTDL_NOTICE, "Purged %d entries from the use table.\n", retval);
+               }
 
-       retval = PurgeEuidIndexTable();
-       lprintf(CTDL_NOTICE, "Purged %d entries from the EUID index.\n", retval);
+               if (!CtdlThreadCheckStop())
+               {
+                       retval = PurgeEuidIndexTable();
+                       CtdlLogPrintf(CTDL_NOTICE, "Purged %d entries from the EUID index.\n", retval);
+               }
 
-       retval = TDAP_ProcessAdjRefCountQueue();
-       lprintf(CTDL_NOTICE, "Processed %d message reference count adjustments.\n", retval);
+               if (!CtdlThreadCheckStop())
+               {
+                       retval = TDAP_ProcessAdjRefCountQueue();
+                       CtdlLogPrintf(CTDL_NOTICE, "Processed %d message reference count adjustments.\n", retval);
+               }
 
-       lprintf(CTDL_INFO, "Auto-purger: finished.\n");
+               if (!CtdlThreadCheckStop())
+               {
+                       CtdlLogPrintf(CTDL_INFO, "Auto-purger: finished.\n");
+                       last_purge = now;       /* So we don't do it again soon */
+               }
+               else
+                       CtdlLogPrintf(CTDL_INFO, "Auto-purger: STOPPED.\n");
 
-       last_purge = now;       /* So we don't do it again soon */
+        }
+        return NULL;
 }
-
 /*****************************************************************************/
 
 
@@ -846,10 +924,10 @@ CTDL_MODULE_INIT(expire)
 {
        if (!threading)
        {
-               CtdlRegisterSessionHook(purge_databases, EVT_TIMER);
                CtdlRegisterProtoHook(cmd_fsck, "FSCK", "Check message ref counts");
        }
-       
+       else
+               CtdlThreadCreate("Auto Purger", CTDLTHREAD_BIGSTACK, purge_databases, NULL);
        /* return our Subversion id for the Log */
        return "$Id$";
 }