|
|
1.1 root 1: /* fido.cpp */
2:
3: /* Synchronet FidoNet-related routines */
4:
5: /* $Id: fido.cpp,v 1.39 2006/04/05 09:45:21 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: #include "sbbs.h"
39: #include "qwk.h"
40:
41: faddr_t atofaddr(scfg_t* cfg, char *str);
42:
43: void pt_zone_kludge(fmsghdr_t hdr,int fido)
44: {
45: char str[256];
46:
47: sprintf(str,"\1INTL %hu:%hu/%hu %hu:%hu/%hu\r"
48: ,hdr.destzone,hdr.destnet,hdr.destnode
49: ,hdr.origzone,hdr.orignet,hdr.orignode);
50: write(fido,str,strlen(str));
51:
52: if(hdr.destpoint) {
53: sprintf(str,"\1TOPT %hu\r"
54: ,hdr.destpoint);
55: write(fido,str,strlen(str)); }
56:
57: if(hdr.origpoint) {
58: sprintf(str,"\1FMPT %hu\r"
59: ,hdr.origpoint);
60: write(fido,str,strlen(str)); }
61: }
62:
63: bool sbbs_t::lookup_netuser(char *into)
64: {
65: char to[128],name[26],str[256],q[128];
66: int i;
67: FILE *stream;
68:
69: if(strchr(into,'@'))
70: return(false);
71: strcpy(to,into);
72: strupr(to);
73: sprintf(str,"%sqnet/users.dat", cfg.data_dir);
74: if((stream=fnopen(&i,str,O_RDONLY))==NULL)
75: return(false);
76: while(!feof(stream)) {
77: if(!fgets(str,sizeof(str),stream))
78: break;
79: str[25]=0;
80: truncsp(str);
81: strcpy(name,str);
82: strupr(name);
83: str[35]=0;
84: truncsp(str+27);
85: sprintf(q,"Do you mean %s @%s",str,str+27);
86: if(strstr(name,to) && yesno(q)) {
87: fclose(stream);
88: sprintf(into,"%s@%s",str,str+27);
89: return(true); }
90: if(sys_status&SS_ABORT)
91: break; }
92: fclose(stream);
93: return(false);
94: }
95:
96: /****************************************************************************/
97: /* Send FidoNet/QWK/Internet NetMail from BBS */
98: /****************************************************************************/
99: bool sbbs_t::netmail(char *into, char *title, long mode)
100: {
101: char str[256],subj[128],to[256],fname[128],*buf,*p,ch;
102: char tmp[512];
103: int file,fido,x,cc_found,cc_sent;
104: uint i;
105: long length,l;
106: faddr_t addr;
107: fmsghdr_t hdr;
108: struct tm tm;
109:
110: if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP) {
111: bputs(text[TooManyEmailsToday]);
112: return(false);
113: }
114:
115: SAFECOPY(subj,title);
116:
117: strcpy(to,into);
118:
119: lookup_netuser(to);
120:
121: p=strrchr(to,'@'); /* Find '@' in name@addr */
122: if(p && !isdigit(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) {
123: mode&=~WM_FILE;
124: qnetmail(to,title,mode|WM_NETMAIL);
125: return(false); }
126: if(!cfg.total_faddrs || p==NULL || !strchr(p+1,'/')) {
127: if(!p && cfg.dflt_faddr.zone)
128: addr=cfg.dflt_faddr;
129: else if(cfg.inetmail_misc&NMAIL_ALLOW) {
130: if(mode&WM_FILE && !SYSOP && !(cfg.inetmail_misc&NMAIL_FILE))
131: mode&=~WM_FILE;
132: return(inetmail(into,title,mode|WM_NETMAIL));
133: }
134: else if(cfg.dflt_faddr.zone)
135: addr=cfg.dflt_faddr;
136: else {
137: bputs(text[InvalidNetMailAddr]);
138: return(false);
139: }
140: } else {
141: addr=atofaddr(&cfg,p+1); /* Get fido address */
142: *p=0; /* Chop off address */
143: }
144:
145: if(mode&WM_FILE && !SYSOP && !(cfg.netmail_misc&NMAIL_FILE))
146: mode&=~WM_FILE;
147:
148: if((!SYSOP && !(cfg.netmail_misc&NMAIL_ALLOW)) || useron.rest&FLAG('M')
149: || !cfg.total_faddrs) {
150: bputs(text[NoNetMailAllowed]);
151: return(false);
152: }
153:
154: truncsp(to); /* Truncate off space */
155:
156: memset(&hdr,0,sizeof(hdr)); /* Initialize header to null */
157: strcpy(hdr.from,cfg.netmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
158: SAFECOPY(hdr.to,to);
159:
160: /* Look-up in nodelist? */
161:
162: if(cfg.netmail_cost && !(useron.exempt&FLAG('S'))) {
163: if(useron.cdt+useron.freecdt<cfg.netmail_cost) {
164: bputs(text[NotEnoughCredits]);
165: return(false);
166: }
167: sprintf(str,text[NetMailCostContinueQ],cfg.netmail_cost);
168: if(noyes(str))
169: return(false);
170: }
171:
172: now=time(NULL);
173: if(localtime_r(&now,&tm)!=NULL)
174: sprintf(hdr.time,"%02u %3.3s %02u %02u:%02u:%02u"
175: ,tm.tm_mday,mon[tm.tm_mon],TM_YEAR(tm.tm_year)
176: ,tm.tm_hour,tm.tm_min,tm.tm_sec);
177:
178: hdr.destzone =addr.zone;
179: hdr.destnet =addr.net;
180: hdr.destnode =addr.node;
181: hdr.destpoint =addr.point;
182:
183: for(i=0;i<cfg.total_faddrs;i++)
184: if(addr.zone==cfg.faddr[i].zone && addr.net==cfg.faddr[i].net)
185: break;
186: if(i==cfg.total_faddrs) {
187: for(i=0;i<cfg.total_faddrs;i++)
188: if(addr.zone==cfg.faddr[i].zone)
189: break;
190: }
191: if(i==cfg.total_faddrs)
192: i=0;
193: hdr.origzone =cfg.faddr[i].zone;
194: hdr.orignet =cfg.faddr[i].net;
195: hdr.orignode =cfg.faddr[i].node;
196: hdr.origpoint =cfg.faddr[i].point;
197:
198: smb_faddrtoa(&cfg.faddr[i],str);
199: bprintf(text[NetMailing],hdr.to,smb_faddrtoa(&addr,tmp),hdr.from,str);
200:
201: hdr.attr=(FIDO_LOCAL|FIDO_PRIVATE);
202:
203: if(cfg.netmail_misc&NMAIL_CRASH) hdr.attr|=FIDO_CRASH;
204: if(cfg.netmail_misc&NMAIL_HOLD) hdr.attr|=FIDO_HOLD;
205: if(cfg.netmail_misc&NMAIL_KILL) hdr.attr|=FIDO_KILLSENT;
206: if(mode&WM_FILE) hdr.attr|=FIDO_FILE;
207:
208: sprintf(str,"%sNETMAIL.MSG", cfg.node_dir);
209: remove(str); /* Just incase it's already there */
210: // mode&=~WM_FILE;
211: if(!writemsg(str,nulstr,subj,WM_NETMAIL|mode,INVALID_SUB,into)) {
212: bputs(text[Aborted]);
213: return(false);
214: }
215:
216: if(mode&WM_FILE) {
217: strcpy(fname,subj);
218: sprintf(str,"%sfile/%04u.out", cfg.data_dir, useron.number);
219: MKDIR(str);
220: strcpy(tmp, cfg.data_dir);
221: if(tmp[0]=='.') /* Relative path */
222: sprintf(tmp,"%s%s", cfg.node_dir, cfg.data_dir);
223: sprintf(str,"%sfile/%04u.out/%s",tmp,useron.number,fname);
224: strcpy(subj,str);
225: if(fexistcase(str)) {
226: bputs(text[FileAlreadyThere]);
227: return(false); }
228: #if 0 /* no such thing as local logon */
229: if(online==ON_LOCAL) { /* Local upload */
230: bputs(text[EnterPath]);
231: if(!getstr(str,60,K_LINE|K_UPPER)) {
232: bputs(text[Aborted]);
233: return(false);
234: }
235: backslash(str);
236: strcat(str,fname);
237: if(mv(str,subj,1))
238: return(false);
239: } else
240: #endif
241: { /* Remote */
242: xfer_prot_menu(XFER_UPLOAD);
243: mnemonics(text[ProtocolOrQuit]);
244: strcpy(str,"Q");
245: for(x=0;x<cfg.total_prots;x++)
246: if(cfg.prot[x]->ulcmd[0] && chk_ar(cfg.prot[x]->ar,&useron)) {
247: sprintf(tmp,"%c",cfg.prot[x]->mnemonic);
248: strcat(str,tmp); }
249: ch=(char)getkeys(str,0);
250: if(ch=='Q' || sys_status&SS_ABORT) {
251: bputs(text[Aborted]);
252: return(false); }
253: for(x=0;x<cfg.total_prots;x++)
254: if(cfg.prot[x]->ulcmd[0] && cfg.prot[x]->mnemonic==ch
255: && chk_ar(cfg.prot[x]->ar,&useron))
256: break;
257: if(x<cfg.total_prots) /* This should be always */
258: protocol(cfg.prot[x],XFER_UPLOAD,subj,nulstr,true);
259: }
260: sprintf(tmp,"%s%s",cfg.temp_dir,title);
261: if(!fexistcase(subj) && fexistcase(tmp))
262: mv(tmp,subj,0);
263: l=flength(subj);
264: if(l>0)
265: bprintf(text[FileNBytesReceived],fname,ultoac(l,tmp));
266: else {
267: bprintf(text[FileNotReceived],fname);
268: return(false);
269: }
270: }
271:
272: p=subj;
273: if((SYSOP || useron.exempt&FLAG('F'))
274: && !strnicmp(p,"CR:",3)) { /* Crash over-ride by sysop */
275: p+=3; /* skip CR: */
276: if(*p==' ') p++; /* skip extra space if it exists */
277: hdr.attr|=FIDO_CRASH; }
278:
279: if((SYSOP || useron.exempt&FLAG('F'))
280: && !strnicmp(p,"FR:",3)) { /* File request */
281: p+=3; /* skip FR: */
282: if(*p==' ') p++;
283: hdr.attr|=FIDO_FREQ; }
284:
285: if((SYSOP || useron.exempt&FLAG('F'))
286: && !strnicmp(p,"RR:",3)) { /* Return receipt request */
287: p+=3; /* skip RR: */
288: if(*p==' ') p++;
289: hdr.attr|=FIDO_RRREQ; }
290:
291: if((SYSOP || useron.exempt&FLAG('F'))
292: && !strnicmp(p,"FA:",3)) { /* File Attachment */
293: p+=3; /* skip FA: */
294: if(*p==' ') p++;
295: hdr.attr|=FIDO_FILE; }
296:
297: SAFECOPY(hdr.subj,p);
298:
299: sprintf(str,"%sNETMAIL.MSG", cfg.node_dir);
300: if((file=nopen(str,O_RDONLY))==-1) {
301: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
302: return(false); }
303: length=filelength(file);
304: if((buf=(char *)malloc(length))==NULL) {
305: close(file);
306: errormsg(WHERE,ERR_ALLOC,str,length);
307: return(false); }
308: read(file,buf,length);
309: close(file);
310:
311: cc_sent=0;
312: while(1) {
313: for(i=1;i;i++) {
314: sprintf(str,"%s%u.msg", cfg.netmail_dir,i);
315: if(!fexistcase(str))
316: break; }
317: if(!i) {
318: bputs(text[TooManyEmailsToday]);
319: return(false); }
320: if((fido=nopen(str,O_WRONLY|O_CREAT|O_EXCL))==-1) {
321: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_EXCL);
322: return(false); }
323: write(fido,&hdr,sizeof(hdr));
324:
325: pt_zone_kludge(hdr,fido);
326:
327: if(cfg.netmail_misc&NMAIL_DIRECT) {
328: sprintf(str,"\1FLAGS DIR\r\n");
329: write(fido,str,strlen(str)); }
330: if(mode&WM_FILE) {
331: sprintf(str,"\1FLAGS KFS\r\n");
332: write(fido,str,strlen(str)); }
333:
334: if(cc_sent) {
335: sprintf(str,"* Originally to: %s\r\n\r\n",into);
336: write(fido,str,strlen(str)); }
337:
338: l=0L;
339: while(l<length) {
340: if(buf[l]==CTRL_A) /* Ctrl-A, so skip it and the next char */
341: l++;
342: else if(buf[l]!=LF) {
343: if((uchar)buf[l]==0x8d) /* r0dent i converted to normal i */
344: buf[l]='i';
345: write(fido,buf+l,1); }
346: l++; }
347: l=0;
348: write(fido,&l,1); /* Null terminator */
349: close(fido);
350:
351: useron.emails++;
352: logon_emails++;
353: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
354: useron.etoday++;
355: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
356:
357: if(!(useron.exempt&FLAG('S')))
358: subtract_cdt(&cfg,&useron,cfg.netmail_cost);
359: if(mode&WM_FILE)
360: sprintf(str,"%s sent NetMail file attachment to %s (%s)"
361: ,useron.alias
362: ,hdr.to,smb_faddrtoa(&addr,tmp));
363: else
364: sprintf(str,"%s sent NetMail to %s (%s)"
365: ,useron.alias
366: ,hdr.to,smb_faddrtoa(&addr,tmp));
367: logline("EN",str);
368:
369: cc_found=0;
370: for(l=0;l<length && cc_found<=cc_sent;l++)
371: if(l+3<length && !strnicmp(buf+l,"CC:",3)) {
372: cc_found++;
373: l+=2; }
374: else {
375: while(l<length && *(buf+l)!=LF)
376: l++; }
377: if(!cc_found)
378: break;
379: while(l<length && *(buf+l)==' ') l++;
380: for(i=0;l<length && *(buf+l)!=LF && i<128;i++,l++)
381: str[i]=buf[l];
382: if(!i)
383: break;
384: str[i]=0;
385: p=strrchr(str,'@');
386: if(p) {
387: addr=atofaddr(&cfg,p+1);
388: *p=0;
389: SAFECOPY(hdr.to,str); }
390: else {
391: atofaddr(&cfg,str);
392: strcpy(hdr.to,"Sysop"); }
393: hdr.destzone =addr.zone;
394: hdr.destnet =addr.net;
395: hdr.destnode =addr.node;
396: hdr.destpoint =addr.point;
397: cc_sent++; }
398:
399: if(cfg.netmail_sem[0]) /* update semaphore file */
400: ftouch(cmdstr(cfg.netmail_sem,nulstr,nulstr,NULL));
401:
402: free(buf);
403: return(true);
404: }
405:
406: /****************************************************************************/
407: /* Send NetMail from QWK REP Packet */
408: /****************************************************************************/
409: void sbbs_t::qwktonetmail(FILE *rep, char *block, char *into, uchar fromhub)
410: {
411: char *qwkbuf,to[129],name[129],sender[129],senderaddr[129]
412: ,str[256],*p,*cp,*addr,fulladdr[129],ch;
413: char tmp[512];
414: int i,fido,inet=0,qnet=0;
415: ushort net,xlat;
416: long l,offset,length,m,n;
417: faddr_t fidoaddr;
418: fmsghdr_t hdr;
419: smbmsg_t msg;
420: struct tm tm;
421:
422: if(useron.rest&FLAG('M')) {
423: bputs(text[NoNetMailAllowed]);
424: return; }
425:
426: sprintf(str,"%.6s",block+116);
427: n=atol(str); /* i = number of 128 byte records */
428:
429: if(n<2L || n>999999L) {
430: errormsg(WHERE,ERR_CHK,"QWK blocks",n);
431: return; }
432: if((qwkbuf=(char *)malloc(n*QWK_BLOCK_LEN))==NULL) {
433: errormsg(WHERE,ERR_ALLOC,nulstr,n*QWK_BLOCK_LEN);
434: return; }
435: memcpy((char *)qwkbuf,block,QWK_BLOCK_LEN);
436: fread(qwkbuf+QWK_BLOCK_LEN,n-1,QWK_BLOCK_LEN,rep);
437:
438: if(into==NULL)
439: sprintf(to,"%-128.128s",(char *)qwkbuf+QWK_BLOCK_LEN); /* To user on first line */
440: else
441: strcpy(to,into);
442:
443: p=strchr(to,QWK_NEWLINE); /* chop off at first CR */
444: if(p) *p=0;
445:
446: strcpy(name,to);
447: p=strchr(name,'@');
448: if(p) *p=0;
449: truncsp(name);
450:
451:
452: p=strrchr(to,'@'); /* Find '@' in name@addr */
453: if(p && !isdigit(*(p+1)) && !strchr(p,'.') && !strchr(p,':')) { /* QWKnet */
454: qnet=1;
455: *p=0; }
456: else if(p==NULL || !isdigit(*(p+1)) || !cfg.total_faddrs) {
457: if(p==NULL && cfg.dflt_faddr.zone)
458: fidoaddr=cfg.dflt_faddr;
459: else if(cfg.inetmail_misc&NMAIL_ALLOW) { /* Internet */
460: inet=1;
461: }
462: else if(cfg.dflt_faddr.zone)
463: fidoaddr=cfg.dflt_faddr;
464: else {
465: bputs(text[InvalidNetMailAddr]);
466: free(qwkbuf);
467: return; } }
468: else {
469: fidoaddr=atofaddr(&cfg,p+1); /* Get fido address */
470: *p=0; /* Chop off address */
471: }
472:
473:
474: if(!inet && !qnet && /* FidoNet */
475: ((!SYSOP && !(cfg.netmail_misc&NMAIL_ALLOW)) || !cfg.total_faddrs)) {
476: bputs(text[NoNetMailAllowed]);
477: free(qwkbuf);
478: return; }
479:
480: truncsp(to); /* Truncate off space */
481:
482: if(!stricmp(to,"SBBS") && !SYSOP && qnet) {
483: free(qwkbuf);
484: return; }
485:
486: l=QWK_BLOCK_LEN; /* Start of message text */
487:
488: if(qnet || inet) {
489:
490: if(into==NULL) { /* If name@addr on first line, skip first line */
491: while(l<(n*QWK_BLOCK_LEN) && qwkbuf[l]!=QWK_NEWLINE) l++;
492: l++; }
493:
494: memset(&msg,0,sizeof(smbmsg_t));
495: msg.hdr.version=smb_ver();
496: msg.hdr.when_imported.time=time(NULL);
497: msg.hdr.when_imported.zone=sys_timezone(&cfg);
498:
499: if(fromhub || useron.rest&FLAG('Q')) {
500: net=NET_QWK;
501: smb_hfield(&msg,SENDERNETTYPE,sizeof(net),&net);
502: if(!strncmp(qwkbuf+l,"@VIA:",5)) {
503: sprintf(str,"%.128s",qwkbuf+l+5);
504: cp=strchr(str,QWK_NEWLINE);
505: if(cp) *cp=0;
506: l+=strlen(str)+1;
507: cp=str;
508: while(*cp && *cp<=' ') cp++;
509: sprintf(senderaddr,"%s/%s"
510: ,fromhub ? cfg.qhub[fromhub-1]->id : useron.alias,cp);
511: strupr(senderaddr);
512: smb_hfield(&msg,SENDERNETADDR,strlen(senderaddr),senderaddr); }
513: else {
514: if(fromhub)
515: strcpy(senderaddr, cfg.qhub[fromhub-1]->id);
516: else
517: strcpy(senderaddr, useron.alias);
518: strupr(senderaddr);
519: smb_hfield(&msg,SENDERNETADDR,strlen(senderaddr),senderaddr); }
520: sprintf(sender,"%.25s",block+46); } /* From name */
521: else { /* Not Networked */
522: msg.hdr.when_written.zone=sys_timezone(&cfg);
523: sprintf(str,"%u",useron.number);
524: smb_hfield(&msg,SENDEREXT,strlen(str),str);
525: strcpy(sender,(qnet || cfg.inetmail_misc&NMAIL_ALIAS)
526: ? useron.alias : useron.name);
527: }
528: truncsp(sender);
529: smb_hfield(&msg,SENDER,strlen(sender),sender);
530: if(fromhub)
531: msg.idx.from=0;
532: else
533: msg.idx.from=useron.number;
534: if(!strncmp(qwkbuf+l,"@TZ:",4)) {
535: sprintf(str,"%.128s",qwkbuf+l);
536: cp=strchr(str,QWK_NEWLINE);
537: if(cp) *cp=0;
538: l+=strlen(str)+1;
539: cp=str+4;
540: while(*cp && *cp<=' ') cp++;
541: msg.hdr.when_written.zone=(short)ahtoul(cp); }
542: else
543: msg.hdr.when_written.zone=sys_timezone(&cfg);
544: memset(&tm,0,sizeof(tm));
545: tm.tm_mon=((qwkbuf[8]&0xf)*10)+(qwkbuf[9]&0xf);
546: if(tm.tm_mon) tm.tm_mon--; /* 0 based */
547: tm.tm_mday=((qwkbuf[11]&0xf)*10)+(qwkbuf[12]&0xf);
548: tm.tm_year=((qwkbuf[14]&0xf)*10)+(qwkbuf[15]&0xf);
549: if(tm.tm_year<Y2K_2DIGIT_WINDOW)
550: tm.tm_year+=100;
551: tm.tm_hour=((qwkbuf[16]&0xf)*10)+(qwkbuf[17]&0xf);
552: tm.tm_min=((qwkbuf[19]&0xf)*10)+(qwkbuf[20]&0xf); /* From QWK time */
553: tm.tm_sec=0;
554:
555: tm.tm_isdst=-1; /* Do not adjust for DST */
556: msg.hdr.when_written.time=mktime(&tm);
557:
558: sprintf(str,"%.25s",block+71); /* Title */
559: smb_hfield(&msg,SUBJECT,strlen(str),str);
560: }
561:
562: if(qnet) {
563:
564: p++;
565: addr=p;
566: msg.idx.to=qwk_route(addr,fulladdr);
567: if(!fulladdr[0]) { /* Invalid address, so BOUNCE it */
568: /**
569: errormsg(WHERE,ERR_CHK,addr,0);
570: free(qwkbuf);
571: smb_freemsgmem(msg);
572: return;
573: **/
574: smb_hfield(&msg,SENDER,strlen(cfg.sys_id),cfg.sys_id);
575: msg.idx.from=0;
576: msg.idx.to=useron.number;
577: strcpy(to,sender);
578: strcpy(fulladdr,senderaddr);
579: sprintf(str,"BADADDR: %s",addr);
580: smb_hfield(&msg,SUBJECT,strlen(str),str);
581: net=NET_NONE;
582: smb_hfield(&msg,SENDERNETTYPE,sizeof(net),&net);
583: }
584: /* This is required for fixsmb to be able to rebuild the index */
585: sprintf(str,"%u",msg.idx.to);
586: smb_hfield_str(&msg,RECIPIENTEXT,str);
587:
588: smb_hfield(&msg,RECIPIENT,strlen(name),name);
589: net=NET_QWK;
590: smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
591:
592: truncsp(fulladdr);
593: smb_hfield(&msg,RECIPIENTNETADDR,strlen(fulladdr),fulladdr);
594:
595: bprintf(text[NetMailing],to,fulladdr,sender,cfg.sys_id); }
596:
597: if(inet) { /* Internet E-mail */
598:
599: if(cfg.inetmail_cost && !(useron.exempt&FLAG('S'))) {
600: if(useron.cdt+useron.freecdt<cfg.inetmail_cost) {
601: bputs(text[NotEnoughCredits]);
602: free(qwkbuf);
603: smb_freemsgmem(&msg);
604: return; }
605: sprintf(str,text[NetMailCostContinueQ],cfg.inetmail_cost);
606: if(noyes(str)) {
607: free(qwkbuf);
608: smb_freemsgmem(&msg);
609: return; } }
610:
611: net=NET_INTERNET;
612: smb_hfield(&msg,RECIPIENT,strlen(name),name);
613: msg.idx.to=0; /* Out-bound NetMail set to 0 */
614: smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
615: smb_hfield(&msg,RECIPIENTNETADDR,strlen(to),to);
616:
617: bprintf(text[NetMailing],name,to
618: ,cfg.inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name
619: ,cfg.sys_inetaddr); }
620:
621: if(qnet || inet) {
622:
623: bputs(text[WritingIndx]);
624:
625: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
626: errormsg(WHERE,ERR_OPEN,"MAIL",i);
627: free(qwkbuf);
628: smb_freemsgmem(&msg);
629: return; }
630: sprintf(smb.file,"%smail", cfg.data_dir);
631: smb.retry_time=cfg.smb_retry_time;
632: smb.subnum=INVALID_SUB;
633: if((i=smb_open(&smb))!=0) {
634: smb_stack(&smb,SMB_STACK_POP);
635: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
636: free(qwkbuf);
637: smb_freemsgmem(&msg);
638: return; }
639:
640: if(smb_fgetlength(smb.shd_fp)<1L) { /* Create it if it doesn't exist */
641: smb.status.max_crcs=cfg.mail_maxcrcs;
642: smb.status.max_msgs=0;
643: smb.status.max_age=cfg.mail_maxage;
644: smb.status.attr=SMB_EMAIL;
645: if((i=smb_create(&smb))!=0) {
646: smb_close(&smb);
647: smb_stack(&smb,SMB_STACK_POP);
648: errormsg(WHERE,ERR_CREATE,smb.file,i,smb.last_error);
649: free(qwkbuf);
650: smb_freemsgmem(&msg);
651: return; } }
652:
653: length=n*256L; // Extra big for CRLF xlat, was (n-1L)*256L (03/16/96)
654:
655:
656: if(length&0xfff00000UL || !length) {
657: smb_close(&smb);
658: smb_stack(&smb,SMB_STACK_POP);
659: sprintf(str,"REP msg (%ld)",n);
660: errormsg(WHERE,ERR_LEN,str,length);
661: free(qwkbuf);
662: smb_freemsgmem(&msg);
663: return; }
664:
665: if((i=smb_open_da(&smb))!=0) {
666: smb_close(&smb);
667: smb_stack(&smb,SMB_STACK_POP);
668: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
669: free(qwkbuf);
670: smb_freemsgmem(&msg);
671: return; }
672: if(cfg.sys_misc&SM_FASTMAIL)
673: offset=smb_fallocdat(&smb,length,1);
674: else
675: offset=smb_allocdat(&smb,length,1);
676: smb_close_da(&smb);
677:
678: smb_fseek(smb.sdt_fp,offset,SEEK_SET);
679: xlat=XLAT_NONE;
680: smb_fwrite(&smb,&xlat,2,smb.sdt_fp);
681: m=2;
682: for(;l<n*QWK_BLOCK_LEN && m<length;l++) {
683: if(qwkbuf[l]==0 || qwkbuf[l]==LF)
684: continue;
685: if(qwkbuf[l]==QWK_NEWLINE) {
686: smb_fwrite(&smb,crlf,2,smb.sdt_fp);
687: m+=2;
688: continue; }
689: smb_fputc(qwkbuf[l],smb.sdt_fp);
690: m++; }
691:
692: for(ch=0;m<length;m++) /* Pad out with NULLs */
693: smb_fputc(ch,smb.sdt_fp);
694: smb_fflush(smb.sdt_fp);
695:
696: msg.hdr.offset=offset;
697:
698: smb_dfield(&msg,TEXT_BODY,length);
699:
700: i=smb_addmsghdr(&smb,&msg,SMB_SELFPACK);
701: smb_close(&smb);
702: smb_stack(&smb,SMB_STACK_POP);
703:
704: smb_freemsgmem(&msg);
705: if(i!=SMB_SUCCESS) {
706: errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
707: smb_freemsgdat(&smb,offset,length,1);
708: }
709: else { /* Successful */
710: if(inet) {
711: if(cfg.inetmail_sem[0]) /* update semaphore file */
712: ftouch(cmdstr(cfg.inetmail_sem,nulstr,nulstr,NULL));
713: if(!(useron.exempt&FLAG('S')))
714: subtract_cdt(&cfg,&useron,cfg.inetmail_cost); }
715:
716: useron.emails++;
717: logon_emails++;
718: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
719: useron.etoday++;
720: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
721:
722: sprintf(str,"%s sent %s NetMail to %s (%s) via QWK"
723: ,useron.alias
724: ,qnet ? "QWK":"Internet",name,qnet ? fulladdr : to);
725: logline("EN",str); }
726:
727: free((char *)qwkbuf);
728: return; }
729:
730:
731: /****************************** FidoNet **********************************/
732:
733: if(!fidoaddr.zone || !cfg.netmail_dir[0]) { // No fido netmail allowed
734: bputs(text[InvalidNetMailAddr]);
735: free(qwkbuf);
736: return;
737: }
738:
739: memset(&hdr,0,sizeof(hdr)); /* Initialize header to null */
740:
741: if(fromhub || useron.rest&FLAG('Q')) {
742: sprintf(str,"%.25s",block+46); /* From */
743: truncsp(str);
744: sprintf(tmp,"@%s",fromhub ? cfg.qhub[fromhub-1]->id : useron.alias);
745: strupr(tmp);
746: strcat(str,tmp); }
747: else
748: strcpy(str,cfg.netmail_misc&NMAIL_ALIAS ? useron.alias : useron.name);
749: SAFECOPY(hdr.from,str);
750:
751: SAFECOPY(hdr.to,to);
752:
753: /* Look-up in nodelist? */
754:
755: if(cfg.netmail_cost && !(useron.exempt&FLAG('S'))) {
756: if(useron.cdt+useron.freecdt<cfg.netmail_cost) {
757: bputs(text[NotEnoughCredits]);
758: free(qwkbuf);
759: return; }
760: sprintf(str,text[NetMailCostContinueQ],cfg.netmail_cost);
761: if(noyes(str)) {
762: free(qwkbuf);
763: return; } }
764:
765: hdr.destzone =fidoaddr.zone;
766: hdr.destnet =fidoaddr.net;
767: hdr.destnode =fidoaddr.node;
768: hdr.destpoint =fidoaddr.point;
769:
770: for(i=0;i<cfg.total_faddrs;i++)
771: if(fidoaddr.zone==cfg.faddr[i].zone && fidoaddr.net==cfg.faddr[i].net)
772: break;
773: if(i==cfg.total_faddrs) {
774: for(i=0;i<cfg.total_faddrs;i++)
775: if(fidoaddr.zone==cfg.faddr[i].zone)
776: break; }
777: if(i==cfg.total_faddrs)
778: i=0;
779: hdr.origzone =cfg.faddr[i].zone;
780: hdr.orignet =cfg.faddr[i].net;
781: hdr.orignode =cfg.faddr[i].node;
782: hdr.origpoint =cfg.faddr[i].point;
783:
784: smb_faddrtoa(&cfg.faddr[i],str);
785: bprintf(text[NetMailing],hdr.to,smb_faddrtoa(&fidoaddr,tmp),hdr.from,str);
786: tm.tm_mon=((qwkbuf[8]&0xf)*10)+(qwkbuf[9]&0xf);
787: if (tm.tm_mon) tm.tm_mon--;
788: tm.tm_mday=((qwkbuf[11]&0xf)*10)+(qwkbuf[12]&0xf);
789: tm.tm_year=((qwkbuf[14]&0xf)*10)+(qwkbuf[15]&0xf)+1900;
790: tm.tm_hour=((qwkbuf[16]&0xf)*10)+(qwkbuf[17]&0xf);
791: tm.tm_min=((qwkbuf[19]&0xf)*10)+(qwkbuf[20]&0xf); /* From QWK time */
792: tm.tm_sec=0;
793: sprintf(hdr.time,"%02u %3.3s %02u %02u:%02u:%02u" /* To FidoNet */
794: ,tm.tm_mday,mon[tm.tm_mon],TM_YEAR(tm.tm_year)
795: ,tm.tm_hour,tm.tm_min,tm.tm_sec);
796: hdr.attr=(FIDO_LOCAL|FIDO_PRIVATE);
797:
798: if(cfg.netmail_misc&NMAIL_CRASH) hdr.attr|=FIDO_CRASH;
799: if(cfg.netmail_misc&NMAIL_HOLD) hdr.attr|=FIDO_HOLD;
800: if(cfg.netmail_misc&NMAIL_KILL) hdr.attr|=FIDO_KILLSENT;
801:
802: sprintf(str,"%.25s",block+71); /* Title */
803: truncsp(str);
804: p=str;
805: if((SYSOP || useron.exempt&FLAG('F'))
806: && !strnicmp(p,"CR:",3)) { /* Crash over-ride by sysop */
807: p+=3; /* skip CR: */
808: if(*p==' ') p++; /* skip extra space if it exists */
809: hdr.attr|=FIDO_CRASH; }
810:
811: if((SYSOP || useron.exempt&FLAG('F'))
812: && !strnicmp(p,"FR:",3)) { /* File request */
813: p+=3; /* skip FR: */
814: if(*p==' ') p++;
815: hdr.attr|=FIDO_FREQ; }
816:
817: if((SYSOP || useron.exempt&FLAG('F'))
818: && !strnicmp(p,"RR:",3)) { /* Return receipt request */
819: p+=3; /* skip RR: */
820: if(*p==' ') p++;
821: hdr.attr|=FIDO_RRREQ; }
822:
823: if((SYSOP || useron.exempt&FLAG('F'))
824: && !strnicmp(p,"FA:",3)) { /* File attachment */
825: p+=3; /* skip FA: */
826: if(*p==' ') p++;
827: hdr.attr|=FIDO_FILE; }
828:
829: SAFECOPY(hdr.subj,p);
830:
831: for(i=1;i;i++) {
832: sprintf(str,"%s%u.msg", cfg.netmail_dir,i);
833: if(!fexistcase(str))
834: break; }
835: if(!i) {
836: bputs(text[TooManyEmailsToday]);
837: return; }
838: if((fido=nopen(str,O_WRONLY|O_CREAT|O_EXCL))==-1) {
839: free(qwkbuf);
840: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_EXCL);
841: return; }
842: write(fido,&hdr,sizeof(hdr));
843:
844: pt_zone_kludge(hdr,fido);
845:
846: if(cfg.netmail_misc&NMAIL_DIRECT) {
847: sprintf(str,"\1FLAGS DIR\r\n");
848: write(fido,str,strlen(str)); }
849:
850: l=QWK_BLOCK_LEN;
851:
852: if(into==NULL) { /* If name@addr on first line, skip first line */
853: while(l<n*QWK_BLOCK_LEN && qwkbuf[l]!=QWK_NEWLINE) l++;
854: l++; }
855:
856: while(l<n*QWK_BLOCK_LEN) {
857: if(qwkbuf[l]==CTRL_A) /* Ctrl-A, so skip it and the next char */
858: l++;
859: else if(qwkbuf[l]!=LF) {
860: if(qwkbuf[l]==QWK_NEWLINE) /* QWK cr/lf char converted to hard CR */
861: qwkbuf[l]=CR;
862: write(fido,(char *)qwkbuf+l,1); }
863: l++; }
864: l=0;
865: write(fido,&l,1); /* Null terminator */
866: close(fido);
867: free((char *)qwkbuf);
868: if(cfg.netmail_sem[0]) /* update semaphore file */
869: ftouch(cmdstr(cfg.netmail_sem,nulstr,nulstr,NULL));
870: if(!(useron.exempt&FLAG('S')))
871: subtract_cdt(&cfg,&useron,cfg.netmail_cost);
872:
873: useron.emails++;
874: logon_emails++;
875: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
876: useron.etoday++;
877: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
878:
879: sprintf(str,"%s sent NetMail to %s @%s via QWK"
880: ,useron.alias
881: ,hdr.to,smb_faddrtoa(&fidoaddr,tmp));
882: logline("EN",str);
883: }
884:
885: /****************************************************************************/
886: /* Returns the FidoNet address kept in str as ASCII. */
887: /****************************************************************************/
888: faddr_t atofaddr(scfg_t* cfg, char *str)
889: {
890: char *p;
891: faddr_t addr;
892:
893: addr.zone=addr.net=addr.node=addr.point=0;
894: if((p=strchr(str,':'))!=NULL) {
895: addr.zone=atoi(str);
896: addr.net=atoi(p+1); }
897: else {
898: if(cfg->total_faddrs)
899: addr.zone=cfg->faddr[0].zone;
900: else
901: addr.zone=1;
902: addr.net=atoi(str); }
903: if(!addr.zone) /* no such thing as zone 0 */
904: addr.zone=1;
905: if((p=strchr(str,'/'))!=NULL)
906: addr.node=atoi(p+1);
907: else {
908: if(cfg->total_faddrs)
909: addr.net=cfg->faddr[0].net;
910: else
911: addr.net=1;
912: addr.node=atoi(str); }
913: if((p=strchr(str,'.'))!=NULL)
914: addr.point=atoi(p+1);
915: return(addr);
916: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.