]> code.citadel.org Git - citadel.git/blob - citadel/netproc.c
netproc.c: Finished the loopzapper
[citadel.git] / citadel / netproc.c
1 /*
2  * Citadel/UX Intelligent Network Processor for IGnet/Open networks
3  * See copyright.txt for copyright information
4  * $Id$
5  */
6
7 /* How long it takes for an old node to drop off the network map */
8 #define EXPIRY_TIME     (2592000L)
9
10 /* How long we keep recently arrived messages in the use table */
11 #define USE_TIME        (604800L)
12
13 /* Where do we keep our lock file? */
14 #define LOCKFILE        "/var/lock/LCK.netproc"
15
16 /* Path to the 'uudecode' utility (needed for network file transfers) */
17 #define UUDECODE        "/usr/bin/uudecode"
18
19 /* Uncomment the DEBUG def to see noisy traces */
20 /* #define DEBUG 1 */
21
22
23 #include "sysdep.h"
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <time.h>
33 #include <signal.h>
34 #include <errno.h>
35 #include <syslog.h>
36 #include <gdbm.h>
37 #include "citadel.h"
38 #include "tools.h"
39
40 /* A list of users you wish to filter out of incoming traffic can be kept
41  * in ./network/filterlist -- messages from these users will be automatically
42  * moved to FILTERROOM.  Normally this will be the same as TWITROOM (the
43  * room problem user messages are moved to) but you can override this by
44  * specifying a different room name here.
45  */
46 #ifndef FILTERROOM
47 #define FILTERROOM TWITROOM
48 #endif
49
50 struct msglist {
51         struct msglist *next;
52         long m_num;
53         char m_rmname[ROOMNAMELEN];
54 };
55
56 struct rmlist {
57         struct rmlist *next;
58         char rm_name[ROOMNAMELEN];
59         long rm_lastsent;
60 };
61
62 struct filterlist {
63         struct filterlist *next;
64         char f_person[64];
65         char f_room[64];
66         char f_system[64];
67 };
68
69 struct syslist {
70         struct syslist *next;
71         char s_name[16];
72         char s_type[4];
73         char s_nexthop[128];
74         time_t s_lastcontact;
75         char s_humannode[64];
76         char s_phonenum[32];
77         char s_gdom[64];
78 };
79
80
81 void attach_to_server(int argc, char **argv);
82 void serv_read(char *buf, int bytes);
83 void serv_write(char *buf, int nbytes);
84 void get_config(void);
85
86 struct filterlist *filter = NULL;
87 struct syslist *slist = NULL;
88
89 struct config config;
90 extern char bbs_home_directory[];
91 extern int home_specified;
92
93
94 #ifndef HAVE_STRERROR
95 /*
96  * replacement strerror() for systems that don't have it
97  */
98 char *strerror(int e)
99 {
100         static char buf[32];
101
102         sprintf(buf, "errno = %d", e);
103         return (buf);
104 }
105 #endif
106
107
108 void strip_trailing_whitespace(char *buf)
109 {
110         while (isspace(buf[strlen(buf) - 1]))
111                 buf[strlen(buf) - 1] = 0;
112 }
113
114
115 /*
116  * we also load the network/mail.sysinfo table into memory, make changes
117  * as we learn more about the network from incoming messages, and write
118  * the table back to disk when we're done.
119  */
120 int load_syslist(void)
121 {
122         FILE *fp;
123         struct syslist *stemp;
124         char insys = 0;
125         char buf[128];
126
127         fp = fopen("network/mail.sysinfo", "r");
128         if (fp == NULL)
129                 return (1);
130
131         while (1) {
132                 if (fgets(buf, 128, fp) == NULL) {
133                         fclose(fp);
134                         return (0);
135                 }
136                 buf[strlen(buf) - 1] = 0;
137                 while (isspace(buf[0]))
138                         strcpy(buf, &buf[1]);
139                 if (buf[0] == '#')
140                         buf[0] = 0;
141                 if ((insys == 0) && (strlen(buf) != 0)) {
142                         insys = 1;
143                         stemp = (struct syslist *) malloc(sizeof(struct syslist));
144                         stemp->next = slist;
145                         slist = stemp;
146                         strcpy(slist->s_name, buf);
147                         strcpy(slist->s_type, "bin");
148                         strcpy(slist->s_nexthop, "Mail");
149                         slist->s_lastcontact = 0L;
150                         strcpy(slist->s_humannode, "");
151                         strcpy(slist->s_phonenum, "");
152                         strcpy(slist->s_gdom, "");
153                 } else if ((insys == 1) && (strlen(buf) == 0)) {
154                         insys = 0;
155                 } else if ((insys == 1) && (!strncasecmp(buf, "bin", 3))) {
156                         strcpy(slist->s_type, "bin");
157                         strcpy(slist->s_nexthop, &buf[4]);
158                 } else if ((insys == 1) && (!strncasecmp(buf, "use", 3))) {
159                         strcpy(slist->s_type, "use");
160                         strcpy(slist->s_nexthop, &buf[4]);
161                 } else if ((insys == 1) && (!strncasecmp(buf, "uum", 3))) {
162                         strcpy(slist->s_type, "uum");
163                         strcpy(slist->s_nexthop, &buf[4]);
164                 } else if ((insys == 1) && (!strncasecmp(buf, "lastcontact", 11))) {
165                         long foo;
166                         sscanf(&buf[12], "%ld", &foo);
167                         slist->s_lastcontact = foo;
168                 } else if ((insys == 1) && (!strncasecmp(buf, "humannode", 9))) {
169                         strcpy(slist->s_humannode, &buf[10]);
170                 } else if ((insys == 1) && (!strncasecmp(buf, "phonenum", 8))) {
171                         strcpy(slist->s_phonenum, &buf[9]);
172                 } else if ((insys == 1) && (!strncasecmp(buf, "gdom", 4))) {
173                         strcpy(slist->s_gdom, &buf[5]);
174                 }
175         }
176 }
177
178 /* now we have to set up two "special" nodes on the list: one
179  * for the local node, and one for an Internet gateway
180  */
181 void setup_special_nodes(void)
182 {
183         struct syslist *stemp, *slocal;
184
185         slocal = NULL;
186         for (stemp = slist; stemp != NULL; stemp = stemp->next) {
187                 if (!strcasecmp(stemp->s_name, config.c_nodename))
188                         slocal = stemp;
189         }
190         if (slocal == NULL) {
191                 slocal = (struct syslist *) malloc(sizeof(struct syslist));
192                 slocal->next = slist;
193                 slist = slocal;
194         }
195         strcpy(slocal->s_name, config.c_nodename);
196         strcpy(slocal->s_type, "bin");
197         strcpy(slocal->s_nexthop, "Mail");
198         time(&slocal->s_lastcontact);
199         strcpy(slocal->s_humannode, config.c_humannode);
200         strcpy(slocal->s_phonenum, config.c_phonenum);
201
202         slocal = NULL;
203         for (stemp = slist; stemp != NULL; stemp = stemp->next) {
204                 if (!strcasecmp(stemp->s_name, "internet"))
205                         slocal = stemp;
206         }
207         if (slocal == NULL) {
208                 slocal = (struct syslist *) malloc(sizeof(struct syslist));
209                 slocal->next = slist;
210                 slist = slocal;
211         }
212         strcpy(slocal->s_name, "internet");
213         strcpy(slocal->s_type, "uum");
214         strcpy(slocal->s_nexthop, "%s");
215         time(&slocal->s_lastcontact);
216         strcpy(slocal->s_humannode, "Internet Gateway");
217         strcpy(slocal->s_phonenum, "");
218         strcpy(slocal->s_gdom, "");
219
220 }
221
222 /*
223  * here's the routine to write the table back to disk.
224  */
225 void rewrite_syslist(void)
226 {
227         struct syslist *stemp;
228         FILE *newfp;
229         time_t now;
230
231         time(&now);
232         newfp = fopen("network/mail.sysinfo", "w");
233         for (stemp = slist; stemp != NULL; stemp = stemp->next) {
234                 if (!strcasecmp(stemp->s_name, config.c_nodename)) {
235                         time(&stemp->s_lastcontact);
236                         strcpy(stemp->s_type, "bin");
237                         strcpy(stemp->s_humannode, config.c_humannode);
238                         strcpy(stemp->s_phonenum, config.c_phonenum);
239                 }
240                 /* remove systems we haven't heard from in a while */
241                 if ((stemp->s_lastcontact == 0L)
242                     || (now - stemp->s_lastcontact < EXPIRY_TIME)) {
243                         fprintf(newfp, "%s\n%s %s\n",
244                          stemp->s_name, stemp->s_type, stemp->s_nexthop);
245                         if (strlen(stemp->s_phonenum) > 0)
246                                 fprintf(newfp, "phonenum %s\n", stemp->s_phonenum);
247                         if (strlen(stemp->s_gdom) > 0)
248                                 fprintf(newfp, "gdom %s\n", stemp->s_gdom);
249                         if (strlen(stemp->s_humannode) > 0)
250                                 fprintf(newfp, "humannode %s\n", stemp->s_humannode);
251                         if (stemp->s_lastcontact > 0L)
252                                 fprintf(newfp, "lastcontact %ld %s",
253                                         (long) stemp->s_lastcontact,
254                                         asctime(localtime(&stemp->s_lastcontact)));
255                         fprintf(newfp, "\n");
256                 }
257         }
258         fclose(newfp);
259         /* now free the list */
260         while (slist != NULL) {
261                 stemp = slist;
262                 slist = slist->next;
263                 free(stemp);
264         }
265 }
266
267
268 /* call this function with the node name of a system and it returns a pointer
269  * to its syslist structure.
270  */
271 struct syslist *get_sys_ptr(char *sysname)
272 {
273         static char sysnambuf[16];
274         static struct syslist *sysptrbuf = NULL;
275         struct syslist *stemp;
276
277         if ((!strcmp(sysname, sysnambuf))
278             && (sysptrbuf != NULL))
279                 return (sysptrbuf);
280
281         strcpy(sysnambuf, sysname);
282         for (stemp = slist; stemp != NULL; stemp = stemp->next) {
283                 if (!strcmp(sysname, stemp->s_name)) {
284                         sysptrbuf = stemp;
285                         return (stemp);
286                 }
287         }
288         sysptrbuf = NULL;
289         return (NULL);
290 }
291
292
293 /*
294  * make sure only one copy of netproc runs at a time, using lock files
295  */
296 int set_lockfile(void)
297 {
298         FILE *lfp;
299         int onppid;
300
301         if ((lfp = fopen(LOCKFILE, "r")) != NULL) {
302                 fscanf(lfp, "%d", &onppid);
303                 fclose(lfp);
304                 if (!kill(onppid, 0) || errno == EPERM)
305                         return 1;
306         }
307         lfp = fopen(LOCKFILE, "w");
308         fprintf(lfp, "%ld\n", (long) getpid());
309         fclose(lfp);
310         return (0);
311 }
312
313 void remove_lockfile(void)
314 {
315         unlink(LOCKFILE);
316 }
317
318 /*
319  * Why both cleanup() and nq_cleanup() ?  Notice the alarm() call in
320  * cleanup() .  If for some reason netproc hangs waiting for the server
321  * to clean up, the alarm clock goes off and the program exits anyway.
322  * The cleanup() routine makes a check to ensure it's not reentering, in
323  * case the ipc module looped it somehow.
324  */
325 void nq_cleanup(int e)
326 {
327         remove_lockfile();
328         closelog();
329         exit(e);
330 }
331
332 void cleanup(int e)
333 {
334         static int nested = 0;
335
336         alarm(30);
337         signal(SIGALRM, nq_cleanup);
338         if (nested++ < 1)
339                 serv_puts("QUIT");
340         nq_cleanup(e);
341 }
342
343 /*
344  * This is implemented as a function rather than as a macro because the
345  * client-side IPC modules expect logoff() to be defined.  They call logoff()
346  * when a problem connecting or staying connected to the server occurs.
347  */
348 void logoff(int e)
349 {
350         cleanup(e);
351 }
352
353 /*
354  * If there is a kill file in place, this function will process it.
355  */
356 void load_filterlist(void)
357 {
358         FILE *fp;
359         struct filterlist *fbuf;
360         char sbuf[256];
361         int a, p;
362         fp = fopen("./network/filterlist", "r");
363         if (fp == NULL)
364                 return;
365         while (fgets(sbuf, 256, fp) != NULL) {
366                 if (sbuf[0] != '#') {
367                         sbuf[strlen(sbuf) - 1] = 0;
368                         fbuf = (struct filterlist *)
369                             malloc((long) sizeof(struct filterlist));
370                         fbuf->next = filter;
371                         filter = fbuf;
372                         strcpy(fbuf->f_person, "*");
373                         strcpy(fbuf->f_room, "*");
374                         strcpy(fbuf->f_system, "*");
375                         p = (-1);
376                         for (a = strlen(sbuf); a >= 0; --a)
377                                 if (sbuf[a] == ',')
378                                         p = a;
379                         if (p >= 0) {
380                                 sbuf[p] = 0;
381                                 strcpy(fbuf->f_person, sbuf);
382                                 strcpy(sbuf, &sbuf[p + 1]);
383                         }
384                         for (a = strlen(sbuf); a >= 0; --a)
385                                 if (sbuf[a] == ',')
386                                         p = a;
387                         if (p >= 0) {
388                                 sbuf[p] = 0;
389                                 strcpy(fbuf->f_room, sbuf);
390                                 strcpy(sbuf, &sbuf[p + 1]);
391                         }
392                         strcpy(fbuf->f_system, sbuf);
393                 }
394         }
395         fclose(fp);
396 }
397
398 /* returns 1 if user/message/room combination is in the kill file */
399 int is_banned(char *k_person, char *k_room, char *k_system)
400 {
401         struct filterlist *fptr;
402
403         for (fptr = filter; fptr != NULL; fptr = fptr->next)
404                 if (
405                            ((!strcasecmp(fptr->f_person, k_person)) || (!strcmp(fptr->f_person, "*")))
406                            &&
407                            ((!strcasecmp(fptr->f_room, k_room)) || (!strcmp(fptr->f_room, "*")))
408                            &&
409                            ((!strcasecmp(fptr->f_system, k_system)) || (!strcmp(fptr->f_system, "*")))
410                     )
411                         return (1);
412
413         return (0);
414 }
415
416 int get_sysinfo_type(char *name)
417 {                               /* determine routing from sysinfo file */
418         struct syslist *stemp;
419       GETSN:for (stemp = slist; stemp != NULL; stemp = stemp->next) {
420                 if (!strcasecmp(stemp->s_name, name)) {
421                         if (!strcasecmp(stemp->s_type, "use")) {
422                                 strcpy(name, stemp->s_nexthop);
423                                 goto GETSN;
424                         }
425                         if (!strcasecmp(stemp->s_type, "bin")) {
426                                 return (MES_BINARY);
427                         }
428                         if (!strcasecmp(stemp->s_type, "uum")) {
429                                 return (MES_INTERNET);
430                         }
431                 }
432         }
433         syslog(LOG_ERR, "cannot find system '%s' in mail.sysinfo", name);
434         return (-1);
435 }
436
437
438 void fpgetfield(FILE * fp, char *string)
439 {
440         int a, b;
441
442         strcpy(string, "");
443         a = 0;
444         do {
445                 b = getc(fp);
446                 if (b < 1) {
447                         string[a] = 0;
448                         return;
449                 }
450                 string[a] = b;
451                 ++a;
452         } while (b != 0);
453 }
454
455
456
457 /*
458  * Load all of the fields of a message, except the actual text, into a
459  * table in memory (so we know how to process the message).
460  */
461 void msgfind(char *msgfile, struct minfo *buffer)
462 {
463         int b, e, mtype, aflag;
464         char bbb[1024];
465         char userid[1024];
466         FILE *fp;
467
468         strcpy(userid, "");
469         fp = fopen(msgfile, "rb");
470         if (fp == NULL) {
471                 syslog(LOG_ERR, "can't open message file: %s", strerror(errno));
472                 return;
473         }
474         e = getc(fp);
475         if (e != 255) {
476                 syslog(LOG_ERR, "incorrect message format");
477                 goto END;
478         }
479         mtype = getc(fp);
480         aflag = getc(fp);
481         buffer->I = 0L;
482         buffer->R[0] = 0;
483         buffer->E[0] = 0;
484         buffer->H[0] = 0;
485         buffer->S[0] = 0;
486         buffer->B[0] = 0;
487         buffer->G[0] = 0;
488
489       BONFGM:b = getc(fp);
490         if (b < 0)
491                 goto END;
492         if (b == 'M')
493                 goto END;
494         fpgetfield(fp, bbb);
495         while ((bbb[0] == ' ') && (strlen(bbb) > 1))
496                 strcpy(bbb, &bbb[1]);
497         if (b == 'A') {
498                 strcpy(buffer->A, bbb);
499                 if (strlen(userid) == 0) {
500                         strcpy(userid, bbb);
501                         for (e = 0; e < strlen(userid); ++e)
502                                 if (userid[e] == ' ')
503                                         userid[e] = '_';
504                 }
505         }
506         if (b == 'O')
507                 strcpy(buffer->O, bbb);
508         if (b == 'C')
509                 strcpy(buffer->C, bbb);
510         if (b == 'N')
511                 strcpy(buffer->N, bbb);
512         if (b == 'S')
513                 strcpy(buffer->S, bbb);
514         if (b == 'P') {
515                 /* extract the user id from the path */
516                 for (e = 0; e < strlen(bbb); ++e)
517                         if (bbb[e] == '!')
518                                 strcpy(userid, &bbb[e + 1]);
519
520                 /* now find the next hop */
521                 for (e = 0; e < strlen(bbb); ++e)
522                         if (bbb[e] == '!')
523                                 bbb[e] = 0;
524                 strcpy(buffer->nexthop, bbb);
525         }
526         if (b == 'R') {
527                 for (e = 0; e < strlen(bbb); ++e)
528                         if (bbb[e] == '_')
529                                 bbb[e] = ' ';
530                 strcpy(buffer->R, bbb);
531         }
532         if (b == 'D')
533                 strcpy(buffer->D, bbb);
534         if (b == 'T')
535                 buffer->T = atol(bbb);
536         if (b == 'I')
537                 buffer->I = atol(bbb);
538         if (b == 'H')
539                 strcpy(buffer->H, bbb);
540         if (b == 'B')
541                 strcpy(buffer->B, bbb);
542         if (b == 'G')
543                 strcpy(buffer->G, bbb);
544         if (b == 'E')
545                 strcpy(buffer->E, bbb);
546         goto BONFGM;
547
548       END:if (buffer->I == 0L)
549                 buffer->I = buffer->T;
550         fclose(fp);
551 }
552
553 void ship_to(char *filenm, char *sysnm)
554 {                               /* send spool file filenm to system sysnm */
555         char sysflnm[100];
556         char commbuf1[100];
557         char commbuf2[100];
558         FILE *sysflfd;
559
560 #ifdef DEBUG
561         syslog(LOG_NOTICE, "shipping %s to %s", filenm, sysnm);
562 #endif
563         sprintf(sysflnm, "./network/systems/%s", sysnm);
564         sysflfd = fopen(sysflnm, "r");
565         if (sysflfd == NULL)
566                 syslog(LOG_ERR, "cannot open %s", sysflnm);
567         fgets(commbuf1, 99, sysflfd);
568         commbuf1[strlen(commbuf1) - 1] = 0;
569         fclose(sysflfd);
570         sprintf(commbuf2, commbuf1, filenm);
571         system(commbuf2);
572 }
573
574 /*
575  * proc_file_transfer()  -  handle a simple file transfer packet
576  *
577  */
578 void proc_file_transfer(char *tname)
579 {                               /* name of temp file containing the whole message */
580         char buf[256];
581         char dest_room[ROOMNAMELEN];
582         char subdir_name[256];
583         FILE *tfp, *uud;
584         int a;
585
586         syslog(LOG_NOTICE, "processing network file transfer...");
587
588         tfp = fopen(tname, "rb");
589         if (tfp == NULL)
590                 syslog(LOG_ERR, "cannot open %s", tname);
591         getc(tfp);
592         getc(tfp);
593         getc(tfp);
594         do {
595                 a = getc(tfp);
596                 if (a != 'M') {
597                         fpgetfield(tfp, buf);
598                         if (a == 'O') {
599                                 strcpy(dest_room, buf);
600                         }
601                 }
602         } while ((a != 'M') && (a >= 0));
603         if (a != 'M') {
604                 fclose(tfp);
605                 syslog(LOG_ERR, "no message text for file transfer");
606                 return;
607         }
608         strcpy(subdir_name, "---xxx---");
609         sprintf(buf, "GOTO %s", dest_room);
610         serv_puts(buf);
611         serv_gets(buf);
612         if (buf[0] == '2') {
613                 extract(subdir_name, &buf[4], 2);
614                 if (strlen(subdir_name) == 0)
615                         strcpy(subdir_name, "--xxx--");
616         }
617         /* Change to the room's directory; if that fails, change to the
618          * bitbucket directory.  Then run uudecode.
619          */
620         sprintf(buf, "(cd %s/files/%s || cd %s/files/%s ) ; exec %s",
621                 bbs_home_directory, subdir_name,
622                 bbs_home_directory, config.c_bucket_dir,
623                 UUDECODE);
624
625         uud = (FILE *) popen(buf, "w");
626         if (uud == NULL) {
627                 syslog(LOG_ERR, "cannot open uudecode pipe");
628                 fclose(tfp);
629                 return;
630         }
631         fgets(buf, 128, tfp);
632         buf[strlen(buf) - 1] = 0;
633         for (a = 0; a < strlen(buf); ++a)
634                 if (buf[a] == '/')
635                         buf[a] = '_';
636         fprintf(uud, "%s\n", buf);
637         printf("netproc: %s\n", buf);
638         while (a = getc(tfp), a > 0)
639                 putc(a, uud);
640         fclose(tfp);
641         pclose(uud);
642         return;
643 }
644
645
646 /* send a bounce message */
647 void bounce(struct minfo *bminfo)
648 {
649
650         FILE *bounce;
651         char bfilename[64];
652         static int bseq = 1;
653         time_t now;
654
655         sprintf(bfilename, "./network/spoolin/bounce.%ld.%d", (long) getpid(),
656                 bseq++);
657         bounce = fopen(bfilename, "wb");
658         time(&now);
659
660         fprintf(bounce, "%c%c%c", 0xFF, MES_NORMAL, 0);
661         fprintf(bounce, "Ppostmaster%c", 0);
662         fprintf(bounce, "T%ld%c", (long) now, 0);
663         fprintf(bounce, "APostmaster%c", 0);
664         fprintf(bounce, "OMail%c", 0);
665         fprintf(bounce, "N%s%c", config.c_nodename, 0);
666         fprintf(bounce, "H%s%c", config.c_humannode, 0);
667
668         if (strlen(bminfo->E) > 0) {
669                 fprintf(bounce, "R%s%c", bminfo->E, 0);
670         } else {
671                 fprintf(bounce, "R%s%c", bminfo->A, 0);
672         }
673
674         fprintf(bounce, "D%s%c", bminfo->N, 0);
675         fprintf(bounce, "M%s could not deliver your mail to:\n",
676                 config.c_humannode);
677         fprintf(bounce, " \n %s\n \n", bminfo->R);
678         fprintf(bounce, " because there is no such user on this system.\n");
679         fprintf(bounce, " (Unsent message does *not* follow.  ");
680         fprintf(bounce, "Help to conserve bandwidth.)\n%c", 0);
681         fclose(bounce);
682 }
683
684
685
686
687 /*
688  * Generate a Message-ID string for the use table
689  */
690 void strmsgid(char *buf, struct minfo *msginfo) {
691         int i;
692
693         sprintf(buf, "%ld@%s", msginfo->I, msginfo->N);
694         for (i=0; i<strlen(buf); ++i) {
695                 if (isspace(buf[i])) {
696                         strcpy(&buf[i], &buf[i+1]);
697                 }
698                 buf[i] = tolower(buf[i]);
699         }
700 }
701
702
703
704 /*
705  * Check the use table to see if a message has been here before.
706  * Returns 1 if the message is a duplicate; otherwise, it returns
707  * 0 and the message ID is added to the use table.
708  */
709 int already_received(GDBM_FILE ut, struct minfo *msginfo) {
710         char buf[256];
711         time_t now;
712         datum mkey, newrec;
713         int retval = 0;
714
715         /* We can't check for dups on a zero msgid, so just pass them through */
716         if ((msginfo->I)==0L) {
717                 return 0;
718         }
719
720         strmsgid(buf, msginfo);
721         now = time(NULL);
722
723         mkey.dptr = buf;
724         mkey.dsize = strlen(buf);
725
726         /* Set return value to 1 if message exists */
727         if (gdbm_exists(ut, mkey)) {
728                 retval = 1;
729         }
730
731         /* Write a record into the use table for this message.
732          * Replace existing records; this keeps the timestamp fresh.
733          */
734         newrec.dptr = (char *)&now;
735         newrec.dsize = sizeof(now);
736         gdbm_store(ut, mkey, newrec, GDBM_REPLACE);
737
738         return(retval);
739 }
740
741
742
743 /*
744  * Purge any old entries out of the use table.
745  * 
746  * Yes, you're reading this correctly: it keeps traversing the table until
747  * it manages to do a complete pass without deleting any records.  Read the
748  * gdbm man page to find out why.
749  *
750  */
751 void purge_use_table(GDBM_FILE ut) {
752         datum mkey, nextkey, therec;
753         int purged_anything = 0;
754         time_t rec_timestamp, now;
755
756         now = time(NULL);
757
758         do {
759                 purged_anything = 0;
760                 mkey = gdbm_firstkey(ut);
761                 while (mkey.dptr != NULL) {
762                         therec = gdbm_fetch(ut, mkey);
763                         if (therec.dptr != NULL) {
764                                 memcpy(&rec_timestamp, therec.dptr,
765                                         sizeof(time_t));
766                                 free(therec.dptr);
767
768                                 if ((now - rec_timestamp) > USE_TIME) {
769                                         gdbm_delete(ut, mkey);
770                                         purged_anything = 1;
771                                 }
772
773                         }
774                         nextkey = gdbm_nextkey(ut, mkey);
775                         free(mkey.dptr);
776                         mkey = nextkey;
777                 }
778         } while (purged_anything != 0);
779 }
780
781
782
783 /*
784  * process incoming files in ./network/spoolin
785  */
786 void inprocess(void)
787 {
788         FILE *fp, *message, *testfp, *ls, *duplist;
789         static struct minfo minfo;
790         struct recentmsg recentmsg;
791         char tname[128], aaa[1024], iname[256], sfilename[256], pfilename[256];
792         int a, b;
793         int FieldID;
794         struct syslist *stemp;
795         char *ptr = NULL;
796         char buf[256];
797         long msglen;
798         int bloklen;
799         GDBM_FILE use_table;
800
801         /* temp file names */
802         sprintf(tname, tmpnam(NULL));
803         sprintf(iname, tmpnam(NULL));
804
805         load_filterlist();
806
807         /* Make sure we're in the right directory */
808         chdir(bbs_home_directory);
809
810         /* Open the use table */
811         use_table = gdbm_open("./data/usetable.gdbm", 512,
812                               GDBM_WRCREAT, 0600, 0);
813         if (use_table == NULL) {
814                 syslog(LOG_ERR, "could not open use table: %s",
815                        strerror(errno));
816         }
817
818
819         /* temporary file to contain a log of rejected dups */
820         duplist = tmpfile();
821
822         /* Let the shell do the dirty work. Get all data from spoolin */
823         do {
824                 sprintf(aaa, "cd %s/network/spoolin; ls", bbs_home_directory);
825                 ls = popen(aaa, "r");
826                 if (ls == NULL) {
827                         syslog(LOG_ERR, "could not open dir cmd: %s", strerror(errno));
828                 }
829                 if (ls != NULL) {
830                         do {
831 SKIP:                           ptr = fgets(sfilename, sizeof sfilename, ls);
832                                 if (ptr != NULL) {
833                                         sfilename[strlen(sfilename) - 1] = 0;
834                                         if (!strcmp(sfilename, ".")) goto SKIP;
835                                         if (!strcmp(sfilename, "..")) goto SKIP;
836                                         if (!strcmp(sfilename, "CVS")) goto SKIP;
837                                         goto PROCESS_IT;
838                                 }
839                         } while (ptr != NULL);
840 PROCESS_IT:             pclose(ls);
841                 }
842                 if (ptr != NULL) {
843                         sprintf(pfilename, "%s/network/spoolin/%s", bbs_home_directory, sfilename);
844                         syslog(LOG_NOTICE, "processing <%s>", pfilename);
845
846                         fp = fopen(pfilename, "rb");
847                         if (fp == NULL) {
848                                 syslog(LOG_ERR, "cannot open %s: %s", pfilename, strerror(errno));
849                                 fp = fopen("/dev/null", "rb");
850                         }
851 NXMSG:  /* Seek to the beginning of the next message */
852                         do {
853                                 a = getc(fp);
854                         } while ((a != 255) && (a >= 0));
855                         if (a < 0)
856                                 goto ENDSTR;
857
858                         /* This crates the temporary file. */
859                         message = fopen(tname, "wb");
860                         if (message == NULL) {
861                                 syslog(LOG_ERR, "error creating %s: %s",
862                                         tname, strerror(errno));
863                                 goto ENDSTR;
864                         }
865                         putc(255, message);     /* 0xFF (start-of-message) */
866                         a = getc(fp);
867                         putc(a, message);       /* type */
868                         a = getc(fp);
869                         putc(a, message);       /* mode */
870                         do {
871                                 FieldID = getc(fp);     /* Header field ID */
872                                 putc(FieldID, message);
873                                 do {
874                                         a = getc(fp);
875                                         putc(a, message);
876                                 } while (a > 0);
877                         } while ((FieldID != 'M') && (a >= 0));
878                         /* M is always last */
879
880                         msglen = ftell(message);
881                         fclose(message);
882
883                         /* process the individual mesage */
884                         minfo.D[0] = 0;
885                         minfo.C[0] = 0;
886                         minfo.B[0] = 0;
887                         minfo.G[0] = 0;
888                         minfo.R[0] = 0;
889                         msgfind(tname, &minfo);
890                         strncpy(recentmsg.RMnodename, minfo.N, 9);
891                         recentmsg.RMnodename[9] = 0;
892                         recentmsg.RMnum = minfo.I;
893                         syslog(LOG_NOTICE, "#%ld fm <%s> in <%s> @ <%s>",
894                                minfo.I, minfo.A, minfo.O, minfo.N);
895                         if (strlen(minfo.R) > 0) {
896                                 syslog(LOG_NOTICE, "     to <%s>", minfo.R);
897                                 if (strlen(minfo.D) > 0) {
898                                         syslog(LOG_NOTICE, "     @ <%s>",
899                                                 minfo.D);
900                                 }
901                         }
902                         if (!strcasecmp(minfo.D, FQDN))
903                                 strcpy(minfo.D, NODENAME);
904
905 /* this routine updates our info on the system that sent the message */
906                         stemp = get_sys_ptr(minfo.N);
907                         if ((stemp == NULL) && (get_sys_ptr(minfo.nexthop) != NULL)) {
908                                 /* add non-neighbor system to map */
909                                 syslog(LOG_NOTICE, "Adding non-neighbor system <%s> to map",
910                                        slist->s_name);
911                                 stemp = (struct syslist *) malloc((long) sizeof(struct syslist));
912                                 stemp->next = slist;
913                                 slist = stemp;
914                                 strcpy(slist->s_name, minfo.N);
915                                 strcpy(slist->s_type, "use");
916                                 strcpy(slist->s_nexthop, minfo.nexthop);
917                                 time(&slist->s_lastcontact);
918                         } else if ((stemp == NULL) && (!strcasecmp(minfo.N, minfo.nexthop))) {
919                                 /* add neighbor system to map */
920                                 syslog(LOG_NOTICE, "Adding neighbor system <%s> to map",
921                                        slist->s_name);
922                                 sprintf(aaa, "%s/network/systems/%s", bbs_home_directory, minfo.N);
923                                 testfp = fopen(aaa, "r");
924                                 if (testfp != NULL) {
925                                         fclose(testfp);
926                                         stemp = (struct syslist *)
927                                             malloc((long) sizeof(struct syslist));
928                                         stemp->next = slist;
929                                         slist = stemp;
930                                         strcpy(slist->s_name, minfo.N);
931                                         strcpy(slist->s_type, "bin");
932                                         strcpy(slist->s_nexthop, "Mail");
933                                         time(&slist->s_lastcontact);
934                                 }
935                         }
936                         /* now update last contact and long node name if we can */
937                         if (stemp != NULL) {
938                                 time(&stemp->s_lastcontact);
939                                 if (strlen(minfo.H) > 0)
940                                         strcpy(stemp->s_humannode, minfo.H);
941                                 if (strlen(minfo.B) > 0)
942                                         strcpy(stemp->s_phonenum, minfo.B);
943                                 if (strlen(minfo.G) > 0)
944                                         strcpy(stemp->s_gdom, minfo.G);
945                         }
946
947                         /* Check the use table; reject message if it's been here before */
948                         if (already_received(use_table, &minfo)) {
949                                 syslog(LOG_NOTICE, "rejected duplicate message");
950                                 fprintf(duplist, "#%ld fm <%s> in <%s> @ <%s>\n",
951                                         minfo.I, minfo.A, minfo.O, minfo.N);
952                         }
953
954
955                         /* route the message if necessary */
956                         else if ((strcasecmp(minfo.D, NODENAME)) && (minfo.D[0] != 0)) {
957                                 a = get_sysinfo_type(minfo.D);
958                                 syslog(LOG_NOTICE, "routing message to system <%s>", minfo.D);
959                                 fflush(stdout);
960                                 if (a == MES_INTERNET) {
961                                         if (fork() == 0) {
962                                                 syslog(LOG_NOTICE, "netmailer %s", tname);
963                                                 fflush(stdout);
964                                                 execlp("./netmailer", "netmailer",
965                                                        tname, NULL);
966                                                 syslog(LOG_ERR, "error running netmailer: %s",
967                                                        strerror(errno));
968                                                 exit(errno);
969                                         } else
970                                                 while (wait(&b) != (-1));
971                                 } else if (a == MES_BINARY) {
972                                         ship_to(tname, minfo.D);
973                                 } else {
974                                         /* message falls into the bit bucket? */
975                                 }
976                         }
977
978                         /* check to see if it's a file transfer */
979                         else if (!strncasecmp(minfo.S, "FILE", 4)) {
980                                 proc_file_transfer(tname);
981                         }
982
983                         /* otherwise process it as a normal message */
984                         else {
985
986                                 if (!strcasecmp(minfo.R, "postmaster")) {
987                                         strcpy(minfo.R, "");
988                                         strcpy(minfo.C, "Aide");
989                                 }
990                                 if (strlen(minfo.R) > 0) {
991                                         sprintf(buf, "GOTO _MAIL_");
992                                 }
993                                 if (is_banned(minfo.A, minfo.C, minfo.N)) {
994                                         sprintf(buf, "GOTO %s", FILTERROOM);
995                                 } else {
996                                         if (strlen(minfo.C) > 0) {
997                                                 sprintf(buf, "GOTO %s", minfo.C);
998                                         } else {
999                                                 sprintf(buf, "GOTO %s", minfo.O);
1000                                         }
1001                                 }
1002                                 serv_puts(buf);
1003                                 serv_gets(buf);
1004                                 if (buf[0] != '2') {
1005                                         syslog(LOG_ERR, "%s", buf);
1006                                         sprintf(buf, "GOTO _BITBUCKET_");
1007                                         serv_puts(buf);
1008                                         serv_gets(buf);
1009                                 }
1010                                 /* Open the temporary file containing the message */
1011                                 message = fopen(tname, "rb");
1012                                 if (message == NULL) {
1013                                         syslog(LOG_ERR, "cannot open %s: %s",
1014                                                tname, strerror(errno));
1015                                         unlink(tname);
1016                                         goto NXMSG;
1017                                 }
1018                                 /* Transmit the message to the server */
1019                                 sprintf(buf, "ENT3 1|%s|%ld", minfo.R, msglen);
1020                                 serv_puts(buf);
1021                                 serv_gets(buf);
1022                                 if (!strncmp(buf, "570", 3)) {
1023                                         /* no such user, do a bounce */
1024                                         bounce(&minfo);
1025                                 }
1026                                 if (buf[0] == '7') {
1027                                         /* Always use the server's idea of the message length,
1028                                          * even though they should both be identical */
1029                                         msglen = atol(&buf[4]);
1030                                         while (msglen > 0L) {
1031                                                 bloklen = ((msglen >= 255L) ? 255 : ((int) msglen));
1032                                                 if (fread(buf, bloklen, 1, message) < 1) {
1033                                                         syslog(LOG_ERR,
1034                                                                "error trying to read %d bytes: %s",
1035                                                                bloklen, strerror(errno));
1036                                                 }
1037                                                 serv_write(buf, bloklen);
1038                                                 msglen = msglen - (long) bloklen;
1039                                         }
1040                                         serv_puts("NOOP");
1041                                         serv_gets(buf);
1042                                 } else {
1043                                         syslog(LOG_ERR, "%s", buf);
1044                                 }
1045
1046                                 fclose(message);
1047                         }
1048
1049                         unlink(tname);
1050                         goto NXMSG;
1051
1052 ENDSTR:                 fclose(fp);
1053                         unlink(pfilename);
1054                 }
1055         } while (ptr != NULL);
1056         unlink(iname);
1057
1058         purge_use_table(use_table);
1059         gdbm_close(use_table);
1060
1061
1062         /*
1063          * If dups were rejected, post a message saying so
1064          */
1065         if (ftell(duplist)!=0L) {
1066                 fp = fopen("./network/spoolin/ctdl_rejects", "ab");
1067                 if (fp != NULL) {
1068                         fprintf(fp, "%cA%c", 255, 1);
1069                         fprintf(fp, "T%ld%c", time(NULL), 0);
1070                         fprintf(fp, "ACitadel%c", 0);
1071                         fprintf(fp, "OAide%cM", 0);
1072                         fprintf(fp, "The following duplicate messages"
1073                                 " were rejected:\n \n");
1074                         rewind(duplist);
1075                         while (fgets(buf, sizeof(buf), duplist) != NULL) {
1076                                 buf[strlen(buf)-1] = 0;
1077                                 fprintf(fp, " %s\n", buf);
1078                         }
1079                         fprintf(fp, "%c", 0);
1080                         pclose(fp);
1081                 }
1082         }
1083
1084         fclose(duplist);
1085
1086 }
1087
1088
1089 /* Checks to see whether its ok to send */
1090 /* Returns 1 for ok, send message       */
1091 /* Returns 0 if message already there   */
1092 int checkpath(char *path, char *sys)
1093 {
1094         int a;
1095         char sys2[512];
1096         strcpy(sys2, sys);
1097         strcat(sys2, "!");
1098
1099 #ifdef DEBUG
1100         syslog(LOG_NOTICE, "checkpath <%s> <%s> ... ", path, sys);
1101 #endif
1102         for (a = 0; a < strlen(path); ++a) {
1103                 if (!strncmp(&path[a], sys2, strlen(sys2)))
1104                         return (0);
1105         }
1106         return (1);
1107 }
1108
1109 /*
1110  * implement split horizon algorithm
1111  */
1112 int ismsgok(long int mpos, FILE * mmfp, char *sysname)
1113 {
1114         int a;
1115         int ok = 0;             /* fail safe - no path, don't send it */
1116         char fbuf[256];
1117
1118         fseek(mmfp, mpos, 0);
1119         if (getc(mmfp) != 255)
1120                 return (0);
1121         getc(mmfp);
1122         getc(mmfp);
1123
1124         while (a = getc(mmfp), ((a != 'M') && (a != 0))) {
1125                 fpgetfield(mmfp, fbuf);
1126                 if (a == 'P') {
1127                         ok = checkpath(fbuf, sysname);
1128                 }
1129         }
1130 #ifdef DEBUG
1131         syslog(LOG_NOTICE, "%s", ((ok) ? "SEND" : "(no)"));
1132 #endif
1133         return (ok);
1134 }
1135
1136
1137
1138 /* spool list of messages to a file */
1139 /* returns # of msgs spooled */
1140 int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
1141 {
1142         struct msglist *cmptr;
1143         FILE *mmfp;
1144         char fbuf[128];
1145         int a;
1146         int msgs_spooled = 0;
1147         long msg_len;
1148         int blok_len;
1149
1150         char buf[256];
1151         char curr_rm[256];
1152
1153         strcpy(curr_rm, "");
1154
1155         /* for each message in the list... */
1156         for (cmptr = cmlist; cmptr != NULL; cmptr = cmptr->next) {
1157
1158                 /* make sure we're in the correct room... */
1159                 if (strcasecmp(curr_rm, cmptr->m_rmname)) {
1160                         sprintf(buf, "GOTO %s", cmptr->m_rmname);
1161                         serv_puts(buf);
1162                         serv_gets(buf);
1163                         if (buf[0] == '2') {
1164                                 strcpy(curr_rm, cmptr->m_rmname);
1165                         } else {
1166                                 syslog(LOG_ERR, "%s", buf);
1167                         }
1168                 }
1169                 /* download the message from the server... */
1170                 mmfp = tmpfile();
1171                 sprintf(buf, "MSG3 %ld", cmptr->m_num);
1172                 serv_puts(buf);
1173                 serv_gets(buf);
1174                 if (buf[0] == '6') {    /* read the msg */
1175                         msg_len = atol(&buf[4]);
1176                         while (msg_len > 0L) {
1177                                 blok_len = ((msg_len >= 256L) ? 256 : (int) msg_len);
1178                                 serv_read(buf, blok_len);
1179                                 fwrite(buf, blok_len, 1, mmfp);
1180                                 msg_len = msg_len - (long) blok_len;
1181                         }
1182                 } else {        /* or print the err */
1183                         syslog(LOG_ERR, "%s", buf);
1184                 }
1185
1186                 rewind(mmfp);
1187
1188                 if (ismsgok(0L, mmfp, sysname)) {
1189                         ++msgs_spooled;
1190                         fflush(stdout);
1191                         fseek(mmfp, 0L, 0);
1192                         fread(fbuf, 3, 1, mmfp);
1193                         fwrite(fbuf, 3, 1, destfp);
1194                         while (a = getc(mmfp), ((a != 0) && (a != 'M'))) {
1195                                 if (a != 'C')
1196                                         putc(a, destfp);
1197                                 fpgetfield(mmfp, fbuf);
1198                                 if (a == 'P')
1199                                         fprintf(destfp, "%s!", NODENAME);
1200                                 if (a != 'C')
1201                                         fwrite(fbuf, strlen(fbuf) + 1, 1, destfp);
1202                         }
1203                         if (a == 'M') {
1204                                 fprintf(destfp, "C%s%c",
1205                                         cmptr->m_rmname, 0);
1206                                 putc('M', destfp);
1207                                 do {
1208                                         a = getc(mmfp);
1209                                         putc(a, destfp);
1210                                 } while (a > 0);
1211                         }
1212                 }
1213                 fclose(mmfp);
1214         }
1215
1216         return (msgs_spooled);
1217 }
1218
1219 void outprocess(char *sysname)
1220 {                               /* send new room messages to sysname */
1221         char sysflnm[64];
1222         char srmname[32];
1223         char shiptocmd[128];
1224         char lbuf[64];
1225         char tempflnm[64];
1226         char buf[256];
1227         struct msglist *cmlist = NULL;
1228         struct rmlist *crmlist = NULL;
1229         struct rmlist *rmptr, *rmptr2;
1230         struct msglist *cmptr, *cmptr2;
1231         FILE *sysflfp, *tempflfp;
1232         int outgoing_msgs;
1233         long thismsg;
1234
1235         sprintf(tempflnm, tmpnam(NULL));
1236         tempflfp = fopen(tempflnm, "w");
1237         if (tempflfp == NULL)
1238                 return;
1239
1240
1241 /*
1242  * Read system file for node in question and put together room list
1243  */
1244         sprintf(sysflnm, "%s/network/systems/%s", bbs_home_directory, sysname);
1245         sysflfp = fopen(sysflnm, "r");
1246         if (sysflfp == NULL)
1247                 return;
1248         fgets(shiptocmd, 128, sysflfp);
1249         shiptocmd[strlen(shiptocmd) - 1] = 0;
1250         while (!feof(sysflfp)) {
1251                 if (fgets(srmname, 32, sysflfp) == NULL)
1252                         break;
1253                 srmname[strlen(srmname) - 1] = 0;
1254                 fgets(lbuf, 32, sysflfp);
1255                 rmptr = (struct rmlist *) malloc(sizeof(struct rmlist));
1256                 rmptr->next = NULL;
1257                 strcpy(rmptr->rm_name, srmname);
1258                 strip_trailing_whitespace(rmptr->rm_name);
1259                 rmptr->rm_lastsent = atol(lbuf);
1260                 if (crmlist == NULL)
1261                         crmlist = rmptr;
1262                 else if (!strcasecmp(rmptr->rm_name, "control")) {
1263                         /* control has to be first in room list */
1264                         rmptr->next = crmlist;
1265                         crmlist = rmptr;
1266                 } else {
1267                         rmptr2 = crmlist;
1268                         while (rmptr2->next != NULL)
1269                                 rmptr2 = rmptr2->next;
1270                         rmptr2->next = rmptr;
1271                 }
1272         }
1273         fclose(sysflfp);
1274
1275 /*
1276  * Assemble list of messages to be spooled
1277  */
1278         for (rmptr = crmlist; rmptr != NULL; rmptr = rmptr->next) {
1279
1280                 sprintf(buf, "GOTO %s", rmptr->rm_name);
1281                 serv_puts(buf);
1282                 serv_gets(buf);
1283                 if (buf[0] != '2') {
1284                         syslog(LOG_ERR, "%s", buf);
1285                 } else {
1286                         sprintf(buf, "MSGS GT|%ld", rmptr->rm_lastsent);
1287                         serv_puts(buf);
1288                         serv_gets(buf);
1289                         if (buf[0] == '1')
1290                                 while (serv_gets(buf), strcmp(buf, "000")) {
1291                                         thismsg = atol(buf);
1292                                         if (thismsg > (rmptr->rm_lastsent)) {
1293                                                 rmptr->rm_lastsent = thismsg;
1294
1295                                                 cmptr = (struct msglist *)
1296                                                     malloc(sizeof(struct msglist));
1297                                                 cmptr->next = NULL;
1298                                                 cmptr->m_num = thismsg;
1299                                                 strcpy(cmptr->m_rmname, rmptr->rm_name);
1300
1301                                                 if (cmlist == NULL)
1302                                                         cmlist = cmptr;
1303                                                 else {
1304                                                         cmptr2 = cmlist;
1305                                                         while (cmptr2->next != NULL)
1306                                                                 cmptr2 = cmptr2->next;
1307                                                         cmptr2->next = cmptr;
1308                                                 }
1309                                         }
1310                         } else {        /* print error from "msgs all" */
1311                                 syslog(LOG_ERR, "%s", buf);
1312                         }
1313                 }
1314         }
1315
1316         outgoing_msgs = 0;
1317         cmptr2 = cmlist;        /* this loop counts the messages */
1318         while (cmptr2 != NULL) {
1319                 ++outgoing_msgs;
1320                 cmptr2 = cmptr2->next;
1321         }
1322         syslog(LOG_NOTICE, "%d messages to be spooled to %s",
1323                outgoing_msgs, sysname);
1324
1325 /*
1326  * Spool out the messages, but only if there are any.
1327  */
1328         if (outgoing_msgs != 0)
1329                 outgoing_msgs = spool_out(cmlist, tempflfp, sysname);
1330         syslog(LOG_NOTICE, "%d messages actually spooled",
1331                outgoing_msgs);
1332
1333 /*
1334  * Deallocate list of spooled messages.
1335  */
1336         while (cmlist != NULL) {
1337                 cmptr = cmlist->next;
1338                 free(cmlist);
1339                 cmlist = cmptr;
1340         }
1341
1342 /*
1343  * Rewrite system file and deallocate room list.
1344  */
1345         syslog(LOG_NOTICE, "Spooling...");
1346         sysflfp = fopen(sysflnm, "w");
1347         fprintf(sysflfp, "%s\n", shiptocmd);
1348         for (rmptr = crmlist; rmptr != NULL; rmptr = rmptr->next)
1349                 fprintf(sysflfp, "%s\n%ld\n", rmptr->rm_name, rmptr->rm_lastsent);
1350         fclose(sysflfp);
1351         while (crmlist != NULL) {
1352                 rmptr = crmlist->next;
1353                 free(crmlist);
1354                 crmlist = rmptr;
1355         }
1356
1357 /* 
1358  * Close temporary file, ship it out, and return
1359  */
1360         fclose(tempflfp);
1361         if (outgoing_msgs != 0)
1362                 ship_to(tempflnm, sysname);
1363         unlink(tempflnm);
1364 }
1365
1366
1367 /*
1368  * Connect netproc to the Citadel server running on this computer.
1369  */
1370 void np_attach_to_server(void)
1371 {
1372         char buf[256];
1373         char portname[8];
1374         char *args[] =
1375         {"netproc", "localhost", NULL, NULL};
1376
1377         syslog(LOG_NOTICE, "Attaching to server...");
1378         sprintf(portname, "%d", config.c_port_number);
1379         args[2] = portname;
1380         attach_to_server(3, args);
1381         serv_gets(buf);
1382         syslog(LOG_NOTICE, "%s", &buf[4]);
1383         sprintf(buf, "IPGM %d", config.c_ipgm_secret);
1384         serv_puts(buf);
1385         serv_gets(buf);
1386         syslog(LOG_NOTICE, "%s", &buf[4]);
1387         if (buf[0] != '2') {
1388                 cleanup(2);
1389         }
1390 }
1391
1392
1393
1394 /*
1395  * main
1396  */
1397 int main(int argc, char **argv)
1398 {
1399         char allst[32];
1400         FILE *allfp;
1401         int a;
1402         int import_only = 0;    /* if set to 1, don't export anything */
1403
1404         openlog("netproc", LOG_PID, LOG_USER);
1405         strcpy(bbs_home_directory, BBSDIR);
1406
1407         /*
1408          * Change directories if specified
1409          */
1410         for (a = 1; a < argc; ++a) {
1411                 if (!strncmp(argv[a], "-h", 2)) {
1412                         strcpy(bbs_home_directory, argv[a]);
1413                         strcpy(bbs_home_directory, &bbs_home_directory[2]);
1414                         home_specified = 1;
1415                 } else if (!strcmp(argv[a], "-i")) {
1416                         import_only = 1;
1417                 } else {
1418                         fprintf(stderr, "netproc: usage: ");
1419                         fprintf(stderr, "netproc [-hHomeDir] [-i]\n");
1420                         exit(1);
1421                 }
1422         }
1423
1424         get_config();
1425
1426         if (set_lockfile() != 0) {
1427                 syslog(LOG_NOTICE, "lock file exists: already running");
1428                 cleanup(1);
1429         }
1430         signal(SIGINT, cleanup);
1431         signal(SIGQUIT, cleanup);
1432         signal(SIGHUP, cleanup);
1433         signal(SIGTERM, cleanup);
1434
1435         syslog(LOG_NOTICE, "started.  pid=%d", getpid());
1436         fflush(stdout);
1437         np_attach_to_server();
1438         fflush(stdout);
1439
1440         if (load_syslist() != 0)
1441                 syslog(LOG_ERR, "cannot load sysinfo");
1442         setup_special_nodes();
1443
1444         inprocess();            /* first collect incoming stuff */
1445
1446         if (import_only != 1) {
1447                 allfp = (FILE *) popen("cd ./network/systems; ls", "r");
1448                 if (allfp != NULL) {
1449                         while (fgets(allst, 32, allfp) != NULL) {
1450                                 allst[strlen(allst) - 1] = 0;
1451                                 outprocess(allst);
1452                         }
1453                         pclose(allfp);
1454                 }
1455                 /* import again in case anything new was generated */
1456                 inprocess();
1457         }
1458         rewrite_syslist();
1459         syslog(LOG_NOTICE, "processing ended.");
1460         cleanup(0);
1461         return 0;
1462 }