* Completed 'fsck'-like reference count verifier (server and client)
authorArt Cancro <ajc@citadel.org>
Sun, 27 Feb 2000 03:57:44 +0000 (03:57 +0000)
committerArt Cancro <ajc@citadel.org>
Sun, 27 Feb 2000 03:57:44 +0000 (03:57 +0000)
12 files changed:
citadel/ChangeLog
citadel/citadel.c
citadel/citadel.rc
citadel/commands.c
citadel/commands.h
citadel/messages.c
citadel/messages.h
citadel/messages/saveopt [deleted file]
citadel/routines2.c
citadel/serv_expire.c
citadel/sysdep.c
citadel/techdoc/session.txt

index e2728305c77d26285449eb0fac0151ff62af2c67..208df46ed7cce10533b672f79204344be19491ec 100644 (file)
@@ -1,4 +1,7 @@
 $Log$
+Revision 1.472  2000/02/27 03:57:35  ajc
+* Completed 'fsck'-like reference count verifier (server and client)
+
 Revision 1.471  2000/02/26 18:30:40  ajc
 * Properly handle all aliases specified in network/mail.aliases for incoming
   SMTP mail (uses the alias() function, so if we replace that function with
@@ -1672,4 +1675,3 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
        * Initial CVS import 
-
index c68173a68603cb252356886ae248b4e53eeccc87..e35044fa57dc28d56b008bdd57bd891b913cc0f6 100644 (file)
@@ -1253,6 +1253,10 @@ GSTA:    termn8 = 0;
                                do_internet_configuration();
                                break;
 
+                       case 83:
+                               check_message_base();
+                               break;
+
                        case 50:
                                enter_config(2);
                                break;
index b195cac0dbdf7be0e980f503aa664125eeb63bd8..c439f5d881f9a6297d084988d0f4ce60e5fbe0ee 100644 (file)
@@ -173,6 +173,7 @@ cmd=70,2,&.,&Aide,&Message edit:
 cmd=78,1,&.,&Aide,&Post
 cmd=80,2,&.,&Aide,&System configuration,&General
 cmd=82,2,&.,&Aide,&System configuration,&Internet
+cmd=83,2,&.,&Aide,&System configuration,check &Message base
 
 cmd=29,0,&.,&Terminate,and &Quit
 cmd=30,0,&.,&Terminate,and &Stay online
index c869fd47c2a660c04e52f0c3ecc779e47d5c612b..1ab8c15b7d9f9bc9a26e64a6349f41550c2a4bbd 100644 (file)
@@ -1,12 +1,9 @@
 /*
- * Citadel/UX
- *
- * commands.c - front end for Citadel
- *
- * This version is the traditional command parser for room prompts.
- *
  * $Id$
  *
+ * This file contains functions which implement parts of the
+ * text-mode user interface.
+ *
  */
 
 #include "sysdep.h"
@@ -108,7 +105,7 @@ void print_express(void)
                putc(7, stdout);
        }
        color(BRIGHT_RED);
-       printf("---\n");
+       printf("\r---\n");
        while (serv_gets(buf), strcmp(buf, "000")) {
                printf("%s\n", buf);
        }
@@ -136,7 +133,7 @@ void do_keepalive(void)
                return;
        time(&idlet);
 
-       /* Do a space-backspace to keep socksified telnet sessions open */
+       /* Do a space-backspace to keep telnet sessions from idling out */
        printf(" %c", 8);
        fflush(stdout);
 
@@ -1129,3 +1126,70 @@ void keyopt(char *buf) {
        }
        color(DIM_WHITE);
 }
+
+
+
+/*
+ * Present a key-menu line choice type of thing
+ */
+char keymenu(char *menuprompt, char *menustring) {
+       int i, c, a;
+       int choices;
+       int do_prompt = 0;
+       char buf[256];
+       int ch;
+       int display_prompt = 1;
+
+       choices = num_tokens(menustring, '|');
+
+       if (menuprompt != NULL) do_prompt = 1;
+       if (menuprompt != NULL) if (strlen(menuprompt)==0) do_prompt = 0;
+
+       while (1) {
+               if (display_prompt) {
+                       if (do_prompt) {
+                               printf("%s ", menuprompt);
+                       } 
+                       else {
+                               for (i=0; i<choices; ++i) {
+                                       extract(buf, menustring, i);
+                                       keyopt(buf);
+                                       printf(" ");
+                               }
+                       }
+                       printf(" -> ");
+                       display_prompt = 0;
+               }
+               ch = lkey();
+       
+               if ( (do_prompt) && (ch=='?') ) {
+                       printf("\rOne of...                               ");
+                       printf("                                      \n");
+                       for (i=0; i<choices; ++i) {
+                               extract(buf, menustring, i);
+                               printf("   ");
+                               keyopt(buf);
+                               printf("\n");
+                       }
+                       printf("\n");
+                       display_prompt = 1;
+               }
+
+               for (i=0; i<choices; ++i) {
+                       extract(buf, menustring, i);
+                       for (c=1; c<strlen(buf); ++c) {
+                               if ( (ch == tolower(buf[c]))
+                                  && (buf[c-1]=='<')
+                                  && (buf[c+1]=='>') ) {
+                                       for (a=0; a<strlen(buf); ++a) {
+                                               if ( (a!=(c-1)) && (a!=(c+1))) {
+                                                       putc(buf[a], stdout);
+                                               }
+                                       }
+                                       printf("\n\n");
+                                       return ch;
+                               }
+                       }
+               }
+       }
+}
index cef70d16dc968e25c2b5af66cf0cc3f8d4d7c6aa..b1335ad0ec5455583b23290b9bb31ad894959a4d 100644 (file)
@@ -47,6 +47,7 @@ extern int enable_color;
 int yesno(void);
 int yesno_d(int d);
 void keyopt(char *);
