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