]> code.citadel.org Git - citadel.git/blobdiff - citadel/netproc.c
* The size constant "256" which shows up everywhere as a buffer size has now
[citadel.git] / citadel / netproc.c
index 4f87696922c327ceb198273e73c07508f0dcc84f..6a887768145540ce268a6f116a74c37ad3238203 100644 (file)
@@ -1,7 +1,9 @@
 /*
+ * $Id$
+ *
  * Citadel/UX Intelligent Network Processor for IGnet/Open networks
  * See copyright.txt for copyright information
- * $Id$
+ *
  */
 
 /* How long it takes for an old node to drop off the network map */
@@ -11,7 +13,7 @@
 #define USE_TIME       (604800L)
 
 /* Where do we keep our lock file? */
-#define LOCKFILE       "/var/lock/LCK.netproc"
+#define LOCKFILE       "/tmp/netproc.LCK"
 
 /* Path to the 'uudecode' utility (needed for network file transfers) */
 #define UUDECODE       "/usr/bin/uudecode"
 #include <signal.h>
 #include <errno.h>
 #include <syslog.h>
-#ifdef HAVE_GDBM_H
-#include <gdbm.h>
-#endif
 #include "citadel.h"
 #include "tools.h"
+#include "ipc.h"
 
 /* A list of users you wish to filter out of incoming traffic can be kept
  * in ./network/filterlist -- messages from these users will be automatically
@@ -83,7 +83,41 @@ struct syslist {
 };
 
 
-void attach_to_server(int argc, char **argv);
+
+/*
+ * This structure is used to hold all of the fields of a message
+ * during conversion, processing, or whatever.
+ */
+struct minfo {
+       char A[512];
+       char B[512];
+       char C[512];
+       char D[512];
+       char E[512];
+       char G[512];
+       char H[512];
+       char I[512];
+       char N[512];
+       char O[512];
+       char P[512];
+       char R[512];
+       char S[512];
+       long T;
+       char U[512];
+       char Z[512];
+       char nexthop[512];
+       };
+
+
+struct usetable {
+       struct usetable *next;
+       char msgid[256];
+       time_t timestamp;
+};
+
+
+
+
 void serv_read(char *buf, int bytes);
 void serv_write(char *buf, int nbytes);
 void get_config(void);
@@ -91,13 +125,12 @@ void get_config(void);
 struct filterlist *filter = NULL;
 struct syslist *slist = NULL;
 struct msglist *purgelist = NULL;
+struct usetable *usetable = NULL;
 
 struct config config;
 extern char bbs_home_directory[];
 extern int home_specified;
 
-GDBM_FILE use_table;
-
 
 #ifndef HAVE_STRERROR
 /*
@@ -375,7 +408,7 @@ void load_filterlist(void)
        fp = fopen("./network/filterlist", "r");
        if (fp == NULL)
                return;
-       while (fgets(sbuf, 256, fp) != NULL) {
+       while (fgets(sbuf, sizeof sbuf, fp) != NULL) {
                if (sbuf[0] != '#') {
                        sbuf[strlen(sbuf) - 1] = 0;
                        fbuf = (struct filterlist *)
@@ -451,7 +484,7 @@ GETSN:      for (stemp = slist; stemp != NULL; stemp = stemp->next) {
 }
 
 
-void fpgetfield(FILE * fp, char *string)
+void fpgetfield(FILE *fp, char *string, int limit)
 {
        int a, b;
 
@@ -459,7 +492,7 @@ void fpgetfield(FILE * fp, char *string)
        a = 0;
        do {
                b = getc(fp);
-               if (b < 1) {
+               if ((b < 1) || (a >= limit)) {
                        string[a] = 0;
                        return;
                }
@@ -496,7 +529,7 @@ BONFGM:     b = getc(fp);
                goto END;
        if (b == 'M')
                goto END;
-       fpgetfield(fp, bbb);
+       fpgetfield(fp, bbb, sizeof bbb);
        while ((bbb[0] == ' ') && (strlen(bbb) > 1))
                strcpy(bbb, &bbb[1]);
        if (b == 'A') {
@@ -539,7 +572,7 @@ BONFGM:     b = getc(fp);
        if (b == 'T')
                buffer->T = atol(bbb);
        if (b == 'I')
-               buffer->I = atol(bbb);
+               strcpy(buffer->I, bbb);
        if (b == 'H')
                strcpy(buffer->H, bbb);
        if (b == 'B')
@@ -554,14 +587,6 @@ BONFGM:    b = getc(fp);
 
 END:
 
-       /* NOTE: we used to use the following two lines of code to assign
-        * the timestamp as a message-ID if there was no message-ID already
-        * in the message.  We don't do this anymore because it screws up
-        * the loopzapper.
-        *
-       if (buffer->I == 0L)
-               buffer->I = buffer->T;
-        */
 }
 
 
