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
9 * Specify where netproc should log to, and the mode for opening the file.
10 * If you are logging to a file, NPLOGMODE should be a; if you are logging to
11 * a device or fifo it should be w.
13 #define NPLOGFILE "./netproc.log"
16 /* How long it takes for an old node to drop off the network map */
17 #define EXPIRY_TIME (2592000L)
19 /* Where do we keep our lock file? */
20 #define LOCKFILE "/var/lock/LCK.netproc"
22 /* Path to the 'uudecode' utility (needed for network file transfers) */
23 #define UUDECODE "/usr/bin/uudecode"
25 /* Uncomment the DEBUG def to see noisy traces */
32 #include <sys/types.h>
43 /* A list of users you wish to filter out of incoming traffic can be kept
44 * in ./network/filterlist -- messages from these users will be automatically
45 * moved to FILTERROOM. Normally this will be the same as TWITROOM (the
46 * room problem user messages are moved to) but you can override this by
47 * specifying a different room name here.
50 #define FILTERROOM TWITROOM
56 char m_rmname[ROOMNAMELEN];
61 char rm_name[ROOMNAMELEN];
66 struct filterlist *next;
101 void attach_to_server(int argc, char **argv);
102 void serv_read(char *buf, int bytes);
103 void serv_write(char *buf, int nbytes);
104 void get_config(void);
106 struct filterlist *filter = NULL;
107 struct syslist *slist = NULL;
109 struct config config;
110 extern char bbs_home_directory[];
111 extern int home_specified;
114 #ifndef HAVE_STRERROR
116 * replacement strerror() for systems that don't have it
118 char *strerror(int e)
122 sprintf(buf,"errno = %d",e);
128 void strip_trailing_whitespace(char *buf)
130 while(isspace(buf[strlen(buf)-1]))
131 buf[strlen(buf)-1]=0;
136 * we also load the network/mail.sysinfo table into memory, make changes
137 * as we learn more about the network from incoming messages, and write
138 * the table back to disk when we're done.
140 int load_syslist(void) {
142 struct syslist *stemp;
146 fp=fopen("network/mail.sysinfo","rb");
147 if (fp==NULL) return(1);
150 if (fgets(buf,128,fp)==NULL) {
154 buf[strlen(buf)-1] = 0;
155 while (isspace(buf[0])) strcpy(buf,&buf[1]);
156 if (buf[0]=='#') buf[0]=0;
157 if ( (insys==0) && (strlen(buf)!=0) ) {
159 stemp =(struct syslist *)malloc(sizeof(struct syslist));
162 strcpy(slist->s_name,buf);
163 strcpy(slist->s_type,"bin");
164 strcpy(slist->s_nexthop,"Mail");
165 slist->s_lastcontact = 0L;
166 strcpy(slist->s_humannode,"");
167 strcpy(slist->s_phonenum,"");
168 strcpy(slist->s_gdom,"");
170 else if ( (insys==1) && (strlen(buf)==0) ) {
173 else if ( (insys==1) && (!strncmp(buf,"bin",3)) ) {
174 strcpy(slist->s_type,"bin");
175 strcpy(slist->s_nexthop,&buf[4]);
177 else if ( (insys==1) && (!strncmp(buf,"use",3)) ) {
178 strcpy(slist->s_type,"use");
179 strcpy(slist->s_nexthop,&buf[4]);
181 else if ( (insys==1) && (!strncmp(buf,"uum",3)) ) {
182 strcpy(slist->s_type,"uum");
183 strcpy(slist->s_nexthop,&buf[4]);
185 else if ( (insys==1) && (!strncmp(buf,"lastcontact",11)) ) {
186 sscanf(&buf[12],"%ld",&slist->s_lastcontact);
188 else if ( (insys==1) && (!strncmp(buf,"humannode",9)) ) {
189 strcpy(slist->s_humannode,&buf[10]);
191 else if ( (insys==1) && (!strncmp(buf,"phonenum",8)) ) {
192 strcpy(slist->s_phonenum,&buf[9]);
194 else if ( (insys==1) && (!strncmp(buf,"gdom",4)) ) {
195 strcpy(slist->s_gdom,&buf[5]);
200 /* now we have to set up two "special" nodes on the list: one
201 * for the local node, and one for an Internet gateway
203 void setup_special_nodes(void) {
204 struct syslist *stemp,*slocal;
207 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
208 if (!strcasecmp(stemp->s_name,config.c_nodename)) slocal=stemp;
211 slocal =(struct syslist *)malloc(sizeof(struct syslist));
212 slocal->next = slist;
215 strcpy(slocal->s_name,config.c_nodename);
216 strcpy(slocal->s_type,"bin");
217 strcpy(slocal->s_nexthop,"Mail");
218 time(&slocal->s_lastcontact);
219 strcpy(slocal->s_humannode,config.c_humannode);
220 strcpy(slocal->s_phonenum,config.c_phonenum);
223 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
224 if (!strcasecmp(stemp->s_name,"internet")) slocal=stemp;
227 slocal =(struct syslist *)malloc(sizeof(struct syslist));
228 slocal->next = slist;
231 strcpy(slocal->s_name,"internet");
232 strcpy(slocal->s_type,"uum");
233 strcpy(slocal->s_nexthop,"%s");
234 time(&slocal->s_lastcontact);
235 strcpy(slocal->s_humannode,"Internet Gateway");
236 strcpy(slocal->s_phonenum,"");
237 strcpy(slocal->s_gdom,"");
242 * here's the routine to write the table back to disk.
244 void rewrite_syslist(void) {
245 struct syslist *stemp;
250 newfp=fopen("network/mail.sysinfo","w");
251 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
252 if (!strcasecmp(stemp->s_name,config.c_nodename)) {
253 time(&stemp->s_lastcontact);
254 strcpy(stemp->s_type,"bin");
255 strcpy(stemp->s_humannode,config.c_humannode);
256 strcpy(stemp->s_phonenum,config.c_phonenum);
258 /* remove systems we haven't heard from in a while */
259 if ( (stemp->s_lastcontact == 0L)
260 || (now - stemp->s_lastcontact < EXPIRY_TIME) ) {
261 fprintf(newfp,"%s\n%s %s\n",
262 stemp->s_name,stemp->s_type,stemp->s_nexthop);
263 if (strlen(stemp->s_phonenum) > 0)
264 fprintf(newfp,"phonenum %s\n",stemp->s_phonenum);
265 if (strlen(stemp->s_gdom) > 0)
266 fprintf(newfp,"gdom %s\n",stemp->s_gdom);
267 if (strlen(stemp->s_humannode) > 0)
268 fprintf(newfp,"humannode %s\n",stemp->s_humannode);
269 if (stemp->s_lastcontact > 0L)
270 fprintf(newfp,"lastcontact %ld %s",
271 stemp->s_lastcontact,
272 asctime(localtime(&stemp->s_lastcontact)));
277 /* now free the list */
278 while (slist!=NULL) {
286 /* call this function with the node name of a system and it returns a pointer
287 * to its syslist structure.
289 struct syslist *get_sys_ptr(char *sysname)
291 static char sysnambuf[16];
292 static struct syslist *sysptrbuf = NULL;
293 struct syslist *stemp;
295 if ( (!strcmp(sysname,sysnambuf))
296 && (sysptrbuf!=NULL) ) return(sysptrbuf);
298 strcpy(sysnambuf,sysname);
299 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
300 if (!strcmp(sysname,stemp->s_name)) {
311 * make sure only one copy of netproc runs at a time, using lock files
313 int set_lockfile(void) {
317 if ((lfp = fopen(LOCKFILE,"r")) != NULL) {
318 fscanf(lfp,"%d",&onppid);
320 if (!kill(onppid, 0) || errno == EPERM) return 1;
323 lfp=fopen(LOCKFILE,"w");
324 fprintf(lfp,"%d\n",getpid());
329 void remove_lockfile(void) {
334 * Why both cleanup() and nq_cleanup() ? Notice the alarm() call in
335 * cleanup() . If for some reason netproc hangs waiting for the server
336 * to clean up, the alarm clock goes off and the program exits anyway.
337 * The cleanup() routine makes a check to ensure it's not reentering, in
338 * case the ipc module looped it somehow.
340 void nq_cleanup(int e)
348 static int nested = 0;
351 signal(SIGALRM,nq_cleanup);
352 if (nested++ < 1) serv_puts("QUIT");
357 * This is implemented as a function rather than as a macro because the
358 * client-side IPC modules expect logoff() to be defined. They call logoff()
359 * when a problem connecting or staying connected to the server occurs.
367 * If there is a kill file in place, this function will process it.
369 void load_filterlist(void) {
371 struct filterlist *fbuf;
374 fp=fopen("./network/filterlist","r");
375 if (fp==NULL) return;
376 while (fgets(sbuf,256,fp)!=NULL) {
378 sbuf[strlen(sbuf)-1]=0;
379 fbuf=(struct filterlist *)
380 malloc((long)sizeof(struct filterlist));
383 strcpy(fbuf->f_person,"*");
384 strcpy(fbuf->f_room,"*");
385 strcpy(fbuf->f_system,"*");
387 for (a=strlen(sbuf); a>=0; --a) if (sbuf[a]==',') p=a;
390 strcpy(fbuf->f_person,sbuf);
391 strcpy(sbuf,&sbuf[p+1]);
393 for (a=strlen(sbuf); a>=0; --a) if (sbuf[a]==',') p=a;
396 strcpy(fbuf->f_room,sbuf);
397 strcpy(sbuf,&sbuf[p+1]);
399 strcpy(fbuf->f_system,sbuf);
405 /* returns 1 if user/message/room combination is in the kill file */
406 int is_banned(char *k_person, char *k_room, char *k_system)
408 struct filterlist *fptr;
410 for (fptr=filter; fptr!=NULL; fptr=fptr->next) if (
411 ((!strcasecmp(fptr->f_person,k_person))||(!strcmp(fptr->f_person,"*")))
413 ((!strcasecmp(fptr->f_room,k_room))||(!strcmp(fptr->f_room,"*")))
415 ((!strcasecmp(fptr->f_system,k_system))||(!strcmp(fptr->f_system,"*")))
421 int get_sysinfo_type(char *name) /* determine routing from sysinfo file */
423 struct syslist *stemp;
424 GETSN: for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
425 if (!strcasecmp(stemp->s_name,name)) {
426 if (!strcasecmp(stemp->s_type,"use")) {
427 strcpy(name,stemp->s_nexthop);
430 if (!strcasecmp(stemp->s_type,"bin")) {
433 if (!strcasecmp(stemp->s_type,"uum")) {
438 printf("netproc: cannot find system '%s' in mail.sysinfo\n",name);
443 void fpgetfield(FILE *fp, char *string)
463 * Load all of the fields of a message, except the actual text, into a
464 * table in memory (so we know how to process the message).
466 void msgfind(char *msgfile, struct minfo *buffer)
474 fp=fopen(msgfile,"rb");
476 fprintf(stderr,"Can't open message file: %s\n",strerror(errno));
481 fprintf(stdout,"Incorrect message format\n");
484 mtype=getc(fp); aflag=getc(fp);
493 BONFGM: b=getc(fp); if (b<0) goto END;
494 if (b=='M') goto END;
496 while ((bbb[0]==' ')&&(strlen(bbb)>1)) strcpy(bbb,&bbb[1]);
498 strcpy(buffer->A,bbb);
499 if (strlen(userid)==0) {
501 for (e=0; e<strlen(userid); ++e)
502 if (userid[e]==' ') userid[e]='_';
505 if (b=='O') strcpy(buffer->O,bbb);
506 if (b=='C') strcpy(buffer->C,bbb);
507 if (b=='N') strcpy(buffer->N,bbb);
508 if (b=='S') strcpy(buffer->S,bbb);
510 /* extract the user id from the path */
511 for (e=0; e<strlen(bbb); ++e)
512 if (bbb[e]=='!') strcpy(userid,&bbb[e+1]);
514 /* now find the next hop */
515 for (e=0; e<strlen(bbb); ++e) if (bbb[e]=='!') bbb[e]=0;
516 strcpy(buffer->nexthop,bbb);
519 for (e=0; e<strlen(bbb); ++e) if (bbb[e]=='_') bbb[e]=' ';
520 strcpy(buffer->R,bbb);
522 if (b=='D') strcpy(buffer->D,bbb);
523 if (b=='T') buffer->T=atol(bbb);
524 if (b=='I') buffer->I=atol(bbb);
525 if (b=='H') strcpy(buffer->H,bbb);
526 if (b=='B') strcpy(buffer->B,bbb);
527 if (b=='G') strcpy(buffer->G,bbb);
528 if (b=='E') strcpy(buffer->E,bbb);
531 END: if (buffer->I==0L) buffer->I=buffer->T;
535 void ship_to(char *filenm, char *sysnm) /* send spool file filenm to system sysnm */
544 fprintf(stdout,"netproc: shipping %s to %s\n",filenm,sysnm);
546 sprintf(sysflnm,"./network/systems/%s",sysnm);
547 sysflfd=fopen(sysflnm,"r");
548 if (sysflfd==NULL) fprintf(stdout,"netproc: cannot open %s\n",sysflnm);
549 fgets(commbuf1,99,sysflfd);
550 commbuf1[strlen(commbuf1)-1] = 0;
552 sprintf(commbuf2,commbuf1,filenm);
557 * proc_file_transfer() - handle a simple file transfer packet
559 * FIX This shouldn't be like this. What it needs to do is begin
560 * FIX an upload and transmit the file to the server.
562 void proc_file_transfer(char *tname)
563 { /* name of temp file containing the whole message */
569 printf("netproc: processing network file transfer...\n");
571 tfp=fopen(tname,"rb");
572 if (tfp==NULL) printf("netproc: cannot open %s\n",tname);
573 getc(tfp); getc(tfp); getc(tfp);
579 strcpy(dest_room, buf);
582 } while ((a!='M')&&(a>=0));
585 printf("netproc: no message text for file transfer\n");
589 sprintf(buf,"cd %s/files/%s; exec %s",bbs_home_directory,config.c_bucket_dir,UUDECODE);
590 uud=(FILE *)popen(buf,"w");
592 printf("netproc: cannot open uudecode pipe\n");
598 buf[strlen(buf)-1] = 0;
599 for (a=0; a<strlen(buf); ++a) if (buf[a]=='/') buf[a]='_';
600 fprintf(uud,"%s\n",buf);
601 printf("netproc: %s\n",buf);
602 while(a=getc(tfp), a>0) putc(a,uud);
609 /* send a bounce message */
610 void bounce(struct minfo *bminfo)
618 sprintf(bfilename,"./network/spoolin/bounce.%d.%d",getpid(),bseq++);
619 bounce = fopen(bfilename,"wb");
622 fprintf(bounce,"%c%c%c",0xFF,MES_NORMAL,0);
623 fprintf(bounce,"Ppostmaster%c",0);
624 fprintf(bounce,"T%ld%c",now,0);
625 fprintf(bounce,"APostmaster%c",0);
626 fprintf(bounce,"OMail%c",0);
627 fprintf(bounce,"N%s%c",config.c_nodename,0);
628 fprintf(bounce,"H%s%c",config.c_humannode,0);
630 if (strlen(bminfo->E) > 0) {
631 fprintf(bounce,"R%s%c",bminfo->E,0);
634 fprintf(bounce,"R%s%c",bminfo->A,0);
637 fprintf(bounce,"D%s%c",bminfo->N,0);
638 fprintf(bounce,"M%s could not deliver your mail to:\n",
640 fprintf(bounce," \n %s\n \n",bminfo->R);
641 fprintf(bounce," because there is no such user on this system.\n");
642 fprintf(bounce," (Unsent message does *not* follow. ");
643 fprintf(bounce,"Help to conserve bandwidth.)\n%c",0);
650 * process incoming files in ./network/spoolin
652 void inprocess(void) {
653 FILE *fp,*message,*testfp,*ls;
654 static struct minfo minfo;
655 struct recentmsg recentmsg;
656 char tname[128],aaa[1024],iname[256],sfilename[256],pfilename[256];
659 struct syslist *stemp;
666 sprintf(tname,"/tmp/net.t%d",getpid()); /* temp file name */
667 sprintf(iname,"/tmp/net.i%d",getpid()); /* temp file name */
671 chdir(bbs_home_directory);
673 /* Let the shell do the dirty work. Get all data from spoolin */
675 sprintf(aaa,"cd %s/network/spoolin; ls",bbs_home_directory);
678 fprintf(stderr,"netproc: could not open dir cmd: %s\n",
683 ptr=fgets(sfilename,256,ls);
684 if (ptr!=NULL) sfilename[strlen(sfilename)-1] = 0;
685 } while( (ptr!=NULL)&&((!strcmp(sfilename,"."))
686 ||(!strcmp(sfilename,".."))));
687 if (ptr!=NULL) printf("netproc: processing %s\n",sfilename);
692 sprintf(pfilename,"%s/network/spoolin/%s",bbs_home_directory,sfilename);
693 fprintf(stderr,"netproc: processing <%s>\n", pfilename);
696 fp = fopen(pfilename, "rb");
698 fprintf(stderr, "netproc: cannot open <%s>: %s\n",
699 pfilename, strerror(errno));
701 fp = fopen("/dev/null" ,"rb");
704 NXMSG: /* Seek to the beginning of the next message */
707 } while((a!=255)&&(a>=0));
708 if (a<0) goto ENDSTR;
710 message = fopen(tname,"wb"); /* This crates the temporary file. */
711 if (message == NULL) {
712 fprintf(stderr, "Error creating %s: %s\n",
713 tname, strerror(errno));
716 putc(255,message); /* 0xFF (start-of-message) */
717 a = getc(fp); putc(a, message); /* type */
718 a = getc(fp); putc(a, message); /* mode */
720 FieldID = getc(fp); /* Header field ID */
721 putc(FieldID, message);
726 } while ((FieldID != 'M') && (a >= 0)); /* M is always last */
728 msglen = ftell(message);
731 /* process the individual mesage */
737 msgfind(tname,&minfo);
738 strncpy(recentmsg.RMnodename,minfo.N,9);
739 recentmsg.RMnodename[9]=0;
740 recentmsg.RMnum=minfo.I;
741 printf("netproc: #%ld fm <%s> in <%s> @ <%s>\n",
742 minfo.I,minfo.A,minfo.O,minfo.N);
743 if (strlen(minfo.R)>0) {
744 printf(" to <%s>",minfo.R);
745 if (strlen(minfo.D)>0) {
746 printf(" @ <%s>",minfo.D);
751 if (!strcasecmp(minfo.D,FQDN)) strcpy(minfo.D,NODENAME);
753 /* this routine updates our info on the system that sent the message */
754 stemp = get_sys_ptr(minfo.N);
755 if ((stemp == NULL) && (get_sys_ptr(minfo.nexthop) != NULL)) {
756 /* add non-neighbor system to map */
757 printf("Adding non-neighbor system <%s> to map\n", slist->s_name);
758 stemp = (struct syslist *)malloc((long)sizeof(struct syslist));
761 strcpy(slist->s_name,minfo.N);
762 strcpy(slist->s_type,"use");
763 strcpy(slist->s_nexthop,minfo.nexthop);
764 time(&slist->s_lastcontact);
766 else if ((stemp == NULL) && (!strcasecmp(minfo.N,minfo.nexthop))) {
767 /* add neighbor system to map */
768 printf("Adding neighbor system <%s> to map\n", slist->s_name);
769 sprintf(aaa,"%s/network/systems/%s",bbs_home_directory,minfo.N);
770 testfp=fopen(aaa,"r");
773 stemp = (struct syslist *)
774 malloc((long)sizeof(struct syslist));
777 strcpy(slist->s_name,minfo.N);
778 strcpy(slist->s_type,"bin");
779 strcpy(slist->s_nexthop,"Mail");
780 time(&slist->s_lastcontact);
783 /* now update last contact and long node name if we can */
785 time(&stemp->s_lastcontact);
786 if (strlen(minfo.H) > 0) strcpy(stemp->s_humannode,minfo.H);
787 if (strlen(minfo.B) > 0) strcpy(stemp->s_phonenum,minfo.B);
788 if (strlen(minfo.G) > 0) strcpy(stemp->s_gdom,minfo.G);
791 /* route the message if necessary */
792 if ((strcasecmp(minfo.D,NODENAME))&&(minfo.D[0]!=0)) {
793 a = get_sysinfo_type(minfo.D);
794 printf("netproc: routing message to system <%s>\n",minfo.D);
798 printf("netproc: netmailer %s\n", tname);
800 execlp("./netmailer","netmailer",
802 printf("netproc: error running netmailer: %s\n",
807 else while (wait(&b)!=(-1));
809 else if (a==M_BINARY) {
810 ship_to(tname,minfo.D);
813 /* message falls into the bit bucket? */
817 /* check to see if it's a file transfer */
818 else if (!strncasecmp(minfo.S,"FILE",4)) {
819 proc_file_transfer(tname);
822 /* otherwise process it as a normal message */
825 if (!strcasecmp(minfo.R, "postmaster")) {
827 strcpy(minfo.C, "Aide");
830 if (strlen(minfo.R) > 0) {
831 sprintf(buf,"GOTO _MAIL_");
833 if (is_banned(minfo.A,minfo.C,minfo.N)) {
834 sprintf(buf,"GOTO %s", FILTERROOM);
837 if (strlen(minfo.C) > 0) {
838 sprintf(buf,"GOTO %s", minfo.C);
841 sprintf(buf,"GOTO %s", minfo.O);
847 puts(buf); fflush(stdout);
848 sprintf(buf,"GOTO _BITBUCKET_");
853 /* Open the temporary file containing the message */
854 message = fopen(tname, "rb");
855 if (message == NULL) {
856 fprintf(stderr, "netproc: cannot open %s: %s\n",
857 tname, strerror(errno));
862 /* Transmit the message to the server */
863 sprintf(buf, "ENT3 1|%s|%ld", minfo.R, msglen);
864 printf("< %s\n", buf);
867 printf("> %s\n", buf);
868 if (!strncmp(buf, "570", 3)) {
869 /* no such user, do a bounce */
873 /* Always use the server's idea of the message length,
874 * even though they should both be identical */
875 msglen = atol(&buf[4]);
876 while (msglen > 0L) {
877 bloklen = ((msglen >= 255L) ? 255 : ((int)msglen));
878 if (fread(buf, bloklen, 1, message) < 1) {
879 fprintf(stderr, "netproc: error trying to read %d bytes: %s\n",
880 bloklen, strerror(errno));
883 serv_write(buf, bloklen);
884 msglen = msglen - (long)bloklen;
908 int checkpath(char *path, char *sys) /* Checks to see whether its ok to send */
909 /* Returns 1 for ok, send message */
910 { /* Returns 0 if message already there */
917 printf("netproc: checkpath <%s> <%s> ... ",path,sys);
919 for (a=0; a<strlen(path); ++a) {
920 if (!strncmp(&path[a],sys2,strlen(sys2))) return(0);
926 * implement split horizon algorithm
928 int ismsgok(long int mpos, FILE *mmfp, char *sysname)
931 int ok = 0; /* fail safe - no path, don't send it */
935 if (getc(mmfp)!=255) return(0);
936 getc(mmfp); getc(mmfp);
938 while (a=getc(mmfp),((a!='M')&&(a!=0))) {
939 fpgetfield(mmfp,fbuf);
941 ok = checkpath(fbuf,sysname);
945 printf("%s\n", ((ok)?"SEND":"(no)") );
950 int spool_out(struct msglist *cmlist, FILE *destfp, char *sysname) /* spool list of messages to a file */
951 /* returns # of msgs spooled */
955 struct msglist *cmptr;
960 int msgs_spooled = 0;
968 sprintf(mmtemp, "/tmp/net.m%d", getpid());
970 /* for each message in the list... */
971 for (cmptr=cmlist; cmptr!=NULL; cmptr=cmptr->next) {
973 /* make sure we're in the correct room... */
974 if (strcasecmp(curr_rm, cmptr->m_rmname)) {
975 sprintf(buf, "GOTO %s", cmptr->m_rmname);
979 strcpy(curr_rm, cmptr->m_rmname);
982 fprintf(stderr,"%s\n", buf);
986 /* download the message from the server... */
987 mmfp = fopen(mmtemp, "wb");
988 sprintf(buf, "MSG3 %ld", cmptr->m_num);
991 if (buf[0]=='6') { /* read the msg */
992 msg_len = atol(&buf[4]);
993 while (msg_len > 0L) {
994 blok_len = ((msg_len >= 256L) ? 256 : (int)msg_len);
995 serv_read(buf, blok_len);
996 fwrite(buf, blok_len, 1, mmfp);
997 msg_len = msg_len - (long)blok_len;
1000 else { /* or print the err */
1001 fprintf(stderr, "%s\n", buf);
1005 mmfp = fopen(mmtemp,"rb");
1007 if (ismsgok(0L,mmfp,sysname)) {
1011 fread(fbuf,3,1,mmfp);
1012 fwrite(fbuf,3,1,destfp);
1013 while (a=getc(mmfp),((a!=0)&&(a!='M'))) {
1014 if (a!='C') putc(a,destfp);
1015 fpgetfield(mmfp,fbuf);
1016 if (a=='P') fprintf(destfp,"%s!",NODENAME);
1018 fwrite(fbuf,strlen(fbuf)+1,1,destfp);
1021 fprintf(destfp, "C%s%c",
1022 cmptr->m_rmname, 0);
1034 return(msgs_spooled);
1037 void outprocess(char *sysname) /* send new room messages to sysname */
1041 char shiptocmd[128];
1045 struct msglist *cmlist = NULL;
1046 struct rmlist *crmlist = NULL;
1047 struct rmlist *rmptr,*rmptr2;
1048 struct msglist *cmptr,*cmptr2;
1049 FILE *sysflfp,*tempflfp;
1053 sprintf(tempflnm,"/tmp/%s.%d",NODENAME,getpid());
1054 tempflfp=fopen(tempflnm,"w");
1055 if (tempflfp==NULL) return;
1059 * Read system file for node in question and put together room list
1061 sprintf(sysflnm,"%s/network/systems/%s",bbs_home_directory,sysname);
1062 sysflfp=fopen(sysflnm,"r");
1063 if (sysflfp==NULL) return;
1064 fgets(shiptocmd,128,sysflfp); shiptocmd[strlen(shiptocmd)-1]=0;
1065 while(!feof(sysflfp)) {
1066 if (fgets(srmname,32,sysflfp)==NULL) break;
1067 srmname[strlen(srmname)-1]=0;
1068 fgets(lbuf,32,sysflfp);
1069 rmptr=(struct rmlist *)malloc(sizeof(struct rmlist));
1071 strcpy(rmptr->rm_name,srmname);
1072 strip_trailing_whitespace(rmptr->rm_name);
1073 rmptr->rm_lastsent = atol(lbuf);
1074 if (crmlist==NULL) crmlist=rmptr;
1075 else if (!strcasecmp(rmptr->rm_name,"control")) {
1076 /* control has to be first in room list */
1077 rmptr->next = crmlist;
1082 while (rmptr2->next != NULL) rmptr2=rmptr2->next;
1089 * Assemble list of messages to be spooled
1091 for (rmptr=crmlist; rmptr!=NULL; rmptr=rmptr->next) {
1093 sprintf(buf,"GOTO %s",rmptr->rm_name);
1097 fprintf(stderr, "%s\n", buf);
1100 sprintf(buf, "MSGS GT|%ld", rmptr->rm_lastsent);
1103 if (buf[0]=='1') while (serv_gets(buf), strcmp(buf,"000")) {
1104 thismsg = atol(buf);
1105 if ( thismsg > (rmptr->rm_lastsent) ) {
1106 rmptr->rm_lastsent = thismsg;
1108 cmptr=(struct msglist *)
1109 malloc(sizeof(struct msglist));
1111 cmptr->m_num = thismsg;
1112 strcpy(cmptr->m_rmname, rmptr->rm_name);
1114 if (cmlist == NULL) cmlist = cmptr;
1117 while (cmptr2->next != NULL)
1118 cmptr2 = cmptr2->next;
1119 cmptr2->next = cmptr;
1123 else { /* print error from "msgs all" */
1124 fprintf(stderr, "%s\n", buf);
1129 outgoing_msgs=0; cmptr2=cmlist; /* this loop counts the messages */
1130 while (cmptr2!=NULL) {
1132 cmptr2 = cmptr2->next;
1134 printf("netproc: %d messages to be spooled to %s\n",
1135 outgoing_msgs,sysname);
1139 * Spool out the messages, but only if there are any.
1142 if (outgoing_msgs!=0) outgoing_msgs=spool_out(cmlist,tempflfp,sysname);
1143 printf("netproc: %d messages actually spooled\n",
1148 * Deallocate list of spooled messages.
1150 while(cmlist!=NULL) {
1157 * Rewrite system file and deallocate room list.
1159 printf("Spooling...\n");
1161 sysflfp=fopen(sysflnm,"w");
1162 fprintf(sysflfp,"%s\n",shiptocmd);
1163 for (rmptr=crmlist; rmptr!=NULL; rmptr=rmptr->next)
1164 fprintf(sysflfp,"%s\n%ld\n",rmptr->rm_name,rmptr->rm_lastsent);
1166 while(crmlist!=NULL) {
1167 rmptr=crmlist->next;
1173 * Close temporary file, ship it out, and return
1176 if (outgoing_msgs!=0) ship_to(tempflnm,sysname);
1182 * Connect netproc to the Citadel server running on this computer.
1184 void np_attach_to_server(void) {
1187 char *args[] = { "netproc", "localhost", NULL, NULL } ;
1189 printf("Attaching to server...\n");
1190 sprintf(portname, "%d", config.c_port_number);
1192 attach_to_server(3, args);
1194 printf("%s\n",&buf[4]);
1195 sprintf(buf,"IPGM %d", config.c_ipgm_secret);
1198 printf("%s\n",&buf[4]);
1209 int main(int argc, char **argv)
1216 strcpy(bbs_home_directory, BBSDIR);
1219 * Change directories if specified
1221 for (a=1; a<argc; ++a) {
1222 if (!strncmp(argv[a], "-h", 2)) {
1223 strcpy(bbs_home_directory, argv[a]);
1224 strcpy(bbs_home_directory, &bbs_home_directory[2]);
1228 fprintf(stderr, "netproc: usage: netproc [-hHomeDir]\n");
1235 /* write all messages to the log from this point onward */
1236 freopen(NPLOGFILE,NPLOGMODE,stdout);
1237 freopen(NPLOGFILE,NPLOGMODE,stderr);
1239 if (set_lockfile()!=0) {
1240 fprintf(stderr,"netproc: lock file exists: already running\n");
1244 signal(SIGINT,cleanup);
1245 signal(SIGQUIT,cleanup);
1246 signal(SIGHUP,cleanup);
1247 signal(SIGTERM,cleanup);
1249 printf("netproc: started. pid=%d\n",getpid());
1251 np_attach_to_server();
1254 if (load_syslist()!=0) fprintf(stdout,"netproc: cannot load sysinfo\n");
1255 setup_special_nodes();
1257 inprocess(); /* first collect incoming stuff */
1259 allfp=(FILE *)popen("cd ./network/systems; ls","r");
1261 while (fgets(allst,32,allfp)!=NULL) {
1262 allst[strlen(allst)-1] = 0;
1268 inprocess(); /* incoming again in case anything new was generated */
1270 printf("netproc: processing ended.\n");