+char keymenu(char *menuprompt, char *menustring);
 
 extern int num_urls;
 extern char urls[MAXURLS][256];
index eb25421a8c95a2d4f8383a56bb9d893be0553d45..aa9dd081e1dde0431e2e2b15ccab04c787ea6ea2 100644 (file)
@@ -671,21 +671,15 @@ MECR:     if (mode==2) {
                if (e_ex_code==0) goto MEFIN;
                goto MEABT2;
                }
-MECR1: printf("Entry cmd (? for options) -> ");
-MECR2: b=inkey();
-       if (b==NEXT_KEY) b='n';
-       if (b==STOP_KEY) b='s';
-       b=(b&127); b=tolower(b);
-       if (b=='?') {
-               printf("Help\n");
-               formout("saveopt");
-               goto MECR1;
-               }
-       if (b=='a') { printf("Abort\n");        goto MEABT;     }
-       if (b=='c') { printf("Continue\n");     goto ME1;       }
-       if (b=='s') { printf("Save message\n"); goto MEFIN;     } 
+
+       b = keymenu("Entry command (? for options)",
+               "<A>bort|<C>ontinue|<S>ave message|<P>rint formatted|"
+               "<R>eplace string|<H>old message");
+
+       if (b=='a') goto MEABT;
+       if (b=='c') goto ME1;
+       if (b=='s') goto MEFIN;
        if (b=='p') {
-               printf("Print formatted\n");
                printf(" %s from %s",datestr,fullname);
                if (strlen(recipient)>0) printf(" to %s",recipient);
                printf("\n");
@@ -700,15 +694,12 @@ MECR2:    b=inkey();
                goto MECR;
                }
        if (b=='r') {
-               printf("Replace string\n");
                replace_string(filename,0L);
                goto MECR;
                }
        if (b=='h') {
-               printf("Hold message\n");
                return(2);
                }
-       goto MECR2;
 
 MEFIN: return(0);
 
@@ -1244,3 +1235,28 @@ void edit_system_message(char *which_message)
        sprintf(write_cmd, "EMSG %s", which_message);
        do_edit(desc, read_cmd, "NOOP", write_cmd);
        }
+
+
+
+
+/*
+ * Verify the message base
+ */
+void check_message_base(void) {
+       char buf[256];
+
+       printf("Please read the documentation before running this command.\n");
+       printf("Having done so, do you still want to check the message base? ");
+       if (yesno()==0) return;
+
+       serv_puts("FSCK");
+       serv_gets(buf);
+       if (buf[0] != '1') {
+               printf("%s\n", &buf[4]);
+               return;
+       }
+
+       while (serv_gets(buf), strcmp(buf, "000")) {
+               printf("%s\n", buf);
+       }
+}
index 73523f76ef6764f55e3fad89ecdd6370a0dd7565..4af8f4286215d642202a5184cd125695fc8fbcd7 100644 (file)
@@ -6,3 +6,4 @@ void edit_system_message(char *which_message);
 extern int lines_printed;
 pid_t ka_wait(int *kstatus);
 void list_urls(void);
+void check_message_base(void);
diff --git a/citadel/messages/saveopt b/citadel/messages/saveopt
deleted file mode 100644 (file)
index 20c01bb..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-One of:
- <A>bort
- <C>ontinue
- <H>old this message
- <P>rint formatted
- <R>eplace string (edit)
- <S>ave message
index 23537c9b390629d3f371aa48c7a2173e2ad48de6..7efce58b4937c569734555a27cd955e9a33cb2b6 100644 (file)
@@ -813,61 +813,51 @@ void do_internet_configuration(void) {
                color(DIM_WHITE);
                }
 
