]> code.citadel.org Git - citadel.git/blob - citadel/netproc.c
* netproc.c: msgfind() no longer uses the timestamp as a message-ID
[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 /*
417  * Determine routing from sysinfo file
418  */
419 int get_sysinfo_type(char *name) {
420         struct syslist *stemp;
421
422 GETSN:  for (stemp = slist; stemp != NULL; stemp = stemp->next) {
423                 if (!strcasecmp(stemp->s_name, name)) {
424                         if (!strcasecmp(stemp->s_type, "use")) {
425                                 strcpy(name, stemp->s_nexthop);
426                                 goto GETSN;
427                         }
428                         if (!strcasecmp(stemp->s_type, "bin")) {
429                                 return (MES_BINARY);
430                         }
431                         if (!strcasecmp(stemp->s_type, "uum")) {
432                                 return (MES_INTERNET);
433                         }
434                 }
435         }
436         syslog(LOG_ERR, "cannot find system '%s' in mail.sysinfo", name);
437         return (-1);
438 }
439
440
441 void fpgetfield(FILE * fp, char *string)
442 {
443         int a, b;
444
445         strcpy(string, "");
446         a = 0;
447         do {
448                 b = getc(fp);
449                 if (b < 1) {
450                         string[a] = 0;
451                         return;
452                 }
453                 string[a] = b;
454                 ++a;
455         } while (b != 0);
456 }
457
458
459
460 /*
461  * Load all of the fields of a message, except the actual text, into a
462  * table in memory (so we know how to process the message).
463  */
464 void msgfind(char *msgfile, struct minfo *buffer)
465 {
466         int b, e, mtype, aflag;
467         char bbb[1024];
468         char userid[1024];
469         FILE *fp;
470
471         strcpy(userid, "");
472         fp = fopen(msgfile, "rb");
473         if (fp == NULL) {
474                 syslog(LOG_ERR, "can't open message file: %s", strerror(errno));
475                 return;
476         }
477         e = getc(fp);
478         if (e != 255) {
479                 syslog(LOG_ERR, "incorrect message format");
480                 goto END;
481         }
482         mtype = getc(fp);
483         aflag = getc(fp);
484         buffer->I = 0L;
485         buffer->R[0] = 0;
486         buffer->E[0] = 0;
487         buffer->H[0] = 0;
488         buffer->S[0] = 0;
489         buffer->B[0] = 0;
490         buffer->G[0] = 0;
491
492 BONFGM: b = getc(fp);
493         if (b < 0)
494                 goto END;
495         if (b == 'M')
496                 goto END;
497         fpgetfield(fp, bbb);
498         while ((bbb[0] == ' ') && (strlen(bbb) > 1))
499                 strcpy(bbb, &bbb[1]);
500         if (b == 'A') {
501                 strcpy(buffer->A, bbb);
502                 if (strlen(userid) == 0) {
503                         strcpy(userid, bbb);
504                         for (e = 0; e < strlen(userid); ++e)
505                                 if (userid[e] == ' ')
506                                         userid[e] = '_';
507                 }
508         }
509         if (b == 'O')
510                 strcpy(buffer->O, bbb);
511         if (b == 'C')
512                 strcpy(buffer->C, bbb);
513         if (b == 'N')
514                 strcpy(buffer->N, bbb);
515         if (b == 'S')
516                 strcpy(buffer->S, bbb);
517         if (b == 'P') {
518                 /* extract the user id from the path */
519                 for (e = 0; e < strlen(bbb); ++e)
520                         if (bbb[e] == '!')
521                                 strcpy(userid, &bbb[e + 1]);
522
523                 /* now find the next hop */
524                 for (e = 0; e < strlen(bbb); ++e)
525                         if (bbb[e] == '!')
526                                 bbb[e] = 0;
527                 strcpy(buffer->nexthop, bbb);
528         }
529         if (b == 'R') {
530                 for (e = 0; e < strlen(bbb); ++e)
531                         if (bbb[e] == '_')
532                                 bbb[e] = ' ';
533                 strcpy(buffer->R, bbb);
534         }
535         if (b == 'D')
536                 strcpy(buffer->D, bbb);
537         if (b == 'T')
538                 buffer->T = atol(bbb);
539         if (b == 'I')
540                 buffer->I = atol(bbb);
541         if (b == 'H')
542                 strcpy(buffer->H, bbb);
543         if (b == 'B')
544                 strcpy(buffer->B, bbb);
545         if (b == 'G')
546                 strcpy(buffer->G, bbb);
547         if (b == 'E')
548                 strcpy(buffer->E, bbb);
549         goto BONFGM;
550
551 END:    fclose(fp);
552
553         /* NOTE: we used to use the following two lines of code to assign
554          * the timestamp as a message-ID if there was no message-ID already
555          * in the message.  We don't do this anymore because it screws up
556          * the loopzapper.
557          *
558         if (buffer->I == 0L)
559                 buffer->I = buffer->T;
560          */
561 }
562
563
564
565
566
567 void ship_to(char *filenm, char *sysnm)
568 {                               /* send spool file filenm to system sysnm */
569         char sysflnm[100];
570         char commbuf1[100];
571         char commbuf2[100];
572         FILE *sysflfd;
573
574 #ifdef DEBUG
575         syslog(LOG_NOTICE, "shipping %s to %s", filenm, sysnm);
576 #endif
577         sprintf(sysflnm, "./network/systems/%s", sysnm);
578         sysflfd = fopen(sysflnm, "r");
579         if (sysflfd == NULL)
580                 syslog(LOG_ERR, "cannot open %s", sysflnm);
581         fgets(commbuf1, 99, sysflfd);
582         commbuf1[strlen(commbuf1) - 1] = 0;
583         fclose(sysflfd);
584         sprintf(commbuf2, commbuf1, filenm);
585         system(commbuf2);
586 }
587
588 /*
589  * proc_file_transfer()  -  handle a simple file transfer packet
590  *
591  */
592 void proc_file_transfer(char *tname)
593 {                               /* name of temp file containing the whole message */
594         char buf[256];
595         char dest_room[ROOMNAMELEN];
596         char subdir_name[256];
597         FILE *tfp, *uud;
598         int a;
599
600         syslog(LOG_NOTICE, "processing network file transfer...");
601
602         tfp = fopen(tname, "rb");
603         if (tfp == NULL)
604                 syslog(LOG_ERR, "cannot open %s", tname);
605         getc(tfp);
606         getc(tfp);
607         getc(tfp);
608         do {
609                 a = getc(tfp);
610                 if (a != 'M') {
611                         fpgetfield(tfp, buf);
612                         if (a == 'O') {
613                                 strcpy(dest_room, buf);
614                         }
615                 }
616         } while ((a != 'M') && (a >= 0));
617         if (a != 'M') {
618                 fclose(tfp);
619                 syslog(LOG_ERR, "no message text for file transfer");
620                 return;
621         }
622         strcpy(subdir_name, "---xxx---");
623         sprintf(buf, "GOTO %s", dest_room);
624         serv_puts(buf);
625         serv_gets(buf);
626         if (buf[0] == '2') {
627                 extract(subdir_name, &buf[4], 2);
628                 if (strlen(subdir_name) == 0)
629                         strcpy(subdir_name, "--xxx--");
630         }
631         /* Change to the room's directory; if that fails, change to the
632          * bitbucket directory.  Then run uudecode.
633          */
634         sprintf(buf, "(cd %s/files/%s || cd %s/files/%s ) ; exec %s",
635                 bbs_home_directory, subdir_name,
636                 bbs_home_directory, config.c_bucket_dir,
637                 UUDECODE);
638
639         uud = (FILE *) popen(buf, "w");
640         if (uud == NULL) {
641                 syslog(LOG_ERR, "cannot open uudecode pipe");
642                 fclose(tfp);
643                 return;
644         }
645         fgets(buf, 128, tfp);
646         buf[strlen(buf) - 1] = 0;
647         for (a = 0; a < strlen(buf); ++a)
648                 if (buf[a] == '/')
649                         buf[a] = '_';
650         fprintf(uud, "%s\n", buf);
651         printf("netproc: %s\n", buf);
652         while (a = getc(tfp), a > 0)
653                 putc(a, uud);
654         fclose(tfp);
655         pclose(uud);
656         return;
657 }
658
659
660 /* send a bounce message */
661 void bounce(struct minfo *bminfo)
662 {
663
664         FILE *bounce;
665         char bfilename[64];
666         static int bseq = 1;
667         time_t now;
668
669         sprintf(bfilename, "./network/spoolin/bounce.%ld.%d", (long) getpid(),
670                 bseq++);
671         bounce = fopen(bfilename, "wb");
672         time(&now);
673
674         fprintf(bounce, "%c%c%c", 0xFF, MES_NORMAL, 0);
675         fprintf(bounce, "Ppostmaster%c", 0);
676         fprintf(bounce, "T%ld%c", (long) now, 0);
677         fprintf(bounce, "APostmaster%c", 0);
678         fprintf(bounce, "OMail%c", 0);
679         fprintf(bounce, "N%s%c", config.c_nodename, 0);
680         fprintf(bounce, "H%s%c", config.c_humannode, 0);
681
682         if (strlen(bminfo->E) > 0) {
683                 fprintf(bounce, "R%s%c", bminfo->E, 0);
684         } else {
685                 fprintf(bounce, "R%s%c", bminfo->A, 0);
686         }
687
688         fprintf(bounce, "D%s%c", bminfo->N, 0);
689         fprintf(bounce, "M%s could not deliver your mail to:\n",
690                 config.c_humannode);
691         fprintf(bounce, " \n %s\n \n", bminfo->R);
692         fprintf(bounce, " because there is no such user on this system.\n");
693         fprintf(bounce, " (Unsent message does *not* follow.  ");
694         fprintf(bounce, "Help to conserve bandwidth.)\n%c", 0);
695         fclose(bounce);
696 }
697
698
699
700
701 /*
702  * Generate a Message-ID string for the use table
703  */
704 void strmsgid(char *buf, struct minfo *msginfo) {
705         int i;
706
707         sprintf(buf, "%ld@%s", msginfo->I, msginfo->N);
708         for (i=0; i<strlen(buf); ++i) {
709                 if (isspace(buf[i])) {
710                         strcpy(&buf[i], &buf[i+1]);
711                 }
712                 buf[i] = tolower(buf[i]);
713         }
714 }
715
716
717
718 /*
719  * Check the use table to see if a message has been here before.
720  * Returns 1 if the message is a duplicate; otherwise, it returns
721  * 0 and the message ID is added to the use table.
722  */
723 int already_received(GDBM_FILE ut, struct minfo *msginfo) {
724         char buf[256];
725         time_t now;
726         datum mkey, newrec;
727         int retval = 0;
728
729         /* We can't check for dups on a zero msgid, so just pass them through */
730         if ((msginfo->I)==0L) {
731                 return 0;
732         }
733
734         strmsgid(buf, msginfo);
735         now = time(NULL);
736
737         mkey.dptr = buf;
738         mkey.dsize = strlen(buf);
739
740         /* Set return value to 1 if message exists */
741         if (gdbm_exists(ut, mkey)) {
742                 retval = 1;
743         }
744
745         /* Write a record into the use table for this message.
746          * Replace existing records; this keeps the timestamp fresh.
747          */
748         newrec.dptr = (char *)&now;
749         newrec.dsize = sizeof(now);
750         gdbm_store(ut, mkey, newrec, GDBM_REPLACE);
751
752         return(retval);
753 }
754
755
756
757 /*
758  * Purge any old entries out of the use table.
759  * 
760  * Yes, you're reading this correctly: it keeps traversing the table until
761  * it manages to do a complete pass without deleting any records.  Read the
762  * gdbm man page to find out why.
763  *
764  */
765 void purge_use_table(GDBM_FILE ut) {
766         datum mkey, nextkey, therec;
767         int purged_anything = 0;
768         time_t rec_timestamp, now;
769
770         now = time(NULL);
771
772         do {
773                 purged_anything = 0;
774                 mkey = gdbm_firstkey(ut);
775                 while (mkey.dptr != NULL) {
776                         therec = gdbm_fetch(ut, mkey);
777                         if (therec.dptr != NULL) {
778                                 memcpy(&rec_timestamp, therec.dptr,
779                                         sizeof(time_t));
780                                 free(therec.dptr);
781
782                                 if ((now - rec_timestamp) > USE_TIME) {
783                                         gdbm_delete(ut, mkey);
784                                         purged_anything = 1;
785                                 }
786
787                         }
788                         nextkey = gdbm_nextkey(ut, mkey);
789                         free(mkey.dptr);
790                         mkey = nextkey;
791                 }
792         } while (purged_anything != 0);
793 }
794
795
796
797 /*
798  * process incoming files in ./network/spoolin
799  */
800 void inprocess(void)
801 {
802         FILE *fp, *message, *testfp, *ls, *duplist;
803         static struct minfo minfo;
804         struct recentmsg recentmsg;
805         char tname[128], aaa[1024], iname[256], sfilename[256], pfilename[256];
806         int a, b;
807         int FieldID;
808         struct syslist *stemp;
809         char *ptr = NULL;
810         char buf[256];
811         long msglen;
812         int bloklen;
813         GDBM_FILE use_table;
814
815         /* temp file names */
816         sprintf(tname, tmpnam(NULL));
817         sprintf(iname, tmpnam(NULL));
818
819         load_filterlist();
820
821         /* Make sure we're in the right directory */
822         chdir(bbs_home_directory);
823
824         /* Open the use table */
825         use_table = gdbm_open("./data/usetable.gdbm", 512,
826                               GDBM_WRCREAT, 0600, 0);
827         if (use_table == NULL) {
828                 syslog(LOG_ERR, "could not open use table: %s",
829                        strerror(errno));
830         }
831
832
833         /* temporary file to contain a log of rejected dups */
834         duplist = tmpfile();
835
836         /* Let the shell do the dirty work. Get all data from spoolin */
837         do {
838                 sprintf(aaa, "cd %s/network/spoolin; ls", bbs_home_directory);
839                 ls = popen(aaa, "r");
840                 if (ls == NULL) {
841                         syslog(LOG_ERR, "could not open dir cmd: %s", strerror(errno));
842                 }
843                 if (ls != NULL) {
844                         do {
845 SKIP:                           ptr = fgets(sfilename, sizeof sfilename, ls);
846                                 if (ptr != NULL) {
847                                         sfilename[strlen(sfilename) - 1] = 0;
848                                         if (!strcmp(sfilename, ".")) goto SKIP;
849                                         if (!strcmp(sfilename, "..")) goto SKIP;
850                                         if (!strcmp(sfilename, "CVS")) goto SKIP;
851                                         goto PROCESS_IT;
852                                 }
853                         } while (ptr != NULL);
854 PROCESS_IT:             pclose(ls);
855                 }
856                 if (ptr != NULL) {
857                         sprintf(pfilename, "%s/network/spoolin/%s", bbs_home_directory, sfilename);
858                         syslog(LOG_NOTICE, "processing <%s>", pfilename);
859
860                         fp = fopen(pfilename, "rb");
861                         if (fp == NULL) {
862                                 syslog(LOG_ERR, "cannot open %s: %s", pfilename, strerror(errno));
863                                 fp = fopen("/dev/null", "rb");
864                         }
865 NXMSG:  /* Seek to the beginning of the next message */
866                         do {
867                                 a = getc(fp);
868                         } while ((a != 255) && (a >= 0));
869                         if (a < 0)
870                                 goto ENDSTR;
871
872                         /* This crates the temporary file. */
873                         message = fopen(tname, "wb");
874                         if (message == NULL) {
875                                 syslog(LOG_ERR, "error creating %s: %s",
876                                         tname, strerror(errno));
877                                 goto ENDSTR;
878                         }
879                         putc(255, message);     /* 0xFF (start-of-message) */
880                         a = getc(fp);
881                         putc(a, message);       /* type */
882                         a = getc(fp);
883                         putc(a, message);       /* mode */
884                         do {
885                                 FieldID = getc(fp);     /* Header field ID */
886                                 putc(FieldID, message);
887                                 do {
888                                         a = getc(fp);
889                                         putc(a, message);
890                                 } while (a > 0);
891                         } while ((FieldID != 'M') && (a >= 0));
892                         /* M is always last */
893
894                         msglen = ftell(message);
895                         fclose(message);
896
897                         /* process the individual mesage */
898                         minfo.D[0] = 0;
899                         minfo.C[0] = 0;
900                         minfo.B[0] = 0;
901                         minfo.G[0] = 0;
902                         minfo.R[0] = 0;
903                         msgfind(tname, &minfo);
904                         strncpy(recentmsg.RMnodename, minfo.N, 9);
905                         recentmsg.RMnodename[9] = 0;
906                         recentmsg.RMnum = minfo.I;
907                         syslog(LOG_NOTICE, "#%ld fm <%s> in <%s> @ <%s>",
908                                minfo.I, minfo.A, minfo.O, minfo.N);
909                         if (strlen(minfo.R) > 0) {
910                                 syslog(LOG_NOTICE, "     to <%s>", minfo.R);
911                                 if (strlen(minfo.D) > 0) {
912                                         syslog(LOG_NOTICE, "     @ <%s>",
913                                                 minfo.D);
914                                 }
915                         }
916                         if (!strcasecmp(minfo.D, FQDN))
917                                 strcpy(minfo.D, NODENAME);
918
919 /* this routine updates our info on the system that sent the message */
920                         stemp = get_sys_ptr(minfo.N);
921                         if ((stemp == NULL) && (get_sys_ptr(minfo.nexthop) != NULL)) {
922                                 /* add non-neighbor system to map */
923                                 syslog(LOG_NOTICE, "Adding non-neighbor system <%s> to map",
924                                        slist->s_name);
925                                 stemp = (struct syslist *) malloc((long) sizeof(struct syslist));
926                                 stemp->next = slist;
927                                 slist = stemp;
928                                 strcpy(slist->s_name, minfo.N);
929                                 strcpy(slist->s_type, "use");
930                                 strcpy(slist->s_nexthop, minfo.nexthop);
931                                 time(&slist->s_lastcontact);
932                         } else if ((stemp == NULL) && (!strcasecmp(minfo.N, minfo.nexthop))) {
933                                 /* add neighbor system to map */
934                                 syslog(LOG_NOTICE, "Adding neighbor system <%s> to map",
935                                        slist->s_name);
936                                 sprintf(aaa, "%s/network/systems/%s", bbs_home_directory, minfo.N);
937                                 testfp = fopen(aaa, "r");
938                                 if (testfp != NULL) {
939                                         fclose(testfp);
940                                         stemp = (struct syslist *)
941                                             malloc((long) sizeof(struct syslist));
942                                         stemp->next = slist;
943                                         slist = stemp;
944                                         strcpy(slist->s_name, minfo.N);
945                                         strcpy(slist->s_type, "bin");
946                                         strcpy(slist->s_nexthop, "Mail");
947                                         time(&slist->s_lastcontact);
948                                 }
949                         }
950                         /* now update last contact and long node name if we can */
951                         if (stemp != NULL) {
952                                 time(&stemp->s_lastcontact);
953                                 if (strlen(minfo.H) > 0)
954                                         strcpy(stemp->s_humannode, minfo.H);
955                                 if (strlen(minfo.B) > 0)
956                                         strcpy(stemp->s_phonenum, minfo.B);
957                                 if (strlen(minfo.G) > 0)
958                                         strcpy(stemp->s_gdom, minfo.G);
959                         }
960
961                         /* Check the use table; reject message if it's been here before */
962                         if (already_received(use_table, &minfo)) {
963                                 syslog(LOG_NOTICE, "rejected duplicate message");
964                                 fprintf(duplist, "#%ld fm <%s> in <%s> @ <%s>\n",
965                                         minfo.I, minfo.A, minfo.O, minfo.N);
966                         }
967
968
969                         /* route the message if necessary */
970                         else if ((strcasecmp(minfo.D, NODENAME)) && (minfo.D[0] != 0)) {
971                                 a = get_sysinfo_type(minfo.D);
972                                 syslog(LOG_NOTICE, "routing message to system <%s>", minfo.D);
973                                 fflush(stdout);
974                                 if (a == MES_INTERNET) {
975                                         if (fork() == 0) {
976                                                 syslog(LOG_NOTICE, "netmailer %s", tname);
977                                                 fflush(stdout);
978                                                 execlp("./netmailer", "netmailer",
979                                                        tname, NULL);
980                                                 syslog(LOG_ERR, "error running netmailer: %s",
981                                                        strerror(errno));
982                                                 exit(errno);
983                                         } else
984                                                 while (wait(&b) != (-1));
985                                 } else if (a == MES_BINARY) {
986                                         ship_to(tname, minfo.D);
987                                 } else {
988                                         /* message falls into the bit bucket? */
989                                 }
990                         }
991
992                         /* check to see if it's a file transfer */
993                         else if (!strncasecmp(minfo.S, "FILE", 4)) {
994                                 proc_file_transfer(tname);
995                         }
996
997                         /* otherwise process it as a normal message */
998                         else {
999
1000                                 if (!strcasecmp(minfo.R, "postmaster")) {
1001                                         strcpy(minfo.R, "");
1002                                         strcpy(minfo.C, "Aide");
1003                                 }
1004                                 if (strlen(minfo.R) > 0) {
1005                                         sprintf(buf, "GOTO _MAIL_");
1006                                 }
1007                                 if (is_banned(minfo.A, minfo.C, minfo.N)) {
1008                                         sprintf(buf, "GOTO %s", FILTERROOM);
1009                                 } else {
1010                                         if (strlen(minfo.C) > 0) {
1011                                                 sprintf(buf, "GOTO %s", minfo.C);
1012                                         } else {
1013                                                 sprintf(buf, "GOTO %s", minfo.O);
1014                                         }
1015                                 }
1016                                 serv_puts(buf);
1017                                 serv_gets(buf);
1018                                 if (buf[0] != '2') {
1019                                         syslog(LOG_ERR, "%s", buf);
1020                                         sprintf(buf, "GOTO _BITBUCKET_");
1021                                         serv_puts(buf);
1022                                         serv_gets(buf);
1023                                 }
1024                                 /* Open the temporary file containing the message */
1025                                 message = fopen(tname, "rb");
1026                                 if (message == NULL) {
1027                                         syslog(LOG_ERR, "cannot open %s: %s",
1028                                                tname, strerror(errno));
1029                                         unlink(tname);
1030                                         goto NXMSG;
1031                                 }
1032                                 /* Transmit the message to the server */
1033                                 sprintf(buf, "ENT3 1|%s|%ld", minfo.R, msglen);
1034                                 serv_puts(buf);
1035                                 serv_gets(buf);
1036                                 if (!strncmp(buf, "570", 3)) {
1037                                         /* no such user, do a bounce */
1038                                         bounce(&minfo);
1039                                 }
1040                                 if (buf[0] == '7') {
1041                                         /* Always use the server's idea of the message length,
1042                                          * even though they should both be identical */
1043                                         msglen = atol(&buf[4]);
1044                                         while (msglen > 0L) {
1045                                                 bloklen = ((msglen >= 255L) ? 255 : ((int) msglen));
1046                                                 if (fread(buf, bloklen, 1, message) < 1) {
1047                                                         syslog(LOG_ERR,
1048                                                                "error trying to read %d bytes: %s",
1049                                                                bloklen, strerror(errno));
1050                                                 }
1051                                                 serv_write(buf, bloklen);
1052                                                 msglen = msglen - (long) bloklen;
1053                                         }
1054                                         serv_puts("NOOP");
1055                                         serv_gets(buf);
1056                                 } else {
1057                                         syslog(LOG_ERR, "%s", buf);
1058                                 }
1059
1060                                 fclose(message);
1061                         }
1062
1063                         unlink(tname);
1064                         goto NXMSG;
1065
1066 ENDSTR:                 fclose(fp);
1067                         unlink(pfilename);
1068                 }
1069         } while (ptr != NULL);
1070         unlink(iname);
1071
1072         purge_use_table(use_table);
1073         gdbm_close(use_table);
1074
1075
1076         /*
1077          * If dups were rejected, post a message saying so
1078          */
1079         if (ftell(duplist)!=0L) {
1080                 fp = fopen("./network/spoolin/ctdl_rejects", "ab");
1081                 if (fp != NULL) {
1082                         fprintf(fp, "%cA%c", 255, 1);
1083                         fprintf(fp, "T%ld%c", time(NULL), 0);
1084                         fprintf(fp, "ACitadel%c", 0);
1085                         fprintf(fp, "OAide%cM", 0);
1086                         fprintf(fp, "The following duplicate messages"
1087                                 " were rejected:\n \n");
1088                         rewind(duplist);
1089                         while (fgets(buf, sizeof(buf), duplist) != NULL) {
1090                                 buf[strlen(buf)-1] = 0;
1091                                 fprintf(fp, " %s\n", buf);
1092                         }
1093                         fprintf(fp, "%c", 0);
1094                         pclose(fp);
1095                 }
1096         }
1097
1098         fclose(duplist);
1099
1100 }
1101
1102
1103 /* Checks to see whether its ok to send */
1104 /* Returns 1 for ok, send message       */
1105 /* Returns 0 if message already there   */
1106 int checkpath(char *path, char *sys)
1107 {
1108         int a;
1109         char sys2[512];
1110         strcpy(sys2, sys);
1111         strcat(sys2, "!");
1112
1113 #ifdef DEBUG
1114         syslog(LOG_NOTICE, "checkpath <%s> <%s> ... ", path, sys);
1115 #endif
1116         for (a = 0; a < strlen(path); ++a) {
1117                 if (!strncmp(&path[a], sys2, strlen(sys2)))
1118                         return (0);
1119         }
1120         return (1);
1121 }
1122
1123 /*
1124  * implement split horizon algorithm
1125  */
1126 int ismsgok(long int mpos, FILE * mmfp, char *sysname)
1127 {
1128         int a;
1129         int ok = 0;             /* fail safe - no path, don't send it */
1130         char fbuf[256];
1131
1132         fseek(mmfp, mpos, 0);
1133         if (getc(mmfp) != 255)
1134                 return (0);
1135         getc(mmfp);
1136         getc(mmfp);
1137
1138         while (a = getc(mmfp), ((a != 'M') && (a != 0))) {
1139                 fpgetfield(mmfp, fbuf);
1140                 if (a == 'P') {
1141                         ok = checkpath(fbuf, sysname);
1142                 }
1143         }
1144 #ifdef DEBUG
1145         syslog(LOG_NOTICE, "%s", ((ok) ? "SEND" : "(no)"));
1146 #endif
1147         return (ok);
1148 }
1149
1150
1151
1152 /* spool list of messages to a file */
1153 /* returns # of msgs spooled */
1154 int spool_out(struct msglist *cmlist, FILE * destfp, char *sysname)
1155 {
1156         struct msglist *cmptr;
1157         FILE *mmfp;
1158         char fbuf[128];
1159         int a;
1160         int msgs_spooled = 0;
1161         long msg_len;
1162         int blok_len;
1163
1164         char buf[256];
1165         char curr_rm[256];
1166
1167         strcpy(curr_rm, "");
1168
1169         /* for each message in the list... */
1170         for (cmptr = cmlist; cmptr != NULL; cmptr = cmptr->next) {
1171
1172                 /* make sure we're in the correct room... */
1173                 if (strcasecmp(curr_rm, cmptr->m_rmname)) {
1174                         sprintf(buf, "GOTO %s", cmptr->m_rmname);
1175                         serv_puts(buf);
1176                         serv_gets(buf);
1177                         if (buf[0] == '2') {
1178                                 strcpy(curr_rm, cmptr->m_rmname);
1179                         } else {
1180                                 syslog(LOG_ERR, "%s", buf);
1181                         }
1182                 }
1183                 /* download the message from the server... */
1184                 mmfp = tmpfile();
1185                 sprintf(buf, "MSG3 %ld", cmptr->m_num);
1186                 serv_puts(buf);
1187                 serv_gets(buf);
1188                 if (buf[0] == '6') {    /* read the msg */
1189                         msg_len = atol(&buf[4]);
1190                         while (msg_len > 0L) {
1191                                 blok_len = ((msg_len >= 256L) ? 256 : (int) msg_len);
1192                                 serv_read(buf, blok_len);
1193                                 fwrite(buf, blok_len, 1, mmfp);
1194                                 msg_len = msg_len - (long) blok_len;
1195                         }
1196                 } else {        /* or print the err */
1197                         syslog(LOG_ERR, "%s", buf);
1198                 }
1199
1200                 rewind(mmfp);
1201
1202                 if (ismsgok(0L, mmfp, sysname)) {
1203                         ++msgs_spooled;
1204                         fflush(stdout);
1205                         fseek(mmfp, 0L, 0);
1206                         fread(fbuf, 3, 1, mmfp);
1207                         fwrite(fbuf, 3, 1, destfp);
1208                         while (a = getc(mmfp), ((a != 0) && (a != 'M'))) {
1209                                 if (a != 'C')
1210                                         putc(a, destfp);
1211                                 fpgetfield(mmfp, fbuf);
1212                                 if (a == 'P')
1213                                         fprintf(destfp, "%s!", NODENAME);
1214                                 if (a != 'C')
1215                                         fwrite(fbuf, strlen(fbuf) + 1, 1, destfp);
1216                         }
1217                         if (a == 'M') {
1218                                 fprintf(destfp, "C%s%c",
1219                                         cmptr->m_rmname, 0);
1220                                 putc('M', destfp);
1221                                 do {
1222                                         a = getc(mmfp);
1223                                         putc(a, destfp);
1224                                 } while (a > 0);
1225                         }
1226                 }
1227                 fclose(mmfp);
1228         }
1229
1230         return (msgs_spooled);
1231 }
1232
1233 void outprocess(char *sysname)
1234 {                               /* send new room messages to sysname */
1235         char sysflnm[64];
1236         char srmname[32];
1237         char shiptocmd[128];
1238         char lbuf[64];
1239         char tempflnm[64];
1240         char buf[256];
1241         struct msglist *cmlist = NULL;
1242         struct rmlist *crmlist = NULL;
1243         struct rmlist *rmptr, *rmptr2;
1244         struct msglist *cmptr, *cmptr2;
1245         FILE *sysflfp, *tempflfp;
1246         int outgoing_msgs;
1247         long thismsg;
1248
1249         sprintf(tempflnm, tmpnam(NULL));
1250         tempflfp = fopen(tempflnm, "w");
1251         if (tempflfp == NULL)
1252                 return;
1253
1254
1255 /*
1256  * Read system file for node in question and put together room list
1257  */
1258         sprintf(sysflnm, "%s/network/systems/%s", bbs_home_directory, sysname);
1259         sysflfp = fopen(sysflnm, "r");
1260         if (sysflfp == NULL)
1261                 return;
1262         fgets(shiptocmd, 128, sysflfp);
1263         shiptocmd[strlen(shiptocmd) - 1] = 0;
1264         while (!feof(sysflfp)) {
1265                 if (fgets(srmname, 32, sysflfp) == NULL)
1266                         break;
1267                 srmname[strlen(srmname) - 1] = 0;
1268                 fgets(lbuf, 32, sysflfp);
1269                 rmptr = (struct rmlist *) malloc(sizeof(struct rmlist));
1270                 rmptr->next = NULL;
1271                 strcpy(rmptr->rm_name, srmname);
1272                 strip_trailing_whitespace(rmptr->rm_name);
1273                 rmptr->rm_lastsent = atol(lbuf);
1274                 if (crmlist == NULL)
1275                         crmlist = rmptr;
1276                 else if (!strcasecmp(rmptr->rm_name, "control")) {
1277                         /* control has to be first in room list */
1278                         rmptr->next = crmlist;
1279                         crmlist = rmptr;
1280                 } else {
1281                         rmptr2 = crmlist;
1282                         while (rmptr2->next != NULL)
1283                                 rmptr2 = rmptr2->next;
1284                         rmptr2->next = rmptr;
1285                 }
1286         }
1287         fclose(sysflfp);
1288
1289 /*
1290  * Assemble list of messages to be spooled
1291  */
1292         for (rmptr = crmlist; rmptr != NULL; rmptr = rmptr->next) {
1293
1294                 sprintf(buf, "GOTO %s", rmptr->rm_name);
1295                 serv_puts(buf);
1296                 serv_gets(buf);
1297                 if (buf[0] != '2') {
1298                         syslog(LOG_ERR, "%s", buf);
1299                 } else {
1300                         sprintf(buf, "MSGS GT|%ld", rmptr->rm_lastsent);
1301                         serv_puts(buf);
1302                         serv_gets(buf);
1303                         if (buf[0] == '1')
1304                                 while (serv_gets(buf), strcmp(buf, "000")) {
1305                                         thismsg = atol(buf);
1306                                         if (thismsg > (rmptr->rm_lastsent)) {
1307                                                 rmptr->rm_lastsent = thismsg;
1308
1309                                                 cmptr = (struct msglist *)
1310                                                     malloc(sizeof(struct msglist));
1311                                                 cmptr->next = NULL;
1312                                                 cmptr->m_num = thismsg;
1313                                                 strcpy(cmptr->m_rmname, rmptr->rm_name);
1314
1315                                                 if (cmlist == NULL)
1316                                                         cmlist = cmptr;
1317                                                 else {
1318                                                         cmptr2 = cmlist;
1319                                                         while (cmptr2->next != NULL)
1320                                                                 cmptr2 = cmptr2->next;
1321                                                         cmptr2->next = cmptr;
1322                                                 }
1323                                         }
1324                         } else {        /* print error from "msgs all" */
1325                                 syslog(LOG_ERR, "%s", buf);
1326                         }
1327                 }
1328         }
1329
1330         outgoing_msgs = 0;
1331         cmptr2 = cmlist;        /* this loop counts the messages */
1332         while (cmptr2 != NULL) {
1333                 ++outgoing_msgs;
1334                 cmptr2 = cmptr2->next;
1335         }
1336         syslog(LOG_NOTICE, "%d messages to be spooled to %s",
1337                outgoing_msgs, sysname);
1338
1339 /*
1340  * Spool out the messages, but only if there are any.
1341  */
1342         if (outgoing_msgs != 0)
1343                 outgoing_msgs = spool_out(cmlist, tempflfp, sysname);
1344         syslog(LOG_NOTICE, "%d messages actually spooled",
1345                outgoing_msgs);
1346
1347 /*
1348  * Deallocate list of spooled messages.
1349  */
1350         while (cmlist != NULL) {
1351                 cmptr = cmlist->next;
1352                 free(cmlist);
1353                 cmlist = cmptr;
1354         }
1355
1356 /*
1357  * Rewrite system file and deallocate room list.
1358  */
1359         syslog(LOG_NOTICE, "Spooling...");
1360         sysflfp = fopen(sysflnm, "w");
1361         fprintf(sysflfp, "%s\n", shiptocmd);
1362         for (rmptr = crmlist; rmptr != NULL; rmptr = rmptr->next)
1363                 fprintf(sysflfp, "%s\n%ld\n", rmptr->rm_name, rmptr->rm_lastsent);
1364         fclose(sysflfp);
1365         while (crmlist != NULL) {
1366                 rmptr = crmlist->next;
1367                 free(crmlist);
1368                 crmlist = rmptr;
1369         }
1370
1371 /* 
1372  * Close temporary file, ship it out, and return
1373  */
1374         fclose(tempflfp);
1375         if (outgoing_msgs != 0)
1376                 ship_to(tempflnm, sysname);
1377         unlink(tempflnm);
1378 }
1379
1380
1381 /*
1382  * Connect netproc to the Citadel server running on this computer.
1383  */
1384 void np_attach_to_server(void)
1385 {
1386         char buf[256];
1387         char portname[8];
1388         char *args[] =
1389         {"netproc", "localhost", NULL, NULL};
1390
1391         syslog(LOG_NOTICE, "Attaching to server...");
1392         sprintf(portname, "%d", config.c_port_number);
1393         args[2] = portname;
1394         attach_to_server(3, args);
1395         serv_gets(buf);
1396         syslog(LOG_NOTICE, "%s", &buf[4]);
1397         sprintf(buf, "IPGM %d", config.c_ipgm_secret);
1398         serv_puts(buf);
1399         serv_gets(buf);
1400         syslog(LOG_NOTICE, "%s", &buf[4]);
1401         if (buf[0] != '2') {
1402                 cleanup(2);
1403         }
1404 }
1405
1406
1407
1408 /*
1409  * main
1410  */
1411 int main(int argc, char **argv)
1412 {
1413         char allst[32];
1414         FILE *allfp;
1415         int a;
1416         int import_only = 0;    /* if set to 1, don't export anything */
1417
1418         openlog("netproc", LOG_PID, LOG_USER);
1419         strcpy(bbs_home_directory, BBSDIR);
1420
1421         /*
1422          * Change directories if specified
1423          */
1424         for (a = 1; a < argc; ++a) {
1425                 if (!strncmp(argv[a], "-h", 2)) {
1426                         strcpy(bbs_home_directory, argv[a]);
1427                         strcpy(bbs_home_directory, &bbs_home_directory[2]);
1428                         home_specified = 1;
1429                 } else if (!strcmp(argv[a], "-i")) {
1430                         import_only = 1;
1431                 } else {
1432                         fprintf(stderr, "netproc: usage: ");
1433                         fprintf(stderr, "netproc [-hHomeDir] [-i]\n");
1434                         exit(1);
1435                 }
1436         }
1437
1438         get_config();
1439
1440         if (set_lockfile() != 0) {
1441                 syslog(LOG_NOTICE, "lock file exists: already running");
1442                 cleanup(1);
1443         }
1444         signal(SIGINT, cleanup);
1445         signal(SIGQUIT, cleanup);
1446         signal(SIGHUP, cleanup);
1447         signal(SIGTERM, cleanup);
1448
1449         syslog(LOG_NOTICE, "started.  pid=%d", getpid());
1450         fflush(stdout);
1451         np_attach_to_server();
1452         fflush(stdout);
1453
1454         if (load_syslist() != 0)
1455                 syslog(LOG_ERR, "cannot load sysinfo");
1456         setup_special_nodes();
1457
1458         inprocess();            /* first collect incoming stuff */
1459
1460         if (import_only != 1) {
1461                 allfp = (FILE *) popen("cd ./network/systems; ls", "r");
1462                 if (allfp != NULL) {
1463                         while (fgets(allst, 32, allfp) != NULL) {
1464                                 allst[strlen(allst) - 1] = 0;
1465                                 outprocess(allst);
1466                         }
1467                         pclose(allfp);
1468                 }
1469                 /* import again in case anything new was generated */
1470                 inprocess();
1471         }
1472         rewrite_syslist();
1473         syslog(LOG_NOTICE, "processing ended.");
1474         cleanup(0);
1475         return 0;
1476 }