@@ -630,7 +655,7 @@ void proc_file_transfer(char *tname)
        do {
                a = getc(tfp);
                if (a != 'M') {
-                       fpgetfield(tfp, buf);
+                       fpgetfield(tfp, buf, sizeof buf);
                        if (a == 'O') {
                                strcpy(dest_room, buf);
                        }
@@ -726,7 +751,12 @@ void bounce(struct minfo *bminfo)
 void strmsgid(char *buf, struct minfo *msginfo) {
        int i;
 
-       sprintf(buf, "%ld@%s", msginfo->I, msginfo->N);
+       strcpy(buf, msginfo->I);
+       if (strchr(buf, '@') == NULL) {
+               strcat(buf, "@");
+               strcat(buf, msginfo->N);
+       }
+
        for (i=0; i<strlen(buf); ++i) {
                if (isspace(buf[i])) {
                        strcpy(&buf[i], &buf[i+1]);
@@ -742,76 +772,81 @@ void strmsgid(char *buf, struct minfo *msginfo) {
  * Returns 1 if the message is a duplicate; otherwise, it returns
  * 0 and the message ID is added to the use table.
  */
-int already_received(GDBM_FILE ut, struct minfo *msginfo) {
+int already_received(struct minfo *msginfo) {
        char buf[256];
+       struct usetable *u;
        time_t now;
-       datum mkey, newrec;
-       int retval = 0;
 
        /* We can't check for dups on a zero msgid, so just pass them through */
-       if ((msginfo->I)==0L) {
+       if (strlen(msginfo->I)==0) {
                return 0;
        }
 
        strmsgid(buf, msginfo);
        now = time(NULL);
 
-       mkey.dptr = buf;
-       mkey.dsize = strlen(buf);
-
        /* Set return value to 1 if message exists */
-       if (gdbm_exists(ut, mkey)) {
-               retval = 1;
+       for (u=usetable; u!=NULL; u=u->next) {
+               if (!strcasecmp(buf, u->msgid)) {
+                       u->timestamp = time(NULL);      /* keep it fresh */
+                       return(1);
+               }
        }
 
-       /* Write a record into the use table for this message.
-        * Replace existing records; this keeps the timestamp fresh.
-        */
-       newrec.dptr = (char *)&now;
-       newrec.dsize = sizeof(now);
-       gdbm_store(ut, mkey, newrec, GDBM_REPLACE);
+       /* Not found, so we're ok, but add it to the use table now */
+       u = (struct usetable *) malloc(sizeof (struct usetable));
+       u->next = usetable;
+       u->timestamp = time(NULL);
+       strncpy(u->msgid, buf, 255);
+       usetable = u;
 
-       return(retval);
+       return(0);
+}
+
+
+/*
+ * Load the use table from disk
+ */
+void read_use_table(void) {
+       struct usetable *u;
+       struct usetable ubuf;
+       FILE *fp;
+
+       unlink("data/usetable.gdbm");   /* we don't use this anymore */
+
+       fp = fopen("usetable", "rb");
+       if (fp == NULL) return;
+
+       while (fread(&ubuf, sizeof (struct usetable), 1, fp) > 0) {
+               u = (struct usetable *) malloc(sizeof (struct usetable));
+               memcpy(u, &ubuf, sizeof (struct usetable));
+               u->next = usetable;
+               usetable = u;
+       }
+
+       fclose(fp);
 }
 
 
 
 /*
- * Purge any old entries out of the use table.
+ * Purge any old entries out of the use table as we write them back to disk.
  * 
- * Yes, you're reading this correctly: it keeps traversing the table until
- * it manages to do a complete pass without deleting any records.  Read the
- * gdbm man page to find out why.
- *
  */
-void purge_use_table(GDBM_FILE ut) {
-       datum mkey, nextkey, therec;
-       int purged_anything = 0;
-       time_t rec_timestamp, now;
+void write_use_table(void) {
+       struct usetable *u;
+       time_t now;
+       FILE *fp;
 
        now = time(NULL);
-
-       do {
-               purged_anything = 0;
-               mkey = gdbm_firstkey(ut);
-               while (mkey.dptr != NULL) {
-                       therec = gdbm_fetch(ut, mkey);
-                       if (therec.dptr != NULL) {
-                               memcpy(&rec_timestamp, therec.dptr,
-                                       sizeof(time_t));
-                               free(therec.dptr);
-
-                               if ((now - rec_timestamp) > USE_TIME) {
-                                       gdbm_delete(ut, mkey);
-                                       purged_anything = 1;
-                               }
-
-                       }
-                       nextkey = gdbm_nextkey(ut, mkey);
-                       free(mkey.dptr);
-                       mkey = nextkey;
+       fp = fopen("usetable", "wb");
+       if (fp == NULL) return;
+       for (u=usetable; u!=NULL; u=u->next) {
+               if ((now - u->timestamp) <= USE_TIME) {
+                       fwrite(u, sizeof(struct usetable), 1, fp);
                }
-       } while (purged_anything != 0);
+       }
+       fclose(fp);
 }
 
 
@@ -825,7 +860,6 @@ void inprocess(void)
 {
        FILE *fp, *message, *testfp, *ls, *duplist;
        static struct minfo minfo;
-       struct recentmsg recentmsg;
        char tname[128], aaa[1024], iname[256], sfilename[256], pfilename[256];
        int a, b;
        int FieldID;
@@ -837,8 +871,8 @@ void inprocess(void)
        int valid_msg;
 
        /* temp file names */
-       sprintf(tname, tmpnam(NULL));
-       sprintf(iname, tmpnam(NULL));
+       sprintf(tname, "%s.netproc.%d", tmpnam(NULL), __LINE__);
+       sprintf(iname, "%s.netproc.%d", tmpnam(NULL), __LINE__);
 
        load_filterlist();
 
@@ -931,9 +965,6 @@ NXMSG:      /* Seek to the beginning of the next message */
 
                        /* process the individual mesage */
                        msgfind(tname, &minfo);
-                       strncpy(recentmsg.RMnodename, minfo.N, 9);
-                       recentmsg.RMnodename[9] = 0;
-                       recentmsg.RMnum = minfo.I;
                        syslog(LOG_NOTICE, "#%ld fm <%s> in <%s> @ <%s>",
                               minfo.I, minfo.A, minfo.O, minfo.N);
                        if (strlen(minfo.R) > 0) {
@@ -989,9 +1020,9 @@ NXMSG:     /* Seek to the beginning of the next message */
                        }
 
                        /* Check the use table; reject message if it's been here before */
-                       if (already_received(use_table, &minfo)) {
+                       if (already_received(&minfo)) {
                                syslog(LOG_NOTICE, "rejected duplicate message");
-                               fprintf(duplist, "#%ld fm <%s> in <%s> @ <%s>\n",
+                               fprintf(duplist, "#<%s> fm <%s> in <%s> @ <%s>\n",
                                        minfo.I, minfo.A, minfo.O, minfo.N);
                        }
 
@@ -1165,7 +1196,7 @@ int ismsgok(FILE *mmfp, char *sysname)
        getc(mmfp);
 
        while (a = getc(mmfp), ((a != 'M') && (a != 0))) {
-               fpgetfield(mmfp, fbuf);
+               fpgetfield(mmfp, fbuf, sizeof fbuf);
                if (a == 'P') {
                        ok = checkpath(fbuf, sysname);
                }
@@ -1243,7 +1274,7 @@ int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
 {
        struct msglist *cmptr;
        FILE *mmfp;
-       char fbuf[128];
+       char fbuf[1024];
        int a;
        int msgs_spooled = 0;
        long msg_len;
@@ -1271,6 +1302,10 @@ int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
                }
                /* download the message from the server... */
                mmfp = tmpfile();
+               if (mmfp == NULL) {
+                       syslog(LOG_NOTICE, "tmpfile() failed: %s\n",
+                               strerror(errno) );
+               }
                sprintf(buf, "MSG3 %ld", cmptr->m_num);
                serv_puts(buf);
                serv_gets(buf);
@@ -1295,13 +1330,16 @@ int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
                        fread(fbuf, 3, 1, mmfp);
                        fwrite(fbuf, 3, 1, destfp);
                        while (a = getc(mmfp), ((a != 0) && (a != 'M'))) {
-                               if (a != 'C')
+                               if (a != 'C') {
                                        putc(a, destfp);
-                               fpgetfield(mmfp, fbuf);
-                               if (a == 'P')
+                               }
+                               fpgetfield(mmfp, fbuf, sizeof fbuf);
+                               if (a == 'P') {
                                        fprintf(destfp, "%s!", NODENAME);
-                               if (a != 'C')
+                               }
+                               if (a != 'C') {
                                        fwrite(fbuf, strlen(fbuf) + 1, 1, destfp);
+                               }
                                if (a == 'S') if (!strcasecmp(fbuf, "CANCEL")) {
                                        delete_locally(cmptr->m_num, cmptr->m_rmname);
                                }
@@ -1321,7 +1359,7 @@ int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
                 */
                fseek(mmfp, 0L, 0);
                fpmsgfind(mmfp, &minfo);
-               already_received(use_table, &minfo);
+               already_received(&minfo);
 
                }
                fclose(mmfp);
@@ -1339,14 +1377,15 @@ void outprocess(char *sysname)
        char tempflnm[64];
        char buf[256];
        struct msglist *cmlist = NULL;
+       struct msglist *cmlast = NULL;
        struct rmlist *crmlist = NULL;
        struct rmlist *rmptr, *rmptr2;
-       struct msglist *cmptr, *cmptr2;
+       struct msglist *cmptr;
        FILE *sysflfp, *tempflfp;
-       int outgoing_msgs;
+       int outgoing_msgs = 0;
        long thismsg;
 
-       sprintf(tempflnm, tmpnam(NULL));
+       sprintf(tempflnm, "%s.netproc.%d", tmpnam(NULL), __LINE__);
        tempflfp = fopen(tempflnm, "w");
        if (tempflfp == NULL)
                return;
@@ -1412,14 +1451,14 @@ void outprocess(char *sysname)
                                                cmptr->m_num = thismsg;
                                                strcpy(cmptr->m_rmname, rmptr->rm_name);
 
-                                               if (cmlist == NULL)
+                                               if (cmlist == NULL) {
                                                        cmlist = cmptr;
+                                               }
                                                else {
-                                                       cmptr2 = cmlist;
-                                                       while (cmptr2->next != NULL)
-                                                               cmptr2 = cmptr2->next;
-                                                       cmptr2->next = cmptr;
+                                                       cmlast->next = cmptr;
                                                }
+                                               cmlast = cmptr;
+                                               ++outgoing_msgs;
                                        }
                        } else {        /* print error from "msgs all" */
                                syslog(LOG_ERR, "%s", buf);
@@ -1427,22 +1466,17 @@ void outprocess(char *sysname)
                }
        }
 
-       outgoing_msgs = 0;
-       cmptr2 = cmlist;        /* this loop counts the messages */
-       while (cmptr2 != NULL) {
-               ++outgoing_msgs;
-               cmptr2 = cmptr2->next;
-       }
        syslog(LOG_NOTICE, "%d messages to be spooled to %s",
               outgoing_msgs, sysname);
 
 /*
  * Spool out the messages, but only if there are any.
  */
-       if (outgoing_msgs != 0)
+       if (outgoing_msgs != 0) {
                outgoing_msgs = spool_out(cmlist, tempflfp, sysname);
-       syslog(LOG_NOTICE, "%d messages actually spooled",
-              outgoing_msgs);
+       }
+
+       syslog(LOG_NOTICE, "%d messages actually spooled", outgoing_msgs);
 
 /*
  * Deallocate list of spooled messages.
@@ -1484,14 +1518,11 @@ void outprocess(char *sysname)
 void np_attach_to_server(void)
 {
        char buf[256];
-       char portname[8];
        char *args[] =
-       {"netproc", "localhost", NULL, NULL};
+       { "netproc", NULL };
 
        syslog(LOG_NOTICE, "Attaching to server...");
-       sprintf(portname, "%d", config.c_port_number);
-       args[2] = portname;
-       attach_to_server(3, args);
+       attach_to_server(1, args, NULL, NULL);
        serv_gets(buf);
        syslog(LOG_NOTICE, "%s", &buf[4]);
        sprintf(buf, "IPGM %d", config.c_ipgm_secret);
@@ -1562,12 +1593,7 @@ int main(int argc, char **argv)
        setup_special_nodes();
 
        /* Open the use table */
-       use_table = gdbm_open("./data/usetable.gdbm", 512,
-                             GDBM_WRCREAT, 0600, 0);
-       if (use_table == NULL) {
-               syslog(LOG_ERR, "could not open use table: %s",
-                      strerror(errno));
-       }
+       read_use_table();
 
        /* first collect incoming stuff */
        inprocess();
@@ -1598,8 +1624,7 @@ int main(int argc, char **argv)
        process_purgelist();
 
        /* Close the use table */
-       purge_use_table(use_table);
-       gdbm_close(use_table);
+       write_use_table();
 
        syslog(LOG_NOTICE, "processing ended.");
        cleanup(0);