-               keyopt("\n<A>dd <D>elete <S>ave <Q>uit -> ");
-               do {
-                       badkey = 0;
-                       ch = inkey();
-                       ch = tolower(ch);
-                       if ( (ch=='d') && (num_recs == 0) ) ch = 0;
-                       switch(ch) {
-                               case 'a':
-                                       printf("Add\n");
-                                       ++num_recs;
-                                       if (num_recs == 1)
-                                               recs = malloc(sizeof(char *));
-                                       else recs = realloc(recs,
-                                               (sizeof(char *)) * num_recs);
-                                       newprompt("Enter host name: ",
-                                               buf, 50);
-                                       strcat(buf, "|");
-                                       get_inet_rec_type(&buf[strlen(buf)]);
-                                       recs[num_recs-1] = strdup(buf);
-                                       break;
-                               case 'd':
-                                       printf("Delete\n");
-                                       i = intprompt("Delete which one",
-                                               1, 1, num_recs) - 1;
-                                       free(recs[i]);
-                                       --num_recs;
-                                       for (j=i; j<num_recs; ++j)
-                                               recs[j] = recs[j+1];
-                                       break;
-                               case 's':
-                                       printf("Save\n");
-                                       sprintf(buf, "CONF putsys|%s",
-                                               INTERNETCFG);
-                                       serv_puts(buf);
-                                       serv_gets(buf);
-                                       if (buf[0] == '4') {
-                                               for (i=0; i<num_recs; ++i) {
-                                                       serv_puts(recs[i]);
-                                               }
-                                               serv_puts("000");
-                                       }
-                                       else {
-                                               printf("%s\n", &buf[4]);
+               ch = keymenu("", "<A>dd|<D>elete|<S>ave|<Q>uit");
+               switch(ch) {
+                       case 'a':
+                               ++num_recs;
+                               if (num_recs == 1)
+                                       recs = malloc(sizeof(char *));
+                               else recs = realloc(recs,
+                                       (sizeof(char *)) * num_recs);
+                               newprompt("Enter host name: ",
+                                       buf, 50);
+                               strcat(buf, "|");
+                               get_inet_rec_type(&buf[strlen(buf)]);
+                               recs[num_recs-1] = strdup(buf);
+                               break;
+                       case 'd':
+                               i = intprompt("Delete which one",
+                                       1, 1, num_recs) - 1;
+                               free(recs[i]);
+                               --num_recs;
+                               for (j=i; j<num_recs; ++j)
+                                       recs[j] = recs[j+1];
+                               break;
+                       case 's':
+                               sprintf(buf, "CONF putsys|%s",
+                                       INTERNETCFG);
+                               serv_puts(buf);
+                               serv_gets(buf);
+                               if (buf[0] == '4') {
+                                       for (i=0; i<num_recs; ++i) {
+                                               serv_puts(recs[i]);
                                        }
-                                       quitting = 1;
-                                       break;
-                               case 'q':
-                                       printf("Quit\n");
-                                       quitting = boolprompt(
-                                               "Quit without saving", 0);
-                                       break;
-                               default:
-                                       badkey = 1;
-                       }
-               } while (badkey == 1);
+                                       serv_puts("000");
+                               }
+                               else {
+                                       printf("%s\n", &buf[4]);
+                               }
+                               quitting = 1;
+                               break;
+                       case 'q':
+                               quitting = boolprompt(
+                                       "Quit without saving", 0);
+                               break;
+                       default:
+                               badkey = 1;
+               }
        } while (quitting == 0);
 
        if (recs != NULL) {
index 3f3cc05aa33f982ebcc29f0668cd89b15df64333..272e73f9474fe1da7ecee8331ed1faef8c5db644 100644 (file)
@@ -84,12 +84,21 @@ struct ValidUser {
        long vu_usernum;
 };
 
+
+struct roomref {
+       struct roomref *next;
+       long msgnum;
+};
+
+
 struct PurgeList *UserPurgeList = NULL;
 struct PurgeList *RoomPurgeList = NULL;
 struct ValidRoom *ValidRoomList = NULL;
 struct ValidUser *ValidUserList = NULL;
 int messages_purged;
 
+struct roomref *rr = NULL;
+
 extern struct CitContext *ContextList;
 
 void DoPurgeMessages(struct quickroom *qrbuf, void *data) {
@@ -534,16 +543,51 @@ void cmd_expi(char *argbuf) {
 /*****************************************************************************/
 
 
+void do_fsck_msg(long msgnum) {
+       struct roomref *ptr;
+
+       ptr = (struct roomref *)mallok(sizeof(struct roomref));
+       ptr->next = rr;
+       ptr->msgnum = msgnum;
+       rr = ptr;
+}
+
+void do_fsck_room(struct quickroom *qrbuf, void *data)
+{
+       getroom(&CC->quickroom, qrbuf->QRname);
+       CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, do_fsck_msg);
+}
+
 /*
- * Check message reference counts (FIXME ... not yet finished)
+ * Check message reference counts
+ */
 void cmd_fsck(char *argbuf) {
        long msgnum;
        struct cdbdata *cdbmsg;
        struct SuppMsgInfo smi;
+       struct roomref *ptr;
+       int realcount;
 
-       cprintf("%d This is not done yet.\n", LISTING_FOLLOWS);
+       if ( (!CC->logged_in) || (CC->usersupp.axlevel < 6) ) {
+               cprintf("%d Higher access required\n",
+                       ERROR+HIGHER_ACCESS_REQUIRED);
+               return;
+       }
+
+       /* Lame way of checking whether anyone else is doing this now */
+       if (rr != NULL) {
+               cprintf("%d Another FSCK is already running.\n", ERROR);
+               return;
+       }
+
+       cprintf("%d Checking message reference counts\n", LISTING_FOLLOWS);
+
+       cprintf("\nThis could take a while.  Please be patient!\n\n");
+       cprintf("Gathering pointers...\n");
+       ForEachRoom(do_fsck_room, NULL);
 
        get_control();
+       cprintf("Checking message base...\n");
        for (msgnum = 0L; msgnum <= CitControl.MMhighest; ++msgnum) {
 
                cdbmsg = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long));
@@ -552,15 +596,36 @@ void cmd_fsck(char *argbuf) {
                        cprintf("Message %7ld    ", msgnum);
 
                        GetSuppMsgInfo(&smi, msgnum);
-                       cprintf("refcount=%-2d   \n", smi.smi_refcount);
+                       cprintf("refcount=%-2d   ", smi.smi_refcount);
+
+                       realcount = 0;
+                       for (ptr = rr; ptr != NULL; ptr = ptr->next) {
+                               if (ptr->msgnum == msgnum) ++realcount;
+                       }
+                       cprintf("realcount=%-2d\n", realcount);
+
+                       if ( (smi.smi_refcount != realcount)
+                          || (realcount == 0) ) {
+                               smi.smi_refcount = realcount;
+                               PutSuppMsgInfo(&smi);
+                               AdjRefCount(msgnum, 0); /* deletes if needed */
+                       }
+
                }
 
        }
 
+       cprintf("Freeing memory...\n");
+       while (rr != NULL) {
+               ptr = rr->next;
+               phree(rr);
+               rr = ptr;
+       }
+
+       cprintf("Done!\n");
        cprintf("000\n");
 
 }
