2 * Citadel/UX Intelligent Network Processor for IGnet/Open networks v3.6
3 * Designed and written by Art Cancro @ Uncensored Communications Group
4 * See copyright.txt for copyright information
8 * Specify where netproc should log to, and the mode for opening the file.
9 * If you are logging to a file, NPLOGMODE should be a; if you are logging to
10 * a device or fifo it should be w.
12 #define NPLOGFILE "./netproc.log"
15 /* How long it takes for an old node to drop off the network map */
16 #define EXPIRY_TIME (2592000L)
18 /* Where do we keep our lock file? */
19 #define LOCKFILE "/var/lock/LCK.netproc"
21 /* Path to the 'uudecode' utility (needed for network file transfers) */
22 #define UUDECODE "/usr/bin/uudecode"
24 /* Uncomment the DEBUG def to see noisy traces */
31 #include <sys/types.h>
42 /* A list of users you wish to filter out of incoming traffic can be kept
43 * in ./network/filterlist -- messages from these users will be automatically
44 * moved to FILTERROOM. Normally this will be the same as TWITROOM (the
45 * room problem user messages are moved to) but you can override this by
46 * specifying a different room name here.
49 #define FILTERROOM TWITROOM
65 struct filterlist *next;
100 void attach_to_server();
105 struct filterlist *filter = NULL;
106 char roomnames[MAXROOMS][20];
107 char roomdirs[MAXROOMS][15];
108 struct syslist *slist = NULL;
110 struct config config;
111 extern char bbs_home_directory[];
112 extern int home_specified;
114 int struncmp(lstr,rstr,len)
120 lc=tolower(lstr[pos]);
121 rc=tolower(rstr[pos]);
122 if ((lc==0)&&(rc==0)) return(0);
123 if (lc<rc) return(-1);
124 if (lc>rc) return(1);
130 /* redefine strucmp, just in case we're using an old version of citadel.h
131 * that has it as a separate routine
136 #define strucmp(lstr,rstr) struncmp(lstr,rstr,32767)
141 * replacement strerror() for systems that don't have it
147 sprintf(buf,"errno = %d",e);
153 void strip_trailing_whitespace(buf)
155 while(isspace(buf[strlen(buf)-1]))
156 buf[strlen(buf)-1]=0;
161 * for performance optimization, netproc loads the list of room names (and
162 * their corresponding directory names, if applicable) into a table in memory.
164 int load_roomnames() {
166 struct quickroom qbuf;
169 fp=fopen("./quickroom","rb");
170 if (fp==NULL) return(1);
171 for (i=0; i<MAXROOMS; ++i) {
172 if (fread((char *)&qbuf,sizeof(struct quickroom),1,fp)!=1)
174 strcpy(roomnames[i],qbuf.QRname);
175 if (qbuf.QRflags & QR_DIRECTORY)
176 strcpy(roomdirs[i],qbuf.QRdirname);
178 strcpy(roomdirs[i],config.c_bucket_dir);
185 * we also load the network/mail.sysinfo table into memory, make changes
186 * as we learn more about the network from incoming messages, and write
187 * the table back to disk when we're done.
191 struct syslist *stemp;
195 fp=fopen("network/mail.sysinfo","rb");
196 if (fp==NULL) return(1);
199 if (fgets(buf,128,fp)==NULL) {
203 buf[strlen(buf)-1] = 0;
204 while (isspace(buf[0])) strcpy(buf,&buf[1]);
205 if (buf[0]=='#') buf[0]=0;
206 if ( (insys==0) && (strlen(buf)!=0) ) {
208 stemp =(struct syslist *)malloc(sizeof(struct syslist));
211 strcpy(slist->s_name,buf);
212 strcpy(slist->s_type,"bin");
213 strcpy(slist->s_nexthop,"Mail");
214 slist->s_lastcontact = 0L;
215 strcpy(slist->s_humannode,"");
216 strcpy(slist->s_phonenum,"");
217 strcpy(slist->s_gdom,"");
219 else if ( (insys==1) && (strlen(buf)==0) ) {
222 else if ( (insys==1) && (!strncmp(buf,"bin",3)) ) {
223 strcpy(slist->s_type,"bin");
224 strcpy(slist->s_nexthop,&buf[4]);
226 else if ( (insys==1) && (!strncmp(buf,"use",3)) ) {
227 strcpy(slist->s_type,"use");
228 strcpy(slist->s_nexthop,&buf[4]);
230 else if ( (insys==1) && (!strncmp(buf,"uum",3)) ) {
231 strcpy(slist->s_type,"uum");
232 strcpy(slist->s_nexthop,&buf[4]);
234 else if ( (insys==1) && (!strncmp(buf,"lastcontact",11)) ) {
235 sscanf(&buf[12],"%ld",&slist->s_lastcontact);
237 else if ( (insys==1) && (!strncmp(buf,"humannode",9)) ) {
238 strcpy(slist->s_humannode,&buf[10]);
240 else if ( (insys==1) && (!strncmp(buf,"phonenum",8)) ) {
241 strcpy(slist->s_phonenum,&buf[9]);
243 else if ( (insys==1) && (!strncmp(buf,"gdom",4)) ) {
244 strcpy(slist->s_gdom,&buf[5]);
249 /* now we have to set up two "special" nodes on the list: one
250 * for the local node, and one for an Internet gateway
252 void setup_special_nodes() {
253 struct syslist *stemp,*slocal;
256 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
257 if (!strucmp(stemp->s_name,config.c_nodename)) slocal=stemp;
260 slocal =(struct syslist *)malloc(sizeof(struct syslist));
261 slocal->next = slist;
264 strcpy(slocal->s_name,config.c_nodename);
265 strcpy(slocal->s_type,"bin");
266 strcpy(slocal->s_nexthop,"Mail");
267 time(&slocal->s_lastcontact);
268 strcpy(slocal->s_humannode,config.c_humannode);
269 strcpy(slocal->s_phonenum,config.c_phonenum);
272 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
273 if (!strucmp(stemp->s_name,"internet")) slocal=stemp;
276 slocal =(struct syslist *)malloc(sizeof(struct syslist));
277 slocal->next = slist;
280 strcpy(slocal->s_name,"internet");
281 strcpy(slocal->s_type,"uum");
282 strcpy(slocal->s_nexthop,"%s");
283 time(&slocal->s_lastcontact);
284 strcpy(slocal->s_humannode,"Internet Gateway");
285 strcpy(slocal->s_phonenum,"");
286 strcpy(slocal->s_gdom,"");
291 * here's the routine to write the table back to disk.
293 void rewrite_syslist() {
294 struct syslist *stemp;
299 newfp=fopen("network/mail.sysinfo","w");
300 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
301 if (!strucmp(stemp->s_name,config.c_nodename)) {
302 time(&stemp->s_lastcontact);
303 strcpy(stemp->s_type,"bin");
304 strcpy(stemp->s_humannode,config.c_humannode);
305 strcpy(stemp->s_phonenum,config.c_phonenum);
307 /* remove systems we haven't heard from in a while */
308 if ( (stemp->s_lastcontact == 0L)
309 || (now - stemp->s_lastcontact < EXPIRY_TIME) ) {
310 fprintf(newfp,"%s\n%s %s\n",
311 stemp->s_name,stemp->s_type,stemp->s_nexthop);
312 if (strlen(stemp->s_phonenum) > 0)
313 fprintf(newfp,"phonenum %s\n",stemp->s_phonenum);
314 if (strlen(stemp->s_gdom) > 0)
315 fprintf(newfp,"gdom %s\n",stemp->s_gdom);
316 if (strlen(stemp->s_humannode) > 0)
317 fprintf(newfp,"humannode %s\n",stemp->s_humannode);
318 if (stemp->s_lastcontact > 0L)
319 fprintf(newfp,"lastcontact %ld %s",
320 stemp->s_lastcontact,
321 asctime(localtime(&stemp->s_lastcontact)));
326 /* now free the list */
327 while (slist!=NULL) {
335 /* call this function with the node name of a system and it returns a pointer
336 * to its syslist structure.
338 struct syslist *get_sys_ptr(sysname)
340 static char sysnambuf[16];
341 static struct syslist *sysptrbuf = NULL;
342 struct syslist *stemp;
344 if ( (!strcmp(sysname,sysnambuf))
345 && (sysptrbuf!=NULL) ) return(sysptrbuf);
347 strcpy(sysnambuf,sysname);
348 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
349 if (!strcmp(sysname,stemp->s_name)) {
360 * make sure only one copy of netproc runs at a time, using lock files
368 if (access(LOCKFILE,0)==0) {
371 * if the /proc filesystem is available, we can further check to
372 * make sure that the process that wrote the lock file is actually
373 * running, and didn't simply terminate and not clean up after itself
376 lfp = fopen(LOCKFILE,"r");
377 fscanf(lfp,"%d",&onppid);
379 sprintf(buf,"/proc/%d/cmdline",onppid);
380 if (access(buf,0)==0) ok = 0;
386 if (ok == 0) return(1);
387 lfp=fopen(LOCKFILE,"w");
388 fprintf(lfp,"%d\n",getpid());
393 void remove_lockfile() {
398 * Why both cleanup() and nq_cleanup() ? Notice the alarm() call in
399 * cleanup() . If for some reason netproc hangs waiting for the server
400 * to clean up, the alarm clock goes off and the program exits anyway.
401 * The cleanup() routine makes a check to ensure it's not reentering, in
402 * case the ipc module looped it somehow.
412 static int nested = 0;
415 signal(SIGALRM,nq_cleanup);
416 if (nested++ < 1) serv_puts("QUIT");
421 * This is implemented as a function rather than as a macro because the
422 * client-side IPC modules expect logoff() to be defined. They call logoff()
423 * when a problem connecting or staying connected to the server occurs.
431 * If there is a kill file in place, this function will process it.
433 void load_filterlist() {
435 struct filterlist *fbuf;
438 fp=fopen("./network/filterlist","r");
439 if (fp==NULL) return;
440 while (fgets(sbuf,256,fp)!=NULL) {
442 sbuf[strlen(sbuf)-1]=0;
443 fbuf=(struct filterlist *)
444 malloc((long)sizeof(struct filterlist));
447 strcpy(fbuf->f_person,"*");
448 strcpy(fbuf->f_room,"*");
449 strcpy(fbuf->f_system,"*");
451 for (a=strlen(sbuf); a>=0; --a) if (sbuf[a]==',') p=a;
454 strcpy(fbuf->f_person,sbuf);
455 strcpy(sbuf,&sbuf[p+1]);
457 for (a=strlen(sbuf); a>=0; --a) if (sbuf[a]==',') p=a;
460 strcpy(fbuf->f_room,sbuf);
461 strcpy(sbuf,&sbuf[p+1]);
463 strcpy(fbuf->f_system,sbuf);
469 /* returns 1 if user/message/room combination is in the kill file */
470 int is_banned(k_person,k_room,k_system)
471 char *k_person,*k_room,*k_system; {
472 struct filterlist *fptr;
474 for (fptr=filter; fptr!=NULL; fptr=fptr->next) if (
475 ((!strucmp(fptr->f_person,k_person))||(!strcmp(fptr->f_person,"*")))
477 ((!strucmp(fptr->f_room,k_room))||(!strcmp(fptr->f_room,"*")))
479 ((!strucmp(fptr->f_system,k_system))||(!strcmp(fptr->f_system,"*")))
485 int get_sysinfo_type(name) /* determine routing from sysinfo file */
487 struct syslist *stemp;
488 GETSN: for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
489 if (!strucmp(stemp->s_name,name)) {
490 if (!strucmp(stemp->s_type,"use")) {
491 strcpy(name,stemp->s_nexthop);
494 if (!strucmp(stemp->s_type,"bin")) {
497 if (!strucmp(stemp->s_type,"uum")) {
502 printf("netproc: cannot find system '%s' in mail.sysinfo\n",name);
507 void fpgetfield(fp,string)
528 * Load all of the fields of a message, except the actual text, into a
529 * table in memory (so we know how to process the message).
531 void msgfind(msgfile,buffer)
533 struct minfo *buffer; {
540 fp=fopen(msgfile,"rb");
542 fprintf(stderr,"Can't open message file: %s\n",strerror(errno));
547 fprintf(stdout,"Incorrect message format\n");
550 mtype=getc(fp); aflag=getc(fp);
559 BONFGM: b=getc(fp); if (b<0) goto END;
560 if (b=='M') goto END;
562 while ((bbb[0]==' ')&&(strlen(bbb)>1)) strcpy(bbb,&bbb[1]);
564 strcpy(buffer->A,bbb);
565 if (strlen(userid)==0) {
567 for (e=0; e<strlen(userid); ++e)
568 if (userid[e]==' ') userid[e]='_';
571 if (b=='O') strcpy(buffer->O,bbb);
572 if (b=='C') strcpy(buffer->C,bbb);
573 if (b=='N') strcpy(buffer->N,bbb);
574 if (b=='S') strcpy(buffer->S,bbb);
576 /* extract the user id from the path */
577 for (e=0; e<strlen(bbb); ++e)
578 if (bbb[e]=='!') strcpy(userid,&bbb[e+1]);
580 /* now find the next hop */
581 for (e=0; e<strlen(bbb); ++e) if (bbb[e]=='!') bbb[e]=0;
582 strcpy(buffer->nexthop,bbb);
585 for (e=0; e<strlen(bbb); ++e) if (bbb[e]=='_') bbb[e]=' ';
586 strcpy(buffer->R,bbb);
588 if (b=='D') strcpy(buffer->D,bbb);
589 if (b=='T') buffer->T=atol(bbb);
590 if (b=='I') buffer->I=atol(bbb);
591 if (b=='H') strcpy(buffer->H,bbb);
592 if (b=='B') strcpy(buffer->B,bbb);
593 if (b=='G') strcpy(buffer->G,bbb);
594 if (b=='E') strcpy(buffer->E,bbb);
597 END: if (buffer->I==0L) buffer->I=buffer->T;
601 void ship_to(filenm,sysnm) /* send spool file filenm to system sysnm */
610 fprintf(stdout,"netproc: shipping %s to %s\n",filenm,sysnm);
612 sprintf(sysflnm,"./network/systems/%s",sysnm);
613 sysflfd=fopen(sysflnm,"r");
614 if (sysflfd==NULL) fprintf(stdout,"netproc: cannot open %s\n",sysflnm);
615 fgets(commbuf1,99,sysflfd);
616 commbuf1[strlen(commbuf1)-1] = 0;
618 sprintf(commbuf2,commbuf1,filenm);
623 * proc_file_transfer() - handle a simple file transfer packet
625 void proc_file_transfer(tname)
626 char *tname; { /* name of temp file containing the whole message */
632 printf("netproc: processing network file transfer...\n");
633 strcpy(dest_dir,config.c_bucket_dir);
635 tfp=fopen(tname,"rb");
636 if (tfp==NULL) printf("netproc: cannot open %s\n",tname);
637 getc(tfp); getc(tfp); getc(tfp);
642 if (a=='O') for (b=0; b<MAXROOMS; ++b) {
643 if (!strucmp(buf,roomnames[b]))
644 strcpy(dest_dir,roomdirs[b]);
647 } while ((a!='M')&&(a>=0));
650 printf("netproc: no message text for file transfer\n");
654 sprintf(buf,"cd %s/files/%s; exec %s",bbs_home_directory,dest_dir,UUDECODE);
655 uud=(FILE *)popen(buf,"w");
657 printf("netproc: cannot open uudecode pipe\n");
663 buf[strlen(buf)-1] = 0;
664 for (a=0; a<strlen(buf); ++a) if (buf[a]=='/') buf[a]='_';
665 fprintf(uud,"%s\n",buf);
666 printf("netproc: %s\n",buf);
667 while(a=getc(tfp), a>0) putc(a,uud);
674 /* send a bounce message */
676 struct minfo *bminfo; {
683 sprintf(bfilename,"./network/spoolin/bounce.%d.%d",getpid(),bseq++);
684 bounce = fopen(bfilename,"wb");
687 fprintf(bounce,"%c%c%c",0xFF,MES_NORMAL,0);
688 fprintf(bounce,"Ppostmaster%c",0);
689 fprintf(bounce,"T%ld%c",now,0);
690 fprintf(bounce,"APostmaster%c",0);
691 fprintf(bounce,"OMail%c",0);
692 fprintf(bounce,"N%s%c",config.c_nodename,0);
693 fprintf(bounce,"H%s%c",config.c_humannode,0);
695 if (strlen(bminfo->E) > 0) {
696 fprintf(bounce,"R%s%c",bminfo->E,0);
699 fprintf(bounce,"R%s%c",bminfo->A,0);
702 fprintf(bounce,"D%s%c",bminfo->N,0);
703 fprintf(bounce,"M%s could not deliver your mail to:\n",
705 fprintf(bounce," \n %s\n \n",bminfo->R);
706 fprintf(bounce," because there is no such user on this system.\n");
707 fprintf(bounce," (Unsent message does *not* follow. ");
708 fprintf(bounce,"Help to conserve bandwidth.)\n%c",0);
715 * process incoming files in ./network/spoolin
718 FILE *fp,*message,*testfp,*ls;
719 static struct minfo minfo;
720 struct recentmsg recentmsg;
721 char tname[128],aaa[1024],iname[256],sfilename[256],pfilename[256];
724 struct syslist *stemp;
731 sprintf(tname,"/tmp/net.t%d",getpid()); /* temp file name */
732 sprintf(iname,"/tmp/net.i%d",getpid()); /* temp file name */
736 chdir(bbs_home_directory);
738 /* Let the shell do the dirty work. Get all data from spoolin */
740 sprintf(aaa,"cd %s/network/spoolin; ls",bbs_home_directory);
743 fprintf(stderr,"netproc: could not open dir cmd: %s\n",
748 ptr=fgets(sfilename,256,ls);
749 if (ptr!=NULL) sfilename[strlen(sfilename)-1] = 0;
750 } while( (ptr!=NULL)&&((!strcmp(sfilename,"."))
751 ||(!strcmp(sfilename,".."))));
752 if (ptr!=NULL) printf("netproc: processing %s\n",sfilename);
757 sprintf(pfilename,"%s/network/spoolin/%s",bbs_home_directory,sfilename);
758 fprintf(stderr,"netproc: processing <%s>\n", pfilename);
761 fp = fopen(pfilename, "rb");
763 fprintf(stderr, "netproc: cannot open <%s>: %s\n",
764 pfilename, strerror(errno));
766 fp = fopen("/dev/null" ,"rb");
769 NXMSG: /* Seek to the beginning of the next message */
772 } while((a!=255)&&(a>=0));
773 if (a<0) goto ENDSTR;
775 message = fopen(tname,"wb"); /* This crates the temporary file. */
776 if (message == NULL) {
777 fprintf(stderr, "Error creating %s: %s\n",
778 tname, strerror(errno));
781 putc(255,message); /* 0xFF (start-of-message) */
782 a = getc(fp); putc(a, message); /* type */
783 a = getc(fp); putc(a, message); /* mode */
785 FieldID = getc(fp); /* Header field ID */
786 putc(FieldID, message);
791 } while ((FieldID != 'M') && (a >= 0)); /* M is always last */
793 msglen = ftell(message);
796 /* process the individual mesage */
802 msgfind(tname,&minfo);
803 strncpy(recentmsg.RMnodename,minfo.N,9);
804 recentmsg.RMnodename[9]=0;
805 recentmsg.RMnum=minfo.I;
806 printf("netproc: #%ld fm <%s> in <%s> @ <%s>\n",
807 minfo.I,minfo.A,minfo.O,minfo.N);
808 if (strlen(minfo.R)>0) {
809 printf(" to <%s>",minfo.R);
810 if (strlen(minfo.D)>0) {
811 printf(" @ <%s>",minfo.D);
816 if (!strucmp(minfo.D,FQDN)) strcpy(minfo.D,NODENAME);
818 /* this routine updates our info on the system that sent the message */
819 stemp = get_sys_ptr(minfo.N);
820 if ((stemp == NULL) && (get_sys_ptr(minfo.nexthop) != NULL)) {
821 /* add non-neighbor system to map */
822 printf("Adding non-neighbor system <%s> to map\n", slist->s_name);
823 stemp = (struct syslist *)malloc((long)sizeof(struct syslist));
826 strcpy(slist->s_name,minfo.N);
827 strcpy(slist->s_type,"use");
828 strcpy(slist->s_nexthop,minfo.nexthop);
829 time(&slist->s_lastcontact);
831 else if ((stemp == NULL) && (!strucmp(minfo.N,minfo.nexthop))) {
832 /* add neighbor system to map */
833 printf("Adding neighbor system <%s> to map\n", slist->s_name);
834 sprintf(aaa,"%s/network/systems/%s",bbs_home_directory,minfo.N);
835 testfp=fopen(aaa,"r");
838 stemp = (struct syslist *)
839 malloc((long)sizeof(struct syslist));
842 strcpy(slist->s_name,minfo.N);
843 strcpy(slist->s_type,"bin");
844 strcpy(slist->s_nexthop,"Mail");
845 time(&slist->s_lastcontact);
848 /* now update last contact and long node name if we can */
850 time(&stemp->s_lastcontact);
851 if (strlen(minfo.H) > 0) strcpy(stemp->s_humannode,minfo.H);
852 if (strlen(minfo.B) > 0) strcpy(stemp->s_phonenum,minfo.B);
853 if (strlen(minfo.G) > 0) strcpy(stemp->s_gdom,minfo.G);
856 /* route the message if necessary */
857 if ((strucmp(minfo.D,NODENAME))&&(minfo.D[0]!=0)) {
858 a = get_sysinfo_type(minfo.D);
859 printf("netproc: routing message to system <%s>\n",minfo.D);
863 printf("netproc: netmailer %s\n", tname);
865 execlp("./netmailer","netmailer",
867 printf("netproc: error running netmailer: %s\n",
872 else while (wait(&b)!=(-1));
874 else if (a==M_BINARY) {
875 ship_to(tname,minfo.D);
878 /* message falls into the bit bucket? */
882 /* check to see if it's a file transfer */
883 else if (!struncmp(minfo.S,"FILE",4)) {
884 proc_file_transfer(tname);
887 /* otherwise process it as a normal message */
890 if (!strucmp(minfo.R, "postmaster")) {
892 strcpy(minfo.C, "Aide");
895 if (strlen(minfo.R) > 0) {
896 sprintf(buf,"GOTO _MAIL_");
898 if (is_banned(minfo.A,minfo.C,minfo.N)) {
899 sprintf(buf,"GOTO %s", FILTERROOM);
902 if (strlen(minfo.C) > 0) {
903 sprintf(buf,"GOTO %s", minfo.C);
906 sprintf(buf,"GOTO %s", minfo.O);
912 puts(buf); fflush(stdout);
913 sprintf(buf,"GOTO _BITBUCKET_");
918 /* Open the temporary file containing the message */
919 message = fopen(tname, "rb");
920 if (message == NULL) {
921 fprintf(stderr, "netproc: cannot open %s: %s\n",
922 tname, strerror(errno));
927 /* Transmit the message to the server */
928 sprintf(buf, "ENT3 1|%s|%ld", minfo.R, msglen);
929 printf("< %s\n", buf);
932 printf("> %s\n", buf);
933 if (!strncmp(buf, "570", 3)) {
934 /* no such user, do a bounce */
938 /* Always use the server's idea of the message length,
939 * even though they should both be identical */
940 msglen = atol(&buf[4]);
941 while (msglen > 0L) {
942 bloklen = ((msglen >= 255L) ? 255 : ((int)msglen));
943 if (fread(buf, bloklen, 1, message) < 1) {
944 fprintf(stderr, "netproc: error trying to read %d bytes: %s\n",
945 bloklen, strerror(errno));
948 serv_write(buf, bloklen);
949 msglen = msglen - (long)bloklen;
973 int checkpath(path,sys) /* Checks to see whether its ok to send */
974 char path[]; /* Returns 1 for ok, send message */
975 char sys[]; { /* Returns 0 if message already there */
982 printf("netproc: checkpath <%s> <%s> ... ",path,sys);
984 for (a=0; a<strlen(path); ++a) {
985 if (!strncmp(&path[a],sys2,strlen(sys2))) return(0);
991 * implement split horizon algorithm
993 int ismsgok(mpos,mmfp,sysname)
998 int ok = 0; /* fail safe - no path, don't send it */
1002 if (getc(mmfp)!=255) return(0);
1003 getc(mmfp); getc(mmfp);
1005 while (a=getc(mmfp),((a!='M')&&(a!=0))) {
1006 fpgetfield(mmfp,fbuf);
1008 ok = checkpath(fbuf,sysname);
1012 printf("%s\n", ((ok)?"SEND":"(no)") );
1017 int spool_out(cmlist,destfp,sysname) /* spool list of messages to a file */
1018 struct msglist *cmlist; /* returns # of msgs spooled */
1022 struct msglist *cmptr;
1027 int msgs_spooled = 0;
1034 strcpy(curr_rm, "");
1035 sprintf(mmtemp, "/tmp/net.m%d", getpid());
1037 /* for each message in the list... */
1038 for (cmptr=cmlist; cmptr!=NULL; cmptr=cmptr->next) {
1040 /* make sure we're in the correct room... */
1041 if (strucmp(curr_rm, cmptr->m_rmname)) {
1042 sprintf(buf, "GOTO %s", cmptr->m_rmname);
1045 if (buf[0] == '2') {
1046 strcpy(curr_rm, cmptr->m_rmname);
1049 fprintf(stderr,"%s\n", buf);
1053 /* download the message from the server... */
1054 mmfp = fopen(mmtemp, "wb");
1055 sprintf(buf, "MSG3 %ld", cmptr->m_num);
1058 if (buf[0]=='6') { /* read the msg */
1059 msg_len = atol(&buf[4]);
1060 while (msg_len > 0L) {
1061 blok_len = ((msg_len >= 256L) ? 256 : (int)msg_len);
1062 serv_read(buf, blok_len);
1063 fwrite(buf, blok_len, 1, mmfp);
1064 msg_len = msg_len - (long)blok_len;
1067 else { /* or print the err */
1068 fprintf(stderr, "%s\n", buf);
1072 mmfp = fopen(mmtemp,"rb");
1074 if (ismsgok(0L,mmfp,sysname)) {
1078 fread(fbuf,3,1,mmfp);
1079 fwrite(fbuf,3,1,destfp);
1080 while (a=getc(mmfp),((a!=0)&&(a!='M'))) {
1081 if (a!='C') putc(a,destfp);
1082 fpgetfield(mmfp,fbuf);
1083 if (a=='P') fprintf(destfp,"%s!",NODENAME);
1085 fwrite(fbuf,strlen(fbuf)+1,1,destfp);
1088 fprintf(destfp, "C%s%c",
1089 cmptr->m_rmname, 0);
1101 return(msgs_spooled);
1104 void outprocess(sysname) /* send new room messages to sysname */
1108 char shiptocmd[128];
1112 struct msglist *cmlist = NULL;
1113 struct rmlist *crmlist = NULL;
1114 struct rmlist *rmptr,*rmptr2;
1115 struct msglist *cmptr,*cmptr2;
1116 FILE *sysflfp,*tempflfp;
1120 sprintf(tempflnm,"/tmp/%s.%d",NODENAME,getpid());
1121 tempflfp=fopen(tempflnm,"w");
1122 if (tempflfp==NULL) return;
1126 * Read system file for node in question and put together room list
1128 sprintf(sysflnm,"%s/network/systems/%s",bbs_home_directory,sysname);
1129 sysflfp=fopen(sysflnm,"r");
1130 if (sysflfp==NULL) return;
1131 fgets(shiptocmd,128,sysflfp); shiptocmd[strlen(shiptocmd)-1]=0;
1132 while(!feof(sysflfp)) {
1133 if (fgets(srmname,32,sysflfp)==NULL) break;
1134 srmname[strlen(srmname)-1]=0;
1135 fgets(lbuf,32,sysflfp);
1136 rmptr=(struct rmlist *)malloc(sizeof(struct rmlist));
1138 strcpy(rmptr->rm_name,srmname);
1139 strip_trailing_whitespace(rmptr->rm_name);
1140 rmptr->rm_lastsent = atol(lbuf);
1141 if (crmlist==NULL) crmlist=rmptr;
1142 else if (!strucmp(rmptr->rm_name,"control")) {
1143 /* control has to be first in room list */
1144 rmptr->next = crmlist;
1149 while (rmptr2->next != NULL) rmptr2=rmptr2->next;
1156 * Assemble list of messages to be spooled
1158 for (rmptr=crmlist; rmptr!=NULL; rmptr=rmptr->next) {
1160 sprintf(buf,"GOTO %s",rmptr->rm_name);
1164 fprintf(stderr, "%s\n", buf);
1167 sprintf(buf, "MSGS GT|%ld", rmptr->rm_lastsent);
1170 if (buf[0]=='1') while (serv_gets(buf), strcmp(buf,"000")) {
1171 thismsg = atol(buf);
1172 if ( thismsg > (rmptr->rm_lastsent) ) {
1173 rmptr->rm_lastsent = thismsg;
1175 cmptr=(struct msglist *)
1176 malloc(sizeof(struct msglist));
1178 cmptr->m_num = thismsg;
1179 strcpy(cmptr->m_rmname, rmptr->rm_name);
1181 if (cmlist == NULL) cmlist = cmptr;
1184 while (cmptr2->next != NULL)
1185 cmptr2 = cmptr2->next;
1186 cmptr2->next = cmptr;
1190 else { /* print error from "msgs all" */
1191 fprintf(stderr, "%s\n", buf);
1196 outgoing_msgs=0; cmptr2=cmlist; /* this loop counts the messages */
1197 while (cmptr2!=NULL) {
1199 cmptr2 = cmptr2->next;
1201 printf("netproc: %d messages to be spooled to %s\n",
1202 outgoing_msgs,sysname);
1206 * Spool out the messages, but only if there are any.
1209 if (outgoing_msgs!=0) outgoing_msgs=spool_out(cmlist,tempflfp,sysname);
1210 printf("netproc: %d messages actually spooled\n",
1215 * Deallocate list of spooled messages.
1217 while(cmlist!=NULL) {
1224 * Rewrite system file and deallocate room list.
1226 printf("Spooling...\n");
1228 sysflfp=fopen(sysflnm,"w");
1229 fprintf(sysflfp,"%s\n",shiptocmd);
1230 for (rmptr=crmlist; rmptr!=NULL; rmptr=rmptr->next)
1231 fprintf(sysflfp,"%s\n%ld\n",rmptr->rm_name,rmptr->rm_lastsent);
1233 while(crmlist!=NULL) {
1234 rmptr=crmlist->next;
1240 * Close temporary file, ship it out, and return
1243 if (outgoing_msgs!=0) ship_to(tempflnm,sysname);
1249 * Connect netproc to the Citadel server running on this computer.
1251 void np_attach_to_server() {
1254 char *args[] = { "netproc", "localhost", NULL, NULL } ;
1256 printf("Attaching to server...\n");
1257 sprintf(portname, "%d", config.c_port_number);
1259 attach_to_server(3, args);
1261 printf("%s\n",&buf[4]);
1262 sprintf(buf,"IPGM %d", config.c_ipgm_secret);
1265 printf("%s\n",&buf[4]);
1276 void main(argc,argv)
1285 strcpy(bbs_home_directory, BBSDIR);
1288 * Change directories if specified
1290 if (argv > 0) for (a=1; a<argc; ++a) {
1291 if (!strncmp(argv[a], "-h", 2)) {
1292 strcpy(bbs_home_directory, argv[a]);
1293 strcpy(bbs_home_directory, &bbs_home_directory[2]);
1297 fprintf(stderr, "netproc: usage: netproc [-hHomeDir]\n");
1304 /* write all messages to the log from this point onward */
1305 freopen(NPLOGFILE,NPLOGMODE,stdout);
1306 freopen(NPLOGFILE,NPLOGMODE,stderr);
1308 if (set_lockfile()!=0) {
1309 fprintf(stderr,"netproc: lock file exists: already running\n");
1313 signal(SIGINT,cleanup);
1314 signal(SIGQUIT,cleanup);
1315 signal(SIGHUP,cleanup);
1316 signal(SIGTERM,cleanup);
1318 printf("netproc: started. pid=%d\n",getpid());
1320 np_attach_to_server();
1323 if (load_roomnames()!=0) fprintf(stdout,"netproc: cannot load rooms\n");
1324 if (load_syslist()!=0) fprintf(stdout,"netproc: cannot load sysinfo\n");
1325 setup_special_nodes();
1327 inprocess(); /* first collect incoming stuff */
1329 allfp=(FILE *)popen("cd ./network/systems; ls","r");
1331 while (fgets(allst,32,allfp)!=NULL) {
1332 allst[strlen(allst)-1] = 0;
1338 inprocess(); /* incoming again in case anything new was generated */
1340 printf("netproc: processing ended.\n");