|
|
1.1 root 1: /* sbbsecho.c */
2:
3: /* Synchronet FidoNet EchoMail Scanning/Tossing and NetMail Tossing Utility */
4:
5: /* $Id: sbbsecho.c,v 1.182 2006/06/27 22:26:15 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: /* Portions written by Allen Christiansen 1994-1996 */
39:
40: #ifdef _WIN32
41: #include <windows.h>
42: #endif
43:
44: #include <time.h>
45: #include <errno.h>
46: #include <stdio.h>
47: #include <ctype.h>
48: #include <fcntl.h>
49: #include <stdarg.h>
50: #include <stdlib.h>
51: #include <string.h>
52: #include <sys/stat.h>
53:
54: #ifdef __WATCOMC__
55: #include <mem.h>
56: #endif
57:
58: #ifndef __unix__
59: #include <malloc.h>
60: #endif
61:
62: #include "conwrap.h" /* getch() */
63: #include "sbbs.h" /* load_cfg() */
64: #include "sbbsdefs.h"
65: #include "smblib.h"
66: #include "scfglib.h"
67: #include "lzh.h"
68: #include "sbbsecho.h"
69: #include "genwrap.h" /* PLATFORM_DESC */
70:
71: smb_t *smb,*email;
72: long misc=(IMPORT_PACKETS|IMPORT_NETMAIL|IMPORT_ECHOMAIL|EXPORT_ECHOMAIL
73: |DELETE_NETMAIL|DELETE_PACKETS);
74: ulong netmail=0;
75: int log_level=LOG_NOTICE;
76: char tmp[256],pkt_type=0;
77: int secure,cur_smb=0;
78: FILE *fidologfile=NULL;
79: two_two_t two_two;
80: two_plus_t two_plus;
81: BOOL twit_list;
82:
83: faddr_t sys_faddr = {1,1,1,0}; /* Default system address: 1:1/1.0 */
84: config_t cfg;
85: scfg_t scfg;
86: char revision[16];
87: char compiler[32];
88:
89: BOOL pause_on_exit=FALSE;
90:
91: #ifndef __NT__
92: #define delfile(x) remove(x)
93: #else
94: int delfile(char *filename)
95: {
96: int i=0;
97:
98: while(remove(filename) && i++<120) /* Wait up to 60 seconds to delete file */
99: delay(500); /* for Win95 bug fix */
100: return(i);
101: }
102: #endif
103:
104: #if defined(__unix__) /* borrowed from MSVC */
105: unsigned _rotr (
106: unsigned val,
107: int shift
108: )
109: {
110: register unsigned lobit; /* non-zero means lo bit set */
111: register unsigned num = val; /* number to rotate */
112:
113: shift &= 0x1f; /* modulo 32 -- this will also make
114: negative shifts work */
115: while (shift--) {
116: lobit = num & 1; /* get high bit */
117: num >>= 1; /* shift right one bit */
118: if (lobit)
119: num |= 0x80000000; /* set hi bit if lo bit was set */
120: }
121:
122: return num;
123: }
124: #endif
125:
126: void logprintf(char *str, ...);
127:
128: /****************************************************************************/
129: /* This is needed by load_cfg.c */
130: /****************************************************************************/
131: int lprintf(int level, char *fmat, ...)
132: {
133: va_list argptr;
134: char sbuf[256];
135: int chcount;
136:
137: va_start(argptr,fmat);
138: chcount=vsnprintf(sbuf,sizeof(sbuf),fmat,argptr);
139: sbuf[sizeof(sbuf)-1]=0;
140: va_end(argptr);
141: truncsp(sbuf);
142: printf("%s\n",sbuf);
143:
144: if(level<=log_level)
145: logprintf("%s",sbuf);
146: return(chcount);
147: }
148:
149: /**********************/
150: /* Log print function */
151: /**********************/
152: void logprintf(char *str, ...)
153: {
154: va_list argptr;
155: char buf[256];
156: time_t now;
157: struct tm *gm;
158:
159: if(!(misc&LOGFILE) || fidologfile==NULL)
160: return;
161: va_start(argptr,str);
162: vsnprintf(buf,sizeof(buf),str,argptr);
163: buf[sizeof(buf)-1]=0;
164: va_end(argptr);
165: now=time(NULL);
166: gm=localtime(&now);
167: fprintf(fidologfile,"%02u/%02u/%02u %02u:%02u:%02u %s\n"
168: ,gm->tm_mon+1,gm->tm_mday,TM_YEAR(gm->tm_year),gm->tm_hour,gm->tm_min,gm->tm_sec
169: ,buf);
170: }
171:
172: /*****************************************************************************/
173: /* Returns command line generated from instr with %c replacments */
174: /*****************************************************************************/
175: char *mycmdstr(scfg_t* cfg, char *instr, char *fpath, char *fspec)
176: {
177: static char cmd[MAX_PATH+1];
178: char str[256],str2[128];
179: int i,j,len;
180:
181: len=strlen(instr);
182: for(i=j=0;i<len && j<128;i++) {
183: if(instr[i]=='%') {
184: i++;
185: cmd[j]=0;
186: switch(toupper(instr[i])) {
187: case 'F': /* File path */
188: strcat(cmd,fpath);
189: break;
190: case 'G': /* Temp directory */
191: if(cfg->temp_dir[0]!='\\'
192: && cfg->temp_dir[0]!='/'
193: && cfg->temp_dir[1]!=':') {
194: strcpy(str,cfg->node_dir);
195: strcat(str,cfg->temp_dir);
196: if(FULLPATH(str2,str,40))
197: strcpy(str,str2);
198: backslash(str);
199: strcat(cmd,str);}
200: else
201: strcat(cmd,cfg->temp_dir);
202: break;
203: case 'J':
204: if(cfg->data_dir[0]!='\\'
205: && cfg->data_dir[0]!='/'
206: && cfg->data_dir[1]!=':') {
207: strcpy(str,cfg->node_dir);
208: strcat(str,cfg->data_dir);
209: if(FULLPATH(str2,str,40))
210: strcpy(str,str2);
211: backslash(str);
212: strcat(cmd,str); }
213: else
214: strcat(cmd,cfg->data_dir);
215: break;
216: case 'K':
217: if(cfg->ctrl_dir[0]!='\\'
218: && cfg->ctrl_dir[0]!='/'
219: && cfg->ctrl_dir[1]!=':') {
220: strcpy(str,cfg->node_dir);
221: strcat(str,cfg->ctrl_dir);
222: if(FULLPATH(str2,str,40))
223: strcpy(str,str2);
224: backslash(str);
225: strcat(cmd,str); }
226: else
227: strcat(cmd,cfg->ctrl_dir);
228: break;
229: case 'N': /* Node Directory (same as SBBSNODE environment var) */
230: strcat(cmd,cfg->node_dir);
231: break;
232: case 'O': /* SysOp */
233: strcat(cmd,cfg->sys_op);
234: break;
235: case 'Q': /* QWK ID */
236: strcat(cmd,cfg->sys_id);
237: break;
238: case 'S': /* File Spec */
239: strcat(cmd,fspec);
240: break;
241: case '!': /* EXEC Directory */
242: strcat(cmd,cfg->exec_dir);
243: break;
244: case '@': /* EXEC Directory for DOS/OS2/Win32, blank for Unix */
245: #ifndef __unix__
246: strcat(cmd,cfg->exec_dir);
247: #endif
248: break;
249: case '#': /* Node number (same as SBBSNNUM environment var) */
250: sprintf(str,"%d",cfg->node_num);
251: strcat(cmd,str);
252: break;
253: case '*':
254: sprintf(str,"%03d",cfg->node_num);
255: strcat(cmd,str);
256: break;
257: case '%': /* %% for percent sign */
258: strcat(cmd,"%");
259: break;
260: case '.': /* .exe for DOS/OS2/Win32, blank for Unix */
261: #ifndef __unix__
262: strcat(cmd,".exe");
263: #endif
264: break;
265: case '?': /* Platform */
266: #ifdef __OS2__
267: strcpy(str,"OS2");
268: #else
269: strcpy(str,PLATFORM_DESC);
270: #endif
271: strlwr(str);
272: strcat(cmd,str);
273: break;
274: default: /* unknown specification */
275: lprintf(LOG_ERR,"ERROR Checking Command Line '%s'",instr);
276: bail(1);
277: break; }
278: j=strlen(cmd); }
279: else
280: cmd[j++]=instr[i]; }
281: cmd[j]=0;
282:
283: return(cmd);
284: }
285:
286: /****************************************************************************/
287: /* Runs an external program directly using spawnvp */
288: /****************************************************************************/
289: int execute(char *cmdline)
290: {
291: #if 1
292: return system(cmdline);
293: #else
294: char c,d,e,cmdlen,*arg[30],str[256];
295: int i;
296:
297: strcpy(str,cmdline);
298: arg[0]=str; /* point to the beginning of the string */
299: cmdlen=strlen(str);
300: for(c=0,d=1,e=0;c<cmdlen;c++,e++) /* Break up command line */
301: if(str[c]==' ') {
302: str[c]=0; /* insert nulls */
303: arg[d++]=str+c+1; /* point to the beginning of the next arg */
304: e=0; }
305: arg[d]=0;
306: i=spawnvp(P_WAIT,arg[0],arg);
307: return(i);
308: #endif
309: }
310:
311: /******************************************************************************
312: Returns the system address with the same zone as the address passed
313: ******************************************************************************/
314: faddr_t getsysfaddr(short zone)
315: {
316: int i;
317:
318: for(i=0;i<scfg.total_faddrs;i++)
319: if(scfg.faddr[i].zone==zone)
320: return(scfg.faddr[i]);
321: return(sys_faddr);
322: }
323:
324: /******************************************************************************
325: This function creates or appends on existing Binkley compatible .?LO file
326: attach file.
327: Returns 0 on success.
328: ******************************************************************************/
329: int write_flofile(char *attachment, faddr_t dest, BOOL bundle)
330: {
331: char fname[MAX_PATH+1];
332: char outbound[MAX_PATH+1];
333: char str[MAX_PATH+1];
334: char ch;
335: char searchstr[MAX_PATH+1];
336: ushort attr=0;
337: int i,file;
338: FILE *stream;
339:
340: i=matchnode(dest,0);
341: if(i<(int)cfg.nodecfgs)
342: attr=cfg.nodecfg[i].attr;
343:
344: if(attr&ATTR_CRASH) ch='c';
345: else if(attr&ATTR_HOLD) ch='h';
346: else if(attr&ATTR_DIRECT) ch='d';
347: else ch='f';
348: if(dest.zone==sys_faddr.zone) /* Default zone, use default outbound */
349: strcpy(outbound,cfg.outbound);
350: else { /* Inter-zone outbound is OUTBOUND.XXX */
351: sprintf(outbound,"%.*s.%03x"
352: ,(int)strlen(cfg.outbound)-1,cfg.outbound,dest.zone);
353: MKDIR(outbound);
354: backslash(outbound);
355: }
356: if(dest.point) { /* Point destination is OUTBOUND\*.PNT */
357: sprintf(str,"%04x%04x.pnt"
358: ,dest.net,dest.node);
359: strcat(outbound,str); }
360: if(outbound[strlen(outbound)-1]=='\\'
361: || outbound[strlen(outbound)-1]=='/')
362: outbound[strlen(outbound)-1]=0;
363: MKDIR(outbound);
364: backslash(outbound);
365: if(dest.point)
366: sprintf(fname,"%s%08x.%clo",outbound,dest.point,ch);
367: else
368: sprintf(fname,"%s%04x%04x.%clo",outbound,dest.net,dest.node,ch);
369: if(bundle && misc&TRUNC_BUNDLES)
370: ch='#';
371: else
372: ch='^';
373: if(*attachment == '^') /* work-around for BRE/FE inter-BBS attachment bug */
374: attachment++;
375: fexistcase(attachment); /* just in-case it's the wrong case for a Unix file system */
376: sprintf(searchstr,"%c%s",ch,attachment);
377: if(findstr(searchstr,fname)) /* file already in FLO file */
378: return(0);
379: if((stream=fopen(fname,"a"))==NULL) {
380: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,fname,strerror(errno));
381: return(-1);
382: }
383: fprintf(stream,"%s\n",searchstr);
384: fclose(stream);
385: return(0);
386: }
387:
388: /* Writes text buffer to file, expanding sole LFs to CRLFs */
389: size_t fwrite_crlf(char* buf, size_t len, FILE* fp)
390: {
391: char ch,last_ch=0;
392: size_t i;
393: size_t wr=0; /* total chars written (may be > len) */
394:
395: for(i=0;i<len;i++) {
396: ch=*buf++;
397: if(ch=='\n' && last_ch!='\r') {
398: if(fputc('\r',fp)==EOF)
399: return(wr);
400: wr++;
401: }
402: if(fputc(ch,fp)==EOF)
403: return(wr);
404: wr++;
405: last_ch=ch;
406: }
407:
408: return(wr);
409: }
410:
411: /******************************************************************************
412: This function will create a netmail message (.MSG format).
413: If file is non-zero, will set file attachment bit (for bundles).
414: Returns 0 on success.
415: ******************************************************************************/
416: int create_netmail(char *to, char *subject, char *body, faddr_t dest, BOOL file_attached)
417: {
418: FILE *fstream;
419: char str[256],fname[MAX_PATH+1];
420: ushort attr=0;
421: int fmsg;
422: uint i;
423: static uint startmsg;
424: time_t t;
425: faddr_t faddr;
426: fmsghdr_t hdr;
427: struct tm *tm;
428:
429: if(!startmsg) startmsg=1;
430: i=matchnode(dest,0);
431: if(i<cfg.nodecfgs) {
432: attr=cfg.nodecfg[i].attr;
433: if(!attr) {
434: i=matchnode(dest,2);
435: if(i<cfg.nodecfgs)
436: attr=cfg.nodecfg[i].attr; } }
437:
438: do {
439: for(i=startmsg;i;i++) {
440: sprintf(fname,"%s%u.msg",scfg.netmail_dir,i);
441: if(!fexistcase(fname))
442: break;
443: }
444: if(!i) {
445: lprintf(LOG_WARNING,"Directory full: %s",scfg.netmail_dir);
446: return(-1); }
447: startmsg=i+1;
448: if((fstream=fnopen(&fmsg,fname,O_RDWR|O_CREAT))==NULL) {
449: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,fname,strerror(errno));
450: return(-1); }
451:
452: faddr=getsysfaddr(dest.zone);
453: memset(&hdr,0,sizeof(fmsghdr_t));
454: hdr.origzone=faddr.zone;
455: hdr.orignet=faddr.net;
456: hdr.orignode=faddr.node;
457: hdr.origpoint=faddr.point;
458: hdr.destzone=dest.zone;
459: hdr.destnet=dest.net;
460: hdr.destnode=dest.node;
461: hdr.destpoint=dest.point;
462:
463: hdr.attr=(FIDO_PRIVATE|FIDO_KILLSENT|FIDO_LOCAL);
464: if(file_attached)
465: hdr.attr|=FIDO_FILE;
466:
467: if(attr&ATTR_HOLD)
468: hdr.attr|=FIDO_HOLD;
469: if(attr&ATTR_CRASH)
470: hdr.attr|=FIDO_CRASH;
471:
472: sprintf(hdr.from,"SBBSecho");
473:
474: t=time(NULL);
475: tm=localtime(&t);
476: sprintf(hdr.time,"%02u %3.3s %02u %02u:%02u:%02u"
477: ,tm->tm_mday,mon[tm->tm_mon],TM_YEAR(tm->tm_year)
478: ,tm->tm_hour,tm->tm_min,tm->tm_sec);
479:
480: if(to)
481: SAFECOPY(hdr.to,to);
482: else
483: SAFECOPY(hdr.to,"SYSOP");
484:
485: SAFECOPY(hdr.subj,subject);
486:
487: fwrite(&hdr,sizeof(fmsghdr_t),1,fstream);
488: sprintf(str,"\1INTL %hu:%hu/%hu %hu:%hu/%hu\r"
489: ,hdr.destzone,hdr.destnet,hdr.destnode
490: ,hdr.origzone,hdr.orignet,hdr.orignode);
491: fwrite(str,strlen(str),1,fstream);
492:
493: /* Add FSC-53 FLAGS kludge */
494: fprintf(fstream,"\1FLAGS");
495: if(attr&ATTR_DIRECT)
496: fprintf(fstream," DIR");
497: if(file_attached) {
498: if(misc&TRUNC_BUNDLES)
499: fprintf(fstream," TFS");
500: else
501: fprintf(fstream," KFS");
502: }
503: fprintf(fstream,"\r");
504:
505: if(hdr.destpoint) {
506: sprintf(str,"\1TOPT %hu\r",hdr.destpoint);
507: fwrite(str,strlen(str),1,fstream); }
508: if(hdr.origpoint) {
509: sprintf(str,"\1FMPT %hu\r",hdr.origpoint);
510: fwrite(str,strlen(str),1,fstream); }
511: if(!file_attached || (!(attr&ATTR_DIRECT) && file_attached))
512: fwrite_crlf(body,strlen(body)+1,fstream); /* Write additional NULL */
513: else
514: fwrite("\0",1,1,fstream); /* Write NULL */
515: fclose(fstream);
516: } while(!fexistcase(fname));
517: return(0);
518: }
519:
520: /******************************************************************************
521: This function takes the contents of 'infile' and puts it into a netmail
522: message bound for addr.
523: ******************************************************************************/
524: void file_to_netmail(FILE *infile,char *title,faddr_t addr,char *to)
525: {
526: char *buf,*p;
527: long l,m,len;
528:
529: l=len=ftell(infile);
530: if(len>8192L)
531: len=8192L;
532: rewind(infile);
533: if((buf=(char *)malloc(len+1))==NULL) {
534: lprintf(LOG_ERR,"ERROR line %d allocating %lu for file to netmail buf",__LINE__,len);
535: return; }
536: while((m=fread(buf,1,(len>8064L) ? 8064L:len,infile))>0) {
537: buf[m]=0;
538: if(l>8064L && (p=strrchr(buf,'\n'))!=NULL) {
539: p++;
540: if(*p) {
541: *p=0;
542: p++;
543: fseek(infile,-1L,SEEK_CUR);
544: while(*p) { /* Seek back to end of last line */
545: p++;
546: fseek(infile,-1L,SEEK_CUR); } } }
547: if(ftell(infile)<l)
548: strcat(buf,"\r\nContinued in next message...\r\n");
549: create_netmail(to,title,buf,addr,FALSE);
550: }
551: free(buf);
552: }
553: /******************************************************************************
554: This function sends a notify list to applicable nodes, this list includes the
555: settings configured for the node, as well as a list of areas the node is
556: connected to.
557: ******************************************************************************/
558: void notify_list(void)
559: {
560: FILE * tmpf;
561: char str[256];
562: uint i,j,k;
563:
564: for(k=0;k<cfg.nodecfgs;k++) {
565:
566: if(!(cfg.nodecfg[k].attr&SEND_NOTIFY))
567: continue;
568:
569: if((tmpf=tmpfile())==NULL) {
570: lprintf(LOG_ERR,"ERROR line %d couldn't open tmpfile",__LINE__);
571: return; }
572:
573: fprintf(tmpf,"Following are the options set for your system and a list "
574: "of areas\r\nyou are connected to. Please make sure everything "
575: "is correct.\r\n\r\n");
576: fprintf(tmpf,"Packet Type %s\r\n"
577: ,cfg.nodecfg[k].pkt_type==PKT_TWO ? "2"
578: :cfg.nodecfg[k].pkt_type==PKT_TWO_TWO ? "2.2":"2+");
579: fprintf(tmpf,"Archive Type %s\r\n"
580: ,(cfg.nodecfg[k].arctype>cfg.arcdefs) ?
581: "None":cfg.arcdef[cfg.nodecfg[k].arctype].name);
582: fprintf(tmpf,"Mail Status %s\r\n"
583: ,cfg.nodecfg[k].attr&ATTR_CRASH ? "Crash"
584: :cfg.nodecfg[k].attr&ATTR_HOLD ? "Hold" : "None");
585: fprintf(tmpf,"Direct %s\r\n"
586: ,cfg.nodecfg[k].attr&ATTR_DIRECT ? "Yes":"No");
587: fprintf(tmpf,"Passive %s\r\n"
588: ,cfg.nodecfg[k].attr&ATTR_PASSIVE ? "Yes":"No");
589: fprintf(tmpf,"Remote AreaMgr %s\r\n\r\n"
590: ,cfg.nodecfg[k].password[0] ? "Yes" : "No");
591:
592: fprintf(tmpf,"Connected Areas\r\n---------------\r\n");
593: for(i=0;i<cfg.areas;i++) {
594: sprintf(str,"%s\r\n",cfg.area[i].name);
595: if(str[0]=='*')
596: continue;
597: for(j=0;j<cfg.area[i].uplinks;j++)
598: if(!memcmp(&cfg.nodecfg[k].faddr,&cfg.area[i].uplink[j]
599: ,sizeof(faddr_t)))
600: break;
601: if(j<cfg.area[i].uplinks)
602: fprintf(tmpf,"%s",str); }
603:
604: if(ftell(tmpf))
605: file_to_netmail(tmpf,"SBBSecho Notify List",cfg.nodecfg[k].faddr, /* To: */NULL);
606: fclose(tmpf); }
607: }
608: /******************************************************************************
609: This function creates a netmail to addr showing a list of available areas (0),
610: a list of connected areas (1), or a list of removed areas (2).
611: ******************************************************************************/
612: void netmail_arealist(int type, faddr_t addr, char* to)
613: {
614: FILE *stream,*tmpf;
615: char str[256],temp[256],title[128],match,*p,*tp;
616: int file,i,j,k,x,y;
617:
618: if(!type)
619: strcpy(title,"List of Available Areas");
620: else if(type==1)
621: strcpy(title,"List of Connected Areas");
622: else
623: strcpy(title,"List of Unlinked Areas");
624:
625: if((tmpf=tmpfile())==NULL) {
626: lprintf(LOG_ERR,"ERROR line %d couldn't open tmpfile",__LINE__);
627: return; }
628:
629: if(type==1 || !(misc&ELIST_ONLY)) {
630: for(i=0;i<cfg.areas;i++) {
631: if(type) {
632: for(j=0;j<cfg.area[i].uplinks;j++)
633: if(!memcmp(&addr,&cfg.area[i].uplink[j],sizeof(faddr_t)))
634: break;
635: if((type==1 && j<cfg.area[i].uplinks) ||
636: (type==2 && j==cfg.area[i].uplinks))
637: fprintf(tmpf,"%s\r\n",cfg.area[i].name); }
638: else
639: fprintf(tmpf,"%s\r\n",cfg.area[i].name); } }
640:
641: if(!type) {
642: i=matchnode(addr,0);
643: if(i<cfg.nodecfgs) {
644: for(j=0;j<cfg.listcfgs;j++) {
645: match=0;
646: for(k=0;k<cfg.listcfg[j].numflags;k++) {
647: if(match) break;
648: for(x=0;x<cfg.nodecfg[i].numflags;x++)
649: if(!stricmp(cfg.listcfg[j].flag[k].flag
650: ,cfg.nodecfg[i].flag[x].flag)) {
651: if((stream=fopen(cfg.listcfg[j].listpath,"r"))==NULL) {
652: lprintf(LOG_ERR,"ERROR line %d couldn't open %s %s"
653: ,__LINE__,cfg.listcfg[j].listpath
654: ,strerror(errno));
655: match=1;
656: break; }
657: while(!feof(stream)) {
658: if(!fgets(str,sizeof(str),stream))
659: break;
660: p=str;
661: SKIP_WHITESPACE(p);
662: if(*p==';') /* Ignore Comment Lines */
663: continue;
664: tp=p;
665: FIND_WHITESPACE(tp);
666: *tp=0;
667: if(!(misc&ELIST_ONLY)) {
668: for(y=0;y<cfg.areas;y++)
669: if(!stricmp(cfg.area[y].name,p))
670: break;
671: if(y==cfg.areas)
672: fprintf(tmpf,"%s\r\n",p); }
673: else
674: fprintf(tmpf,"%s\r\n",p); }
675: fclose(stream);
676: match=1;
677: break; } } } } }
678:
679: if(!ftell(tmpf))
680: create_netmail(to,title,"None.",addr,FALSE);
681: else
682: file_to_netmail(tmpf,title,addr,to);
683: fclose(tmpf);
684: }
685: /******************************************************************************
686: Imitation of Borland's tempnam function because Watcom doesn't have it
687: ******************************************************************************/
688: char *tempname(char *dir, char *prefix)
689: {
690: char str[MAX_PATH+1],*p;
691: int i;
692:
693: for(i=0;i<1000;i++) {
694: sprintf(str,"%s%s%03u.$$$",dir,prefix,i);
695: if(!fexist(str))
696: break; }
697: if(i>=1000) {
698: lprintf(LOG_ERR,"tempnam: too many files");
699: return(NULL); }
700: p=malloc(strlen(str)+1);
701: if(!p) {
702: lprintf(LOG_CRIT,"tempnam: couldn't malloc %u",strlen(str)+1);
703: return(NULL); }
704: strcpy(p,str);
705: return(p);
706: }
707:
708: int check_elists(char *areatag,faddr_t addr)
709: {
710: FILE *stream;
711: char str[1025],quit=0,*p,*tp;
712: int i,j,k,x,file,match=0;
713:
714: i=matchnode(addr,0);
715: if(i<cfg.nodecfgs) {
716: for(j=0;j<cfg.listcfgs;j++) {
717: quit=0;
718: for(k=0;k<cfg.listcfg[j].numflags;k++) {
719: if(quit) break;
720: for(x=0;x<cfg.nodecfg[i].numflags;x++)
721: if(!stricmp(cfg.listcfg[j].flag[k].flag
722: ,cfg.nodecfg[i].flag[x].flag)) {
723: if((stream=fopen(cfg.listcfg[j].listpath,"r"))==NULL) {
724: lprintf(LOG_ERR,"ERROR line %d opening %s"
725: ,__LINE__,cfg.listcfg[j].listpath);
726: quit=1;
727: break; }
728: while(!feof(stream)) {
729: if(!fgets(str,sizeof(str),stream))
730: break;
731: p=str;
732: SKIP_WHITESPACE(p);
733: if(*p==';') /* Ignore Comment Lines */
734: continue;
735: tp=p;
736: FIND_WHITESPACE(tp);
737: *tp=0;
738: if(!stricmp(areatag,p)) {
739: match=1;
740: break; } }
741: fclose(stream);
742: quit=1;
743: if(match)
744: return(match);
745: break; } } } }
746: return(match);
747: }
748: /******************************************************************************
749: Used by AREAFIX to add/remove/change areas in the areas file
750: ******************************************************************************/
751: void alter_areas(area_t* add_area, area_t* del_area, faddr_t addr, char* to)
752: {
753: FILE *nmfile,*afilein,*afileout,*fwdfile;
754: char str[1024],fields[1024],field1[256],field2[256],field3[256]
755: ,outpath[MAX_PATH+1]
756: ,*outname,*p,*tp,nomatch=0,match=0;
757: int i,j,k,x,y;
758: ulong tagcrc;
759:
760: SAFECOPY(outpath,cfg.areafile);
761: *getfname(outpath)=0;
762: if((outname=tempname(outpath,"AREAS"))==NULL) {
763: lprintf(LOG_ERR,"ERROR tempnam(%s,AREAS)",outpath);
764: return; }
765: if((nmfile=tmpfile())==NULL) {
766: lprintf(LOG_ERR,"ERROR in tmpfile()");
767: free(outname);
768: return; }
769: if((afileout=fopen(outname,"w+"))==NULL) {
770: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,outname
771: ,strerror(errno));
772: fclose(nmfile);
773: free(outname);
774: return; }
775: if((afilein=fopen(cfg.areafile,"r"))==NULL) {
776: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,cfg.areafile
777: ,strerror(errno));
778: fclose(afileout);
779: fclose(nmfile);
780: free(outname);
781: return; }
782: while(!feof(afilein)) {
783: if(!fgets(fields,sizeof(fields),afilein))
784: break;
785: truncsp(fields);
786: p=fields;
787: SKIP_WHITESPACE(p);
788: if(*p==';') { /* Skip Comment Lines */
789: fprintf(afileout,"%s\n",fields);
790: continue; }
791: SAFECOPY(field1,p); /* Internal Code Field */
792: truncstr(field1," \t\r\n");
793: FIND_WHITESPACE(p);
794: SKIP_WHITESPACE(p);
795: SAFECOPY(field2,p); /* Areatag Field */
796: truncstr(field2," \t\r\n");
797: FIND_WHITESPACE(p);
798: SKIP_WHITESPACE(p);
799: if((tp=strchr(p,';'))!=NULL) {
800: SAFECOPY(field3,p); /* Comment Field (if any) */
801: FIND_WHITESPACE(tp);
802: *tp=0; }
803: else
804: field3[0]=0;
805: if(del_area->tags) { /* Check for areas to remove */
806: for(i=0;i<del_area->tags;i++) {
807: if(!stricmp(del_area->tag[i],field2) ||
808: !stricmp(del_area->tag[0],"-ALL")) /* Match Found */
809: break; }
810: if(i<del_area->tags) {
811: for(i=0;i<cfg.areas;i++) {
812: if(!stricmp(field2,cfg.area[i].name)) {
813: for(j=0;j<cfg.area[i].uplinks;j++)
814: if(!memcmp(&cfg.area[i].uplink[j],&addr
815: ,sizeof(faddr_t)))
816: break;
817: if(j==cfg.area[i].uplinks) {
818: fprintf(afileout,"%s\n",fields);
819: /* bugfix here Mar-25-2004 (wasn't breaking for "-ALL") */
820: if(stricmp(del_area->tag[0],"-ALL"))
821: fprintf(nmfile,"%s not connected.\r\n",field2);
822: break;
823: }
824:
825: /* Added 12/4/95 to remove uplink from connected uplinks */
826:
827: for(k=j;k<cfg.area[i].uplinks-1;k++)
828: memcpy(&cfg.area[i].uplink[k],&cfg.area[i].uplink[k+1]
829: ,sizeof(faddr_t));
830: --cfg.area[i].uplinks;
831: if(cfg.area[i].uplinks==0) {
832: FREE_AND_NULL(cfg.area[i].uplink);
833: } else
834: if((cfg.area[i].uplink=(faddr_t *)
835: realloc(cfg.area[i].uplink,sizeof(faddr_t)
836: *(cfg.area[i].uplinks)))==NULL) {
837: lprintf(LOG_ERR,"ERROR line %d allocating memory for area "
838: "#%u uplinks.",__LINE__,i+1);
839: bail(1);
840: }
841:
842: fprintf(afileout,"%-16s%-23s ",field1,field2);
843: for(j=0;j<cfg.area[i].uplinks;j++) {
844: if(!memcmp(&cfg.area[i].uplink[j],&addr
845: ,sizeof(faddr_t)))
846: continue;
847: fprintf(afileout,"%s "
848: ,smb_faddrtoa(&cfg.area[i].uplink[j],NULL)); }
849: if(field3[0])
850: fprintf(afileout,"%s",field3);
851: fprintf(afileout,"\n");
852: fprintf(nmfile,"%s removed.\r\n",field2);
853: break;
854: }
855: }
856: if(i==cfg.areas) /* Something screwy going on */
857: fprintf(afileout,"%s\n",fields);
858: continue; } } /* Area match so continue on */
859: if(add_area->tags) { /* Check for areas to add */
860: for(i=0;i<add_area->tags;i++)
861: if(!stricmp(add_area->tag[i],field2) ||
862: !stricmp(add_area->tag[0],"+ALL")) /* Match Found */
863: break;
864: if(i<add_area->tags) {
865: if(stricmp(add_area->tag[i],"+ALL"))
866: add_area->tag[i][0]=0; /* So we can check other lists */
867: for(i=0;i<cfg.areas;i++) {
868: if(!stricmp(field2,cfg.area[i].name)) {
869: for(j=0;j<cfg.area[i].uplinks;j++)
870: if(!memcmp(&cfg.area[i].uplink[j],&addr
871: ,sizeof(faddr_t)))
872: break;
873: if(j<cfg.area[i].uplinks) {
874: fprintf(afileout,"%s\n",fields);
875: fprintf(nmfile,"%s already connected.\r\n",field2);
876: break; }
877: if(misc&ELIST_ONLY && !check_elists(field2,addr)) {
878: fprintf(afileout,"%s\n",fields);
879: break; }
880:
881: /* Added 12/4/95 to add uplink to connected uplinks */
882:
883: ++cfg.area[i].uplinks;
884: if((cfg.area[i].uplink=(faddr_t *)
885: realloc(cfg.area[i].uplink,sizeof(faddr_t)
886: *(cfg.area[i].uplinks)))==NULL) {
887: lprintf(LOG_ERR,"ERROR line %d allocating memory for area "
888: "#%u uplinks.",__LINE__,i+1);
889: bail(1); }
890: memcpy(&cfg.area[i].uplink[j],&addr,sizeof(faddr_t));
891:
892: fprintf(afileout,"%-16s%-23s ",field1,field2);
893: for(j=0;j<cfg.area[i].uplinks;j++)
894: fprintf(afileout,"%s "
895: ,smb_faddrtoa(&cfg.area[i].uplink[j],NULL));
896: if(field3[0])
897: fprintf(afileout,"%s",field3);
898: fprintf(afileout,"\n");
899: fprintf(nmfile,"%s added.\r\n",field2);
900: break; } }
901: if(i==cfg.areas) /* Something screwy going on */
902: fprintf(afileout,"%s\n",fields);
903: continue; } /* Area match so continue on */
904: nomatch=1; } /* This area wasn't in there */
905: fprintf(afileout,"%s\n",fields); } /* No match so write back line */
906: fclose(afilein);
907: if(nomatch || (add_area->tags && !stricmp(add_area->tag[0],"+ALL"))) {
908: i=matchnode(addr,0);
909: if(i<cfg.nodecfgs) {
910: for(j=0;j<cfg.listcfgs;j++) {
911: match=0;
912: for(k=0;k<cfg.listcfg[j].numflags;k++) {
913: if(match) break;
914: for(x=0;x<cfg.nodecfg[i].numflags;x++)
915: if(!stricmp(cfg.listcfg[j].flag[k].flag
916: ,cfg.nodecfg[i].flag[x].flag)) {
917: if((fwdfile=tmpfile())==NULL) {
918: lprintf(LOG_ERR,"ERROR line %d opening forward temp "
919: "file",__LINE__);
920: match=1;
921: break; }
922: if((afilein=fopen(cfg.listcfg[j].listpath,"r"))==NULL) {
923: lprintf(LOG_ERR,"ERROR line %d opening %s"
924: ,__LINE__,cfg.listcfg[j].listpath);
925: fclose(fwdfile);
926: match=1;
927: break; }
928: while(!feof(afilein)) {
929: if(!fgets(str,sizeof(str),afilein))
930: break;
931: p=str;
932: SKIP_WHITESPACE(p);
933: if(*p==';') /* Ignore Comment Lines */
934: continue;
935: tp=p;
936: FIND_WHITESPACE(tp);
937: *tp=0;
938: if(!stricmp(add_area->tag[0],"+ALL")) {
939: SAFECOPY(tmp,p);
940: tagcrc=crc32(strupr(tmp),0);
941: for(y=0;y<cfg.areas;y++)
942: if(tagcrc==cfg.area[y].tag)
943: break;
944: if(y<cfg.areas)
945: continue; }
946: for(y=0;y<add_area->tags;y++)
947: if((!stricmp(add_area->tag[y],str) &&
948: add_area->tag[y][0]) ||
949: !stricmp(add_area->tag[0],"+ALL"))
950: break;
951: if(y<add_area->tags) {
952: fprintf(afileout,"%-16s%-23s","P",str);
953: if(cfg.listcfg[j].forward.zone)
954: fprintf(afileout," %s"
955: ,smb_faddrtoa(&cfg.listcfg[j].forward,NULL));
956: fprintf(afileout," %s\n",smb_faddrtoa(&addr,NULL));
957: fprintf(nmfile,"%s added.\r\n",str);
958: if(stricmp(add_area->tag[0],"+ALL"))
959: add_area->tag[y][0]=0;
960: if(!(cfg.listcfg[j].misc&NOFWD)
961: && cfg.listcfg[j].forward.zone)
962: fprintf(fwdfile,"%s\r\n",str); } }
963: fclose(afilein);
964: if(!(cfg.listcfg[j].misc&NOFWD) && ftell(fwdfile)>0)
965: file_to_netmail(fwdfile,cfg.listcfg[j].password
966: ,cfg.listcfg[j].forward,/* To: */"Areafix");
967: fclose(fwdfile);
968: match=1;
969: break; } } } } }
970: if(add_area->tags && stricmp(add_area->tag[0],"+ALL")) {
971: for(i=0;i<add_area->tags;i++)
972: if(add_area->tag[i][0])
973: fprintf(nmfile,"%s not found.\r\n",add_area->tag[i]); }
974: if(!ftell(nmfile))
975: create_netmail(to,"Area Change Request","No changes made.",addr,FALSE);
976: else
977: file_to_netmail(nmfile,"Area Change Request",addr,to);
978: fclose(nmfile);
979: fclose(afileout);
980: if(delfile(cfg.areafile)) /* Delete AREAS.BBS */
981: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,cfg.areafile
982: ,strerror(errno));
983: if(rename(outname,cfg.areafile)) /* Rename new AREAS.BBS file */
984: lprintf(LOG_ERR,"ERROR line %d renaming %s to %s",__LINE__,outname,cfg.areafile);
985: free(outname);
986: }
987: /******************************************************************************
988: Used by AREAFIX to add/remove/change uplink info in the configuration file
989: old = the old setting for this option, new = what the setting is changing to
990: option = 0 for compression type change
991: 1 for areafix password change
992: 2 to set this node to passive
993: 3 to set this node to active (remove passive)
994: ******************************************************************************/
995: void alter_config(faddr_t addr, char *old, char *new, int option)
996: {
997: FILE *outfile,*cfgfile;
998: char str[257],outpath[MAX_PATH+1],tmp[257],tmp2[257],*outname,*p,*tp
999: ,match=0;
1000: int i,j,k,file;
1001: faddr_t taddr;
1002:
1003: i=matchnode(addr,0); /* i = config number from here on */
1004: SAFECOPY(outpath,cfg.cfgfile);
1005: *getfname(outpath)=0;
1006: if((outname=tempname(outpath,"CFG"))==NULL) {
1007: lprintf(LOG_ERR,"ERROR tempnam(%s,CFG)",outpath);
1008: return; }
1009: if((outfile=fopen(outname,"w+"))==NULL) {
1010: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,outname
1011: ,strerror(errno));
1012: free(outname);
1013: return; }
1014: if((cfgfile=fopen(cfg.cfgfile,"r"))==NULL) {
1015: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,cfg.cfgfile
1016: ,strerror(errno));
1017: fclose(outfile);
1018: free(outname);
1019: return; }
1020:
1021: while(!feof(cfgfile)) {
1022: if(!fgets(str,sizeof(str),cfgfile))
1023: break;
1024: truncsp(str);
1025: p=str;
1026: SKIP_WHITESPACE(p);
1027: if(*p==';') {
1028: fprintf(outfile,"%s\n",str);
1029: continue; }
1030: sprintf(tmp,"%-.25s",p);
1031: tp=strchr(tmp,' ');
1032: if(tp)
1033: *tp=0; /* Chop off at space */
1034: strupr(tmp); /* Convert code to uppercase */
1035: FIND_WHITESPACE(p); /* Skip code */
1036: SKIP_WHITESPACE(p); /* Skip white space */
1037:
1038: if(option==0 && !strcmp(tmp,"USEPACKER")) { /* Change Compression */
1039: if(!*p)
1040: continue;
1041: strcpy(tmp2,p);
1042: p=tmp2;
1043: FIND_WHITESPACE(p);
1044: *p=0;
1045: p++;
1046: if(!stricmp(new,tmp2)) { /* Add to new definition */
1047: fprintf(outfile,"%-10s %s %s %s\n",tmp,tmp2
1048: ,smb_faddrtoa(&cfg.nodecfg[i].faddr,NULL)
1049: ,(*p) ? p : "");
1050: match=1;
1051: continue; }
1052: else if(!stricmp(old,tmp2)) { /* Remove from old def */
1053: for(j=k=0;j<cfg.nodecfgs;j++) {
1054: if(j==i)
1055: continue;
1056: if(!stricmp(cfg.arcdef[cfg.nodecfg[j].arctype].name,tmp2)) {
1057: if(!k) {
1058: fprintf(outfile,"%-10s %s",tmp,tmp2);
1059: k++; }
1060: fprintf(outfile," %s"
1061: ,smb_faddrtoa(&cfg.nodecfg[j].faddr,NULL)); } }
1062: fprintf(outfile,"\n");
1063: continue; } }
1064:
1065: if(option==1 && !strcmp(tmp,"AREAFIX")) { /* Change Password */
1066: if(!*p)
1067: continue;
1068: taddr=smb_atofaddr(&sys_faddr,p);
1069: if(!memcmp(&cfg.nodecfg[i].faddr,&taddr,sizeof(faddr_t))) {
1070: FIND_WHITESPACE(p); /* Skip over address */
1071: SKIP_WHITESPACE(p); /* Skip over whitespace */
1072: FIND_WHITESPACE(p); /* Skip over password */
1073: SKIP_WHITESPACE(p); /* Skip over whitespace */
1074: fprintf(outfile,"%-10s %s %s %s\n",tmp
1075: ,smb_faddrtoa(&cfg.nodecfg[i].faddr,NULL),new,p);
1076: continue; } }
1077:
1078: if(option>1 && !strcmp(tmp,"PASSIVE")) { /* Toggle Passive Areas */
1079: match=1;
1080: for(j=k=0;j<cfg.nodecfgs;j++) {
1081: if(option==2 && j==i) {
1082: if(!k) fprintf(outfile,"%-10s",tmp);
1083: fprintf(outfile," %s",smb_faddrtoa(&cfg.nodecfg[j].faddr,NULL));
1084: k++;
1085: continue; }
1086: if(option==3 && j==i)
1087: continue;
1088: if(cfg.nodecfg[j].attr&ATTR_PASSIVE) {
1089: if(!k) fprintf(outfile,"%-10s",tmp);
1090: fprintf(outfile," %s",smb_faddrtoa(&cfg.nodecfg[j].faddr,NULL));
1091: k++; } }
1092: if(k) fprintf(outfile,"\n");
1093: continue; }
1094: fprintf(outfile,"%s\n",str); }
1095:
1096: if(!match) {
1097: if(option==0)
1098: fprintf(outfile,"%-10s %s %s\n","USEPACKER",new
1099: ,smb_faddrtoa(&cfg.nodecfg[i].faddr,NULL));
1100: if(option==2)
1101: fprintf(outfile,"%-10s %s\n","PASSIVE"
1102: ,smb_faddrtoa(&cfg.nodecfg[i].faddr,NULL)); }
1103:
1104: fclose(cfgfile);
1105: fclose(outfile);
1106: if(delfile(cfg.cfgfile))
1107: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,cfg.cfgfile
1108: ,strerror(errno));
1109: if(rename(outname,cfg.cfgfile))
1110: lprintf(LOG_ERR,"ERROR line %d renaming %s to %s",__LINE__,outname,cfg.cfgfile);
1111: free(outname);
1112: }
1113: /******************************************************************************
1114: Used by AREAFIX to process any '%' commands that come in via netmail
1115: ******************************************************************************/
1116: void command(char* instr, faddr_t addr, char* to)
1117: {
1118: FILE *stream,*tmpf;
1119: char str[MAX_PATH+1],temp[256],*buf,*p;
1120: int file,i,node;
1121: long l;
1122: area_t add_area,del_area;
1123:
1124: node=matchnode(addr,0);
1125: if(node>=cfg.nodecfgs)
1126: return;
1127: memset(&add_area,0,sizeof(area_t));
1128: memset(&del_area,0,sizeof(area_t));
1129: strupr(instr);
1130: if((p=strstr(instr,"HELP"))!=NULL) {
1131: sprintf(str,"%sAREAMGR.HLP",scfg.exec_dir);
1132: if(!fexistcase(str))
1133: return;
1134: if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
1135: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,str
1136: ,strerror(errno));
1137: return;
1138: }
1139: l=filelength(file);
1140: if((buf=(char *)malloc(l+1L))==NULL) {
1141: lprintf(LOG_CRIT,"ERROR line %d allocating %lu bytes for %s",__LINE__,l,str);
1142: return;
1143: }
1144: fread(buf,l,1,stream);
1145: fclose(stream);
1146: buf[l]=0;
1147: create_netmail(to,"Area Manager Help",buf,addr,FALSE);
1148: free(buf);
1149: return;
1150: }
1151:
1152: if((p=strstr(instr,"LIST"))!=NULL) {
1153: netmail_arealist(0,addr,to);
1154: return;
1155: }
1156:
1157: if((p=strstr(instr,"QUERY"))!=NULL) {
1158: netmail_arealist(1,addr,to);
1159: return;
1160: }
1161:
1162: if((p=strstr(instr,"UNLINKED"))!=NULL) {
1163: netmail_arealist(2,addr,to);
1164: return;
1165: }
1166:
1167: if((p=strstr(instr,"COMPRESSION"))!=NULL) {
1168: FIND_WHITESPACE(p);
1169: SKIP_WHITESPACE(p);
1170: for(i=0;i<cfg.arcdefs;i++)
1171: if(!stricmp(p,cfg.arcdef[i].name))
1172: break;
1173: if(!stricmp(p,"NONE"))
1174: i=0xffff;
1175: if(i==cfg.arcdefs) {
1176: if((tmpf=tmpfile())==NULL) {
1177: lprintf(LOG_ERR,"ERROR line %d opening tmpfile()",__LINE__);
1178: return; }
1179: fprintf(tmpf,"Compression type unavailable.\r\n\r\n"
1180: "Available types are:\r\n");
1181: for(i=0;i<cfg.arcdefs;i++)
1182: fprintf(tmpf," %s\r\n",cfg.arcdef[i].name);
1183: file_to_netmail(tmpf,"Compression Type Change",addr,to);
1184: fclose(tmpf);
1185: return;
1186: }
1187: alter_config(addr,cfg.arcdef[cfg.nodecfg[node].arctype].name
1188: ,cfg.arcdef[i].name,0);
1189: cfg.nodecfg[node].arctype=i;
1190: sprintf(str,"Compression type changed to %s.",cfg.arcdef[i].name);
1191: create_netmail(to,"Compression Type Change",str,addr,FALSE);
1192: return;
1193: }
1194:
1195: if((p=strstr(instr,"PASSWORD"))!=NULL) {
1196: FIND_WHITESPACE(p);
1197: SKIP_WHITESPACE(p);
1198: sprintf(temp,"%-.25s",p);
1199: p=temp;
1200: FIND_WHITESPACE(p);
1201: *p=0;
1202: if(node>=cfg.nodecfgs) /* Should never happen */
1203: return;
1204: if(!stricmp(temp,cfg.nodecfg[node].password)) {
1205: sprintf(str,"Your password was already set to %s."
1206: ,cfg.nodecfg[node].password);
1207: create_netmail(to,"Password Change Request",str,addr,FALSE);
1208: return; }
1209: alter_config(addr,cfg.nodecfg[node].password,temp,1);
1210: sprintf(str,"Your password has been changed from %s to %.25s."
1211: ,cfg.nodecfg[node].password,temp);
1212: sprintf(cfg.nodecfg[node].password,"%.25s",temp);
1213: create_netmail(to,"Password Change Request",str,addr,FALSE);
1214: return;
1215: }
1216:
1217: if((p=strstr(instr,"RESCAN"))!=NULL) {
1218: export_echomail("",addr);
1219: create_netmail(to,"Rescan Areas"
1220: ,"All connected areas carried by your hub have been rescanned."
1221: ,addr,FALSE);
1222: return;
1223: }
1224:
1225: if((p=strstr(instr,"ACTIVE"))!=NULL) {
1226: if(!(cfg.nodecfg[node].attr&ATTR_PASSIVE)) {
1227: create_netmail(to,"Reconnect Disconnected Areas"
1228: ,"Your areas are already connected.",addr,FALSE);
1229: return; }
1230: alter_config(addr,0,0,3);
1231: create_netmail(to,"Reconnect Disconnected Areas"
1232: ,"Temporarily disconnected areas have been reconnected.",addr,FALSE);
1233: return;
1234: }
1235:
1236: if((p=strstr(instr,"PASSIVE"))!=NULL) {
1237: if(cfg.nodecfg[node].attr&ATTR_PASSIVE) {
1238: create_netmail(to,"Temporarily Disconnect Areas"
1239: ,"Your areas are already temporarily disconnected.",addr,FALSE);
1240: return;
1241: }
1242: alter_config(addr,0,0,2);
1243: create_netmail(to,"Temporarily Disconnect Areas"
1244: ,"Your areas have been temporarily disconnected.",addr,FALSE);
1245: return;
1246: }
1247:
1248: if((p=strstr(instr,"FROM"))!=NULL);
1249:
1250: if((p=strstr(instr,"+ALL"))!=NULL) {
1251: if((add_area.tag=(char **)realloc(add_area.tag
1252: ,sizeof(char *)*add_area.tags+1))==NULL) {
1253: lprintf(LOG_ERR,"ERROR line %d allocating memory for add area tag #%u"
1254: ,__LINE__,add_area.tags+1);
1255: bail(1); }
1256: if((add_area.tag[add_area.tags]=(char *)malloc(strlen(instr)+1))==NULL) {
1257: lprintf(LOG_ERR,"ERROR line %d allocating memory for add area tag #%u"
1258: ,__LINE__,add_area.tags+1);
1259: bail(1); }
1260: strcpy(add_area.tag[add_area.tags],instr);
1261: add_area.tags++;
1262: alter_areas(&add_area,&del_area,addr,to);
1263: for(i=0;i<add_area.tags;i++)
1264: free(add_area.tag[i]);
1265: FREE_AND_NULL(add_area.tag);
1266: return;
1267: }
1268:
1269: if((p=strstr(instr,"-ALL"))!=NULL) {
1270: if((del_area.tag=(char **)realloc(del_area.tag
1271: ,sizeof(char *)*del_area.tags+1))==NULL) {
1272: lprintf(LOG_ERR,"ERROR line %d allocating memory for del area tag #%u"
1273: ,__LINE__,del_area.tags+1);
1274: bail(1); }
1275: if((del_area.tag[del_area.tags]=(char *)malloc(strlen(instr)+1))==NULL) {
1276: lprintf(LOG_ERR,"ERROR line %d allocating memory for del area tag #%u"
1277: ,__LINE__,del_area.tags+1);
1278: bail(1); }
1279: strcpy(del_area.tag[del_area.tags],instr);
1280: del_area.tags++;
1281: alter_areas(&add_area,&del_area,addr,to);
1282: for(i=0;i<del_area.tags;i++)
1283: free(del_area.tag[i]);
1284: FREE_AND_NULL(del_area.tag);
1285: return;
1286: }
1287: }
1288: /******************************************************************************
1289: This is where we're gonna process any netmail that comes in for areafix.
1290: Returns text for message body for the local sysop if necessary.
1291: ******************************************************************************/
1292: char* process_areafix(faddr_t addr, char* inbuf, char* password, char* to)
1293: {
1294: static char body[512];
1295: char str[128];
1296: char *p,*tp,action,percent=0;
1297: int i;
1298: ulong l,m;
1299: area_t add_area,del_area;
1300:
1301: p=(char *)inbuf;
1302:
1303: while(*p==1) { /* Skip kludge lines 11/05/95 */
1304: FIND_CHAR(p,'\r');
1305: if(*p) {
1306: p++; /* Skip CR (required) */
1307: if(*p=='\n')
1308: p++; /* Skip LF (optional) */
1309: }
1310: }
1311:
1312: if(((tp=strstr(p,"---\r"))!=NULL || (tp=strstr(p,"--- "))!=NULL) &&
1313: (*(tp-1)=='\r' || *(tp-1)=='\n'))
1314: *tp=0;
1315:
1316: if(!strnicmp(p,"%FROM",5)) { /* Remote Remote Maintenance (must be first) */
1317: SAFECOPY(str,p+6);
1318: truncstr(str,"\r\n");
1319: lprintf(LOG_NOTICE,"Remote maintenance for %s requested via %s",str
1320: ,smb_faddrtoa(&addr,NULL));
1321: addr=atofaddr(str); }
1322:
1323: i=matchnode(addr,0);
1324: if(i>=cfg.nodecfgs) {
1325: create_netmail(to,"Areafix Request"
1326: ,"Your node is not configured for Areafix, please contact your hub.\r\n",addr,FALSE);
1327: sprintf(body,"An areafix request was made by node %s.\r\nThis node "
1328: "is not currently configured for areafix.\r\n"
1329: ,smb_faddrtoa(&addr,NULL));
1330: return(body); }
1331:
1332: if(stricmp(cfg.nodecfg[i].password,password)) {
1333: create_netmail(to,"Areafix Request","Invalid Password.",addr,FALSE);
1334: sprintf(body,"Node %s attempted an areafix request using an invalid "
1335: "password.\r\nThe password attempted was %s.\r\nThe correct password "
1336: "for this node is %s.\r\n",smb_faddrtoa(&addr,NULL),password
1337: ,(cfg.nodecfg[i].password[0]) ? cfg.nodecfg[i].password
1338: : "[None Defined]");
1339: return(body); }
1340:
1341: m=strlen(p);
1342: add_area.tags=0;
1343: add_area.tag=NULL;
1344: del_area.tags=0;
1345: del_area.tag=NULL;
1346: for(l=0;l<m;l++) {
1347: while(*(p+l) && isspace(*(p+l))) l++;
1348: while(*(p+l)==1) { /* Ignore kludge lines June-13-2004 */
1349: while(*(p+l) && *(p+l)!='\r') l++;
1350: continue;
1351: }
1352: if(!(*(p+l))) break;
1353: if(*(p+l)=='+' || *(p+l)=='-' || *(p+l)=='%') {
1354: action=*(p+l);
1355: l++; }
1356: else
1357: action='+';
1358: SAFECOPY(str,p+l);
1359: truncstr(str,"\r\n");
1360: switch(action) {
1361: case '+': /* Add Area */
1362: if((add_area.tag=(char **)realloc(add_area.tag
1363: ,sizeof(char *)*add_area.tags+1))==NULL) {
1364: lprintf(LOG_ERR,"ERROR line %d allocating memory for add area "
1365: "tag #%u",__LINE__,add_area.tags+1);
1366: bail(1); }
1367: if((add_area.tag[add_area.tags]=(char *)malloc(strlen(str)+1))
1368: ==NULL) {
1369: lprintf(LOG_ERR,"ERROR line %d allocating memory for add area "
1370: "tag #%u",__LINE__,add_area.tags+1);
1371: bail(1); }
1372: strcpy(add_area.tag[add_area.tags],str);
1373: add_area.tags++;
1374: break;
1375: case '-': /* Remove Area */
1376: if((del_area.tag=(char **)realloc(del_area.tag
1377: ,sizeof(char *)*del_area.tags+1))==NULL) {
1378: lprintf(LOG_ERR,"ERROR line %d allocating memory for del area "
1379: "tag #%u",__LINE__,del_area.tags+1);
1380: bail(1); }
1381: if((del_area.tag[del_area.tags]=(char *)malloc(strlen(str)+1))
1382: ==NULL) {
1383: lprintf(LOG_ERR,"ERROR line %d allocating memory for del area "
1384: "tag #%u",__LINE__,del_area.tags+1);
1385: bail(1); }
1386: strcpy(del_area.tag[del_area.tags],str);
1387: del_area.tags++;
1388: break;
1389: case '%': /* Process Command */
1390: command(str,addr,to);
1391: percent++;
1392: break; }
1393:
1394: while(*(p+l) && *(p+l)!='\r') l++; }
1395:
1396: if(!percent && !add_area.tags && !del_area.tags) {
1397: create_netmail(to,"Areafix Request","No commands to process.",addr,FALSE);
1398: sprintf(body,"Node %s attempted an areafix request with an empty message "
1399: "body or with no valid commands.\r\n",smb_faddrtoa(&addr,NULL));
1400: return(body); }
1401: if(add_area.tags || del_area.tags)
1402: alter_areas(&add_area,&del_area,addr,to);
1403: if(add_area.tags) {
1404: for(i=0;i<add_area.tags;i++)
1405: free(add_area.tag[i]);
1406: FREE_AND_NULL(add_area.tag); }
1407: if(del_area.tags) {
1408: for(i=0;i<del_area.tags;i++)
1409: free(del_area.tag[i]);
1410: FREE_AND_NULL(del_area.tag); }
1411: return(0);
1412: }
1413: /******************************************************************************
1414: This function will compare the archive signatures defined in the CFG file and
1415: extract 'infile' using the appropriate de-archiver.
1416: ******************************************************************************/
1417: int unpack(char *infile)
1418: {
1419: FILE *stream;
1420: char str[256],tmp[128];
1421: int i,j,ch,file;
1422:
1423: if((stream=fnopen(&file,infile,O_RDONLY))==NULL) {
1424: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,infile
1425: ,strerror(errno));
1426: bail(1); }
1427: for(i=0;i<cfg.arcdefs;i++) {
1428: str[0]=0;
1429: fseek(stream,cfg.arcdef[i].byteloc,SEEK_SET);
1430: for(j=0;j<strlen(cfg.arcdef[i].hexid)/2;j++) {
1431: ch=fgetc(stream);
1432: if(ch==EOF) {
1433: i=cfg.arcdefs;
1434: break; }
1435: sprintf(tmp,"%02X",ch);
1436: strcat(str,tmp);
1437: }
1438: if(!stricmp(str,cfg.arcdef[i].hexid))
1439: break;
1440: }
1441: fclose(stream);
1442:
1443: if(i==cfg.arcdefs) {
1444: lprintf(LOG_ERR,"ERROR line %d determining filetype of %s",__LINE__,infile);
1445: return(1); }
1446:
1447: j=execute(mycmdstr(&scfg,cfg.arcdef[i].unpack,infile
1448: ,secure ? cfg.secure : cfg.inbound));
1449: if(j) {
1450: lprintf(LOG_ERR,"ERROR %d (%d) line %d executing %s"
1451: ,j,errno,__LINE__,mycmdstr(&scfg,cfg.arcdef[i].unpack,infile
1452: ,secure ? cfg.secure : cfg.inbound));
1453: return(j); }
1454: return(0);
1455: }
1456: /******************************************************************************
1457: This function will check the 'dest' for the type of archiver to use (as
1458: defined in the CFG file) and compress 'srcfile' into 'destfile' using the
1459: appropriate archive program.
1460: ******************************************************************************/
1461: void pack(char *srcfile,char *destfile,faddr_t dest)
1462: {
1463: int i,j;
1464: uint use=0;
1465:
1466: i=matchnode(dest,0);
1467: if(i<cfg.nodecfgs)
1468: use=cfg.nodecfg[i].arctype;
1469:
1470: j=execute(mycmdstr(&scfg,cfg.arcdef[use].pack,destfile,srcfile));
1471: if(j) {
1472: lprintf(LOG_ERR,"ERROR %d (%d) line %d executing %s"
1473: ,j,errno,__LINE__,mycmdstr(&scfg,cfg.arcdef[use].pack,destfile,srcfile)); }
1474: }
1475:
1476: enum {
1477: ATTACHMENT_ADD
1478: ,ATTACHMENT_NETMAIL
1479: ,ATTACHMENT_CHECK
1480: };
1481:
1482: int attachment(char *bundlename,faddr_t dest, int mode)
1483: {
1484: FILE *fidomsg,*stream;
1485: char str[1025],*path,fname[129],*p;
1486: int fmsg,file,error=0L;
1487: long fncrc,*mfncrc=0L,num_mfncrc=0L,crcidx;
1488: attach_t attach;
1489: fmsghdr_t hdr;
1490: size_t f;
1491: glob_t g;
1492:
1493: if(bundlename==NULL && mode!=ATTACHMENT_NETMAIL) {
1494: lprintf(LOG_ERR,"ERROR line %d NULL bundlename",__LINE__);
1495: return(1);
1496: }
1497: sprintf(fname,"%sBUNDLES.SBE",cfg.outbound);
1498: if((stream=fnopen(&file,fname,O_RDWR|O_CREAT))==NULL) {
1499: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,fname,strerror(errno));
1500: return(1);
1501: }
1502:
1503: if(mode==ATTACHMENT_CHECK) { /* Check for existance in BUNDLES.SBE */
1504: while(!feof(stream)) {
1505: if(!fread(&attach,1,sizeof(attach_t),stream))
1506: break;
1507: if(!stricmp(attach.fname,bundlename)) {
1508: fclose(stream);
1509: return(1);
1510: }
1511: }
1512: fclose(stream);
1513: if(!flength(fname))
1514: remove(fname);
1515: return(0);
1516: }
1517:
1518: if(mode==ATTACHMENT_NETMAIL) { /* Create netmail attaches */
1519:
1520: if(!filelength(file)) {
1521: fclose(stream);
1522: return(0);
1523: }
1524: /* Get attach names from existing MSGs */
1525: #ifdef __unix__
1526: sprintf(str,"%s*.[Mm][Ss][Gg]",scfg.netmail_dir);
1527: #else
1528: sprintf(str,"%s*.msg",scfg.netmail_dir);
1529: #endif
1530: glob(str,0,NULL,&g);
1531: for(f=0;f<g.gl_pathc;f++) {
1532:
1533: path=g.gl_pathv[f];
1534:
1535: if((fidomsg=fnopen(&fmsg,path,O_RDWR))==NULL) {
1536: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,path
1537: ,strerror(errno));
1538: continue;
1539: }
1540: if(filelength(fmsg)<sizeof(fmsghdr_t)) {
1541: lprintf(LOG_ERR,"ERROR line %d %s has invalid length of %lu bytes"
1542: ,__LINE__
1543: ,path
1544: ,filelength(fmsg));
1545: fclose(fidomsg);
1546: continue;
1547: }
1548: if(fread(&hdr,sizeof(fmsghdr_t),1,fidomsg)!=1) {
1549: fclose(fidomsg);
1550: lprintf(LOG_ERR,"ERROR line %d reading %u bytes from %s"
1551: ,__LINE__,sizeof(fmsghdr_t),path);
1552: continue;
1553: }
1554: fclose(fidomsg);
1555: if(!(hdr.attr&FIDO_FILE)) /* Not a file attach */
1556: continue;
1557: num_mfncrc++;
1558: p=getfname(hdr.subj);
1559: if((mfncrc=(long *)realloc(mfncrc,num_mfncrc*sizeof(long)))==NULL) {
1560: lprintf(LOG_ERR,"ERROR line %d allocating %lu for bundle name crc"
1561: ,__LINE__,num_mfncrc*sizeof(long));
1562: continue;
1563: }
1564: mfncrc[num_mfncrc-1]=crc32(strupr(p),0);
1565: }
1566: globfree(&g);
1567:
1568: while(!feof(stream)) {
1569: if(!fread(&attach,1,sizeof(attach_t),stream))
1570: break;
1571: sprintf(str,"%s%s",cfg.outbound,attach.fname);
1572: if(!fexistcase(str))
1573: continue;
1574: fncrc=crc32(strupr(attach.fname),0);
1575: for(crcidx=0;crcidx<num_mfncrc;crcidx++)
1576: if(mfncrc[crcidx]==fncrc)
1577: break;
1578: if(crcidx==num_mfncrc)
1579: if(create_netmail(/* To: */NULL,str
1580: ,misc&TRUNC_BUNDLES ? "\1FLAGS TFS\r" : "\1FLAGS KFS\r"
1581: ,attach.dest,TRUE))
1582: error=1;
1583: }
1584: fclose(stream);
1585: if(!error) /* remove bundles.sbe if no error occurred */
1586: remove(fname); /* used to truncate here, August-20-2002 */
1587: if(num_mfncrc)
1588: free(mfncrc);
1589: return(0);
1590: }
1591:
1592: while(!feof(stream)) {
1593: if(!fread(&attach,1,sizeof(attach_t),stream))
1594: break;
1595: if(!stricmp(attach.fname,bundlename)) {
1596: fclose(stream);
1597: return(0);
1598: }
1599: }
1600:
1601: memcpy(&attach.dest,&dest,sizeof(faddr_t));
1602: strcpy(attach.fname,bundlename);
1603: fwrite(&attach,sizeof(attach_t),1,stream);
1604: fclose(stream);
1605: return(0);
1606: }
1607:
1608: /******************************************************************************
1609: This function is called when a message packet has reached it's maximum size.
1610: It places packets into a bundle until that bundle is full, at which time the
1611: last character of the extension increments (1 thru 0 and then A thru Z). If
1612: all bundles have reached their maximum size remaining packets are placed into
1613: the Z bundle.
1614: ******************************************************************************/
1615: void pack_bundle(char *infile,faddr_t dest)
1616: {
1617: char str[256],fname[256],outbound[128],day[3],*p;
1618: int i,j,file,node;
1619: time_t now;
1620:
1621: if(infile==NULL || infile[0]==0) {
1622: lprintf(LOG_ERR,"ERROR line %d invalid filename",__LINE__);
1623: bail(1);
1624: }
1625:
1626: node=matchnode(dest,0);
1627: strcpy(str,infile);
1628: str[strlen(str)-1]='t';
1629: if(rename(infile,str)) /* Change .PK_ file to .PKT file */
1630: lprintf(LOG_ERR,"ERROR line %d renaming %s to %s",__LINE__,infile,str);
1631: infile[strlen(infile)-1]='t';
1632: time(&now);
1633: sprintf(day,"%-.2s",ctime(&now));
1634: strupr(day);
1635: if(misc&FLO_MAILER) {
1636: if(node<cfg.nodecfgs && cfg.nodecfg[node].route.zone) {
1637: dest=cfg.nodecfg[node].route;
1638: if(cfg.log&LOG_ROUTING)
1639: lprintf(LOG_NOTICE,"Routing %s to %s",infile,smb_faddrtoa(&dest,NULL));
1640: }
1641:
1642: if(dest.zone==sys_faddr.zone) /* Default zone, use default outbound */
1643: strcpy(outbound,cfg.outbound);
1644: else { /* Inter-zone outbound is OUTBOUND.XXX */
1645: sprintf(outbound,"%.*s.%03x"
1646: ,(int)strlen(cfg.outbound)-1,cfg.outbound,dest.zone);
1647: MKDIR(outbound);
1648: backslash(outbound);
1649: }
1650: if(dest.point) { /* Point destination is OUTBOUND\*.PNT */
1651: sprintf(str,"%04x%04x.pnt"
1652: ,dest.net,dest.node);
1653: strcat(outbound,str); }
1654: }
1655: else
1656: strcpy(outbound,cfg.outbound);
1657: if(outbound[strlen(outbound)-1]=='\\'
1658: || outbound[strlen(outbound)-1]=='/')
1659: outbound[strlen(outbound)-1]=0;
1660: MKDIR(outbound);
1661: backslash(outbound);
1662:
1663: if(node<cfg.nodecfgs)
1664: if(cfg.nodecfg[node].arctype==0xffff) { /* Uncompressed! */
1665: if(misc&FLO_MAILER)
1666: i=write_flofile(infile,dest,TRUE /* bundle */);
1667: else
1668: i=create_netmail(/* To: */NULL,infile
1669: ,misc&TRUNC_BUNDLES ? "\1FLAGS TFS\r" : "\1FLAGS KFS\r"
1670: ,dest,TRUE);
1671: if(i) bail(1);
1672: return; }
1673:
1674: if(dest.point && !(misc&FLO_MAILER))
1675: sprintf(fname,"%s%04hxp%03hx.%s",outbound,0,(short)dest.point,day);
1676: else
1677: sprintf(fname,"%s%04hx%04hx.%s",outbound,(short)(sys_faddr.net-dest.net)
1678: ,(short)(sys_faddr.node-dest.node),day);
1679: for(i='0';i<='Z';i++) {
1680: if(i==':')
1681: i='A';
1682: sprintf(str,"%s%c",fname,i);
1683: if(flength(str)==0) {
1684: /* Feb-10-2003: Don't overwrite or delete 0-byte file less than 24hrs old */
1685: if((time(NULL)-fdate(str))<24L*60L*60L)
1686: continue;
1687: if(delfile(str))
1688: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,str
1689: ,strerror(errno));
1690: }
1691: if(fexistcase(str)) {
1692: if(flength(str)>=cfg.maxbdlsize)
1693: continue;
1694: file=sopen(str,O_WRONLY,SH_DENYRW);
1695: if(file==-1) /* Can't open?!? Probably being sent */
1696: continue;
1697: close(file);
1698: p=getfname(str);
1699: if(!attachment(p,dest,ATTACHMENT_CHECK))
1700: attachment(p,dest,ATTACHMENT_ADD);
1701: pack(infile,str,dest);
1702: if(delfile(infile))
1703: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,infile
1704: ,strerror(errno));
1705: return; }
1706: else {
1707: if(misc&FLO_MAILER)
1708: j=write_flofile(str,dest,TRUE /* bundle */);
1709: else {
1710: p=getfname(str);
1711: j=attachment(p,dest,ATTACHMENT_ADD); }
1712: if(j)
1713: bail(1);
1714: pack(infile,str,dest);
1715: if(delfile(infile))
1716: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,infile
1717: ,strerror(errno));
1718: return; } }
1719:
1720: pack(infile,str,dest); /* Won't get here unless all bundles are full */
1721: }
1722: /******************************************************************************
1723: This function checks the inbound directory for the first bundle it finds, it
1724: will then unpack and delete the bundle. If no bundles exist this function
1725: returns a FALSE, otherwise a TRUE is returned.
1726: ******************************************************************************/
1727: BOOL unpack_bundle(void)
1728: {
1729: char* p;
1730: char str[MAX_PATH+1];
1731: char fname[MAX_PATH+1];
1732: int i;
1733: static glob_t g;
1734: static int gi;
1735:
1736: for(i=0;i<7;i++) {
1737: #if defined(__unix__) /* support upper or lower case */
1738: switch(i) {
1739: case 0:
1740: p="[Ss][Uu]";
1741: break;
1742: case 1:
1743: p="[Mm][Oo]";
1744: break;
1745: case 2:
1746: p="[Tt][Uu]";
1747: break;
1748: case 3:
1749: p="[Ww][Ee]";
1750: break;
1751: case 4:
1752: p="[Tt][Hh]";
1753: break;
1754: case 5:
1755: p="[Ff][Rr]";
1756: break;
1757: default:
1758: p="[Ss][Aa]";
1759: break;
1760: }
1761: #else
1762: switch(i) {
1763: case 0:
1764: p="su";
1765: break;
1766: case 1:
1767: p="mo";
1768: break;
1769: case 2:
1770: p="tu";
1771: break;
1772: case 3:
1773: p="we";
1774: break;
1775: case 4:
1776: p="th";
1777: break;
1778: case 5:
1779: p="fr";
1780: break;
1781: default:
1782: p="sa";
1783: break;
1784: }
1785: #endif
1786: sprintf(str,"%s*.%s?",secure ? cfg.secure : cfg.inbound,p);
1787: if(gi>=g.gl_pathc) {
1788: gi=0;
1789: globfree(&g);
1790: glob(str,0,NULL,&g);
1791: }
1792: if(gi<g.gl_pathc) {
1793: SAFECOPY(fname,g.gl_pathv[gi]);
1794: lprintf(LOG_DEBUG,"Unpacking bundle: %s",fname);
1795: if(unpack(fname)) { /* failure */
1796: lprintf(LOG_ERR,"!Unpack failure");
1797: if(fdate(fname)+(48L*60L*60L)>time(NULL)) {
1798: SAFECOPY(str,fname);
1799: str[strlen(str)-2]='_';
1800: if(fexistcase(str))
1801: str[strlen(str)-2]='-';
1802: if(fexistcase(str))
1803: delfile(str);
1804: if(rename(fname,str))
1805: lprintf(LOG_ERR,"ERROR line %d renaming %s to %s"
1806: ,__LINE__,fname,str);
1807: }
1808: }
1809: else {
1810: lprintf(LOG_DEBUG,"Deleting bundle: %s", fname);
1811: if(delfile(fname)) /* successful, so delete bundle */
1812: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,fname
1813: ,strerror(errno));
1814: }
1815: gi++;
1816: return(TRUE);
1817: }
1818: }
1819:
1820: return(FALSE);
1821: }
1822:
1823: /****************************************************************************/
1824: /* Moves or copies a file from one dir to another */
1825: /* both 'src' and 'dest' must contain full path and filename */
1826: /* returns 0 if successful, -1 if error */
1827: /****************************************************************************/
1828: int mv(char *src, char *dest, BOOL copy)
1829: {
1830: char buf[4096],str[256];
1831: int ind,outd;
1832: long length,chunk=4096,l;
1833: FILE *inp,*outp;
1834:
1835: if(!strcmp(src,dest)) /* source and destination are the same! */
1836: return(0);
1837: if(!fexistcase(src)) {
1838: lprintf(LOG_WARNING,"MV ERROR: Source doesn't exist '%s",src);
1839: return(-1);
1840: }
1841: if(!copy && fexistcase(dest)) {
1842: lprintf(LOG_WARNING,"MV ERROR: Destination already exists '%s'",dest);
1843: return(-1);
1844: }
1845: if(!copy
1846: #ifndef __unix__
1847: && ((src[1]!=':' && dest[1]!=':')
1848: || (src[1]==':' && dest[1]==':' && toupper(src[0])==toupper(dest[0])))
1849: #endif
1850: ) {
1851: if(rename(src,dest)==0) /* same drive, so move */
1852: return(0);
1853: /* rename failed, so attempt copy */
1854: }
1855: if((ind=nopen(src,O_RDONLY))==-1) {
1856: lprintf(LOG_ERR,"MV ERROR: ERR_OPEN %s",src);
1857: return(-1);
1858: }
1859: if((inp=fdopen(ind,"rb"))==NULL) {
1860: close(ind);
1861: lprintf(LOG_ERR,"MV ERROR: ERR_FDOPEN %s",str);
1862: return(-1);
1863: }
1864: setvbuf(inp,NULL,_IOFBF,8*1024);
1865: if((outd=nopen(dest,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
1866: fclose(inp);
1867: lprintf(LOG_ERR,"MV ERROR: ERR_OPEN %s",dest);
1868: return(-1);
1869: }
1870: if((outp=fdopen(outd,"wb"))==NULL) {
1871: close(outd);
1872: fclose(inp);
1873: lprintf(LOG_ERR,"MV ERROR: ERR_FDOPEN %s",str);
1874: return(-1);
1875: }
1876: setvbuf(outp,NULL,_IOFBF,8*1024);
1877: length=filelength(ind);
1878: l=0L;
1879: while(l<length) {
1880: if(l+chunk>length)
1881: chunk=length-l;
1882: fread(buf,chunk,1,inp);
1883: fwrite(buf,chunk,1,outp);
1884: l+=chunk;
1885: }
1886: fclose(inp);
1887: fclose(outp);
1888: if(!copy && delfile(src)) {
1889: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,src,strerror(errno));
1890: return(-1);
1891: }
1892: return(0);
1893: }
1894:
1895: /****************************************************************************/
1896: /* Returns the total number of msgs in the sub-board and sets 'ptr' to the */
1897: /* date of the last message in the sub (0) if no messages. */
1898: /****************************************************************************/
1899: ulong getlastmsg(uint subnum, ulong *ptr, time_t *t)
1900: {
1901: int i;
1902: smb_t smbfile;
1903:
1904: ZERO_VAR(smbfile);
1905: if(subnum>=scfg.total_subs) {
1906: lprintf(LOG_ERR,"ERROR line %d getlastmsg %d",__LINE__,subnum);
1907: bail(1); }
1908: sprintf(smbfile.file,"%s%s",scfg.sub[subnum]->data_dir,scfg.sub[subnum]->code);
1909: smbfile.retry_time=scfg.smb_retry_time;
1910: if((i=smb_open(&smbfile))!=SMB_SUCCESS) {
1911: lprintf(LOG_ERR,"ERROR %d line %d opening %s",i,__LINE__,smbfile.file);
1912: return(0); }
1913:
1914: if(!filelength(fileno(smbfile.shd_fp))) { /* Empty base */
1915: if(ptr) (*ptr)=0;
1916: smb_close(&smbfile);
1917: return(0); }
1918: smb_close(&smbfile);
1919: if(ptr) (*ptr)=smbfile.status.last_msg;
1920: return(smbfile.status.total_msgs);
1921: }
1922:
1923:
1924: ulong loadmsgs(post_t** post, ulong ptr)
1925: {
1926: int i;
1927: long l,total;
1928: idxrec_t idx;
1929:
1930:
1931: if((i=smb_locksmbhdr(&smb[cur_smb]))!=SMB_SUCCESS) {
1932: lprintf(LOG_ERR,"ERROR %d line %d locking %s",i,__LINE__,smb[cur_smb].file);
1933: return(0);
1934: }
1935:
1936: /* total msgs in sub */
1937: total=filelength(fileno(smb[cur_smb].sid_fp))/sizeof(idxrec_t);
1938:
1939: if(!total) { /* empty */
1940: smb_unlocksmbhdr(&smb[cur_smb]);
1941: return(0);
1942: }
1943:
1944: if(((*post)=(post_t*)malloc(sizeof(post_t)*total)) /* alloc for max */
1945: ==NULL) {
1946: smb_unlocksmbhdr(&smb[cur_smb]);
1947: lprintf(LOG_ERR,"ERROR line %d allocating %lu bytes for %s",__LINE__
1948: ,sizeof(post_t *)*total,smb[cur_smb].file);
1949: return(0);
1950: }
1951:
1952: fseek(smb[cur_smb].sid_fp,0L,SEEK_SET);
1953: for(l=0;l<total && !feof(smb[cur_smb].sid_fp); ) {
1954: if(smb_fread(&smb[cur_smb], &idx,sizeof(idx),smb[cur_smb].sid_fp) != sizeof(idx))
1955: break;
1956:
1957: if(idx.number==0) /* invalid message number, ignore */
1958: continue;
1959:
1960: if(idx.number<=ptr || idx.attr&MSG_DELETE)
1961: continue;
1962:
1963: if(idx.attr&MSG_MODERATED && !(idx.attr&MSG_VALIDATED))
1964: break;
1965:
1966: (*post)[l++]=idx;
1967: }
1968: smb_unlocksmbhdr(&smb[cur_smb]);
1969: if(!l)
1970: FREE_AND_NULL(*post);
1971: return(l);
1972: }
1973:
1974: void bail(int code)
1975: {
1976: if(code || pause_on_exit) {
1977: fprintf(stderr,"\nHit any key...");
1978: getch();
1979: fprintf(stderr,"\n");
1980: }
1981: exit(code);
1982: }
1983:
1984: typedef struct {
1985: ulong alias,
1986: real;
1987: } username_t;
1988:
1989: /****************************************************************************/
1990: /* Note: Wrote another version of this function that read all userdata into */
1991: /****************************************************************************/
1992: /* Looks for a perfect match amoung all usernames (not deleted users) */
1993: /* Returns the number of the perfect matched username or 0 if no match */
1994: /* Called from functions waitforcall and newuser */
1995: /* memory then scanned it from memory... took longer - always. */
1996: /****************************************************************************/
1997: ulong matchname(char *inname)
1998: {
1999: static ulong total_users;
2000: static username_t *username;
2001: ulong last_user;
2002: int userdat,i;
2003: char str[256],name[LEN_NAME+1],alias[LEN_ALIAS+1];
2004: ulong l,crc;
2005:
2006: if(!total_users) { /* Load CRCs */
2007: fprintf(stderr,"\n%-25s","Loading user names...");
2008: sprintf(str,"%suser/user.dat",scfg.data_dir);
2009: if((userdat=nopen(str,O_RDONLY|O_DENYNONE))==-1)
2010: return(0);
2011: last_user=filelength(userdat)/U_LEN;
2012: for(total_users=0;total_users<last_user;total_users++) {
2013: printf("%5ld\b\b\b\b\b",total_users);
2014: if((username=(username_t *)realloc(username
2015: ,(total_users+1L)*sizeof(username_t)))==NULL)
2016: break;
2017: username[total_users].alias=0;
2018: username[total_users].real=0;
2019: i=0;
2020: while(i<LOOP_NODEDAB
2021: && lock(userdat,(long)((long)(total_users)*U_LEN)+U_ALIAS
2022: ,LEN_ALIAS+LEN_NAME)==-1)
2023: i++;
2024: if(i>=LOOP_NODEDAB) { /* Couldn't lock USER.DAT record */
2025: lprintf(LOG_ERR,"ERROR locking USER.DAT record #%ld",total_users);
2026: continue; }
2027: lseek(userdat,(long)((long)(total_users)*U_LEN)+U_ALIAS,SEEK_SET);
2028: read(userdat,alias,LEN_ALIAS);
2029: read(userdat,name,LEN_NAME);
2030: lseek(userdat,(long)(((long)total_users)*U_LEN)+U_MISC,SEEK_SET);
2031: read(userdat,tmp,8);
2032: for(i=0;i<8;i++)
2033: if(tmp[i]==ETX || tmp[i]=='\r') break;
2034: tmp[i]=0;
2035: unlock(userdat,(long)((long)(total_users)*U_LEN)+U_ALIAS
2036: ,LEN_ALIAS+LEN_NAME);
2037: if(ahtoul(tmp)&DELETED)
2038: continue;
2039: for(i=0;i<LEN_ALIAS;i++)
2040: if(alias[i]==ETX || alias[i]=='\r') break;
2041: alias[i]=0;
2042: strupr(alias);
2043: for(i=0;i<LEN_NAME;i++)
2044: if(name[i]==ETX || name[i]=='\r') break;
2045: name[i]=0;
2046: strupr(name);
2047: username[total_users].alias=crc32(alias,0);
2048: username[total_users].real=crc32(name,0); }
2049: close(userdat);
2050: fprintf(stderr," \b\b\b\b\b"); /* Clear counter */
2051: fprintf(stderr,
2052: "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
2053: "%25s"
2054: "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
2055: ,""); }
2056:
2057: strcpy(str,inname);
2058: strupr(str);
2059: crc=crc32(str,0);
2060: for(l=0;l<total_users;l++)
2061: if((crc==username[l].alias || crc==username[l].real))
2062: return(l+1);
2063: return(0);
2064: }
2065:
2066: /****************************************************************************/
2067: /* Converts goofy FidoNet time format into Unix format */
2068: /****************************************************************************/
2069: time_t fmsgtime(char *str)
2070: {
2071: char month[4];
2072: struct tm tm;
2073:
2074: memset(&tm,0,sizeof(tm));
2075: tm.tm_isdst=-1; /* Do not adjust for DST */
2076:
2077: if(isdigit(str[1])) { /* Regular format: "01 Jan 86 02:34:56" */
2078: tm.tm_mday=atoi(str);
2079: sprintf(month,"%3.3s",str+3);
2080: if(!stricmp(month,"jan"))
2081: tm.tm_mon=0;
2082: else if(!stricmp(month,"feb"))
2083: tm.tm_mon=1;
2084: else if(!stricmp(month,"mar"))
2085: tm.tm_mon=2;
2086: else if(!stricmp(month,"apr"))
2087: tm.tm_mon=3;
2088: else if(!stricmp(month,"may"))
2089: tm.tm_mon=4;
2090: else if(!stricmp(month,"jun"))
2091: tm.tm_mon=5;
2092: else if(!stricmp(month,"jul"))
2093: tm.tm_mon=6;
2094: else if(!stricmp(month,"aug"))
2095: tm.tm_mon=7;
2096: else if(!stricmp(month,"sep"))
2097: tm.tm_mon=8;
2098: else if(!stricmp(month,"oct"))
2099: tm.tm_mon=9;
2100: else if(!stricmp(month,"nov"))
2101: tm.tm_mon=10;
2102: else
2103: tm.tm_mon=11;
2104: tm.tm_year=atoi(str+7);
2105: if(tm.tm_year<Y2K_2DIGIT_WINDOW)
2106: tm.tm_year+=100;
2107: tm.tm_hour=atoi(str+11);
2108: tm.tm_min=atoi(str+14);
2109: tm.tm_sec=atoi(str+17); }
2110:
2111: else { /* SEAdog format: "Mon 1 Jan 86 02:34" */
2112: tm.tm_mday=atoi(str+4);
2113: sprintf(month,"%3.3s",str+7);
2114: if(!stricmp(month,"jan"))
2115: tm.tm_mon=0;
2116: else if(!stricmp(month,"feb"))
2117: tm.tm_mon=1;
2118: else if(!stricmp(month,"mar"))
2119: tm.tm_mon=2;
2120: else if(!stricmp(month,"apr"))
2121: tm.tm_mon=3;
2122: else if(!stricmp(month,"may"))
2123: tm.tm_mon=4;
2124: else if(!stricmp(month,"jun"))
2125: tm.tm_mon=5;
2126: else if(!stricmp(month,"jul"))
2127: tm.tm_mon=6;
2128: else if(!stricmp(month,"aug"))
2129: tm.tm_mon=7;
2130: else if(!stricmp(month,"sep"))
2131: tm.tm_mon=8;
2132: else if(!stricmp(month,"oct"))
2133: tm.tm_mon=9;
2134: else if(!stricmp(month,"nov"))
2135: tm.tm_mon=10;
2136: else
2137: tm.tm_mon=11;
2138: tm.tm_year=atoi(str+11);
2139: if(tm.tm_year<Y2K_2DIGIT_WINDOW)
2140: tm.tm_year+=100;
2141: tm.tm_hour=atoi(str+14);
2142: tm.tm_min=atoi(str+17);
2143: tm.tm_sec=0; }
2144: return(mktime(&tm));
2145: }
2146:
2147: static short fmsgzone(char* p)
2148: {
2149: char hr[4]="";
2150: char min[4]="";
2151: short val;
2152: BOOL west=TRUE;
2153:
2154: if(*p=='-')
2155: p++;
2156: else
2157: west=FALSE;
2158:
2159: if(strlen(p)>=2)
2160: sprintf(hr,"%.2s",p);
2161: if(strlen(p+2)>=2)
2162: sprintf(min,"%.2s",p+2);
2163:
2164: val=atoi(hr)*60;
2165: val+=atoi(min);
2166:
2167: if(west)
2168: switch(val|US_ZONE) {
2169: case AST:
2170: case EST:
2171: case CST:
2172: case MST:
2173: case PST:
2174: case YST:
2175: case HST:
2176: case BST:
2177: /* standard US timezone */
2178: return(val|US_ZONE);
2179: default:
2180: /* non-standard timezone */
2181: return(-val);
2182: }
2183: return(val);
2184: }
2185:
2186: char* getfmsg(FILE *stream, ulong *outlen)
2187: {
2188: uchar* fbuf;
2189: int ch;
2190: ulong l,length,start;
2191:
2192: length=0L;
2193: start=ftell(stream); /* Beginning of Message */
2194: while(1) {
2195: ch=fgetc(stream); /* Look for Terminating NULL */
2196: if(ch==0 || ch==EOF) /* Found end of message */
2197: break;
2198: length++; /* Increment the Length */
2199: }
2200:
2201: if((fbuf=(char *)malloc(length+1))==NULL) {
2202: lprintf(LOG_ERR,"ERROR line %d allocating %lu bytes of memory",__LINE__,length+1);
2203: bail(1);
2204: }
2205:
2206: fseek(stream,start,SEEK_SET);
2207: for(l=0;l<length;l++)
2208: fbuf[l]=fgetc(stream);
2209: if(ch==0)
2210: fgetc(stream); /* Read NULL */
2211:
2212: while(length && fbuf[length-1]<=' ') /* truncate white-space */
2213: length--;
2214: fbuf[length]=0;
2215:
2216: if(outlen)
2217: *outlen=length;
2218: return((char*)fbuf);
2219: }
2220:
2221: #define MAX_TAILLEN 1024
2222:
2223: /****************************************************************************/
2224: /* Coverts a FidoNet message into a Synchronet message */
2225: /* Returns 0 on success, 1 dupe, 2 filtered, 3 empty, or other SMB error */
2226: /****************************************************************************/
2227: int fmsgtosmsg(uchar* fbuf, fmsghdr_t fmsghdr, uint user, uint subnum)
2228: {
2229: uchar ch,*sbody,stail[MAX_TAILLEN+1],*outbuf
2230: ,*p,str[128];
2231: char msg_id[256];
2232: BOOL done,esc,cr;
2233: int i,storage=SMB_SELFPACK;
2234: uint col;
2235: ushort xlat=XLAT_NONE,net;
2236: ulong l,m,length,bodylen,taillen,crc;
2237: ulong save;
2238: long dupechk_hashes=SMB_HASH_SOURCE_ALL;
2239: faddr_t faddr,origaddr,destaddr;
2240: smb_t* smbfile;
2241: char fname[MAX_PATH+1];
2242: smbmsg_t msg;
2243:
2244: if(twit_list) {
2245: sprintf(fname,"%stwitlist.cfg",scfg.ctrl_dir);
2246: if(findstr(fmsghdr.from,fname) || findstr(fmsghdr.to,fname)) {
2247: lprintf(LOG_INFO,"Filtering message from %s to %s",fmsghdr.from,fmsghdr.to);
2248: return(2);
2249: }
2250: }
2251:
2252: memset(&msg,0,sizeof(smbmsg_t));
2253: if(fmsghdr.attr&FIDO_PRIVATE)
2254: msg.idx.attr|=MSG_PRIVATE;
2255: msg.hdr.attr=msg.idx.attr;
2256:
2257: if(fmsghdr.attr&FIDO_FILE)
2258: msg.hdr.auxattr|=MSG_FILEATTACH;
2259:
2260: msg.hdr.when_imported.time=time(NULL);
2261: msg.hdr.when_imported.zone=sys_timezone(&scfg);
2262: msg.hdr.when_written.time=fmsgtime(fmsghdr.time);
2263:
2264: origaddr.zone=fmsghdr.origzone; /* only valid if NetMail */
2265: origaddr.net=fmsghdr.orignet;
2266: origaddr.node=fmsghdr.orignode;
2267: origaddr.point=fmsghdr.origpoint;
2268:
2269: destaddr.zone=fmsghdr.destzone; /* only valid if NetMail */
2270: destaddr.net=fmsghdr.destnet;
2271: destaddr.node=fmsghdr.destnode;
2272: destaddr.point=fmsghdr.destpoint;
2273:
2274: smb_hfield_str(&msg,SENDER,fmsghdr.from);
2275: smb_hfield_str(&msg,RECIPIENT,fmsghdr.to);
2276:
2277: if(user) {
2278: sprintf(str,"%u",user);
2279: smb_hfield_str(&msg,RECIPIENTEXT,str);
2280: }
2281:
2282: smb_hfield_str(&msg,SUBJECT,fmsghdr.subj);
2283:
2284: if(fbuf==NULL) {
2285: lprintf(LOG_ERR,"ERROR line %d allocating fbuf",__LINE__);
2286: smb_freemsgmem(&msg);
2287: return(-1);
2288: }
2289: length=strlen((char *)fbuf);
2290: if((sbody=(char*)malloc((length+1)*2))==NULL) {
2291: lprintf(LOG_ERR,"ERROR line %d allocating %lu bytes for body",__LINE__
2292: ,(length+1)*2L);
2293: smb_freemsgmem(&msg);
2294: return(-1);
2295: }
2296:
2297: for(col=l=esc=done=bodylen=taillen=0,cr=1;l<length;l++) {
2298:
2299: if(!l && !strncmp((char *)fbuf,"AREA:",5)) {
2300: save=l;
2301: l+=5;
2302: while(l<length && fbuf[l]<=' ') l++;
2303: m=l;
2304: while(m<length && fbuf[m]!='\r') m++;
2305: while(m && fbuf[m-1]<=' ') m--;
2306: if(m>l)
2307: smb_hfield(&msg,FIDOAREA,(ushort)(m-l),fbuf+l);
2308: while(l<length && fbuf[l]!='\r') l++;
2309: /* If unknown echo, keep AREA: line in message body */
2310: if(cfg.badecho>=0 && subnum==cfg.area[cfg.badecho].sub)
2311: l=save;
2312: else
2313: continue;
2314: }
2315:
2316: ch=fbuf[l];
2317: if(ch==1 && cr) { /* kludge line */
2318:
2319: if(!strncmp((char *)fbuf+l+1,"TOPT ",5))
2320: destaddr.point=atoi((char *)fbuf+l+6);
2321:
2322: else if(!strncmp((char *)fbuf+l+1,"FMPT ",5))
2323: origaddr.point=atoi((char *)fbuf+l+6);
2324:
2325: else if(!strncmp((char *)fbuf+l+1,"INTL ",5)) {
2326: faddr=atofaddr((char *)fbuf+l+6);
2327: destaddr.zone=faddr.zone;
2328: destaddr.net=faddr.net;
2329: destaddr.node=faddr.node;
2330: l+=6;
2331: while(l<length && fbuf[l]!=' ') l++;
2332: faddr=atofaddr((char *)fbuf+l+1);
2333: origaddr.zone=faddr.zone;
2334: origaddr.net=faddr.net;
2335: origaddr.node=faddr.node; }
2336:
2337: else if(!strncmp((char *)fbuf+l+1,"MSGID:",6)) {
2338: l+=7;
2339: while(l<length && fbuf[l]<=' ') l++;
2340: m=l;
2341: while(m<length && fbuf[m]!='\r') m++;
2342: while(m && fbuf[m-1]<=' ') m--;
2343: if(m>l)
2344: smb_hfield(&msg,FIDOMSGID,(ushort)(m-l),fbuf+l); }
2345:
2346: else if(!strncmp((char *)fbuf+l+1,"REPLY:",6)) {
2347: l+=7;
2348: while(l<length && fbuf[l]<=' ') l++;
2349: m=l;
2350: while(m<length && fbuf[m]!='\r') m++;
2351: while(m && fbuf[m-1]<=' ') m--;
2352: if(m>l)
2353: smb_hfield(&msg,FIDOREPLYID,(ushort)(m-l),fbuf+l); }
2354:
2355: else if(!strncmp((char *)fbuf+l+1,"FLAGS ",6) /* correct */
2356: || !strncmp((char *)fbuf+l+1,"FLAGS:",6)) { /* incorrect */
2357: l+=7;
2358: while(l<length && fbuf[l]<=' ') l++;
2359: m=l;
2360: while(m<length && fbuf[m]!='\r') m++;
2361: while(m && fbuf[m-1]<=' ') m--;
2362: if(m>l)
2363: smb_hfield(&msg,FIDOFLAGS,(ushort)(m-l),fbuf+l); }
2364:
2365: else if(!strncmp((char *)fbuf+l+1,"PATH:",5)) {
2366: l+=6;
2367: while(l<length && fbuf[l]<=' ') l++;
2368: m=l;
2369: while(m<length && fbuf[m]!='\r') m++;
2370: while(m && fbuf[m-1]<=' ') m--;
2371: if(m>l && misc&STORE_PATH)
2372: smb_hfield(&msg,FIDOPATH,(ushort)(m-l),fbuf+l); }
2373:
2374: else if(!strncmp((char *)fbuf+l+1,"PID:",4)) {
2375: l+=5;
2376: while(l<length && fbuf[l]<=' ') l++;
2377: m=l;
2378: while(m<length && fbuf[m]!='\r') m++;
2379: while(m && fbuf[m-1]<=' ') m--;
2380: if(m>l)
2381: smb_hfield(&msg,FIDOPID,(ushort)(m-l),fbuf+l); }
2382:
2383: else if(!strncmp((char *)fbuf+l+1,"TID:",4)) {
2384: l+=5;
2385: while(l<length && fbuf[l]<=' ') l++;
2386: m=l;
2387: while(m<length && fbuf[m]!='\r') m++;
2388: while(m && fbuf[m-1]<=' ') m--;
2389: if(m>l)
2390: smb_hfield(&msg,FIDOTID,(ushort)(m-l),fbuf+l); }
2391:
2392: else if(!strncmp((char *)fbuf+l+1,"TZUTC:",6)) { /* FSP-1001 */
2393: l+=7;
2394: while(l<length && fbuf[l]<=' ') l++;
2395: msg.hdr.when_written.zone = fmsgzone(fbuf+l);
2396: }
2397:
2398: else if(!strncmp((char *)fbuf+l+1,"TZUTCINFO:",10)) { /* non-standard */
2399: l+=11;
2400: while(l<length && fbuf[l]<=' ') l++;
2401: msg.hdr.when_written.zone = fmsgzone(fbuf+l);
2402: }
2403:
2404: else { /* Unknown kludge line */
2405: while(l<length && fbuf[l]<=' ') l++;
2406: m=l;
2407: while(m<length && fbuf[m]!='\r') m++;
2408: while(m && fbuf[m-1]<=' ') m--;
2409: if(m>l && misc&STORE_KLUDGE)
2410: smb_hfield(&msg,FIDOCTRL,(ushort)(m-l),fbuf+l); }
2411:
2412: while(l<length && fbuf[l]!='\r') l++;
2413: continue; }
2414:
2415: if(ch!='\n' && ch!=0x8d) { /* ignore LF and soft CRs */
2416: if(cr && (!strncmp((char *)fbuf+l,"--- ",4)
2417: || !strncmp((char *)fbuf+l,"---\r",4)))
2418: done=1; /* tear line and down go into tail */
2419: if(done && cr && !strncmp((char *)fbuf+l,"SEEN-BY:",8)) {
2420: l+=8;
2421: while(l<length && fbuf[l]<=' ') l++;
2422: m=l;
2423: while(m<length && fbuf[m]!='\r') m++;
2424: while(m && fbuf[m-1]<=' ') m--;
2425: if(m>l && misc&STORE_SEENBY)
2426: smb_hfield(&msg,FIDOSEENBY,(ushort)(m-l),fbuf+l);
2427: while(l<length && fbuf[l]!='\r') l++;
2428: continue; }
2429: if(done) {
2430: if(taillen<MAX_TAILLEN)
2431: stail[taillen++]=ch; }
2432: else
2433: sbody[bodylen++]=ch;
2434: col++;
2435: if(ch=='\r') {
2436: cr=1;
2437: col=0;
2438: if(done) {
2439: if(taillen<MAX_TAILLEN)
2440: stail[taillen++]='\n'; }
2441: else
2442: sbody[bodylen++]='\n'; }
2443: else {
2444: cr=0;
2445: if(col==1 && !strncmp((char *)fbuf+l," * Origin: ",11)) {
2446: p=(char *)fbuf+l+11;
2447: while(*p && *p!='\r') p++; /* Find CR */
2448: while(p && *p!='(') p--; /* rewind to '(' */
2449: if(p)
2450: origaddr=atofaddr(p+1); /* get orig address */
2451: done=1; }
2452: if(done)
2453: continue;
2454:
2455: if(ch==ESC) esc=1; /* ANSI codes */
2456: if(ch==' ' && col>40 && !esc) { /* word wrap */
2457: for(m=l+1;m<length;m++) /* find next space */
2458: if(fbuf[m]<=' ')
2459: break;
2460: if(m<length && m-l>80-col) { /* if it's beyond the eol */
2461: sbody[bodylen++]='\r';
2462: sbody[bodylen++]='\n';
2463: col=0; } }
2464: } } }
2465:
2466: if(bodylen>=2 && sbody[bodylen-2]=='\r' && sbody[bodylen-1]=='\n')
2467: bodylen-=2; /* remove last CRLF if present */
2468: sbody[bodylen]=0;
2469:
2470: while(taillen && stail[taillen-1]<=' ') /* trim all garbage off the tail */
2471: taillen--;
2472: stail[taillen]=0;
2473:
2474: if(subnum==INVALID_SUB && !bodylen && !taillen && misc&KILL_EMPTY_MAIL) {
2475: lprintf(LOG_INFO,"Empty NetMail - Ignored ");
2476: smb_freemsgmem(&msg);
2477: free(sbody);
2478: return(3);
2479: }
2480:
2481: if(!origaddr.zone && subnum==INVALID_SUB)
2482: net=NET_NONE; /* Message from SBBSecho */
2483: else
2484: net=NET_FIDO; /* Record origin address */
2485:
2486: if(net) {
2487: smb_hfield(&msg,SENDERNETTYPE,sizeof(ushort),&net);
2488: smb_hfield(&msg,SENDERNETADDR,sizeof(fidoaddr_t),&origaddr); }
2489:
2490: if(subnum==INVALID_SUB) {
2491: smbfile=email;
2492: if(net) {
2493: smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(ushort),&net);
2494: smb_hfield(&msg,RECIPIENTNETADDR,sizeof(fidoaddr_t),&destaddr);
2495: }
2496: smbfile->status.attr = SMB_EMAIL;
2497: smbfile->status.max_age = scfg.mail_maxage;
2498: smbfile->status.max_crcs = scfg.mail_maxcrcs;
2499: if(scfg.sys_misc&SM_FASTMAIL)
2500: storage= SMB_FASTALLOC;
2501: } else {
2502: smbfile=&smb[cur_smb];
2503: smbfile->status.max_age = scfg.sub[subnum]->maxage;
2504: smbfile->status.max_crcs = scfg.sub[subnum]->maxcrcs;
2505: smbfile->status.max_msgs = scfg.sub[subnum]->maxmsgs;
2506: if(scfg.sub[subnum]->misc&SUB_HYPER)
2507: storage = smbfile->status.attr = SMB_HYPERALLOC;
2508: else if(scfg.sub[subnum]->misc&SUB_FAST)
2509: storage = SMB_FASTALLOC;
2510: if(scfg.sub[subnum]->misc&SUB_LZH)
2511: xlat=XLAT_LZH;
2512:
2513: msg.idx.time=msg.hdr.when_imported.time; /* needed for MSG-ID generation */
2514: msg.idx.number=smbfile->status.last_msg+1; /* needed for MSG-ID generation */
2515:
2516: /* Generate default (RFC822) message-id (always) */
2517: SAFECOPY(msg_id,get_msgid(&scfg,subnum,&msg));
2518: smb_hfield_str(&msg,RFC822MSGID,msg_id);
2519: }
2520: if(smbfile->status.max_crcs==0)
2521: dupechk_hashes&=~(1<<SMB_HASH_SOURCE_BODY);
2522:
2523: i=smb_addmsg(smbfile, &msg, storage, dupechk_hashes, xlat, sbody, stail);
2524:
2525: if(i!=SMB_SUCCESS) {
2526: lprintf(LOG_ERR,"ERROR smb_addmsg returned %d: %s"
2527: ,i,smbfile->last_error);
2528: }
2529: smb_freemsgmem(&msg);
2530:
2531: return(i);
2532: }
2533:
2534: /***********************************************************************/
2535: /* Get zone and point from kludge lines from the stream if they exist */
2536: /***********************************************************************/
2537: void getzpt(FILE *stream, fmsghdr_t *hdr)
2538: {
2539: char buf[0x1000];
2540: int i,len,cr=0;
2541: long pos;
2542: faddr_t faddr;
2543:
2544: pos=ftell(stream);
2545: len=fread(buf,1,0x1000,stream);
2546: for(i=0;i<len;i++) {
2547: if(buf[i]=='\n') /* ignore line-feeds */
2548: continue;
2549: if((!i || cr) && buf[i]==1) { /* kludge */
2550: if(!strncmp(buf+i+1,"TOPT ",5))
2551: hdr->destpoint=atoi(buf+i+6);
2552: else if(!strncmp(buf+i+1,"FMPT ",5))
2553: hdr->origpoint=atoi(buf+i+6);
2554: else if(!strncmp(buf+i+1,"INTL ",5)) {
2555: faddr=atofaddr(buf+i+6);
2556: hdr->destzone=faddr.zone;
2557: hdr->destnet=faddr.net;
2558: hdr->destnode=faddr.node;
2559: i+=6;
2560: while(buf[i] && buf[i]!=' ') i++;
2561: faddr=atofaddr(buf+i+1);
2562: hdr->origzone=faddr.zone;
2563: hdr->orignet=faddr.net;
2564: hdr->orignode=faddr.node; }
2565: while(i<len && buf[i]!='\r') i++;
2566: cr=1;
2567: continue; }
2568: if(buf[i]=='\r')
2569: cr=1;
2570: else
2571: cr=0; }
2572: fseek(stream,pos,SEEK_SET);
2573: }
2574: /******************************************************************************
2575: This function will seek to the next NULL found in stream
2576: ******************************************************************************/
2577: void seektonull(FILE *stream)
2578: {
2579: char ch;
2580:
2581: while(!feof(stream)) {
2582: if(!fread(&ch,1,1,stream))
2583: break;
2584: if(!ch)
2585: break;
2586: }
2587: }
2588:
2589: /******************************************************************************
2590: This function returns a packet name - used for outgoing packets
2591: ******************************************************************************/
2592: char *pktname(BOOL temp)
2593: {
2594: static char str[128];
2595: int i;
2596: time_t now;
2597: struct tm *tm;
2598:
2599: now=time(NULL);
2600: for(i=0;i<MAX_TOTAL_PKTS*2;i++) {
2601: now++;
2602: tm=localtime(&now);
2603: sprintf(str,"%s%02u%02u%02u%02u.%s",cfg.outbound,tm->tm_mday,tm->tm_hour
2604: ,tm->tm_min,tm->tm_sec,temp ? "pk_" : "pkt");
2605: if(!fexist(str)) /* Add 1 second if name exists */
2606: break;
2607: }
2608: return(str);
2609: }
2610: /******************************************************************************
2611: This function puts a message into a Fido packet, writing both the header
2612: information and the message body
2613: ******************************************************************************/
2614: void putfmsg(FILE *stream,uchar *fbuf,fmsghdr_t fmsghdr,areasbbs_t area
2615: ,addrlist_t seenbys,addrlist_t paths)
2616: {
2617: char str[256],seenby[256];
2618: short i,j,lastlen=0,net_exists=0;
2619: faddr_t addr,sysaddr;
2620: fpkdmsg_t pkdmsg;
2621: time_t t;
2622: size_t len;
2623: struct tm* tm;
2624:
2625: addr=getsysfaddr(fmsghdr.destzone);
2626:
2627: /* Write fixed-length header fields */
2628: memset(&pkdmsg,0,sizeof(pkdmsg));
2629: pkdmsg.type = 2;
2630: pkdmsg.orignet = addr.net;
2631: pkdmsg.orignode = addr.node;
2632: pkdmsg.destnet = fmsghdr.destnet;
2633: pkdmsg.destnode = fmsghdr.destnode;
2634: pkdmsg.attr = fmsghdr.attr;
2635: pkdmsg.cost = fmsghdr.cost;
2636: SAFECOPY(pkdmsg.time,fmsghdr.time);
2637: fwrite(&pkdmsg ,sizeof(pkdmsg) ,1,stream);
2638:
2639: /* Write variable-length (ASCIIZ) header fields */
2640: fwrite(fmsghdr.to ,strlen(fmsghdr.to)+1 ,1,stream);
2641: fwrite(fmsghdr.from ,strlen(fmsghdr.from)+1 ,1,stream);
2642: fwrite(fmsghdr.subj ,strlen(fmsghdr.subj)+1 ,1,stream);
2643:
2644: len = strlen((char *)fbuf);
2645:
2646: /* Write message body */
2647: if(area.name)
2648: if(strncmp((char *)fbuf,"AREA:",5)) /* No AREA: Line */
2649: fprintf(stream,"AREA:%s\r",area.name); /* So add one */
2650: fwrite(fbuf,len,1,stream);
2651: lastlen=9;
2652: if(len && fbuf[len-1]!='\r')
2653: fputc('\r',stream);
2654:
2655: if(area.name==NULL) { /* NetMail, so add FSP-1010 Via kludge line */
2656: t=time(NULL);
2657: tm=gmtime(&t);
2658: fprintf(stream,"\1Via %s @%04u%02u%02u.%02u%02u%02u.UTC "
2659: "SBBSecho %s-%s r%s\r"
2660: ,smb_faddrtoa(&addr,NULL)
2661: ,tm->tm_year+1900
2662: ,tm->tm_mon+1
2663: ,tm->tm_mday
2664: ,tm->tm_hour
2665: ,tm->tm_min
2666: ,tm->tm_sec
2667: ,SBBSECHO_VER,PLATFORM_DESC,revision);
2668: }
2669:
2670:
2671: if(area.name && addr.zone!=fmsghdr.destzone) /* Zone Gate */
2672: fprintf(stream,"SEEN-BY: %d/%d\r",fmsghdr.destnet,fmsghdr.destnode);
2673:
2674: if(area.name && addr.zone==fmsghdr.destzone) { /* Not NetMail */
2675: fprintf(stream,"SEEN-BY:");
2676: for(i=0;i<seenbys.addrs;i++) { /* Put back original SEEN-BYs */
2677: strcpy(seenby," ");
2678: if(seenbys.addr[i].zone!=addr.zone)
2679: continue;
2680: if(seenbys.addr[i].net!=addr.net || !net_exists) {
2681: net_exists=1;
2682: addr.net=seenbys.addr[i].net;
2683: sprintf(str,"%d/",addr.net);
2684: strcat(seenby,str); }
2685: sprintf(str,"%d",seenbys.addr[i].node);
2686: strcat(seenby,str);
2687: if(lastlen+strlen(seenby)<80) {
2688: fwrite(seenby,strlen(seenby),1,stream);
2689: lastlen+=strlen(seenby); }
2690: else {
2691: --i;
2692: lastlen=9; /* +strlen(seenby); */
2693: net_exists=0;
2694: fprintf(stream,"\rSEEN-BY:"); } }
2695:
2696: for(i=0;i<area.uplinks;i++) { /* Add all uplinks to SEEN-BYs */
2697: strcpy(seenby," ");
2698: if(area.uplink[i].zone!=addr.zone || area.uplink[i].point)
2699: continue;
2700: for(j=0;j<seenbys.addrs;j++)
2701: if(!memcmp(&area.uplink[i],&seenbys.addr[j],sizeof(faddr_t)))
2702: break;
2703: if(j==seenbys.addrs) {
2704: if(area.uplink[i].net!=addr.net || !net_exists) {
2705: net_exists=1;
2706: addr.net=area.uplink[i].net;
2707: sprintf(str,"%d/",addr.net);
2708: strcat(seenby,str); }
2709: sprintf(str,"%d",area.uplink[i].node);
2710: strcat(seenby,str);
2711: if(lastlen+strlen(seenby)<80) {
2712: fwrite(seenby,strlen(seenby),1,stream);
2713: lastlen+=strlen(seenby); }
2714: else {
2715: --i;
2716: lastlen=9; /* +strlen(seenby); */
2717: net_exists=0;
2718: fprintf(stream,"\rSEEN-BY:"); } } }
2719:
2720: for(i=0;i<scfg.total_faddrs;i++) { /* Add AKAs to SEEN-BYs */
2721: strcpy(seenby," ");
2722: if(scfg.faddr[i].zone!=addr.zone || scfg.faddr[i].point)
2723: continue;
2724: for(j=0;j<seenbys.addrs;j++)
2725: if(!memcmp(&scfg.faddr[i],&seenbys.addr[j],sizeof(faddr_t)))
2726: break;
2727: if(j==seenbys.addrs) {
2728: if(scfg.faddr[i].net!=addr.net || !net_exists) {
2729: net_exists=1;
2730: addr.net=scfg.faddr[i].net;
2731: sprintf(str,"%d/",addr.net);
2732: strcat(seenby,str); }
2733: sprintf(str,"%d",scfg.faddr[i].node);
2734: strcat(seenby,str);
2735: if(lastlen+strlen(seenby)<80) {
2736: fwrite(seenby,strlen(seenby),1,stream);
2737: lastlen+=strlen(seenby); }
2738: else {
2739: --i;
2740: lastlen=9; /* +strlen(seenby); */
2741: net_exists=0;
2742: fprintf(stream,"\rSEEN-BY:"); } } }
2743:
2744: lastlen=7;
2745: net_exists=0;
2746: fprintf(stream,"\r\1PATH:");
2747: addr=getsysfaddr(fmsghdr.destzone);
2748: for(i=0;i<paths.addrs;i++) { /* Put back the original PATH */
2749: strcpy(seenby," ");
2750: if(paths.addr[i].zone!=addr.zone || paths.addr[i].point)
2751: continue;
2752: if(paths.addr[i].net!=addr.net || !net_exists) {
2753: net_exists=1;
2754: addr.net=paths.addr[i].net;
2755: sprintf(str,"%d/",addr.net);
2756: strcat(seenby,str); }
2757: sprintf(str,"%d",paths.addr[i].node);
2758: strcat(seenby,str);
2759: if(lastlen+strlen(seenby)<80) {
2760: fwrite(seenby,strlen(seenby),1,stream);
2761: lastlen+=strlen(seenby); }
2762: else {
2763: --i;
2764: lastlen=7; /* +strlen(seenby); */
2765: net_exists=0;
2766: fprintf(stream,"\r\1PATH:"); } }
2767:
2768: strcpy(seenby," "); /* Add first address with same zone to PATH */
2769: sysaddr=getsysfaddr(fmsghdr.destzone);
2770: if(!sysaddr.point) {
2771: if(sysaddr.net!=addr.net || !net_exists) {
2772: net_exists=1;
2773: addr.net=sysaddr.net;
2774: sprintf(str,"%d/",addr.net);
2775: strcat(seenby,str); }
2776: sprintf(str,"%d",sysaddr.node);
2777: strcat(seenby,str);
2778: if(lastlen+strlen(seenby)<80)
2779: fwrite(seenby,strlen(seenby),1,stream);
2780: else {
2781: fprintf(stream,"\r\1PATH:");
2782: fwrite(seenby,strlen(seenby),1,stream); } }
2783:
2784: fputc('\r',stream); }
2785:
2786: fputc(FIDO_PACKED_MSG_TERMINATOR, stream);
2787: }
2788:
2789: size_t terminate_packet(FILE* stream)
2790: {
2791: WORD terminator=FIDO_PACKET_TERMINATOR;
2792:
2793: return fwrite(&terminator, sizeof(terminator), 1, stream);
2794: }
2795:
2796: long find_packet_terminator(FILE* stream)
2797: {
2798: WORD terminator;
2799: long offset;
2800:
2801: fseek(stream, 0, SEEK_END);
2802: offset = ftell(stream);
2803: if(offset >= sizeof(fpkthdr_t)+sizeof(terminator)) {
2804: fseek(stream, offset-sizeof(terminator), SEEK_SET);
2805: if(fread(&terminator, sizeof(terminator), 1, stream)
2806: && terminator==FIDO_PACKET_TERMINATOR)
2807: offset -= sizeof(terminator);
2808: }
2809: return(offset);
2810: }
2811:
2812: /******************************************************************************
2813: This function creates a binary list of the message seen-bys and path from
2814: inbuf.
2815: ******************************************************************************/
2816: void gen_psb(addrlist_t *seenbys,addrlist_t *paths,char *inbuf
2817: ,ushort zone)
2818: {
2819: char str[128],seenby[256],*p,*p1,*p2,*fbuf;
2820: int i,j,len;
2821: faddr_t addr;
2822:
2823: if(!inbuf)
2824: return;
2825: fbuf=strstr((char *)inbuf,"\r * Origin: ");
2826: if(!fbuf)
2827: fbuf=strstr((char *)inbuf,"\n * Origin: ");
2828: if(!fbuf)
2829: fbuf=inbuf;
2830: if(seenbys->addr) {
2831: free(seenbys->addr);
2832: seenbys->addr=0;
2833: seenbys->addrs=0; }
2834: addr.zone=addr.net=addr.node=addr.point=seenbys->addrs=0;
2835: p=strstr((char *)fbuf,"\rSEEN-BY:");
2836: if(!p) p=strstr((char *)fbuf,"\nSEEN-BY:");
2837: if(p) {
2838: while(1) {
2839: sprintf(str,"%-.100s",p+10);
2840: if((p1=strchr(str,'\r'))!=NULL)
2841: *p1=0;
2842: p1=str;
2843: i=j=0;
2844: len=strlen(str);
2845: while(i<len) {
2846: j=i;
2847: while(i<len && *(p1+i)!=' ')
2848: ++i;
2849: if(j>len)
2850: break;
2851: sprintf(seenby,"%-.*s",(i-j),p1+j);
2852: if((p2=strchr(seenby,':'))!=NULL) {
2853: addr.zone=atoi(seenby);
2854: addr.net=atoi(p2+1); }
2855: else if((p2=strchr(seenby,'/'))!=NULL)
2856: addr.net=atoi(seenby);
2857: if((p2=strchr(seenby,'/'))!=NULL)
2858: addr.node=atoi(p2+1);
2859: else
2860: addr.node=atoi(seenby);
2861: if((p2=strchr(seenby,'.'))!=NULL)
2862: addr.point=atoi(p2+1);
2863: if(!addr.zone)
2864: addr.zone=zone; /* Was 1 */
2865: if((seenbys->addr=(faddr_t *)realloc(seenbys->addr
2866: ,sizeof(faddr_t)*(seenbys->addrs+1)))==NULL) {
2867: lprintf(LOG_ERR,"ERROR line %d allocating memory for message "
2868: "seenbys.",__LINE__);
2869: bail(1); }
2870: memcpy(&seenbys->addr[seenbys->addrs],&addr,sizeof(faddr_t));
2871: seenbys->addrs++;
2872: ++i; }
2873: p1=strstr(p+10,"\rSEEN-BY:");
2874: if(!p1)
2875: p1=strstr(p+10,"\nSEEN-BY:");
2876: if(!p1)
2877: break;
2878: p=p1; } }
2879: else {
2880: if((seenbys->addr=(faddr_t *)realloc(seenbys->addr
2881: ,sizeof(faddr_t)))==NULL) {
2882: lprintf(LOG_ERR,"ERROR line %d allocating memory for message seenbys."
2883: ,__LINE__);
2884: bail(1); }
2885: memset(&seenbys->addr[0],0,sizeof(faddr_t)); }
2886:
2887: if(paths->addr) {
2888: free(paths->addr);
2889: paths->addr=0;
2890: paths->addrs=0; }
2891: addr.zone=addr.net=addr.node=addr.point=paths->addrs=0;
2892: if((p=strstr((char *)fbuf,"\1PATH:"))!=NULL) {
2893: while(1) {
2894: sprintf(str,"%-.100s",p+7);
2895: if((p1=strchr(str,'\r'))!=NULL)
2896: *p1=0;
2897: p1=str;
2898: i=j=0;
2899: len=strlen(str);
2900: while(i<len) {
2901: j=i;
2902: while(i<len && *(p1+i)!=' ')
2903: ++i;
2904: if(j>len)
2905: break;
2906: sprintf(seenby,"%-.*s",(i-j),p1+j);
2907: if((p2=strchr(seenby,':'))!=NULL) {
2908: addr.zone=atoi(seenby);
2909: addr.net=atoi(p2+1); }
2910: else if((p2=strchr(seenby,'/'))!=NULL)
2911: addr.net=atoi(seenby);
2912: if((p2=strchr(seenby,'/'))!=NULL)
2913: addr.node=atoi(p2+1);
2914: else
2915: addr.node=atoi(seenby);
2916: if((p2=strchr(seenby,'.'))!=NULL)
2917: addr.point=atoi(p2+1);
2918: if(!addr.zone)
2919: addr.zone=zone; /* Was 1 */
2920: if((paths->addr=(faddr_t *)realloc(paths->addr
2921: ,sizeof(faddr_t)*(paths->addrs+1)))==NULL) {
2922: lprintf(LOG_ERR,"ERROR line %d allocating memory for message "
2923: "paths.",__LINE__);
2924: bail(1); }
2925: memcpy(&paths->addr[paths->addrs],&addr,sizeof(faddr_t));
2926: paths->addrs++;
2927: ++i; }
2928: if((p1=strstr(p+7,"\1PATH:"))==NULL)
2929: break;
2930: p=p1; } }
2931: else {
2932: if((paths->addr=(faddr_t *)realloc(paths->addr
2933: ,sizeof(faddr_t)))==NULL) {
2934: lprintf(LOG_ERR,"ERROR line %d allocating memory for message paths."
2935: ,__LINE__);
2936: bail(1); }
2937: memset(&paths->addr[0],0,sizeof(faddr_t)); }
2938: }
2939:
2940: /******************************************************************************
2941: This function takes the addrs passed to it and compares them to the address
2942: passed in inaddr. 1 is returned if inaddr matches any of the addrs
2943: otherwise a 0 is returned.
2944: ******************************************************************************/
2945: int check_psb(addrlist_t* addrlist,faddr_t inaddr)
2946: {
2947: int i;
2948:
2949: for(i=0;i<addrlist->addrs;i++) {
2950: if(!memcmp(&addrlist->addr[i],&inaddr,sizeof(faddr_t)))
2951: return(1);
2952: }
2953: return(0);
2954: }
2955: /******************************************************************************
2956: This function strips the message seen-bys and path from inbuf.
2957: ******************************************************************************/
2958: void strip_psb(char *inbuf)
2959: {
2960: char *p,*fbuf;
2961:
2962: if(!inbuf)
2963: return;
2964: fbuf=strstr((char *)inbuf,"\r * Origin: ");
2965: if(!fbuf)
2966: fbuf=inbuf;
2967: if((p=strstr((char *)fbuf,"\rSEEN-BY:"))!=NULL)
2968: *(p)=0;
2969: if((p=strstr((char *)fbuf,"\r\1PATH:"))!=NULL)
2970: *(p)=0;
2971: }
2972: void attach_bundles(void)
2973: {
2974: FILE *fidomsg;
2975: char str[1025],path[MAX_PATH+1],*packet;
2976: int fmsg;
2977: faddr_t pkt_faddr;
2978: pkthdr_t pkthdr;
2979: size_t f;
2980: glob_t g;
2981:
2982: sprintf(path,"%s*.pk_",cfg.outbound);
2983: glob(path,0,NULL,&g);
2984: for(f=0;f<g.gl_pathc && !kbhit();f++) {
2985:
2986: packet=g.gl_pathv[f];
2987:
2988: printf("%21s: %s ","Outbound Packet",packet);
2989: if((fmsg=sopen(packet,O_RDWR|O_BINARY,SH_DENYRW))==-1) {
2990: lprintf(LOG_ERR,"ERROR %d line %d opening %s",errno,__LINE__,packet);
2991: continue; }
2992: if((fidomsg=fdopen(fmsg,"r+b"))==NULL) {
2993: close(fmsg);
2994: lprintf(LOG_ERR,"ERROR line %d fdopening %s",__LINE__,packet);
2995: continue; }
2996: if(filelength(fmsg)<sizeof(pkthdr_t)) {
2997: lprintf(LOG_ERR,"ERROR line %d invalid length of %lu bytes for %s"
2998: ,__LINE__,filelength(fmsg),packet);
2999: fclose(fidomsg);
3000: if(delfile(packet))
3001: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,packet
3002: ,strerror(errno));
3003: continue; }
3004: if(fread(&pkthdr,sizeof(pkthdr_t),1,fidomsg)!=1) {
3005: fclose(fidomsg);
3006: lprintf(LOG_ERR,"ERROR line %d reading %u bytes from %s",__LINE__
3007: ,sizeof(pkthdr_t),packet);
3008: continue; }
3009: fseek(fidomsg,-2L,SEEK_END);
3010: fread(str,2,1,fidomsg);
3011: fclose(fidomsg);
3012: if(!str[0] && !str[1]) { /* Check for two nulls at end of packet */
3013: pkt_faddr.zone=pkthdr.destzone;
3014: pkt_faddr.net=pkthdr.destnet;
3015: pkt_faddr.node=pkthdr.destnode;
3016: pkt_faddr.point=0; /* No point info in the 2.0 hdr! */
3017: memcpy(&two_plus,&pkthdr.empty,sizeof(pkthdr.empty));
3018: if(two_plus.cword==_rotr(two_plus.cwcopy,8) /* 2+ Packet Header */
3019: && two_plus.cword && two_plus.cword&1)
3020: pkt_faddr.point=two_plus.destpoint;
3021: else if(pkthdr.baud==2) { /* Type 2.2 Packet Header */
3022: memcpy(&two_two,&pkthdr.empty,sizeof(pkthdr.empty));
3023: pkt_faddr.point=pkthdr.month; }
3024: lprintf(LOG_INFO,"Sending to %s",smb_faddrtoa(&pkt_faddr,NULL));
3025: pack_bundle(packet,pkt_faddr);
3026: } else
3027: lprintf(LOG_WARNING,"Outbound Packet (%s) possibly still in use (invalid terminator: %02X%02X)"
3028: ,packet,(BYTE)str[0],(BYTE)str[1]);
3029: }
3030: globfree(&g);
3031: }
3032: /******************************************************************************
3033: This is where we put outgoing messages into packets. Set the 'cleanup'
3034: parameter to 1 to force all the remaining packets closed and stuff them into
3035: a bundle.
3036: ******************************************************************************/
3037: void pkt_to_pkt(uchar *fbuf,areasbbs_t area,faddr_t faddr
3038: ,fmsghdr_t fmsghdr,addrlist_t seenbys,addrlist_t paths, int cleanup)
3039: {
3040: int i,j,k,file;
3041: short node;
3042: time_t now;
3043: struct tm *tm;
3044: pkthdr_t pkthdr;
3045: static ushort openpkts,totalpkts;
3046: static outpkt_t outpkt[MAX_TOTAL_PKTS];
3047: faddr_t sysaddr;
3048: two_two_t two;
3049: two_plus_t two_p;
3050:
3051:
3052: if(cleanup==1) {
3053: for(i=0;i<totalpkts;i++) {
3054: if(i>=MAX_TOTAL_PKTS) {
3055: lprintf(LOG_ERR,"MAX_TOTAL_PKTS (%d) REACHED!",MAX_TOTAL_PKTS);
3056: break;
3057: }
3058: if(outpkt[i].curopen) {
3059: terminate_packet(outpkt[i].stream);
3060: fclose(outpkt[i].stream); }
3061: else {
3062: if((outpkt[i].stream=fnopen(&file,outpkt[i].filename
3063: ,O_WRONLY|O_APPEND))==NULL) {
3064: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__
3065: ,outpkt[i].filename,strerror(errno));
3066: continue; }
3067: terminate_packet(outpkt[i].stream);
3068: fclose(outpkt[i].stream); }
3069: /* pack_nundle() disabled. Why? ToDo */
3070: /* pack_bundle(outpkt[i].filename,outpkt[i].uplink); */
3071: memset(&outpkt[i],0,sizeof(outpkt_t)); }
3072: totalpkts=openpkts=0;
3073: attach_bundles();
3074: if(!(misc&FLO_MAILER))
3075: attachment(0,faddr,ATTACHMENT_NETMAIL);
3076: return; }
3077:
3078: if(fbuf==NULL) {
3079: lprintf(LOG_ERR,"ERROR line %d allocating fbuf",__LINE__);
3080: return; }
3081: /* We want to see if there's already a packet open for this area. */
3082: /* If not, we'll open a new one. Once we have a packet, we'll add */
3083: /* messages to it as they come in. If necessary, we'll close an */
3084: /* open packet to open a new one. */
3085:
3086: for(j=0;j<area.uplinks;j++) {
3087: if((cleanup==2 && memcmp(&faddr,&area.uplink[j],sizeof(faddr_t))) ||
3088: (!cleanup && (!memcmp(&faddr,&area.uplink[j],sizeof(faddr_t)) ||
3089: check_psb(&seenbys,area.uplink[j]))))
3090: continue;
3091: node=matchnode(area.uplink[j],0);
3092: if(node<cfg.nodecfgs && cfg.nodecfg[node].attr&ATTR_PASSIVE)
3093: continue;
3094: sysaddr=getsysfaddr(area.uplink[j].zone);
3095: printf("%s ",smb_faddrtoa(&area.uplink[j],NULL));
3096: for(i=0;i<totalpkts;i++) {
3097: if(i>=MAX_TOTAL_PKTS) {
3098: lprintf(LOG_ERR,"MAX_TOTAL_PKTS (%d) REACHED!",MAX_TOTAL_PKTS);
3099: break;
3100: }
3101: if(!memcmp(&area.uplink[j],&outpkt[i].uplink,sizeof(faddr_t))) {
3102: if(!outpkt[i].curopen) {
3103: if(openpkts==DFLT_OPEN_PKTS)
3104: for(k=0;k<totalpkts;k++) {
3105: if(outpkt[k].curopen) {
3106: fclose(outpkt[k].stream);
3107: outpkt[k].curopen=0;
3108: break; } }
3109: if((outpkt[i].stream=fnopen(&file,outpkt[i].filename
3110: ,O_WRONLY|O_APPEND))==NULL) {
3111: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__
3112: ,outpkt[i].filename,strerror(errno));
3113: bail(1); }
3114: outpkt[i].curopen=1; }
3115: if((strlen((char *)fbuf)+1+ftell(outpkt[i].stream))
3116: <=cfg.maxpktsize) {
3117: fmsghdr.destnode=area.uplink[j].node;
3118: fmsghdr.destnet=area.uplink[j].net;
3119: fmsghdr.destzone=area.uplink[j].zone;
3120: putfmsg(outpkt[i].stream,fbuf,fmsghdr,area,seenbys,paths); }
3121: else {
3122: terminate_packet(outpkt[i].stream);
3123: fclose(outpkt[i].stream);
3124: /* pack_bundle() disabled. Why? ToDo */
3125: /* pack_bundle(outpkt[i].filename,outpkt[i].uplink); */
3126: outpkt[i].stream=outpkt[totalpkts-1].stream;
3127: memcpy(&outpkt[i],&outpkt[totalpkts-1],sizeof(outpkt_t));
3128: memset(&outpkt[totalpkts-1],0,sizeof(outpkt_t));
3129: --totalpkts;
3130: --openpkts;
3131: i=totalpkts;
3132: }
3133: break;
3134: }
3135: }
3136: if(i==totalpkts) {
3137: if(openpkts==DFLT_OPEN_PKTS)
3138: for(k=0;k<totalpkts;k++) {
3139: if(outpkt[k].curopen) {
3140: fclose(outpkt[k].stream);
3141: outpkt[k].curopen=0;
3142: --openpkts;
3143: break; } }
3144: strcpy(outpkt[i].filename,pktname(/* temp? */ TRUE));
3145: now=time(NULL);
3146: tm=localtime(&now);
3147: if((outpkt[i].stream=fnopen(&file,outpkt[i].filename
3148: ,O_WRONLY|O_CREAT))==NULL) {
3149: lprintf(LOG_ERR,"ERROR line %d opening %s %s"
3150: ,__LINE__,outpkt[i].filename,strerror(errno));
3151: bail(1); }
3152: pkthdr.orignode=sysaddr.node;
3153: fmsghdr.destnode=pkthdr.destnode=area.uplink[j].node;
3154: if(node<cfg.nodecfgs && cfg.nodecfg[node].pkt_type==PKT_TWO_TWO) {
3155: pkthdr.year=sysaddr.point;
3156: pkthdr.month=area.uplink[j].point;
3157: pkthdr.day=0;
3158: pkthdr.hour=0;
3159: pkthdr.min=0;
3160: pkthdr.sec=0;
3161: pkthdr.baud=0x0002; }
3162: else {
3163: pkthdr.year=tm->tm_year+1900;
3164: pkthdr.month=tm->tm_mon;
3165: pkthdr.day=tm->tm_mday;
3166: pkthdr.hour=tm->tm_hour;
3167: pkthdr.min=tm->tm_min;
3168: pkthdr.sec=tm->tm_sec;
3169: pkthdr.baud=0; }
3170: pkthdr.pkttype=0x0002;
3171: pkthdr.orignet=sysaddr.net;
3172: fmsghdr.destnet=pkthdr.destnet=area.uplink[j].net;
3173: pkthdr.prodcode=0;
3174: pkthdr.sernum=0;
3175: if(node<cfg.nodecfgs)
3176: memcpy(pkthdr.password,cfg.nodecfg[node].pktpwd,sizeof(pkthdr.password));
3177: else
3178: memset(pkthdr.password,0,sizeof(pkthdr.password));
3179: pkthdr.origzone=sysaddr.zone;
3180: fmsghdr.destzone=pkthdr.destzone=area.uplink[j].zone;
3181: memset(pkthdr.empty,0,sizeof(two_two_t));
3182:
3183: if(node<cfg.nodecfgs) {
3184: if(cfg.nodecfg[node].pkt_type==PKT_TWO_TWO) {
3185: memset(&two,0,sizeof(two));
3186: strcpy(two.origdomn,"fidonet");
3187: strcpy(two.destdomn,"fidonet");
3188: memcpy(&pkthdr.empty,&two,sizeof(pkthdr.empty)); }
3189: else if(cfg.nodecfg[node].pkt_type==PKT_TWO_PLUS) {
3190: memset(&two_p,0,sizeof(two_p));
3191: if(sysaddr.point) {
3192: pkthdr.orignet=-1;
3193: two_p.auxnet=sysaddr.net; }
3194: two_p.cwcopy=0x0100;
3195: two_p.prodcode=pkthdr.prodcode;
3196: two_p.revision=pkthdr.sernum;
3197: two_p.cword=0x0001;
3198: two_p.origzone=pkthdr.origzone;
3199: two_p.destzone=pkthdr.destzone;
3200: two_p.origpoint=sysaddr.point;
3201: two_p.destpoint=area.uplink[j].point;
3202: memcpy(&pkthdr.empty,&two_p,sizeof(pkthdr.empty)); }
3203: }
3204: fwrite(&pkthdr,sizeof(pkthdr_t),1,outpkt[totalpkts].stream);
3205: putfmsg(outpkt[totalpkts].stream,fbuf,fmsghdr,area,seenbys,paths);
3206: outpkt[totalpkts].curopen=1;
3207: memcpy(&outpkt[totalpkts].uplink,&area.uplink[j]
3208: ,sizeof(faddr_t));
3209: ++openpkts;
3210: ++totalpkts;
3211: if(totalpkts>=MAX_TOTAL_PKTS) {
3212: fclose(outpkt[totalpkts-1].stream);
3213: /* pack_bundle() disabled. Why? ToDo */
3214: /* pack_bundle(outpkt[totalpkts-1].filename
3215: ,outpkt[totalpkts-1].uplink); */
3216: --totalpkts;
3217: --openpkts;
3218: }
3219: }
3220: }
3221: }
3222:
3223: int pkt_to_msg(FILE* fidomsg, fmsghdr_t* hdr, char* info)
3224: {
3225: char path[MAX_PATH+1];
3226: uchar* fmsgbuf;
3227: int i,file;
3228: ulong l;
3229:
3230: if((fmsgbuf=getfmsg(fidomsg,&l))==NULL) {
3231: lprintf(LOG_ERR,"ERROR line %d netmail allocation",__LINE__);
3232: return(-1);
3233: }
3234:
3235: if(!l && misc&KILL_EMPTY_MAIL)
3236: printf("Empty NetMail");
3237: else {
3238: printf("Exporting: ");
3239: for(i=1;i;i++) {
3240: sprintf(path,"%s%u.msg",scfg.netmail_dir,i);
3241: if(!fexistcase(path))
3242: break;
3243: }
3244: if(!i) {
3245: lprintf(LOG_WARNING,"Too many netmail messages");
3246: return(-1);
3247: }
3248: if((file=nopen(path,O_WRONLY|O_CREAT))==-1) {
3249: lprintf(LOG_ERR,"ERROR %u line %d creating %s",errno,__LINE__,path);
3250: return(-1);
3251: }
3252: write(file,hdr,sizeof(fmsghdr_t));
3253: write(file,fmsgbuf,l+1); /* Write the '\0' terminator too */
3254: close(file);
3255: printf("%s", path);
3256: lprintf(LOG_INFO,"%s Exported to %s",info,path);
3257: }
3258: free(fmsgbuf);
3259:
3260: return(0);
3261: }
3262:
3263:
3264: /**************************************/
3265: /* Send netmail, returns 0 on success */
3266: /**************************************/
3267: int import_netmail(char *path,fmsghdr_t hdr, FILE *fidomsg)
3268: {
3269: uchar info[512],str[256],tmp[256],subj[256]
3270: ,*fmsgbuf=NULL,*p,*tp,*sp;
3271: int i,match,usernumber;
3272: ulong length;
3273: faddr_t addr;
3274:
3275: hdr.destzone=hdr.origzone=sys_faddr.zone;
3276: hdr.destpoint=hdr.origpoint=0;
3277: getzpt(fidomsg,&hdr); /* use kludge if found */
3278: for(match=0;match<scfg.total_faddrs;match++)
3279: if((hdr.destzone==scfg.faddr[match].zone || misc&FUZZY_ZONE)
3280: && hdr.destnet==scfg.faddr[match].net
3281: && hdr.destnode==scfg.faddr[match].node
3282: && hdr.destpoint==scfg.faddr[match].point)
3283: break;
3284: if(match<scfg.total_faddrs && misc&FUZZY_ZONE)
3285: hdr.origzone=hdr.destzone=scfg.faddr[match].zone;
3286: if(hdr.origpoint)
3287: sprintf(tmp,".%hu",hdr.origpoint);
3288: else
3289: tmp[0]=0;
3290: if(hdr.destpoint)
3291: sprintf(str,".%hu",hdr.destpoint);
3292: else
3293: str[0]=0;
3294: sprintf(info,"%s%s%s (%hu:%hu/%hu%s) To: %s (%hu:%hu/%hu%s)"
3295: ,path,path[0] ? " ":""
3296: ,hdr.from,hdr.origzone,hdr.orignet,hdr.orignode,tmp
3297: ,hdr.to,hdr.destzone,hdr.destnet,hdr.destnode,str);
3298: printf("%s ",info);
3299:
3300: if(!(misc&IMPORT_NETMAIL)) {
3301: printf("Ignored");
3302: if(!path[0]) {
3303: printf(" - ");
3304: pkt_to_msg(fidomsg,&hdr,info);
3305: } else if(cfg.log&LOG_IGNORED)
3306: lprintf(LOG_INFO,"%s Ignored",info);
3307:
3308: return(-1);
3309: }
3310:
3311: if(match>=scfg.total_faddrs && !(misc&IGNORE_ADDRESS)) {
3312: printf("Wrong address");
3313: if(!path[0]) {
3314: printf(" - ");
3315: pkt_to_msg(fidomsg,&hdr,info);
3316: }
3317: return(2);
3318: }
3319:
3320: if(path[0]) { /* .msg file, not .pkt */
3321: if(hdr.attr&FIDO_ORPHAN) {
3322: printf("Orphaned");
3323: return(1);
3324: }
3325: if(hdr.attr&FIDO_RECV && !(misc&IGNORE_RECV)) {
3326: printf("Already received");
3327: return(3);
3328: }
3329: if(hdr.attr&FIDO_LOCAL && !(misc&LOCAL_NETMAIL)) {
3330: printf("Created locally");
3331: return(4);
3332: }
3333: if(hdr.attr&FIDO_INTRANS) {
3334: printf("In-transit");
3335: return(5);
3336: }
3337: }
3338:
3339: if(email->shd_fp==NULL) {
3340: sprintf(email->file,"%smail",scfg.data_dir);
3341: email->retry_time=scfg.smb_retry_time;
3342: if((i=smb_open(email))!=SMB_SUCCESS) {
3343: lprintf(LOG_ERR,"ERROR %d line %d opening %s",i,__LINE__,email->file);
3344: bail(1); } }
3345:
3346: if(!filelength(fileno(email->shd_fp))) {
3347: email->status.max_crcs=scfg.mail_maxcrcs;
3348: email->status.max_msgs=0;
3349: email->status.max_age=scfg.mail_maxage;
3350: email->status.attr=SMB_EMAIL;
3351: if((i=smb_create(email))!=SMB_SUCCESS) {
3352: lprintf(LOG_ERR,"ERROR %d creating %s",i,email->file);
3353: bail(1); } }
3354:
3355: if(!stricmp(hdr.to,"AREAFIX") || !stricmp(hdr.to,"SBBSECHO")) {
3356: fmsgbuf=getfmsg(fidomsg,NULL);
3357: if(path[0]) {
3358: if(misc&DELETE_NETMAIL) {
3359: fclose(fidomsg);
3360: if(delfile(path))
3361: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,path
3362: ,strerror(errno)); }
3363: else {
3364: hdr.attr|=FIDO_RECV;
3365: fseek(fidomsg,0L,SEEK_SET);
3366: fwrite(&hdr,sizeof(fmsghdr_t),1,fidomsg);
3367: fclose(fidomsg); } } /* Gotta close it here for areafix stuff */
3368: addr.zone=hdr.origzone;
3369: addr.net=hdr.orignet;
3370: addr.node=hdr.orignode;
3371: addr.point=hdr.origpoint;
3372: p=process_areafix(addr,fmsgbuf,/* Password: */hdr.subj, /* To: */hdr.from);
3373: if(p && cfg.notify) {
3374: SAFECOPY(hdr.to,scfg.sys_op);
3375: SAFECOPY(hdr.from,"SBBSecho");
3376: SAFECOPY(hdr.subj,"Areafix Request");
3377: hdr.origzone=hdr.orignet=hdr.orignode=hdr.origpoint=0;
3378: if(fmsgtosmsg(p,hdr,cfg.notify,INVALID_SUB)==0) {
3379: sprintf(str,"\7\1n\1hSBBSecho \1n\1msent you mail\r\n");
3380: putsmsg(&scfg,cfg.notify,str);
3381: }
3382: }
3383: if(fmsgbuf)
3384: free(fmsgbuf);
3385: if(cfg.log&LOG_AREAFIX)
3386: logprintf(info);
3387: return(-2);
3388: }
3389:
3390: usernumber=atoi(hdr.to);
3391: if(!stricmp(hdr.to,"SYSOP")) /* NetMail to "sysop" goes to #1 */
3392: usernumber=1;
3393: if(!usernumber && match<scfg.total_faddrs)
3394: usernumber=matchname(hdr.to);
3395: if(!usernumber) {
3396: if(misc&UNKNOWN_NETMAIL && match<scfg.total_faddrs) /* receive unknown user */
3397: usernumber=1; /* mail to 1 */
3398: else {
3399: if(match<scfg.total_faddrs) {
3400: printf("Unknown user");
3401: if(cfg.log&LOG_UNKNOWN)
3402: lprintf(LOG_WARNING,"%s Unknown user",info);
3403: }
3404:
3405: if(!path[0]) {
3406: printf(" - ");
3407: pkt_to_msg(fidomsg,&hdr,info);
3408: }
3409: return(2);
3410: }
3411: }
3412:
3413: /*********************/
3414: /* Importing NetMail */
3415: /*********************/
3416:
3417: fmsgbuf=getfmsg(fidomsg,&length);
3418:
3419: switch(i=fmsgtosmsg(fmsgbuf,hdr,usernumber,INVALID_SUB)) {
3420: case 0: /* success */
3421: break;
3422: case 2: /* filtered */
3423: if(cfg.log&LOG_IGNORED)
3424: lprintf(LOG_WARNING,"%s Filtered - Ignored",info);
3425: break;
3426: case 3: /* empty */
3427: if(cfg.log&LOG_IGNORED)
3428: lprintf(LOG_WARNING,"%s Empty - Ignored",info);
3429: break;
3430: default:
3431: lprintf(LOG_ERR,"ERROR (%d) Importing %s",i,info);
3432: break;
3433: }
3434: if(i) {
3435: if(fmsgbuf)
3436: free(fmsgbuf);
3437: return(0);
3438: }
3439:
3440: addr.zone=hdr.origzone;
3441: addr.net=hdr.orignet;
3442: addr.node=hdr.orignode;
3443: addr.point=hdr.origpoint;
3444: sprintf(str,"\7\1n\1hSBBSecho: \1m%.*s \1n\1msent you NetMail from \1h%s\1n\r\n"
3445: ,FIDO_NAME_LEN-1
3446: ,hdr.from
3447: ,smb_faddrtoa(&addr,NULL));
3448: putsmsg(&scfg,usernumber,str);
3449:
3450: if(hdr.attr&FIDO_FILE) { /* File attachment */
3451: strcpy(subj,hdr.subj);
3452: tp=subj;
3453: while(1) {
3454: p=strchr(tp,' ');
3455: if(p) *p=0;
3456: sp=strrchr(tp,'/'); /* sp is slash pointer */
3457: if(!sp) sp=strrchr(tp,'\\');
3458: if(sp) tp=sp+1;
3459: sprintf(str,"%s%s",secure ? cfg.secure : cfg.inbound,tp);
3460: sprintf(tmp,"%sfile/%04u.in",scfg.data_dir,usernumber);
3461: MKDIR(tmp);
3462: backslash(tmp);
3463: strcat(tmp,tp);
3464: mv(str,tmp,0);
3465: if(!p)
3466: break;
3467: tp=p+1; } }
3468: netmail++;
3469:
3470: if(fmsgbuf)
3471: free(fmsgbuf);
3472:
3473: /***************************/
3474: /* Updating message header */
3475: /***************************/
3476: /*** NOT packet compatible
3477: if(!(misc&DONT_SET_RECV)) {
3478: hdr.attr|=FIDO_RECV;
3479: fseek(fidomsg,0L,SEEK_SET);
3480: fwrite(&hdr,sizeof(fmsghdr_t),1,fidomsg); }
3481: ***/
3482: if(cfg.log&LOG_IMPORTED)
3483: lprintf(LOG_INFO,"%s Imported",info);
3484: return(0);
3485: }
3486:
3487: /******************************************************************************
3488: This is where we export echomail. This was separated from function main so
3489: it could be used for the remote rescan function. Passing anything but an
3490: empty address as 'addr' designates that a rescan should be done for that
3491: address.
3492: ******************************************************************************/
3493: void export_echomail(char *sub_code,faddr_t addr)
3494: {
3495: char str[1025],tear,cr;
3496: char* buf=NULL;
3497: char* minus;
3498: uchar* fmsgbuf=NULL;
3499: ulong fmsgbuflen;
3500: int tzone;
3501: int g,i,j,k=0,file;
3502: ulong f,l,m,exp,ptr,msgs,lastmsg,posts,exported=0;
3503: float export_time;
3504: smbmsg_t msg;
3505: smbmsg_t orig_msg;
3506: fmsghdr_t hdr;
3507: struct tm *tm;
3508: faddr_t pkt_faddr;
3509: post_t *post;
3510: areasbbs_t fakearea;
3511: addrlist_t msg_seen,msg_path;
3512: clock_t start_tick=0,export_ticks=0;
3513:
3514: memset(&msg_seen,0,sizeof(addrlist_t));
3515: memset(&msg_path,0,sizeof(addrlist_t));
3516: memset(&fakearea,0,sizeof(areasbbs_t));
3517: memset(&pkt_faddr,0,sizeof(faddr_t));
3518: memset(&hdr,0,sizeof(hdr));
3519: start_tick=0;
3520:
3521: lprintf(LOG_DEBUG,"\nScanning for Outbound EchoMail...");
3522:
3523: for(g=0;g<scfg.total_grps;g++)
3524: for(i=0;i<scfg.total_subs;i++)
3525: if(scfg.sub[i]->misc&SUB_FIDO && scfg.sub[i]->grp==g) {
3526: for(j=0;j<cfg.areas;j++) /* Skip areas with no uplinks */
3527: if(cfg.area[j].sub==i)
3528: break;
3529: if(j==cfg.areas || (j<cfg.areas && !cfg.area[j].uplinks))
3530: continue;
3531: if(addr.zone) { /* Skip areas not meant for this address */
3532: if(j<cfg.areas)
3533: for(k=0;k<cfg.area[j].uplinks;k++)
3534: if(!memcmp(&cfg.area[j].uplink[k],&addr,sizeof(faddr_t)))
3535: break;
3536: if(k==cfg.area[j].uplinks)
3537: continue; }
3538: if(sub_code[0] && stricmp(sub_code,scfg.sub[i]->code))
3539: continue;
3540: lprintf(LOG_DEBUG,"\nScanning %-15.15s %s"
3541: ,scfg.grp[scfg.sub[i]->grp]->sname,scfg.sub[i]->lname);
3542: ptr=0;
3543: if(!addr.zone && !(misc&IGNORE_MSGPTRS)) {
3544: sprintf(str,"%s%s.sfp",scfg.sub[i]->data_dir,scfg.sub[i]->code);
3545: if((file=nopen(str,O_RDONLY))!=-1) {
3546: read(file,&ptr,sizeof(time_t));
3547: close(file); } }
3548:
3549: msgs=getlastmsg(i,&lastmsg,0);
3550: if(!msgs || (!addr.zone && !(misc&IGNORE_MSGPTRS) && ptr>=lastmsg)) {
3551: lprintf(LOG_INFO,"No new messages.");
3552: if(ptr>lastmsg && !addr.zone && !(misc&LEAVE_MSGPTRS)) {
3553: lprintf(LOG_DEBUG,"Fixing new-scan pointer.");
3554: sprintf(str,"%s%s.sfp",scfg.sub[i]->data_dir,scfg.sub[i]->code);
3555: if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
3556: lprintf(LOG_ERR,"ERROR %d line %d opening/creating %s"
3557: ,errno,__LINE__,str); }
3558: else {
3559: write(file,&lastmsg,4);
3560: close(file); } }
3561: continue; }
3562:
3563: sprintf(smb[cur_smb].file,"%s%s"
3564: ,scfg.sub[i]->data_dir,scfg.sub[i]->code);
3565: smb[cur_smb].retry_time=scfg.smb_retry_time;
3566: if((j=smb_open(&smb[cur_smb]))!=SMB_SUCCESS) {
3567: lprintf(LOG_ERR,"ERROR %d line %d opening %s",j,__LINE__
3568: ,smb[cur_smb].file);
3569: continue; }
3570:
3571: post=NULL;
3572: posts=loadmsgs(&post,ptr);
3573:
3574: if(!posts) { /* no new messages */
3575: smb_close(&smb[cur_smb]);
3576: FREE_AND_NULL(post);
3577: continue;
3578: }
3579:
3580: if(start_tick)
3581: export_ticks+=msclock()-start_tick;
3582: start_tick=msclock();
3583:
3584: for(m=exp=0;m<posts;m++) {
3585: printf("\r%8s %5lu of %-5lu "
3586: ,scfg.sub[i]->code,m+1,posts);
3587: memset(&msg,0,sizeof(msg));
3588: msg.idx=post[m];
3589: if((k=smb_lockmsghdr(&smb[cur_smb],&msg))!=SMB_SUCCESS) {
3590: lprintf(LOG_ERR,"ERROR %d line %d locking %s msghdr"
3591: ,k,__LINE__,smb[cur_smb].file);
3592: continue;
3593: }
3594: k=smb_getmsghdr(&smb[cur_smb],&msg);
3595: if(k || msg.hdr.number!=post[m].number) {
3596: smb_unlockmsghdr(&smb[cur_smb],&msg);
3597: smb_freemsgmem(&msg);
3598:
3599: msg.hdr.number=post[m].number;
3600: if((k=smb_getmsgidx(&smb[cur_smb],&msg))!=SMB_SUCCESS) {
3601: lprintf(LOG_ERR,"ERROR %d line %d reading %s index",k,__LINE__
3602: ,smb[cur_smb].file);
3603: continue; }
3604: if((k=smb_lockmsghdr(&smb[cur_smb],&msg))!=SMB_SUCCESS) {
3605: lprintf(LOG_ERR,"ERROR %d line %d locking %s msghdr",k,__LINE__
3606: ,smb[cur_smb].file);
3607: continue; }
3608: if((k=smb_getmsghdr(&smb[cur_smb],&msg))!=SMB_SUCCESS) {
3609: smb_unlockmsghdr(&smb[cur_smb],&msg);
3610: lprintf(LOG_ERR,"ERROR %d line %d reading %s msghdr",k,__LINE__
3611: ,smb[cur_smb].file);
3612: continue; } }
3613:
3614: if((!addr.zone && !(misc&EXPORT_ALL)
3615: && (msg.from_net.type==NET_FIDO || msg.from_net.type==NET_FIDO_ASCII))
3616: || !strnicmp(msg.subj,"NE:",3)) { /* no echo */
3617: smb_unlockmsghdr(&smb[cur_smb],&msg);
3618: smb_freemsgmem(&msg);
3619: continue; } /* From a Fido node, ignore it */
3620:
3621: if(msg.from_net.type!=NET_NONE
3622: && msg.from_net.type!=NET_FIDO
3623: && msg.from_net.type!=NET_FIDO_ASCII
3624: && !(scfg.sub[i]->misc&SUB_GATE)) {
3625: smb_unlockmsghdr(&smb[cur_smb],&msg);
3626: smb_freemsgmem(&msg);
3627: continue; }
3628:
3629: memset(&hdr,0,sizeof(fmsghdr_t)); /* Zero the header */
3630: hdr.origzone=scfg.sub[i]->faddr.zone;
3631: hdr.orignet=scfg.sub[i]->faddr.net;
3632: hdr.orignode=scfg.sub[i]->faddr.node;
3633: hdr.origpoint=scfg.sub[i]->faddr.point;
3634:
3635: hdr.attr=FIDO_LOCAL;
3636: if(msg.hdr.attr&MSG_PRIVATE)
3637: hdr.attr|=FIDO_PRIVATE;
3638:
3639: SAFECOPY(hdr.from,msg.from);
3640:
3641: tm=localtime((time_t *)&msg.hdr.when_written.time);
3642: sprintf(hdr.time,"%02u %3.3s %02u %02u:%02u:%02u"
3643: ,tm->tm_mday,mon[tm->tm_mon],TM_YEAR(tm->tm_year)
3644: ,tm->tm_hour,tm->tm_min,tm->tm_sec);
3645:
3646: SAFECOPY(hdr.to,msg.to);
3647:
3648: SAFECOPY(hdr.subj,msg.subj);
3649:
3650: buf=smb_getmsgtxt(&smb[cur_smb],&msg,GETMSGTXT_ALL);
3651: if(!buf) {
3652: smb_unlockmsghdr(&smb[cur_smb],&msg);
3653: smb_freemsgmem(&msg);
3654: continue;
3655: }
3656: fmsgbuflen=strlen((char *)buf)+4096; /* over alloc for kludge lines */
3657: fmsgbuf=malloc(fmsgbuflen);
3658: if(!fmsgbuf) {
3659: lprintf(LOG_ERR,"ERROR line %d allocating %lu bytes for fmsgbuf"
3660: ,__LINE__,fmsgbuflen);
3661: smb_unlockmsghdr(&smb[cur_smb],&msg);
3662: smb_freemsgmem(&msg);
3663: continue;
3664: }
3665: fmsgbuflen-=1024; /* give us a bit of a guard band here */
3666:
3667: tear=0;
3668: f=0;
3669:
3670: tzone=smb_tzutc(msg.hdr.when_written.zone);
3671: if(tzone<0) {
3672: minus="-";
3673: tzone=-tzone;
3674: } else
3675: minus="";
3676: f+=sprintf(fmsgbuf+f,"\1TZUTC: %s%02d%02u\r" /* TZUTC (FSP-1001) */
3677: ,minus,tzone/60,tzone%60);
3678:
3679: if(msg.ftn_flags!=NULL)
3680: f+=sprintf(fmsgbuf+f,"\1FLAGS %.256s\r", msg.ftn_flags);
3681:
3682: f+=sprintf(fmsgbuf+f,"\1MSGID: %.256s\r"
3683: ,ftn_msgid(scfg.sub[i],&msg));
3684:
3685: if(msg.ftn_reply!=NULL) /* use original REPLYID */
3686: f+=sprintf(fmsgbuf+f,"\1REPLY: %.256s\r", msg.ftn_reply);
3687: else if(msg.hdr.thread_back) { /* generate REPLYID */
3688: memset(&orig_msg,0,sizeof(orig_msg));
3689: orig_msg.hdr.number=msg.hdr.thread_back;
3690: if(smb_getmsgidx(&smb[cur_smb], &orig_msg))
3691: f+=sprintf(fmsgbuf+f,"\1REPLY: <%s>\r",smb[cur_smb].last_error);
3692: else {
3693: smb_lockmsghdr(&smb[cur_smb],&orig_msg);
3694: smb_getmsghdr(&smb[cur_smb],&orig_msg);
3695: smb_unlockmsghdr(&smb[cur_smb],&orig_msg);
3696: f+=sprintf(fmsgbuf+f,"\1REPLY: %.256s\r"
3697: ,ftn_msgid(scfg.sub[i],&orig_msg));
3698: }
3699: }
3700: if(msg.ftn_pid!=NULL) /* use original PID */
3701: f+=sprintf(fmsgbuf+f,"\1PID: %.256s\r", msg.ftn_pid);
3702: if(msg.ftn_tid!=NULL) /* use original TID */
3703: f+=sprintf(fmsgbuf+f,"\1TID: %.256s\r", msg.ftn_tid);
3704: else /* generate TID */
3705: f+=sprintf(fmsgbuf+f,"\1TID: SBBSecho %s-%s r%s %s %s\r"
3706: ,SBBSECHO_VER,PLATFORM_DESC,revision,__DATE__,compiler);
3707:
3708: /* Unknown kludge lines are added here */
3709: for(l=0;l<msg.total_hfields && f<fmsgbuflen;l++)
3710: if(msg.hfield[l].type == FIDOCTRL)
3711: f+=sprintf(fmsgbuf+f,"\1%.512s\r",(char*)msg.hfield_dat[l]);
3712:
3713: for(l=0,cr=1;buf[l] && f<fmsgbuflen;l++) {
3714: if(buf[l]==1) { /* Ctrl-A, so skip it and the next char */
3715: l++;
3716: if(!buf[l])
3717: break;
3718: continue; }
3719:
3720: if(misc&STRIP_LF && buf[l]=='\n') /* Ignore line feeds */
3721: continue;
3722:
3723: if(cr) {
3724: if(buf[l]=='-' && buf[l+1]=='-'
3725: && buf[l+2]=='-'
3726: && (buf[l+3]==' ' || buf[l+3]=='\r')) {
3727: if(misc&CONVERT_TEAR) /* Convert to === */
3728: buf[l]=buf[l+1]=buf[l+2]='=';
3729: else
3730: tear=1; }
3731: else if(!strncmp((char *)buf+l," * Origin: ",11))
3732: buf[l+1]='#'; } /* Convert * Origin into # Origin */
3733:
3734: if(buf[l]=='\r')
3735: cr=1;
3736: else
3737: cr=0;
3738: if(scfg.sub[i]->misc&SUB_ASCII || misc&ASCII_ONLY) {
3739: if(buf[l]<' ' && buf[l]!='\r'
3740: && buf[l]!='\n') /* Ctrl ascii */
3741: buf[l]='.'; /* converted to '.' */
3742: if((uchar)buf[l]>0x7f) /* extended ASCII */
3743: buf[l]='*'; } /* converted to '*' */
3744:
3745: fmsgbuf[f++]=buf[l]; }
3746:
3747: FREE_AND_NULL(buf);
3748: fmsgbuf[f]=0;
3749:
3750: if(!(scfg.sub[i]->misc&SUB_NOTAG)) {
3751: if(!tear) { /* No previous tear line */
3752: sprintf(str,"--- SBBSecho %s-%s\r"
3753: ,SBBSECHO_VER,PLATFORM_DESC);
3754: strcat((char *)fmsgbuf,str); }
3755:
3756: sprintf(str," * Origin: %s (%s)\r"
3757: ,scfg.sub[i]->origline[0] ? scfg.sub[i]->origline : scfg.origline
3758: ,smb_faddrtoa(&scfg.sub[i]->faddr,NULL));
3759: strcat((char *)fmsgbuf,str); }
3760:
3761: for(k=0;k<cfg.areas;k++)
3762: if(cfg.area[k].sub==i) {
3763: cfg.area[k].exported++;
3764: pkt_to_pkt(fmsgbuf,cfg.area[k]
3765: ,(addr.zone) ? addr:pkt_faddr,hdr,msg_seen
3766: ,msg_path,(addr.zone) ? 2:0);
3767: break; }
3768: FREE_AND_NULL(fmsgbuf);
3769: exported++;
3770: exp++;
3771: printf("Exp: %lu ",exp);
3772: smb_unlockmsghdr(&smb[cur_smb],&msg);
3773: smb_freemsgmem(&msg); }
3774:
3775: smb_close(&smb[cur_smb]);
3776: FREE_AND_NULL(post);
3777:
3778: /***********************/
3779: /* Update FIDO_PTR.DAB */
3780: /***********************/
3781: if(!addr.zone && !(misc&LEAVE_MSGPTRS) && lastmsg>ptr) {
3782: sprintf(str,"%s%s.sfp",scfg.sub[i]->data_dir,scfg.sub[i]->code);
3783: if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
3784: lprintf(LOG_ERR,"ERROR %d line %d opening/creating %s"
3785: ,errno,__LINE__,str); }
3786: else {
3787: write(file,&lastmsg,4);
3788: close(file); } } }
3789:
3790: printf("\n");
3791: if(start_tick) /* Last possible increment of export_ticks */
3792: export_ticks+=msclock()-start_tick;
3793:
3794: pkt_to_pkt(buf,fakearea,pkt_faddr,hdr,msg_seen,msg_path,1);
3795:
3796: if(!addr.zone && cfg.log&LOG_AREA_TOTALS && exported)
3797: for(i=0;i<cfg.areas;i++)
3798: if(cfg.area[i].exported)
3799: lprintf(LOG_INFO,"Exported: %5u msgs %8s -> %s"
3800: ,cfg.area[i].exported,scfg.sub[cfg.area[i].sub]->code
3801: ,cfg.area[i].name);
3802:
3803: export_time=((float)export_ticks)/(float)MSCLOCKS_PER_SEC;
3804: if(cfg.log&LOG_TOTALS && exported && export_time) {
3805: lprintf(LOG_INFO,"Exported: %5lu msgs in %.1f sec (%.1f/min %.1f/sec)"
3806: ,exported,export_time
3807: ,export_time/60.0 ? (float)exported/(export_time/60.0) :(float)exported
3808: ,(float)exported/export_time);
3809: }
3810: }
3811:
3812: char* freadstr(FILE* fp, char* str, size_t maxlen)
3813: {
3814: int ch;
3815: size_t rd=0;
3816: size_t len=0;
3817:
3818: memset(str,0,maxlen); /* pre-terminate */
3819:
3820: while(rd<maxlen && (ch=fgetc(fp))!=EOF) {
3821: if(ch==0)
3822: break;
3823: if((uchar)ch>=' ') /* not a ctrl char (garbage?) */
3824: str[len++]=ch;
3825: rd++;
3826: }
3827:
3828: str[maxlen-1]=0; /* Force terminator */
3829:
3830: return(str);
3831: }
3832:
3833: /***********************************/
3834: /* Synchronet/FidoNet Message util */
3835: /***********************************/
3836: int main(int argc, char **argv)
3837: {
3838: FILE* fidomsg;
3839: char packet[MAX_PATH+1];
3840: char ch,str[1025],fname[MAX_PATH+1],path[MAX_PATH+1]
3841: ,sub_code[LEN_EXTCODE+1]
3842: ,*p,*tp
3843: ,areatagstr[128],outbound[128]
3844: ,password[16];
3845: uchar *fmsgbuf=NULL;
3846: ushort attr;
3847: int i,j,k,file,fmsg,grp,node;
3848: BOOL grunged;
3849: uint subnum[MAX_OPEN_SMBS]={INVALID_SUB};
3850: ulong echomail=0,l,m/* f, */,areatag;
3851: time_t now;
3852: time_t ftime;
3853: float import_time;
3854: clock_t start_tick=0,import_ticks=0;
3855: struct tm *tm;
3856: size_t f;
3857: glob_t g;
3858: size_t offset;
3859: fmsghdr_t hdr;
3860: fpkdmsg_t pkdmsg;
3861: faddr_t addr,pkt_faddr;
3862: FILE *stream;
3863: pkthdr_t pkthdr;
3864: addrlist_t msg_seen,msg_path;
3865: areasbbs_t fakearea,curarea;
3866: char *usage="\n"
3867: "usage: sbbsecho [cfg_file] [-switches] [sub_code]\n"
3868: "\n"
3869: "where: cfg_file is the filename of config file (default is ctrl/sbbsecho.cfg)\n"
3870: " sub_code is the internal code for a sub-board (default is ALL subs)\n"
3871: "\n"
3872: "valid switches:\n"
3873: "\n"
3874: "p: do not import packets x: do not delete packets after import\n"
3875: "n: do not import netmail d: do not delete netmail after import\n"
3876: "i: do not import echomail e: do not export echomail\n"
3877: "m: ignore echomail ptrs (export all) u: update echomail ptrs (export none)\n"
3878: "j: ignore recieved bit on netmail t: do not update echomail ptrs\n"
3879: "l: create log file (data/sbbsecho.log) r: create report of import totals\n"
3880: "h: export all echomail (hub rescan) b: import locally created netmail too\n"
3881: "a: export ASCII characters only f: create packets for outbound netmail\n"
3882: "g: generate notify lists =: change existing tear lines to ===\n"
3883: "y: import netmail for unknown users to sysop\n"
3884: "o: import all netmail regardless of destination address\n"
3885: "s: import private echomail override (strip private status)\n"
3886: "!: notify users of received echomail @: prompt for key upon exiting (debug)\n";
3887:
3888: if((email=(smb_t *)malloc(sizeof(smb_t)))==NULL) {
3889: printf("ERROR allocating memory for email.\n");
3890: bail(1); }
3891: memset(email,0,sizeof(smb_t));
3892: if((smb=(smb_t *)malloc(MAX_OPEN_SMBS*sizeof(smb_t)))==NULL) {
3893: printf("ERROR allocating memory for smbs.\n");
3894: bail(1); }
3895: for(i=0;i<MAX_OPEN_SMBS;i++)
3896: memset(&smb[i],0,sizeof(smb_t));
3897: memset(&cfg,0,sizeof(config_t));
3898: memset(&hdr,0,sizeof(hdr));
3899: memset(&pkt_faddr,0,sizeof(pkt_faddr));
3900: memset(&msg_seen,0,sizeof(addrlist_t));
3901: memset(&msg_path,0,sizeof(addrlist_t));
3902: memset(&fakearea,0,sizeof(areasbbs_t));
3903:
3904: sscanf("$Revision: 1.182 $", "%*s %s", revision);
3905:
3906: DESCRIBE_COMPILER(compiler);
3907:
3908: printf("\nSBBSecho v%s-%s (rev %s) - Synchronet FidoNet Packet "
3909: "Tosser\n"
3910: ,SBBSECHO_VER
3911: ,PLATFORM_DESC
3912: ,revision
3913: );
3914:
3915: putenv("TMP=");
3916: setvbuf(stdout,NULL,_IONBF,0);
3917:
3918: sub_code[0]=0;
3919:
3920: for(i=1;i<argc;i++) {
3921: if(argv[i][0]=='-'
3922: #if !defined(__unix__)
3923: || argv[i][0]=='/'
3924: #endif
3925: ) {
3926: j=1;
3927: while(argv[i][j]) {
3928: switch(toupper(argv[i][j])) {
3929: case 'A':
3930: misc|=ASCII_ONLY;
3931: break;
3932: case 'B':
3933: misc|=LOCAL_NETMAIL;
3934: break;
3935: case 'D':
3936: misc&=~DELETE_NETMAIL;
3937: break;
3938: case 'E':
3939: misc&=~EXPORT_ECHOMAIL;
3940: break;
3941: case 'F':
3942: misc|=PACK_NETMAIL;
3943: break;
3944: case 'G':
3945: misc|=GEN_NOTIFY_LIST;
3946: break;
3947: case 'H':
3948: misc|=EXPORT_ALL;
3949: break;
3950: case 'I':
3951: misc&=~IMPORT_ECHOMAIL;
3952: break;
3953: case 'J':
3954: misc|=IGNORE_RECV;
3955: break;
3956: case 'L':
3957: misc|=LOGFILE;
3958: break;
3959: case 'M':
3960: misc|=IGNORE_MSGPTRS;
3961: break;
3962: case 'N':
3963: misc&=~IMPORT_NETMAIL;
3964: break;
3965: case 'O':
3966: misc|=IGNORE_ADDRESS;
3967: break;
3968: case 'P':
3969: misc&=~IMPORT_PACKETS;
3970: break;
3971: case 'R':
3972: misc|=REPORT;
3973: break;
3974: case 'S':
3975: misc|=IMPORT_PRIVATE;
3976: break;
3977: case 'T':
3978: misc|=LEAVE_MSGPTRS;
3979: break;
3980: case 'U':
3981: misc|=UPDATE_MSGPTRS;
3982: misc&=~EXPORT_ECHOMAIL;
3983: break;
3984: case 'X':
3985: misc&=~DELETE_PACKETS;
3986: break;
3987: case 'Y':
3988: misc|=UNKNOWN_NETMAIL;
3989: break;
3990: case '=':
3991: misc|=CONVERT_TEAR;
3992: break;
3993: case '!':
3994: misc|=NOTIFY_RECEIPT;
3995: break;
3996: case '@':
3997: pause_on_exit=TRUE;
3998: break;
3999: case 'Q':
4000: bail(0);
4001: default:
4002: printf(usage);
4003: bail(0); }
4004: j++; } }
4005: else {
4006: if(strchr(argv[i],'\\') || strchr(argv[i],'/')
4007: || argv[i][1]==':' || strchr(argv[i],'.'))
4008: SAFECOPY(cfg.cfgfile,argv[i]);
4009: else
4010: SAFECOPY(sub_code,argv[i]); } }
4011:
4012: if(!(misc&(IMPORT_NETMAIL|IMPORT_ECHOMAIL)))
4013: misc&=~IMPORT_PACKETS;
4014:
4015: p=getenv("SBBSCTRL");
4016: if(p==NULL) {
4017: printf("\7\nSBBSCTRL environment variable not set.\n");
4018: bail(1); }
4019: SAFECOPY(scfg.ctrl_dir,p);
4020:
4021: if(chdir(scfg.ctrl_dir)!=0)
4022: printf("!ERROR changing directory to: %s", scfg.ctrl_dir);
4023:
4024: printf("\nLoading configuration files from %s\n", scfg.ctrl_dir);
4025: scfg.size=sizeof(scfg);
4026: SAFECOPY(str,UNKNOWN_LOAD_ERROR);
4027: if(!load_cfg(&scfg, NULL, TRUE, str)) {
4028: fprintf(stderr,"!ERROR %s\n",str);
4029: fprintf(stderr,"!Failed to load configuration files\n");
4030: bail(1);
4031: }
4032:
4033: sprintf(str,"%stwitlist.cfg",scfg.ctrl_dir);
4034: twit_list=fexist(str);
4035:
4036: if(scfg.total_faddrs)
4037: sys_faddr=scfg.faddr[0];
4038:
4039: if(!cfg.cfgfile[0])
4040: sprintf(cfg.cfgfile,"%ssbbsecho.cfg",scfg.ctrl_dir);
4041: strcpy(cfg.inbound,scfg.fidofile_dir);
4042: sprintf(cfg.areafile,"%sareas.bbs",scfg.data_dir);
4043: sprintf(cfg.logfile,"%ssbbsecho.log",scfg.logs_dir);
4044:
4045: read_echo_cfg();
4046:
4047: if(misc&LOGFILE)
4048: if((fidologfile=fopen(cfg.logfile,"a"))==NULL) {
4049: fprintf(stderr,"\7ERROR line %d opening %s\n",__LINE__,cfg.logfile);
4050: bail(1);
4051: }
4052:
4053: /******* READ IN AREAS.BBS FILE *********/
4054:
4055: printf("Reading %s",cfg.areafile);
4056: if((stream=fopen(cfg.areafile,"r"))==NULL) {
4057: fprintf(stderr,"\nError opening %s for read: %s\n"
4058: ,cfg.areafile,strerror(errno));
4059: bail(1); }
4060: cfg.areas=0; /* Total number of areas in AREAS.BBS */
4061: cfg.area=NULL;
4062: while(1) {
4063: if(!fgets(str,sizeof(str),stream))
4064: break;
4065: truncsp(str);
4066: p=str;
4067: SKIP_WHITESPACE(p); /* Find first printable char */
4068: if(*p==';' || !*p) /* Ignore blank lines or start with ; */
4069: continue;
4070: if((cfg.area=(areasbbs_t *)realloc(cfg.area,sizeof(areasbbs_t)*
4071: (cfg.areas+1)))==NULL) {
4072: fprintf(stderr,"ERROR allocating memory for area #%u.\n",cfg.areas+1);
4073: bail(1); }
4074: memset(&cfg.area[cfg.areas],0,sizeof(areasbbs_t));
4075:
4076: cfg.area[cfg.areas].sub=INVALID_SUB; /* Default to passthru */
4077:
4078: sprintf(tmp,"%-.*s",LEN_EXTCODE,p);
4079: tp=tmp;
4080: FIND_WHITESPACE(tp);
4081: *tp=0;
4082: for(i=0;i<scfg.total_subs;i++)
4083: if(!stricmp(tmp,scfg.sub[i]->code))
4084: break;
4085: if(i<scfg.total_subs)
4086: cfg.area[cfg.areas].sub=i;
4087: else if(stricmp(tmp,"P")) {
4088: lprintf(LOG_WARNING,"%s: Unrecognized internal code, assumed passthru",tmp);
4089: }
4090:
4091: FIND_WHITESPACE(p); /* Skip code */
4092: SKIP_WHITESPACE(p); /* Skip white space */
4093: sprintf(tmp,"%-.50s",p); /* Area tag */
4094: truncstr(tmp,"\t ");
4095: strupr(tmp);
4096: if(tmp[0]=='*') /* UNKNOWN-ECHO area */
4097: cfg.badecho=cfg.areas;
4098: if((cfg.area[cfg.areas].name=(char *)malloc(strlen(tmp)+1))==NULL) {
4099: fprintf(stderr,"ERROR allocating memory for area #%u tag name.\n"
4100: ,cfg.areas+1);
4101: bail(1); }
4102: strcpy(cfg.area[cfg.areas].name,tmp);
4103: strupr(tmp);
4104: cfg.area[cfg.areas].tag=crc32(tmp,0);
4105:
4106: FIND_WHITESPACE(p); /* Skip tag */
4107: SKIP_WHITESPACE(p); /* Skip white space */
4108:
4109: while(*p && *p!=';') {
4110: if((cfg.area[cfg.areas].uplink=(faddr_t *)
4111: realloc(cfg.area[cfg.areas].uplink
4112: ,sizeof(faddr_t)*(cfg.area[cfg.areas].uplinks+1)))==NULL) {
4113: fprintf(stderr,"ERROR allocating memory for area #%u uplinks.\n"
4114: ,cfg.areas+1);
4115: bail(1); }
4116: cfg.area[cfg.areas].uplink[cfg.area[cfg.areas].uplinks]=atofaddr(p);
4117: FIND_WHITESPACE(p); /* Skip address */
4118: SKIP_WHITESPACE(p); /* Skip white space */
4119: cfg.area[cfg.areas].uplinks++; }
4120:
4121: if(cfg.area[cfg.areas].sub!=INVALID_SUB || cfg.area[cfg.areas].uplinks)
4122: cfg.areas++; /* Don't allocate if no tossing */
4123: }
4124: fclose(stream);
4125:
4126: printf("\n");
4127:
4128: if(!cfg.areas) {
4129: lprintf(LOG_WARNING,"No areas defined!");
4130: bail(1);
4131: }
4132:
4133: #if 0 /* AREAS.BBS DEBUG */
4134: for(i=0;i<cfg.areas;i++) {
4135: printf("%4u: %-8s"
4136: ,i+1
4137: ,cfg.area[i].sub==INVALID_SUB ? "Passthru" :
4138: scfg.sub[cfg.area[i].sub]->code);
4139: for(j=0;j<cfg.area[i].uplinks;j++)
4140: printf(" %s",smb_faddrtoa(&cfg.area[i].uplink[j],NULL));
4141: printf("\n"); }
4142: #endif
4143:
4144: if(misc&GEN_NOTIFY_LIST) {
4145: lprintf(LOG_DEBUG,"\nGenerating Notify Lists...");
4146: notify_list();
4147: }
4148:
4149: /* Find any packets that have been left behind in the OUTBOUND directory */
4150: now=time(NULL);
4151: lprintf(LOG_DEBUG,"\nScanning for Stray Outbound Packets...");
4152: sprintf(path,"%s*.pk_",cfg.outbound);
4153: glob(path,0,NULL,&g);
4154: for(f=0;f<g.gl_pathc && !kbhit();f++) {
4155:
4156: strcpy(packet,(char*)g.gl_pathv[f]);
4157:
4158: lprintf(LOG_DEBUG,"%21s: %s ","Outbound Packet",packet);
4159: if((fmsg=sopen(packet,O_RDWR|O_BINARY,SH_DENYRW))==-1) {
4160: lprintf(LOG_ERR,"ERROR line %d opening %s",__LINE__,packet);
4161: continue; }
4162: if((fidomsg=fdopen(fmsg,"r+b"))==NULL) {
4163: close(fmsg);
4164: lprintf(LOG_ERR,"ERROR line %d fdopening %s",__LINE__,packet);
4165: continue; }
4166: if(filelength(fmsg)<sizeof(pkthdr_t)) {
4167: lprintf(LOG_ERR,"ERROR line %d invalid length of %lu bytes for %s"
4168: ,__LINE__,filelength(fmsg),packet);
4169: fclose(fidomsg);
4170: if(delfile(packet))
4171: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,packet
4172: ,strerror(errno));
4173: continue; }
4174: if(fread(&pkthdr,sizeof(pkthdr_t),1,fidomsg)!=1) {
4175: fclose(fidomsg);
4176: lprintf(LOG_ERR,"ERROR line %d reading %u bytes from %s",__LINE__
4177: ,sizeof(pkthdr_t),packet);
4178: continue; }
4179: ftime=fdate(packet);
4180: if((ftime+(60L*60L))<=now) {
4181: fseek(fidomsg,-3L,SEEK_END);
4182: fread(str,3,1,fidomsg);
4183: if(str[2]) /* No ending NULL, probably junk */
4184: fputc(FIDO_PACKED_MSG_TERMINATOR,fidomsg);
4185: if(str[1])
4186: fputc(FIDO_PACKED_MSG_TERMINATOR,fidomsg);
4187: if(str[0])
4188: fputc(FIDO_PACKED_MSG_TERMINATOR,fidomsg);
4189: fclose(fidomsg);
4190: pkt_faddr.zone=pkthdr.destzone;
4191: pkt_faddr.net=pkthdr.destnet;
4192: pkt_faddr.node=pkthdr.destnode;
4193: pkt_faddr.point=0; /* No point info in the 2.0 hdr! */
4194: memcpy(&two_plus,&pkthdr.empty,sizeof(two_plus));
4195: if(two_plus.cword==_rotr(two_plus.cwcopy,8) /* 2+ Packet Header */
4196: && two_plus.cword && two_plus.cword&1)
4197: pkt_faddr.point=two_plus.destpoint;
4198: else if(pkthdr.baud==2) { /* Type 2.2 Packet Header */
4199: memcpy(&two_two,&pkthdr.empty,sizeof(two_two));
4200: pkt_faddr.point=pkthdr.month; }
4201: lprintf(LOG_DEBUG,"Sending to %s",smb_faddrtoa(&pkt_faddr,NULL));
4202: pack_bundle(packet,pkt_faddr); }
4203: else {
4204: fclose(fidomsg);
4205: lprintf(LOG_WARNING,"Stray Outbound Packet (%s) possibly still in use (ftime: %.24s)"
4206: ,packet,ctime(&ftime));
4207: }
4208: }
4209: globfree(&g);
4210:
4211: if(misc&IMPORT_PACKETS) {
4212:
4213: lprintf(LOG_DEBUG,"\nScanning for Inbound Packets...");
4214:
4215: /* We want to loop while there are bundles waiting for us, but first we want */
4216: /* to take care of any packets that may already be hanging around for some */
4217: /* reason or another (thus the do/while loop) */
4218:
4219: echomail=0;
4220: for(secure=0;secure<2;secure++) {
4221: if(secure && !cfg.secure[0])
4222: break;
4223: do {
4224: /****** START OF IMPORT PKT ROUTINE ******/
4225:
4226: offset=strlen(secure ? cfg.secure : cfg.inbound);
4227: #ifdef __unix__
4228: sprintf(path,"%s*.[Pp][Kk][Tt]",secure ? cfg.secure : cfg.inbound);
4229: #else
4230: sprintf(path,"%s*.pkt",secure ? cfg.secure : cfg.inbound);
4231: #endif
4232: glob(path,0,NULL,&g);
4233: for(f=0;f<g.gl_pathc && !kbhit();f++) {
4234:
4235: strcpy(packet,g.gl_pathv[f]);
4236:
4237: if((fidomsg=fnopen(&fmsg,packet,O_RDWR))==NULL) {
4238: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,packet
4239: ,strerror(errno));
4240: continue;
4241: }
4242: if(filelength(fmsg)<sizeof(pkthdr_t)) {
4243: lprintf(LOG_WARNING,"Invalid length of %s: %lu bytes"
4244: ,fmsg,filelength(fmsg));
4245: fclose(fidomsg);
4246: continue;
4247: }
4248:
4249: fseek(fidomsg,-2L,SEEK_END);
4250: fread(str,2,1,fidomsg);
4251: if((str[0] || str[1]) &&
4252: (fdate(packet)+(48L*60L*60L))<=time(NULL)) {
4253: fclose(fidomsg);
4254: lprintf(LOG_WARNING,"WARNING line %d packet %s not terminated correctly",__LINE__
4255: ,packet);
4256: continue;
4257: }
4258: fseek(fidomsg,0L,SEEK_SET);
4259: if(fread(&pkthdr,sizeof(pkthdr_t),1,fidomsg)!=1) {
4260: fclose(fidomsg);
4261: lprintf(LOG_ERR,"ERROR line %d reading %u bytes from %s",__LINE__
4262: ,sizeof(pkthdr_t),packet);
4263: continue;
4264: }
4265:
4266: pkt_faddr.zone=pkthdr.origzone ? pkthdr.origzone:sys_faddr.zone;
4267: pkt_faddr.net=pkthdr.orignet;
4268: pkt_faddr.node=pkthdr.orignode;
4269: pkt_faddr.point=0;
4270:
4271: printf("%21s: %s "
4272: ,secure ? "Importing Secure Pkt" : "Importing Packet",packet+offset);
4273: memcpy(&two_plus,&pkthdr.empty,sizeof(two_plus));
4274: if(two_plus.cword==_rotr(two_plus.cwcopy,8) /* 2+ Packet Header */
4275: && two_plus.cword && two_plus.cword&1) {
4276: pkt_type=PKT_TWO_PLUS;
4277: pkt_faddr.point=two_plus.origpoint ? two_plus.origpoint:0;
4278: if(pkt_faddr.point && pkthdr.orignet==-1)
4279: pkt_faddr.net=two_plus.auxnet ? two_plus.auxnet:sys_faddr.zone;
4280: printf("(Type 2+)");
4281: if(cfg.log&LOG_PACKETS)
4282: logprintf("Importing %s%s (Type 2+) from %s"
4283: ,secure ? "(secure) ":"",packet+offset,smb_faddrtoa(&pkt_faddr,NULL));
4284: }
4285: else if(pkthdr.baud==2) { /* Type 2.2 Packet Header */
4286: pkt_type=PKT_TWO_TWO;
4287: memcpy(&two_two,&pkthdr.empty,sizeof(two_two));
4288: pkt_faddr.point=pkthdr.year ? pkthdr.year:0;
4289: printf("(Type 2.2)");
4290: if(cfg.log&LOG_PACKETS)
4291: logprintf("Importing %s%s (Type 2.2) from %s"
4292: ,secure ? "(secure) ":"",packet+offset,smb_faddrtoa(&pkt_faddr,NULL));
4293: }
4294: else {
4295: pkt_type=PKT_TWO;
4296: printf("(Type 2)");
4297: if(cfg.log&LOG_PACKETS)
4298: logprintf("Importing %s%s (Type 2) from %s"
4299: ,secure ? "(secure) ":"",packet+offset,smb_faddrtoa(&pkt_faddr,NULL));
4300: }
4301:
4302: printf(" from %s\n",smb_faddrtoa(&pkt_faddr,NULL));
4303:
4304: if(misc&SECURE) {
4305: k=matchnode(pkt_faddr,1);
4306: sprintf(password,"%.*s",FIDO_PASS_LEN,pkthdr.password);
4307: if(k<cfg.nodecfgs && cfg.nodecfg[k].pktpwd[0] &&
4308: stricmp(password,cfg.nodecfg[k].pktpwd)) {
4309: sprintf(str,"Packet %s from %s - "
4310: "Incorrect password ('%s' instead of '%s')"
4311: ,packet+offset,smb_faddrtoa(&pkt_faddr,NULL)
4312: ,password,cfg.nodecfg[k].pktpwd);
4313: printf("Security Violation (Incorrect Password)\n");
4314: if(cfg.log&LOG_SECURE)
4315: logprintf(str);
4316: fclose(fidomsg);
4317: continue;
4318: }
4319: }
4320:
4321: while(!feof(fidomsg)) {
4322:
4323: memset(&hdr,0,sizeof(fmsghdr_t));
4324:
4325: if(start_tick)
4326: import_ticks+=msclock()-start_tick;
4327: start_tick=msclock();
4328:
4329: if(fmsgbuf) {
4330: free(fmsgbuf);
4331: fmsgbuf=0;
4332: }
4333:
4334: grunged=FALSE;
4335:
4336: #if 0 /* Old way */
4337:
4338: if(!fread(&ch,1,1,fidomsg)) /* Message type (0200h) */
4339: break;
4340: if(ch!=02)
4341: continue;
4342: if(!fread(&ch,1,1,fidomsg))
4343: break;
4344: if(ch!=00)
4345: continue;
4346: fread(&hdr.orignode,2,1,fidomsg);
4347: fread(&hdr.destnode,2,1,fidomsg);
4348: fread(&hdr.orignet,2,1,fidomsg);
4349: fread(&hdr.destnet,2,1,fidomsg);
4350: fread(&hdr.attr,2,1,fidomsg);
4351: fread(&hdr.cost,2,1,fidomsg);
4352:
4353: for(i=0;i<sizeof(hdr.time);i++) /* Read in the Date/Time */
4354: if(!fread(hdr.time+i,1,1,fidomsg) || !hdr.time[i])
4355: break;
4356: if(i==sizeof(hdr.time)) grunged=1;
4357:
4358: for(i=0;!grunged && i<sizeof(hdr.to);i++) /* Read in the 'To' Field */
4359: if(!fread(hdr.to+i,1,1,fidomsg) || !hdr.to[i])
4360: break;
4361: if(i==sizeof(hdr.to)) grunged=1;
4362:
4363: for(i=0;!grunged && i<sizeof(hdr.from);i++) /* Read in 'From' Field */
4364: if(!fread(hdr.from+i,1,1,fidomsg) || !hdr.from[i])
4365: break;
4366: if(i==sizeof(hdr.from)) grunged=1;
4367:
4368: for(i=0;!grunged && i<sizeof(hdr.subj);i++) /* Read in 'Subj' Field */
4369: if(!fread(hdr.subj+i,1,1,fidomsg) || !hdr.subj[i])
4370: break;
4371: if(i==sizeof(hdr.subj)) grunged=1;
4372:
4373: #else /* New way */
4374:
4375: /* Read fixed-length header fields */
4376: if(fread(&pkdmsg,sizeof(BYTE),sizeof(pkdmsg),fidomsg)!=sizeof(pkdmsg))
4377: continue;
4378:
4379: if(pkdmsg.type==2) { /* Recognized type, copy fields */
4380: hdr.orignode = pkdmsg.orignode;
4381: hdr.destnode = pkdmsg.destnode;
4382: hdr.orignet = pkdmsg.orignet;
4383: hdr.destnet = pkdmsg.destnet;
4384: hdr.attr = pkdmsg.attr;
4385: hdr.cost = pkdmsg.cost;
4386: SAFECOPY(hdr.time,pkdmsg.time);
4387: } else
4388: grunged=TRUE;
4389:
4390: /* Read variable-length header fields */
4391: if(!grunged) {
4392: freadstr(fidomsg,hdr.to,sizeof(hdr.to));
4393: freadstr(fidomsg,hdr.from,sizeof(hdr.from));
4394: freadstr(fidomsg,hdr.subj,sizeof(hdr.subj));
4395: }
4396: #endif
4397: hdr.attr&=~FIDO_LOCAL; /* Strip local bit, obviously not created locally */
4398:
4399: str[0]=0;
4400: for(i=0;!grunged && i<sizeof(str);i++) /* Read in the 'AREA' Field */
4401: if(!fread(str+i,1,1,fidomsg) || str[i]=='\r')
4402: break;
4403: if(i<sizeof(str))
4404: str[i]=0;
4405: else
4406: grunged=1;
4407:
4408: if(grunged) {
4409: start_tick=0;
4410: if(cfg.log&LOG_GRUNGED)
4411: logprintf("Grunged message");
4412: seektonull(fidomsg);
4413: printf("Grunged message!\n");
4414: continue;
4415: }
4416:
4417: if(i)
4418: fseek(fidomsg,(long)-(i+1),SEEK_CUR);
4419:
4420: truncsp(str);
4421: p=strstr(str,"AREA:");
4422: if(p!=str) { /* Netmail */
4423: start_tick=0;
4424: if(import_netmail("",hdr,fidomsg))
4425: seektonull(fidomsg);
4426: printf("\n");
4427: continue;
4428: }
4429:
4430: if(!(misc&IMPORT_ECHOMAIL)) {
4431: start_tick=0;
4432: printf("EchoMail Ignored");
4433: seektonull(fidomsg);
4434: printf("\n");
4435: continue;
4436: }
4437:
4438: p+=5; /* Skip "AREA:" */
4439: SKIP_WHITESPACE(p); /* Skip any white space */
4440: printf("%21s: ",p); /* Show areaname: */
4441: SAFECOPY(areatagstr,p);
4442: strupr(p);
4443: areatag=crc32(p,0);
4444:
4445: for(i=0;i<cfg.areas;i++) /* Do we carry this area? */
4446: if(cfg.area[i].tag==areatag) {
4447: if(cfg.area[i].sub!=INVALID_SUB)
4448: printf("%s ",scfg.sub[cfg.area[i].sub]->code);
4449: else
4450: printf("(Passthru) ");
4451: fmsgbuf=getfmsg(fidomsg,NULL);
4452: gen_psb(&msg_seen,&msg_path,fmsgbuf,pkthdr.destzone);
4453: break;
4454: }
4455:
4456: if(i==cfg.areas) {
4457: printf("(Unknown) ");
4458: if(cfg.badecho>=0) {
4459: i=cfg.badecho;
4460: if(cfg.area[i].sub!=INVALID_SUB)
4461: printf("%s ",scfg.sub[cfg.area[i].sub]->code);
4462: else
4463: printf("(Passthru) ");
4464: fmsgbuf=getfmsg(fidomsg,NULL);
4465: gen_psb(&msg_seen,&msg_path,fmsgbuf,pkthdr.destzone);
4466: }
4467: else {
4468: start_tick=0;
4469: printf("Skipped\n");
4470: seektonull(fidomsg);
4471: continue;
4472: }
4473: }
4474:
4475: if(misc&SECURE && cfg.area[i].sub!=INVALID_SUB) {
4476: for(j=0;j<cfg.area[i].uplinks;j++)
4477: if(!memcmp(&cfg.area[i].uplink[j],&pkt_faddr,sizeof(faddr_t)))
4478: break;
4479: if(j==cfg.area[i].uplinks) {
4480: if(cfg.log&LOG_SECURE)
4481: logprintf("%s: Security violation - %s not in AREAS.BBS"
4482: ,areatagstr,smb_faddrtoa(&pkt_faddr,NULL));
4483: printf("Security Violation (Not in AREAS.BBS)\n");
4484: seektonull(fidomsg);
4485: continue;
4486: }
4487: }
4488:
4489: /* From here on out, i = area number and area[i].sub = sub number */
4490:
4491: memcpy(&curarea,&cfg.area[i],sizeof(areasbbs_t));
4492: curarea.name=areatagstr;
4493:
4494: if(cfg.area[i].sub==INVALID_SUB) { /* Passthru */
4495: start_tick=0;
4496: strip_psb(fmsgbuf);
4497: pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen,msg_path,0);
4498: printf("\n");
4499: continue;
4500: } /* On to the next message */
4501:
4502:
4503: if(cfg.check_path) {
4504: for(j=0;j<scfg.total_faddrs;j++)
4505: if(check_psb(&msg_path,scfg.faddr[j]))
4506: break;
4507: if(j<scfg.total_faddrs) {
4508: start_tick=0;
4509: printf("Circular path (%s) ",smb_faddrtoa(&scfg.faddr[j],NULL));
4510: cfg.area[i].circular++;
4511: if(cfg.log&LOG_CIRCULAR)
4512: logprintf("%s: Circular path detected for %s"
4513: ,areatagstr,smb_faddrtoa(&scfg.faddr[j],NULL));
4514: strip_psb(fmsgbuf);
4515: pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen,msg_path,0);
4516: printf("\n");
4517: continue;
4518: }
4519: }
4520:
4521: for(j=0;j<MAX_OPEN_SMBS;j++)
4522: if(subnum[j]==cfg.area[i].sub)
4523: break;
4524: if(j<MAX_OPEN_SMBS) /* already open */
4525: cur_smb=j;
4526: else {
4527: if(smb[cur_smb].shd_fp) /* If open */
4528: cur_smb=!cur_smb; /* toggle between 0 and 1 */
4529: smb_close(&smb[cur_smb]); /* close, if open */
4530: subnum[cur_smb]=INVALID_SUB; /* reset subnum (just incase) */
4531: }
4532:
4533: if(smb[cur_smb].shd_fp==NULL) { /* Currently closed */
4534: sprintf(smb[cur_smb].file,"%s%s",scfg.sub[cfg.area[i].sub]->data_dir
4535: ,scfg.sub[cfg.area[i].sub]->code);
4536: smb[cur_smb].retry_time=scfg.smb_retry_time;
4537: if((j=smb_open(&smb[cur_smb]))!=SMB_SUCCESS) {
4538: sprintf(str,"ERROR %d opening %s area #%d, sub #%d)"
4539: ,j,smb[cur_smb].file,i+1,cfg.area[i].sub+1);
4540: printf(str);
4541: logprintf(str);
4542: strip_psb(fmsgbuf);
4543: pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen
4544: ,msg_path,0);
4545: printf("\n");
4546: continue;
4547: }
4548: if(!filelength(fileno(smb[cur_smb].shd_fp))) {
4549: smb[cur_smb].status.max_crcs=scfg.sub[cfg.area[i].sub]->maxcrcs;
4550: smb[cur_smb].status.max_msgs=scfg.sub[cfg.area[i].sub]->maxmsgs;
4551: smb[cur_smb].status.max_age=scfg.sub[cfg.area[i].sub]->maxage;
4552: smb[cur_smb].status.attr=scfg.sub[cfg.area[i].sub]->misc&SUB_HYPER
4553: ? SMB_HYPERALLOC:0;
4554: if((j=smb_create(&smb[cur_smb]))!=SMB_SUCCESS) {
4555: sprintf(str,"ERROR %d creating %s",j,smb[cur_smb].file);
4556: printf(str);
4557: logprintf(str);
4558: smb_close(&smb[cur_smb]);
4559: strip_psb(fmsgbuf);
4560: pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen
4561: ,msg_path,0);
4562: printf("\n");
4563: continue;
4564: }
4565: }
4566:
4567: subnum[cur_smb]=cfg.area[i].sub;
4568: }
4569:
4570: if(hdr.attr&FIDO_PRIVATE && !(scfg.sub[cfg.area[i].sub]->misc&SUB_PRIV)) {
4571: if(misc&IMPORT_PRIVATE)
4572: hdr.attr&=~FIDO_PRIVATE;
4573: else {
4574: start_tick=0;
4575: printf("Private posts disallowed.");
4576: if(cfg.log&LOG_PRIVATE)
4577: logprintf("%s: Private posts disallowed"
4578: ,areatagstr);
4579: strip_psb(fmsgbuf);
4580: pkt_to_pkt(fmsgbuf,curarea,pkt_faddr,hdr,msg_seen
4581: ,msg_path,0);
4582: printf("\n");
4583: continue;
4584: }
4585: }
4586:
4587: if(!(hdr.attr&FIDO_PRIVATE) && scfg.sub[cfg.area[i].sub]->misc&SUB_PONLY)
4588: hdr.attr|=MSG_PRIVATE;
4589:
4590: /**********************/
4591: /* Importing EchoMail */
4592: /**********************/
4593: j=fmsgtosmsg(fmsgbuf,hdr,0,cfg.area[i].sub);
4594:
4595: if(start_tick) {
4596: import_ticks+=msclock()-start_tick;
4597: start_tick=0;
4598: }
4599:
4600: if(j==SMB_DUPE_MSG) {
4601: if(cfg.log&LOG_DUPES)
4602: logprintf("%s Duplicate message",areatagstr);
4603: cfg.area[i].dupes++;
4604: }
4605: else { /* Not a dupe */
4606: strip_psb(fmsgbuf);
4607: pkt_to_pkt(fmsgbuf,curarea,pkt_faddr
4608: ,hdr,msg_seen,msg_path,0);
4609: }
4610:
4611: if(j==0) { /* Successful import */
4612: echomail++;
4613: cfg.area[i].imported++;
4614: if(misc&NOTIFY_RECEIPT && (m=matchname(hdr.to))!=0) {
4615: sprintf(str
4616: ,"\7\1n\1hSBBSecho: \1m%.*s \1n\1msent you EchoMail on "
4617: "\1h%s \1n\1m%s\1n\r\n"
4618: ,FIDO_NAME_LEN-1
4619: ,hdr.from
4620: ,scfg.grp[scfg.sub[cfg.area[i].sub]->grp]->sname
4621: ,scfg.sub[cfg.area[i].sub]->sname);
4622: putsmsg(&scfg,m,str);
4623: }
4624: }
4625: printf("\n");
4626: }
4627: fclose(fidomsg);
4628:
4629: if(misc&DELETE_PACKETS)
4630: if(delfile(packet))
4631: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,packet
4632: ,strerror(errno));
4633: }
4634: globfree(&g);
4635:
4636: if(start_tick) {
4637: import_ticks+=msclock()-start_tick;
4638: start_tick=0;
4639: }
4640:
4641: } while(!kbhit() && unpack_bundle());
4642:
4643: if(kbhit()) lprintf(LOG_NOTICE,"\nKey pressed - premature termination");
4644: while(kbhit()) getch();
4645:
4646: } /* End of Secure : Inbound loop */
4647:
4648: if(start_tick) /* Last possible increment of import_ticks */
4649: import_ticks+=msclock()-start_tick;
4650:
4651: for(j=MAX_OPEN_SMBS-1;(int)j>=0;j--) /* Close open bases */
4652: if(smb[j].shd_fp)
4653: smb_close(&smb[j]);
4654:
4655: pkt_to_pkt(fmsgbuf,fakearea,pkt_faddr,hdr,msg_seen,msg_path,1);
4656:
4657: /******* END OF IMPORT PKT ROUTINE *******/
4658:
4659: if(cfg.log&LOG_AREA_TOTALS) {
4660: for(i=0;i<cfg.areas;i++) {
4661: if(cfg.area[i].imported)
4662: lprintf(LOG_INFO,"Imported: %5u msgs %8s <- %s"
4663: ,cfg.area[i].imported,scfg.sub[cfg.area[i].sub]->code
4664: ,cfg.area[i].name); }
4665: for(i=0;i<cfg.areas;i++) {
4666: if(cfg.area[i].circular)
4667: lprintf(LOG_INFO,"Circular: %5u detected in %s"
4668: ,cfg.area[i].circular,cfg.area[i].name); }
4669: for(i=0;i<cfg.areas;i++) {
4670: if(cfg.area[i].dupes)
4671: lprintf(LOG_INFO,"Duplicate: %5u detected in %s"
4672: ,cfg.area[i].dupes,cfg.area[i].name); } }
4673:
4674: import_time=((float)import_ticks)/(float)MSCLOCKS_PER_SEC;
4675: if(cfg.log&LOG_TOTALS && import_time && echomail) {
4676: lprintf(LOG_INFO,"Imported: %5lu msgs in %.1f sec (%.1f/min %.1f/sec)"
4677: ,echomail,import_time
4678: ,import_time/60.0 ? (float)echomail/(import_time/60.0) :(float)echomail
4679: ,(float)echomail/import_time);
4680: }
4681: if(fmsgbuf) {
4682: free(fmsgbuf);
4683: fmsgbuf=0; }
4684:
4685: }
4686:
4687: if(misc&IMPORT_NETMAIL) {
4688:
4689: lprintf(LOG_DEBUG,"\nScanning for Inbound NetMail Messages...");
4690:
4691: #ifdef __unix__
4692: sprintf(str,"%s*.[Mm][Ss][Gg]",scfg.netmail_dir);
4693: #else
4694: sprintf(str,"%s*.msg",scfg.netmail_dir);
4695: #endif
4696: glob(str,0,NULL,&g);
4697: for(f=0;f<g.gl_pathc && !kbhit();f++) {
4698:
4699: strcpy(path,g.gl_pathv[f]);
4700:
4701: if((fidomsg=fnopen(&fmsg,path,O_RDWR))==NULL) {
4702: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,path
4703: ,strerror(errno));
4704: continue; }
4705: if(filelength(fmsg)<sizeof(fmsghdr_t)) {
4706: lprintf(LOG_ERR,"ERROR line %d invalid length of %lu bytes for %s",__LINE__
4707: ,filelength(fmsg),path);
4708: fclose(fidomsg);
4709: continue; }
4710: if(fread(&hdr,sizeof(fmsghdr_t),1,fidomsg)!=1) {
4711: fclose(fidomsg);
4712: lprintf(LOG_ERR,"ERROR line %d reading %u bytes from %s",__LINE__
4713: ,sizeof(fmsghdr_t),path);
4714: continue; }
4715: i=import_netmail(path,hdr,fidomsg);
4716: /**************************************/
4717: /* Delete source netmail if specified */
4718: /**************************************/
4719: if(i==0) {
4720: if(misc&DELETE_NETMAIL) {
4721: fclose(fidomsg);
4722: if(delfile(path))
4723: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,path
4724: ,strerror(errno)); }
4725: else {
4726: hdr.attr|=FIDO_RECV;
4727: fseek(fidomsg,0L,SEEK_SET);
4728: fwrite(&hdr,sizeof(fmsghdr_t),1,fidomsg);
4729: fclose(fidomsg); } }
4730: else if(i!=-2)
4731: fclose(fidomsg);
4732: printf("\n");
4733: }
4734: globfree(&g);
4735: }
4736:
4737:
4738: if(misc&EXPORT_ECHOMAIL) {
4739: memset(&addr,0,sizeof(faddr_t));
4740: export_echomail(sub_code,addr);
4741: }
4742:
4743:
4744: if(misc&PACK_NETMAIL) {
4745:
4746: memset(&msg_seen,0,sizeof(addrlist_t));
4747: memset(&msg_path,0,sizeof(addrlist_t));
4748: memset(&fakearea,0,sizeof(areasbbs_t));
4749:
4750: lprintf(LOG_DEBUG,"\nPacking Outbound NetMail...");
4751:
4752: #ifdef __unix__
4753: sprintf(str,"%s*.[Mm][Ss][Gg]",scfg.netmail_dir);
4754: #else
4755: sprintf(str,"%s*.msg",scfg.netmail_dir);
4756: #endif
4757: glob(str,0,NULL,&g);
4758: for(f=0;f<g.gl_pathc && !kbhit();f++) {
4759:
4760: strcpy(path,g.gl_pathv[f]);
4761:
4762: if((fidomsg=fnopen(&fmsg,path,O_RDWR))==NULL) {
4763: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,path
4764: ,strerror(errno));
4765: continue; }
4766: if(filelength(fmsg)<sizeof(fmsghdr_t)) {
4767: lprintf(LOG_WARNING,"%s Invalid length of %lu bytes",path,filelength(fmsg));
4768: fclose(fidomsg);
4769: continue; }
4770: if(fread(&hdr,sizeof(fmsghdr_t),1,fidomsg)!=1) {
4771: fclose(fidomsg);
4772: lprintf(LOG_ERR,"ERROR line %d reading %u bytes from %s",__LINE__
4773: ,sizeof(fmsghdr_t),path);
4774: continue; }
4775: hdr.destzone=hdr.origzone=sys_faddr.zone;
4776: hdr.destpoint=hdr.origpoint=0;
4777: getzpt(fidomsg,&hdr); /* use kludge if found */
4778: addr.zone=hdr.destzone;
4779: addr.net=hdr.destnet;
4780: addr.node=hdr.destnode;
4781: addr.point=hdr.destpoint;
4782: for(i=0;i<scfg.total_faddrs;i++)
4783: if(!memcmp(&addr,&scfg.faddr[i],sizeof(faddr_t)))
4784: break;
4785: if(i<scfg.total_faddrs) { /* In-bound, so ignore */
4786: fclose(fidomsg);
4787: continue;
4788: }
4789: printf("\n%s to %s ",path,smb_faddrtoa(&addr,NULL));
4790: if(cfg.log&LOG_PACKING)
4791: logprintf("Packing %s (%s)",path,smb_faddrtoa(&addr,NULL));
4792: fmsgbuf=getfmsg(fidomsg,NULL);
4793: if(!fmsgbuf) {
4794: lprintf(LOG_ERR,"ERROR line %d allocating memory for NetMail fmsgbuf"
4795: ,__LINE__);
4796: bail(1); }
4797: fclose(fidomsg);
4798:
4799: attr=0;
4800: node=matchnode(addr,0);
4801: if(node<cfg.nodecfgs && cfg.nodecfg[node].route.zone
4802: && !(hdr.attr&(FIDO_CRASH|FIDO_HOLD))) {
4803: addr=cfg.nodecfg[node].route; /* Routed */
4804: if(cfg.log&LOG_ROUTING)
4805: logprintf("Routing %s to %s",path,smb_faddrtoa(&addr,NULL));
4806: node=matchnode(addr,0);
4807: }
4808: if(node<cfg.nodecfgs)
4809: attr=cfg.nodecfg[node].attr;
4810:
4811: if(misc&FLO_MAILER) {
4812: if(hdr.attr&FIDO_CRASH)
4813: attr|=ATTR_CRASH;
4814: else if(hdr.attr&FIDO_HOLD)
4815: attr|=ATTR_HOLD;
4816: if(attr&ATTR_CRASH) ch='c';
4817: else if(attr&ATTR_HOLD) ch='h';
4818: else if(attr&ATTR_DIRECT) ch='d';
4819: else ch='o';
4820: if(addr.zone==sys_faddr.zone) /* Default zone, use default outbound */
4821: strcpy(outbound,cfg.outbound);
4822: else { /* Inter-zone outbound is OUTBOUND.XXX */
4823: sprintf(outbound,"%.*s.%03x"
4824: ,(int)strlen(cfg.outbound)-1,cfg.outbound,addr.zone);
4825: MKDIR(outbound);
4826: backslash(outbound);
4827: }
4828: if(addr.point) { /* Point destination is OUTBOUND.PNT */
4829: sprintf(str,"%04x%04x.pnt"
4830: ,addr.net,addr.node);
4831: strcat(outbound,str); }
4832: if(outbound[strlen(outbound)-1]=='\\'
4833: || outbound[strlen(outbound)-1]=='/')
4834: outbound[strlen(outbound)-1]=0;
4835: MKDIR(outbound);
4836: backslash(outbound);
4837: if(addr.point)
4838: sprintf(packet,"%s%08x.%cut",outbound,addr.point,ch);
4839: else
4840: sprintf(packet,"%s%04x%04x.%cut",outbound,addr.net,addr.node,ch);
4841: if(hdr.attr&FIDO_FILE)
4842: if(write_flofile(hdr.subj,addr,FALSE /* !bundle */))
4843: bail(1); }
4844: else
4845: strcpy(packet,pktname(/* Temp? */ FALSE));
4846:
4847: now=time(NULL);
4848: tm=localtime(&now);
4849: if((stream=fnopen(&file,packet,O_RDWR|O_CREAT))==NULL) {
4850: lprintf(LOG_ERR,"ERROR line %d opening %s %s",__LINE__,packet
4851: ,strerror(errno));
4852: bail(1);
4853: }
4854:
4855: if(filelength(file) < sizeof(pkthdr_t)) {
4856: chsize(file,0);
4857: rewind(stream);
4858: memset(&pkthdr,0,sizeof(pkthdr));
4859: pkthdr.orignode=hdr.orignode;
4860: pkthdr.destnode=addr.node;
4861: pkthdr.year=tm->tm_year+1900;
4862: pkthdr.month=tm->tm_mon;
4863: pkthdr.day=tm->tm_mday;
4864: pkthdr.hour=tm->tm_hour;
4865: pkthdr.min=tm->tm_min;
4866: pkthdr.sec=tm->tm_sec;
4867: pkthdr.baud=0x00;
4868: pkthdr.pkttype=0x0002;
4869: pkthdr.orignet=hdr.orignet;
4870: pkthdr.destnet=addr.net;
4871: pkthdr.prodcode=0x00;
4872: pkthdr.sernum=0;
4873: pkthdr.origzone=hdr.origzone;
4874: pkthdr.destzone=addr.zone;
4875: if(node<cfg.nodecfgs) {
4876: if(cfg.nodecfg[node].pkt_type==PKT_TWO_PLUS) {
4877: memset(&two_plus,0,sizeof(two_plus));
4878: if(hdr.origpoint) {
4879: pkthdr.orignet=-1;
4880: two_plus.auxnet=hdr.orignet;
4881: }
4882: two_plus.cwcopy=0x0100;
4883: two_plus.prodcode=pkthdr.prodcode;
4884: two_plus.revision=pkthdr.sernum;
4885: two_plus.cword=0x0001;
4886: two_plus.origzone=pkthdr.origzone;
4887: two_plus.destzone=pkthdr.destzone;
4888: two_plus.origpoint=hdr.origpoint;
4889: two_plus.destpoint=addr.point;
4890: memcpy(&pkthdr.empty,&two_plus,sizeof(pkthdr.empty));
4891: }
4892: memcpy(pkthdr.password,cfg.nodecfg[node].pktpwd,sizeof(pkthdr.password));
4893: }
4894: fwrite(&pkthdr,sizeof(pkthdr_t),1,stream);
4895: } else
4896: fseek(stream,find_packet_terminator(stream),SEEK_SET);
4897:
4898: putfmsg(stream,fmsgbuf,hdr,fakearea,msg_seen,msg_path);
4899:
4900: /* Write packet terminator */
4901: terminate_packet(stream);
4902:
4903: free(fmsgbuf);
4904: fclose(stream);
4905: /**************************************/
4906: /* Delete source netmail if specified */
4907: /**************************************/
4908: if(misc&DELETE_NETMAIL)
4909: if(delfile(path))
4910: lprintf(LOG_ERR,"ERROR line %d removing %s %s",__LINE__,path
4911: ,strerror(errno));
4912: printf("\n");
4913: }
4914: globfree(&g);
4915: }
4916:
4917: if(misc&UPDATE_MSGPTRS) {
4918:
4919: lprintf(LOG_DEBUG,"\nUpdating Message Pointers to Last Posted Message...");
4920:
4921: for(grp=0;grp<scfg.total_grps;grp++) {
4922: for(i=0;i<scfg.total_subs;i++) {
4923: if(scfg.sub[i]->misc&SUB_FIDO && scfg.sub[i]->grp==grp) {
4924: lprintf(LOG_DEBUG,"\n%-15.15s %s"
4925: ,scfg.grp[scfg.sub[i]->grp]->sname,scfg.sub[i]->lname);
4926: getlastmsg(i,&l,0);
4927: sprintf(str,"%s%s.sfp",scfg.sub[i]->data_dir,scfg.sub[i]->code);
4928: if((file=nopen(str,O_WRONLY|O_CREAT))==-1) {
4929: lprintf(LOG_ERR,"ERROR %d line %d opening/creating %s"
4930: ,errno,__LINE__,str); }
4931: else {
4932: write(file,&l,sizeof(time_t));
4933: close(file);
4934: }
4935: }
4936: }
4937: }
4938: }
4939:
4940: if(misc&(IMPORT_NETMAIL|IMPORT_ECHOMAIL) && misc&REPORT) {
4941: now=time(NULL);
4942: sprintf(str,"%ssbbsecho.msg",scfg.text_dir);
4943: if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
4944: lprintf(LOG_ERR,"ERROR line %d opening %s",__LINE__,str);
4945: bail(1); }
4946: sprintf(fname,"\1c\1h "
4947: "���������������������������������������������������\r\n");
4948: sprintf(path,"\1c\1h "
4949: "���������������������������������������������������\r\n");
4950: write(file,fname,strlen(fname));
4951: sprintf(str," \1n\1k\0016"
4952: " Last FidoNet Transfer on %.24s \1n\r\n",ctime(&now));
4953: write(file,str,strlen(str));
4954: write(file,path,strlen(path));
4955: write(file,fname,strlen(fname));
4956: sprintf(tmp,"Imported %lu EchoMail and %lu NetMail Messages"
4957: ,echomail,netmail);
4958: sprintf(str," \1n\1k\0016 %-50.50s\1n\r\n",tmp);
4959: write(file,str,strlen(str));
4960: write(file,path,strlen(path));
4961: close(file);
4962: }
4963:
4964: pkt_to_pkt(NULL,fakearea,pkt_faddr,hdr,msg_seen,msg_path,1);
4965: if(email->shd_fp)
4966: smb_close(email);
4967:
4968: free(smb);
4969: free(email);
4970:
4971: bail(0);
4972: return(0);
4973: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.