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 /* How long it takes for an old node to drop off the network map */
9 #define EXPIRY_TIME (2592000L)
11 /* Where do we keep our lock file? */
12 #define LOCKFILE "/var/lock/LCK.netproc"
14 /* Path to the 'uudecode' utility (needed for network file transfers) */
15 #define UUDECODE "/usr/bin/uudecode"
17 /* Uncomment the DEBUG def to see noisy traces */
24 #include <sys/types.h>
37 /* A list of users you wish to filter out of incoming traffic can be kept
38 * in ./network/filterlist -- messages from these users will be automatically
39 * moved to FILTERROOM. Normally this will be the same as TWITROOM (the
40 * room problem user messages are moved to) but you can override this by
41 * specifying a different room name here.
44 #define FILTERROOM TWITROOM
50 char m_rmname[ROOMNAMELEN];
55 char rm_name[ROOMNAMELEN];
60 struct filterlist *next;
78 void attach_to_server(int argc, char **argv);
79 void serv_read(char *buf, int bytes);
80 void serv_write(char *buf, int nbytes);
81 void get_config(void);
83 struct filterlist *filter = NULL;
84 struct syslist *slist = NULL;
87 extern char bbs_home_directory[];
88 extern int home_specified;
93 * replacement strerror() for systems that don't have it
99 sprintf(buf,"errno = %d",e);
105 void strip_trailing_whitespace(char *buf)
107 while(isspace(buf[strlen(buf)-1]))
108 buf[strlen(buf)-1]=0;
113 * we also load the network/mail.sysinfo table into memory, make changes
114 * as we learn more about the network from incoming messages, and write
115 * the table back to disk when we're done.
117 int load_syslist(void) {
119 struct syslist *stemp;
123 fp=fopen("network/mail.sysinfo","rb");
124 if (fp==NULL) return(1);
127 if (fgets(buf,128,fp)==NULL) {
131 buf[strlen(buf)-1] = 0;
132 while (isspace(buf[0])) strcpy(buf,&buf[1]);
133 if (buf[0]=='#') buf[0]=0;
134 if ( (insys==0) && (strlen(buf)!=0) ) {
136 stemp =(struct syslist *)malloc(sizeof(struct syslist));
139 strcpy(slist->s_name,buf);
140 strcpy(slist->s_type,"bin");
141 strcpy(slist->s_nexthop,"Mail");
142 slist->s_lastcontact = 0L;
143 strcpy(slist->s_humannode,"");
144 strcpy(slist->s_phonenum,"");
145 strcpy(slist->s_gdom,"");
147 else if ( (insys==1) && (strlen(buf)==0) ) {
150 else if ( (insys==1) && (!strncmp(buf,"bin",3)) ) {
151 strcpy(slist->s_type,"bin");
152 strcpy(slist->s_nexthop,&buf[4]);
154 else if ( (insys==1) && (!strncmp(buf,"use",3)) ) {
155 strcpy(slist->s_type,"use");
156 strcpy(slist->s_nexthop,&buf[4]);
158 else if ( (insys==1) && (!strncmp(buf,"uum",3)) ) {
159 strcpy(slist->s_type,"uum");
160 strcpy(slist->s_nexthop,&buf[4]);
162 else if ( (insys==1) && (!strncmp(buf,"lastcontact",11)) ) {
163 sscanf(&buf[12],"%ld",&slist->s_lastcontact);
165 else if ( (insys==1) && (!strncmp(buf,"humannode",9)) ) {
166 strcpy(slist->s_humannode,&buf[10]);
168 else if ( (insys==1) && (!strncmp(buf,"phonenum",8)) ) {
169 strcpy(slist->s_phonenum,&buf[9]);
171 else if ( (insys==1) && (!strncmp(buf,"gdom",4)) ) {
172 strcpy(slist->s_gdom,&buf[5]);
177 /* now we have to set up two "special" nodes on the list: one
178 * for the local node, and one for an Internet gateway
180 void setup_special_nodes(void) {
181 struct syslist *stemp,*slocal;
184 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
185 if (!strcasecmp(stemp->s_name,config.c_nodename)) slocal=stemp;
188 slocal =(struct syslist *)malloc(sizeof(struct syslist));
189 slocal->next = slist;
192 strcpy(slocal->s_name,config.c_nodename);
193 strcpy(slocal->s_type,"bin");
194 strcpy(slocal->s_nexthop,"Mail");
195 time(&slocal->s_lastcontact);
196 strcpy(slocal->s_humannode,config.c_humannode);
197 strcpy(slocal->s_phonenum,config.c_phonenum);
200 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
201 if (!strcasecmp(stemp->s_name,"internet")) slocal=stemp;
204 slocal =(struct syslist *)malloc(sizeof(struct syslist));
205 slocal->next = slist;
208 strcpy(slocal->s_name,"internet");
209 strcpy(slocal->s_type,"uum");
210 strcpy(slocal->s_nexthop,"%s");
211 time(&slocal->s_lastcontact);
212 strcpy(slocal->s_humannode,"Internet Gateway");
213 strcpy(slocal->s_phonenum,"");
214 strcpy(slocal->s_gdom,"");
219 * here's the routine to write the table back to disk.
221 void rewrite_syslist(void) {
222 struct syslist *stemp;
227 newfp=fopen("network/mail.sysinfo","w");
228 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
229 if (!strcasecmp(stemp->s_name,config.c_nodename)) {
230 time(&stemp->s_lastcontact);
231 strcpy(stemp->s_type,"bin");
232 strcpy(stemp->s_humannode,config.c_humannode);
233 strcpy(stemp->s_phonenum,config.c_phonenum);
235 /* remove systems we haven't heard from in a while */
236 if ( (stemp->s_lastcontact == 0L)
237 || (now - stemp->s_lastcontact < EXPIRY_TIME) ) {
238 fprintf(newfp,"%s\n%s %s\n",
239 stemp->s_name,stemp->s_type,stemp->s_nexthop);
240 if (strlen(stemp->s_phonenum) > 0)
241 fprintf(newfp,"phonenum %s\n",stemp->s_phonenum);
242 if (strlen(stemp->s_gdom) > 0)
243 fprintf(newfp,"gdom %s\n",stemp->s_gdom);
244 if (strlen(stemp->s_humannode) > 0)
245 fprintf(newfp,"humannode %s\n",stemp->s_humannode);
246 if (stemp->s_lastcontact > 0L)
247 fprintf(newfp,"lastcontact %ld %s",
248 stemp->s_lastcontact,
249 asctime(localtime(&stemp->s_lastcontact)));
254 /* now free the list */
255 while (slist!=NULL) {
263 /* call this function with the node name of a system and it returns a pointer
264 * to its syslist structure.
266 struct syslist *get_sys_ptr(char *sysname)
268 static char sysnambuf[16];
269 static struct syslist *sysptrbuf = NULL;
270 struct syslist *stemp;
272 if ( (!strcmp(sysname,sysnambuf))
273 && (sysptrbuf!=NULL) ) return(sysptrbuf);
275 strcpy(sysnambuf,sysname);
276 for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
277 if (!strcmp(sysname,stemp->s_name)) {
288 * make sure only one copy of netproc runs at a time, using lock files
290 int set_lockfile(void) {
294 if ((lfp = fopen(LOCKFILE,"r")) != NULL) {
295 fscanf(lfp,"%d",&onppid);
297 if (!kill(onppid, 0) || errno == EPERM) return 1;
300 lfp=fopen(LOCKFILE,"w");
301 fprintf(lfp,"%ld\n",(long)getpid());
306 void remove_lockfile(void) {
311 * Why both cleanup() and nq_cleanup() ? Notice the alarm() call in
312 * cleanup() . If for some reason netproc hangs waiting for the server
313 * to clean up, the alarm clock goes off and the program exits anyway.
314 * The cleanup() routine makes a check to ensure it's not reentering, in
315 * case the ipc module looped it somehow.
317 void nq_cleanup(int e)
326 static int nested = 0;
329 signal(SIGALRM,nq_cleanup);
330 if (nested++ < 1) serv_puts("QUIT");
335 * This is implemented as a function rather than as a macro because the
336 * client-side IPC modules expect logoff() to be defined. They call logoff()
337 * when a problem connecting or staying connected to the server occurs.
345 * If there is a kill file in place, this function will process it.
347 void load_filterlist(void) {
349 struct filterlist *fbuf;
352 fp=fopen("./network/filterlist","r");
353 if (fp==NULL) return;
354 while (fgets(sbuf,256,fp)!=NULL) {
356 sbuf[strlen(sbuf)-1]=0;
357 fbuf=(struct filterlist *)
358 malloc((long)sizeof(struct filterlist));
361 strcpy(fbuf->f_person,"*");
362 strcpy(fbuf->f_room,"*");
363 strcpy(fbuf->f_system,"*");
365 for (a=strlen(sbuf); a>=0; --a) if (sbuf[a]==',') p=a;
368 strcpy(fbuf->f_person,sbuf);
369 strcpy(sbuf,&sbuf[p+1]);
371 for (a=strlen(sbuf); a>=0; --a) if (sbuf[a]==',') p=a;
374 strcpy(fbuf->f_room,sbuf);
375 strcpy(sbuf,&sbuf[p+1]);
377 strcpy(fbuf->f_system,sbuf);
383 /* returns 1 if user/message/room combination is in the kill file */
384 int is_banned(char *k_person, char *k_room, char *k_system)
386 struct filterlist *fptr;
388 for (fptr=filter; fptr!=NULL; fptr=fptr->next) if (
389 ((!strcasecmp(fptr->f_person,k_person))||(!strcmp(fptr->f_person,"*")))
391 ((!strcasecmp(fptr->f_room,k_room))||(!strcmp(fptr->f_room,"*")))
393 ((!strcasecmp(fptr->f_system,k_system))||(!strcmp(fptr->f_system,"*")))
399 int get_sysinfo_type(char *name) /* determine routing from sysinfo file */
401 struct syslist *stemp;
402 GETSN: for (stemp=slist; stemp!=NULL; stemp=stemp->next) {
403 if (!strcasecmp(stemp->s_name,name)) {
404 if (!strcasecmp(stemp->s_type,"use")) {
405 strcpy(name,stemp->s_nexthop);
408 if (!strcasecmp(stemp->s_type,"bin")) {
411 if (!strcasecmp(stemp->s_type,"uum")) {
416 syslog(LOG_ERR, "cannot find system '%s' in mail.sysinfo", name);
421 void fpgetfield(FILE *fp, char *string)
441 * Load all of the fields of a message, except the actual text, into a
442 * table in memory (so we know how to process the message).
444 void msgfind(char *msgfile, struct minfo *buffer)
452 fp=fopen(msgfile,"rb");
454 syslog(LOG_ERR, "can't open message file: %s",strerror(errno));
459 syslog(LOG_ERR, "incorrect message format");
462 mtype=getc(fp); aflag=getc(fp);
471 BONFGM: b=getc(fp); if (b<0) goto END;
472 if (b=='M') goto END;
474 while ((bbb[0]==' ')&&(strlen(bbb)>1)) strcpy(bbb,&bbb[1]);
476 strcpy(buffer->A,bbb);
477 if (strlen(userid)==0) {
479 for (e=0; e<strlen(userid); ++e)
480 if (userid[e]==' ') userid[e]='_';
483 if (b=='O') strcpy(buffer->O,bbb);
484 if (b=='C') strcpy(buffer->C,bbb);
485 if (b=='N') strcpy(buffer->N,bbb);
486 if (b=='S') strcpy(buffer->S,bbb);
488 /* extract the user id from the path */
489 for (e=0; e<strlen(bbb); ++e)
490 if (bbb[e]=='!') strcpy(userid,&bbb[e+1]);
492 /* now find the next hop */
493 for (e=0; e<strlen(bbb); ++e) if (bbb[e]=='!') bbb[e]=0;
494 strcpy(buffer->nexthop,bbb);
497 for (e=0; e<strlen(bbb); ++e) if (bbb[e]=='_') bbb[e]=' ';
498 strcpy(buffer->R,bbb);
500 if (b=='D') strcpy(buffer->D,bbb);
501 if (b=='T') buffer->T=atol(bbb);
502 if (b=='I') buffer->I=atol(bbb);
503 if (b=='H') strcpy(buffer->H,bbb);
504 if (b=='B') strcpy(buffer->B,bbb);
505 if (b=='G') strcpy(buffer->G,bbb);
506 if (b=='E') strcpy(buffer->E,bbb);
509 END: if (buffer->I==0L) buffer->I=buffer->T;
513 void ship_to(char *filenm, char *sysnm) /* send spool file filenm to system sysnm */
522 syslog(LOG_NOTICE, "shipping %s to %s", filenm, sysnm);
524 sprintf(sysflnm,"./network/systems/%s",sysnm);
525 sysflfd=fopen(sysflnm,"r");
526 if (sysflfd==NULL) syslog(LOG_ERR, "cannot open %s", sysflnm);
527 fgets(commbuf1,99,sysflfd);
528 commbuf1[strlen(commbuf1)-1] = 0;
530 sprintf(commbuf2,commbuf1,filenm);
535 * proc_file_transfer() - handle a simple file transfer packet
538 void proc_file_transfer(char *tname)
539 { /* name of temp file containing the whole message */
541 char dest_room[ROOMNAMELEN];
542 char subdir_name[256];
546 syslog(LOG_NOTICE, "processing network file transfer...");
548 tfp=fopen(tname,"rb");
549 if (tfp==NULL) syslog(LOG_ERR, "cannot open %s", tname);
550 getc(tfp); getc(tfp); getc(tfp);
556 strcpy(dest_room, buf);
559 } while ((a!='M')&&(a>=0));
562 syslog(LOG_ERR, "no message text for file transfer");
566 strcpy(subdir_name, "---xxx---");
567 sprintf(buf, "GOTO %s", dest_room);
571 extract(subdir_name, &buf[4], 2);
572 if (strlen(subdir_name) == 0) strcpy(subdir_name, "--xxx--");
575 /* Change to the room's directory; if that fails, change to the
576 * bitbucket directory. Then run uudecode.
578 sprintf(buf,"(cd %s/files/%s || cd %s/files/%s ) ; exec %s",
579 bbs_home_directory, subdir_name,
580 bbs_home_directory, config.c_bucket_dir,
583 uud=(FILE *)popen(buf,"w");
585 syslog(LOG_ERR, "cannot open uudecode pipe");
591 buf[strlen(buf)-1] = 0;
592 for (a=0; a<strlen(buf); ++a) if (buf[a]=='/') buf[a]='_';
593 fprintf(uud,"%s\n",buf);
594 printf("netproc: %s\n",buf);
595 while(a=getc(tfp), a>0) putc(a,uud);
602 /* send a bounce message */
603 void bounce(struct minfo *bminfo)
611 sprintf(bfilename,"./network/spoolin/bounce.%ld.%d",(long)getpid(),
613 bounce = fopen(bfilename,"wb");
616 fprintf(bounce,"%c%c%c",0xFF,MES_NORMAL,0);
617 fprintf(bounce,"Ppostmaster%c",0);
618 fprintf(bounce,"T%ld%c",now,0);
619 fprintf(bounce,"APostmaster%c",0);
620 fprintf(bounce,"OMail%c",0);
621 fprintf(bounce,"N%s%c",config.c_nodename,0);
622 fprintf(bounce,"H%s%c",config.c_humannode,0);
624 if (strlen(bminfo->E) > 0) {
625 fprintf(bounce,"R%s%c",bminfo->E,0);
628 fprintf(bounce,"R%s%c",bminfo->A,0);
631 fprintf(bounce,"D%s%c",bminfo->N,0);
632 fprintf(bounce,"M%s could not deliver your mail to:\n",
634 fprintf(bounce," \n %s\n \n",bminfo->R);
635 fprintf(bounce," because there is no such user on this system.\n");
636 fprintf(bounce," (Unsent message does *not* follow. ");
637 fprintf(bounce,"Help to conserve bandwidth.)\n%c",0);
644 * process incoming files in ./network/spoolin
646 void inprocess(void) {
647 FILE *fp,*message,*testfp,*ls;
648 static struct minfo minfo;
649 struct recentmsg recentmsg;
650 char tname[128],aaa[1024],iname[256],sfilename[256],pfilename[256];
653 struct syslist *stemp;
660 sprintf(tname,"/tmp/net.t%ld",(long)getpid()); /* temp file name */
661 sprintf(iname,"/tmp/net.i%ld",(long)getpid()); /* temp file name */
665 chdir(bbs_home_directory);
667 /* Let the shell do the dirty work. Get all data from spoolin */
669 sprintf(aaa,"cd %s/network/spoolin; ls",bbs_home_directory);
672 syslog(LOG_ERR, "could not open dir cmd: %s", strerror(errno));
676 SKIP: ptr=fgets(sfilename, sizeof sfilename, ls);
678 sfilename[strlen(sfilename)-1] = 0;
679 if (!strcmp(sfilename, ".")) goto SKIP;
680 if (!strcmp(sfilename, "..")) goto SKIP;
681 if (!strcmp(sfilename, "CVS")) goto SKIP;
685 PROCESS_IT: pclose(ls);
689 sprintf(pfilename,"%s/network/spoolin/%s",bbs_home_directory,sfilename);
690 syslog(LOG_NOTICE, "processing <%s>", pfilename);
692 fp = fopen(pfilename, "rb");
694 syslog(LOG_ERR, "cannot open %s: %s", pfilename, strerror(errno));
695 fp = fopen("/dev/null" ,"rb");
698 NXMSG: /* Seek to the beginning of the next message */
701 } while((a!=255)&&(a>=0));
702 if (a<0) goto ENDSTR;
704 message = fopen(tname,"wb"); /* This crates the temporary file. */
705 if (message == NULL) {
706 syslog(LOG_ERR, "error creating %s: %s", tname,strerror(errno));
709 putc(255,message); /* 0xFF (start-of-message) */
710 a = getc(fp); putc(a, message); /* type */
711 a = getc(fp); putc(a, message); /* mode */
713 FieldID = getc(fp); /* Header field ID */
714 putc(FieldID, message);
719 } while ((FieldID != 'M') && (a >= 0)); /* M is always last */
721 msglen = ftell(message);
724 /* process the individual mesage */
730 msgfind(tname,&minfo);
731 strncpy(recentmsg.RMnodename,minfo.N,9);
732 recentmsg.RMnodename[9]=0;
733 recentmsg.RMnum=minfo.I;
734 syslog(LOG_NOTICE, "#%ld fm <%s> in <%s> @ <%s>",
735 minfo.I,minfo.A,minfo.O,minfo.N);
736 if (strlen(minfo.R)>0) {
737 syslog(LOG_NOTICE, " to <%s>",minfo.R);
738 if (strlen(minfo.D)>0) {
739 syslog(LOG_NOTICE, " @ <%s>",minfo.D);
742 if (!strcasecmp(minfo.D,FQDN)) strcpy(minfo.D,NODENAME);
744 /* this routine updates our info on the system that sent the message */
745 stemp = get_sys_ptr(minfo.N);
746 if ((stemp == NULL) && (get_sys_ptr(minfo.nexthop) != NULL)) {
747 /* add non-neighbor system to map */
748 syslog(LOG_NOTICE, "Adding non-neighbor system <%s> to map",
750 stemp = (struct syslist *)malloc((long)sizeof(struct syslist));
753 strcpy(slist->s_name,minfo.N);
754 strcpy(slist->s_type,"use");
755 strcpy(slist->s_nexthop,minfo.nexthop);
756 time(&slist->s_lastcontact);
758 else if ((stemp == NULL) && (!strcasecmp(minfo.N,minfo.nexthop))) {
759 /* add neighbor system to map */
760 syslog(LOG_NOTICE, "Adding neighbor system <%s> to map",
762 sprintf(aaa,"%s/network/systems/%s",bbs_home_directory,minfo.N);
763 testfp=fopen(aaa,"r");
766 stemp = (struct syslist *)
767 malloc((long)sizeof(struct syslist));
770 strcpy(slist->s_name,minfo.N);
771 strcpy(slist->s_type,"bin");
772 strcpy(slist->s_nexthop,"Mail");
773 time(&slist->s_lastcontact);
776 /* now update last contact and long node name if we can */
778 time(&stemp->s_lastcontact);
779 if (strlen(minfo.H) > 0) strcpy(stemp->s_humannode,minfo.H);
780 if (strlen(minfo.B) > 0) strcpy(stemp->s_phonenum,minfo.B);
781 if (strlen(minfo.G) > 0) strcpy(stemp->s_gdom,minfo.G);
784 /* route the message if necessary */
785 if ((strcasecmp(minfo.D,NODENAME))&&(minfo.D[0]!=0)) {
786 a = get_sysinfo_type(minfo.D);
787 syslog(LOG_NOTICE, "routing message to system <%s>", minfo.D);
791 syslog(LOG_NOTICE, "netmailer %s", tname);
793 execlp("./netmailer","netmailer",
795 syslog(LOG_ERR, "error running netmailer: %s",
799 else while (wait(&b)!=(-1));
801 else if (a==M_BINARY) {
802 ship_to(tname,minfo.D);
805 /* message falls into the bit bucket? */
809 /* check to see if it's a file transfer */
810 else if (!strncasecmp(minfo.S,"FILE",4)) {
811 proc_file_transfer(tname);
814 /* otherwise process it as a normal message */
817 if (!strcasecmp(minfo.R, "postmaster")) {
819 strcpy(minfo.C, "Aide");
822 if (strlen(minfo.R) > 0) {
823 sprintf(buf,"GOTO _MAIL_");
825 if (is_banned(minfo.A,minfo.C,minfo.N)) {
826 sprintf(buf,"GOTO %s", FILTERROOM);
829 if (strlen(minfo.C) > 0) {
830 sprintf(buf,"GOTO %s", minfo.C);
833 sprintf(buf,"GOTO %s", minfo.O);
839 syslog(LOG_ERR, "%s", buf);
840 sprintf(buf,"GOTO _BITBUCKET_");
845 /* Open the temporary file containing the message */
846 message = fopen(tname, "rb");
847 if (message == NULL) {
848 syslog(LOG_ERR, "cannot open %s: %s",
849 tname, strerror(errno));
854 /* Transmit the message to the server */
855 sprintf(buf, "ENT3 1|%s|%ld", minfo.R, msglen);
858 if (!strncmp(buf, "570", 3)) {
859 /* no such user, do a bounce */
863 /* Always use the server's idea of the message length,
864 * even though they should both be identical */
865 msglen = atol(&buf[4]);
866 while (msglen > 0L) {
867 bloklen = ((msglen >= 255L) ? 255 : ((int)msglen));
868 if (fread(buf, bloklen, 1, message) < 1) {
870 "error trying to read %d bytes: %s",
871 bloklen, strerror(errno));
873 serv_write(buf, bloklen);
874 msglen = msglen - (long)bloklen;
880 syslog(LOG_ERR, "%s", buf);
897 int checkpath(char *path, char *sys) /* Checks to see whether its ok to send */
898 /* Returns 1 for ok, send message */
899 { /* Returns 0 if message already there */
906 syslog(LOG_NOTICE, "checkpath <%s> <%s> ... ", path, sys);
908 for (a=0; a<strlen(path); ++a) {
909 if (!strncmp(&path[a],sys2,strlen(sys2))) return(0);
915 * implement split horizon algorithm
917 int ismsgok(long int mpos, FILE *mmfp, char *sysname)
920 int ok = 0; /* fail safe - no path, don't send it */
924 if (getc(mmfp)!=255) return(0);
925 getc(mmfp); getc(mmfp);
927 while (a=getc(mmfp),((a!='M')&&(a!=0))) {
928 fpgetfield(mmfp,fbuf);
930 ok = checkpath(fbuf,sysname);
934 syslog(LOG_NOTICE, "%s", ((ok)?"SEND":"(no)") );
939 int spool_out(struct msglist *cmlist, FILE *destfp, char *sysname) /* spool list of messages to a file */
940 /* returns # of msgs spooled */
944 struct msglist *cmptr;
949 int msgs_spooled = 0;
957 sprintf(mmtemp, "/tmp/net.m%ld", (long)getpid());
959 /* for each message in the list... */
960 for (cmptr=cmlist; cmptr!=NULL; cmptr=cmptr->next) {
962 /* make sure we're in the correct room... */
963 if (strcasecmp(curr_rm, cmptr->m_rmname)) {
964 sprintf(buf, "GOTO %s", cmptr->m_rmname);
968 strcpy(curr_rm, cmptr->m_rmname);
971 syslog(LOG_ERR, "%s", buf);
975 /* download the message from the server... */
976 mmfp = fopen(mmtemp, "wb");
977 sprintf(buf, "MSG3 %ld", cmptr->m_num);
980 if (buf[0]=='6') { /* read the msg */
981 msg_len = atol(&buf[4]);
982 while (msg_len > 0L) {
983 blok_len = ((msg_len >= 256L) ? 256 : (int)msg_len);
984 serv_read(buf, blok_len);
985 fwrite(buf, blok_len, 1, mmfp);
986 msg_len = msg_len - (long)blok_len;
989 else { /* or print the err */
990 syslog(LOG_ERR, "%s", buf);
994 mmfp = fopen(mmtemp,"rb");
996 if (ismsgok(0L,mmfp,sysname)) {
1000 fread(fbuf,3,1,mmfp);
1001 fwrite(fbuf,3,1,destfp);
1002 while (a=getc(mmfp),((a!=0)&&(a!='M'))) {
1003 if (a!='C') putc(a,destfp);
1004 fpgetfield(mmfp,fbuf);
1005 if (a=='P') fprintf(destfp,"%s!",NODENAME);
1007 fwrite(fbuf,strlen(fbuf)+1,1,destfp);
1010 fprintf(destfp, "C%s%c",
1011 cmptr->m_rmname, 0);
1023 return(msgs_spooled);
1026 void outprocess(char *sysname) /* send new room messages to sysname */
1030 char shiptocmd[128];
1034 struct msglist *cmlist = NULL;
1035 struct rmlist *crmlist = NULL;
1036 struct rmlist *rmptr,*rmptr2;
1037 struct msglist *cmptr,*cmptr2;
1038 FILE *sysflfp,*tempflfp;
1042 sprintf(tempflnm,"/tmp/%s.%ld",NODENAME,(long)getpid());
1043 tempflfp=fopen(tempflnm,"w");
1044 if (tempflfp==NULL) return;
1048 * Read system file for node in question and put together room list
1050 sprintf(sysflnm,"%s/network/systems/%s",bbs_home_directory,sysname);
1051 sysflfp=fopen(sysflnm,"r");
1052 if (sysflfp==NULL) return;
1053 fgets(shiptocmd,128,sysflfp); shiptocmd[strlen(shiptocmd)-1]=0;
1054 while(!feof(sysflfp)) {
1055 if (fgets(srmname,32,sysflfp)==NULL) break;
1056 srmname[strlen(srmname)-1]=0;
1057 fgets(lbuf,32,sysflfp);
1058 rmptr=(struct rmlist *)malloc(sizeof(struct rmlist));
1060 strcpy(rmptr->rm_name,srmname);
1061 strip_trailing_whitespace(rmptr->rm_name);
1062 rmptr->rm_lastsent = atol(lbuf);
1063 if (crmlist==NULL) crmlist=rmptr;
1064 else if (!strcasecmp(rmptr->rm_name,"control")) {
1065 /* control has to be first in room list */
1066 rmptr->next = crmlist;
1071 while (rmptr2->next != NULL) rmptr2=rmptr2->next;
1078 * Assemble list of messages to be spooled
1080 for (rmptr=crmlist; rmptr!=NULL; rmptr=rmptr->next) {
1082 sprintf(buf,"GOTO %s",rmptr->rm_name);
1086 syslog(LOG_ERR, "%s", buf);
1089 sprintf(buf, "MSGS GT|%ld", rmptr->rm_lastsent);
1092 if (buf[0]=='1') while (serv_gets(buf), strcmp(buf,"000")) {
1093 thismsg = atol(buf);
1094 if ( thismsg > (rmptr->rm_lastsent) ) {
1095 rmptr->rm_lastsent = thismsg;
1097 cmptr=(struct msglist *)
1098 malloc(sizeof(struct msglist));
1100 cmptr->m_num = thismsg;
1101 strcpy(cmptr->m_rmname, rmptr->rm_name);
1103 if (cmlist == NULL) cmlist = cmptr;
1106 while (cmptr2->next != NULL)
1107 cmptr2 = cmptr2->next;
1108 cmptr2->next = cmptr;
1112 else { /* print error from "msgs all" */
1113 syslog(LOG_ERR, "%s", buf);
1118 outgoing_msgs=0; cmptr2=cmlist; /* this loop counts the messages */
1119 while (cmptr2!=NULL) {
1121 cmptr2 = cmptr2->next;
1123 syslog(LOG_NOTICE, "%d messages to be spooled to %s",
1124 outgoing_msgs,sysname);
1127 * Spool out the messages, but only if there are any.
1129 if (outgoing_msgs!=0) outgoing_msgs=spool_out(cmlist,tempflfp,sysname);
1130 syslog(LOG_NOTICE, "%d messages actually spooled",
1134 * Deallocate list of spooled messages.
1136 while(cmlist!=NULL) {
1143 * Rewrite system file and deallocate room list.
1145 syslog(LOG_NOTICE, "Spooling...");
1146 sysflfp=fopen(sysflnm,"w");
1147 fprintf(sysflfp,"%s\n",shiptocmd);
1148 for (rmptr=crmlist; rmptr!=NULL; rmptr=rmptr->next)
1149 fprintf(sysflfp,"%s\n%ld\n",rmptr->rm_name,rmptr->rm_lastsent);
1151 while(crmlist!=NULL) {
1152 rmptr=crmlist->next;
1158 * Close temporary file, ship it out, and return
1161 if (outgoing_msgs!=0) ship_to(tempflnm,sysname);
1167 * Connect netproc to the Citadel server running on this computer.
1169 void np_attach_to_server(void) {
1172 char *args[] = { "netproc", "localhost", NULL, NULL } ;
1174 syslog(LOG_NOTICE, "Attaching to server...");
1175 sprintf(portname, "%d", config.c_port_number);
1177 attach_to_server(3, args);
1179 syslog(LOG_NOTICE, "%s", &buf[4]);
1180 sprintf(buf,"IPGM %d", config.c_ipgm_secret);
1183 syslog(LOG_NOTICE, "%s", &buf[4]);
1194 int main(int argc, char **argv)
1199 int import_only = 0; /* if set to 1, don't export anything */
1201 openlog("netproc", LOG_PID, LOG_USER);
1202 strcpy(bbs_home_directory, BBSDIR);
1205 * Change directories if specified
1207 for (a=1; a<argc; ++a) {
1208 if (!strncmp(argv[a], "-h", 2)) {
1209 strcpy(bbs_home_directory, argv[a]);
1210 strcpy(bbs_home_directory, &bbs_home_directory[2]);
1213 else if (!strcmp(argv[a], "-i")) {
1217 fprintf(stderr, "netproc: usage: ");
1218 fprintf(stderr, "netproc [-hHomeDir] [-i]\n");
1225 if (set_lockfile()!=0) {
1226 syslog(LOG_NOTICE, "lock file exists: already running");
1230 signal(SIGINT,cleanup);
1231 signal(SIGQUIT,cleanup);
1232 signal(SIGHUP,cleanup);
1233 signal(SIGTERM,cleanup);
1235 syslog(LOG_NOTICE, "started. pid=%d", getpid());
1237 np_attach_to_server();
1240 if (load_syslist()!=0) syslog(LOG_ERR, "cannot load sysinfo");
1241 setup_special_nodes();
1243 inprocess(); /* first collect incoming stuff */
1245 if (import_only != 1) {
1246 allfp=(FILE *)popen("cd ./network/systems; ls","r");
1248 while (fgets(allst,32,allfp)!=NULL) {
1249 allst[strlen(allst)-1] = 0;
1254 /* import again in case anything new was generated */
1259 syslog(LOG_NOTICE, "processing ended.");