- */
 
 
 
@@ -570,6 +635,6 @@ void cmd_fsck(char *argbuf) {
 char *Dynamic_Module_Init(void)
 {
        CtdlRegisterProtoHook(cmd_expi, "EXPI", "Expire old system objects");
-/* CtdlRegisterProtoHook(cmd_fsck, "FSCK", "Check message ref counts"); */
+       CtdlRegisterProtoHook(cmd_fsck, "FSCK", "Check message ref counts");
        return "$Id$";
 }
index d7eee1f7358a7c7cbffa01953a21e0edae6baeda..53f48392c6c17912ca699f4be32c4519ec7caa62 100644 (file)
@@ -501,7 +501,17 @@ int client_gets(char *buf)
  * The system-dependent part of master_cleanup() - close the master socket.
  */
 void sysdep_master_cleanup(void) {
-       /* FIXME close all protocol master sockets here */
+       struct ServiceFunctionHook *serviceptr;
+
+       /*
+        * close all protocol master sockets
+        */
+       for (serviceptr = ServiceHookTable; serviceptr != NULL;
+           serviceptr = serviceptr->next ) {
+               lprintf(3, "Closing listener on port %d\n",
+                       serviceptr->tcp_port);
+               close(serviceptr->msock);
+       }
 }
 
 
index 490375bab8bbd8953044d329a30fc6378fcc1642..1c0b0e0fe2fb51b41df6cf2a1959a03d058b2531 100644 (file)
@@ -1538,11 +1538,8 @@ UCLS command.
  ->  _userpic_   (Server will attempt to write to the user's online photo)
  ->  Any of the "well known" filenames described in the writeup for the 
      OIMG command.
-
-----------------------------------------------
-The following are for citserver 5.02 and above
-----------------------------------------------
-
+   
+  
  HCHG  (Hostname CHanGe)
 
  HCHG is a command, usable by any user, that allows a user to change their RWHO
@@ -1781,3 +1778,13 @@ and statuses.
  CICQ status
  
  Always returns OK followed by a 1 (connected to ICQ) or 0 (not connected).
+   
+  
+ FSCK   (check message base reference counts)
+ Verify, via the long way, that all message referenmce counts are correct.  If
+the user has permission to do this then LISTING_FOLLOWS is returned, followed
+by a transcript of the run.  Otherwise ERROR is returned.
+