4 * This module handles the expiry of old messages and the purging of old users.
16 #include <sys/types.h>
26 #include "sysdep_decls.h"
27 #include "citserver.h"
30 #include "dynloader.h"
40 char v_roomname[ROOMNAMELEN];
47 struct PurgeList *next;
48 char name[ROOMNAMELEN]; /* use the larger of username or roomname */
51 struct PurgeList *UserPurgeList = NULL;
52 struct PurgeList *RoomPurgeList = NULL;
54 extern struct CitContext *ContextList;
56 #define MODULE_NAME "Expire old messages, users, rooms"
57 #define MODULE_AUTHOR "Art Cancro"
58 #define MODULE_EMAIL "ajc@uncnsrd.mt-kisco.ny.us"
59 #define MAJOR_VERSION 0
60 #define MINOR_VERSION 1
62 static struct DLModule_Info info = {
70 void DoPurgeMessages(struct quickroom *qrbuf) {
71 struct ExpirePolicy epbuf;
78 GetExpirePolicy(&epbuf, qrbuf);
81 lprintf(9, "ExpirePolicy for <%s> is <%d> <%d>\n",
82 qrbuf->QRname, epbuf.expire_mode, epbuf.expire_value);
85 /* If the room is set to never expire messages ... do nothing */
86 if (epbuf.expire_mode == EXPIRE_NEXTLEVEL) return;
87 if (epbuf.expire_mode == EXPIRE_MANUAL) return;
89 begin_critical_section(S_QUICKROOM);
92 /* Nothing to do if there aren't any messages */
93 if (CC->num_msgs == 0) {
94 end_critical_section(S_QUICKROOM);
98 /* If the room is set to expire by count, do that */
99 if (epbuf.expire_mode == EXPIRE_NUMMSGS) {
100 while (CC->num_msgs > epbuf.expire_value) {
101 delnum = MessageFromList(0);
102 lprintf(5, "Expiring message %ld\n", delnum);
103 cdb_delete(CDB_MSGMAIN, &delnum, sizeof(long));
104 memcpy(&CC->msglist[0], &CC->msglist[1],
105 (sizeof(long)*(CC->num_msgs - 1)));
106 CC->num_msgs = CC->num_msgs - 1;
110 /* If the room is set to expire by age... */
111 if (epbuf.expire_mode == EXPIRE_AGE) {
112 for (a=0; a<(CC->num_msgs); ++a) {
113 delnum = MessageFromList(a);
114 sprintf(msgid, "%ld", delnum);
115 xtime = output_message(msgid, MT_DATE, 0, 0);
118 && (now - xtime > (time_t)(epbuf.expire_value * 86400L))) {
119 cdb_delete(CDB_MSGMAIN, &delnum, sizeof(long));
120 SetMessageInList(a, 0L);
121 lprintf(5, "Expiring message %ld\n", delnum);
125 CC->num_msgs = sort_msglist(CC->msglist, CC->num_msgs);
127 end_critical_section(S_QUICKROOM);
130 void PurgeMessages(void) {
131 lprintf(5, "PurgeMessages() called\n");
132 ForEachRoom(DoPurgeMessages);
136 void DoPurgeRooms(struct quickroom *qrbuf) {
138 struct PurgeList *pptr;
140 /* Any of these attributes render a room non-purgable */
141 if (qrbuf->QRflags & QR_PERMANENT) return;
142 if (qrbuf->QRflags & QR_DIRECTORY) return;
143 if (qrbuf->QRflags & QR_NETWORK) return;
144 if (qrbuf->QRflags & QR_MAILBOX) return;
145 if (is_noneditable(qrbuf)) return;
147 /* Otherwise, check the date of last modification */
149 age = now - (qrbuf->QRmtime);
150 lprintf(9, "<%s> is <%ld> seconds old\n", qrbuf->QRname, age);
151 if ( (qrbuf->QRmtime > 0L)
152 && (age > (time_t)(config.c_roompurge * 86400L))) {
154 pptr = (struct PurgeList *) malloc(sizeof(struct PurgeList));
155 pptr->next = RoomPurgeList;
156 strcpy(pptr->name, qrbuf->QRname);
157 RoomPurgeList = pptr;
163 int PurgeRooms(void) {
164 struct PurgeList *pptr;
165 int num_rooms_purged = 0;
166 struct quickroom qrbuf;
168 lprintf(5, "PurgeRooms() called\n");
169 if (config.c_roompurge > 0) {
170 ForEachRoom(DoPurgeRooms);
173 while (RoomPurgeList != NULL) {
174 if (getroom(&qrbuf, RoomPurgeList->name) == 0) {
177 pptr = RoomPurgeList->next;
179 RoomPurgeList = pptr;
183 lprintf(5, "Purged %d rooms.\n", num_rooms_purged);
184 return(num_rooms_purged);
188 void do_user_purge(struct usersupp *us) {
192 struct PurgeList *pptr;
194 /* Set purge time; if the user overrides the system default, use it */
195 if (us->USuserpurge > 0) {
196 purge_time = ((time_t)us->USuserpurge) * 86400L;
199 purge_time = ((time_t)config.c_userpurge) * 86400L;
202 /* The default rule is to not purge. */
205 /* If the user hasn't called in two months, his/her account
206 * has expired, so purge the record.
209 if ((now - us->lastcall) > purge_time) purge = 1;
211 /* If the user set his/her password to 'deleteme', he/she
212 * wishes to be deleted, so purge the record.
214 if (!strcasecmp(us->password, "deleteme")) purge = 1;
216 /* If the record is marked as permanent, don't purge it.
218 if (us->flags & US_PERM) purge = 0;
220 /* If the access level is 0, the record should already have been
221 * deleted, but maybe the user was logged in at the time or something.
222 * Delete the record now.
224 if (us->axlevel == 0) purge = 1;
226 /* 0 calls is impossible. If there are 0 calls, it must
227 * be a corrupted record, so purge it.
229 if (us->timescalled == 0) purge = 1;
232 pptr = (struct PurgeList *) malloc(sizeof(struct PurgeList));
233 pptr->next = UserPurgeList;
234 strcpy(pptr->name, us->fullname);
235 UserPurgeList = pptr;
242 int PurgeUsers(void) {
243 struct PurgeList *pptr;
244 int num_users_purged = 0;
246 lprintf(5, "PurgeUsers() called\n");
247 if (config.c_userpurge > 0) {
248 ForEachUser(do_user_purge);
251 while (UserPurgeList != NULL) {
252 purge_user(UserPurgeList->name);
253 pptr = UserPurgeList->next;
255 UserPurgeList = pptr;
259 lprintf(5, "Purged %d users.\n", num_users_purged);
260 return(num_users_purged);
265 int PurgeVisits(void) {
266 struct cdbdata *cdbvisit;
273 cdb_rewind(CDB_VISIT);
274 while(cdbvisit = cdb_next_item(CDB_VISIT), cdbvisit != NULL) {
275 memset(&vbuf, 0, sizeof(struct visit));
276 memcpy(&vbuf, cdbvisit->ptr,
277 ( (cdbvisit->len > sizeof(struct visit)) ?
278 sizeof(struct visit) : cdbvisit->len) );
287 void cmd_expi(char *argbuf) {
292 if ((!(CC->logged_in))&&(!(CC->internal_pgm))) {
293 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
297 if ((!is_room_aide()) && (!(CC->internal_pgm)) ) {
298 cprintf("%d Higher access required.\n",
299 ERROR+HIGHER_ACCESS_REQUIRED);
303 extract(cmd, argbuf, 0);
304 if (!strcasecmp(cmd, "users")) {
305 retval = PurgeUsers();
306 cprintf("%d Purged %d users.\n", OK, retval);
309 else if (!strcasecmp(cmd, "messages")) {
311 cprintf("%d Finished purging messages.\n", OK);
314 else if (!strcasecmp(cmd, "rooms")) {
315 retval = PurgeRooms();
316 cprintf("%d Purged %d rooms.\n", OK, retval);
319 else if (!strcasecmp(cmd, "visits")) {
320 retval = PurgeVisits();
321 cprintf("%d There are %d visits...\n", OK, retval);
323 else if (!strcasecmp(cmd, "defrag")) {
325 cprintf("%d Defragmented the databases.\n", OK);
328 cprintf("%d Invalid command.\n", ERROR+ILLEGAL_VALUE);
335 struct DLModule_Info *Dynamic_Module_Init(void)
337 CtdlRegisterProtoHook(cmd_expi, "EXPI", "Expire old system objects");