|
|
1.1 root 1: #line 1 "MSG2.C"
2:
3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
4:
5: #include "sbbs.h"
6:
7: #define MAX_LINE_LEN 82L
8:
9: char *qstr=" > %.76s\r\n";
10:
11: int qwk_route(char *inaddr, char *fulladdr);
12:
13: void remove_re(char *str)
14: {
15: while(!strnicmp(str,"RE:",3)) {
16: strcpy(str,str+3);
17: while(str[0]==SP)
18: strcpy(str,str+1); }
19: }
20:
21: /****************************************************************************/
22: /* Modify 'str' to for quoted format. Remove ^A codes, etc. */
23: /****************************************************************************/
24: void quotestr(char *str)
25: {
26: char tmp[512];
27: int i,j;
28:
29: j=strlen(str);
30: while(j && (str[j-1]==SP || str[j-1]==LF || str[j-1]==CR)) j--;
31: str[j]=0;
32: remove_ctrl_a(str);
33: }
34:
35: void editor_inf(int xeditnum,char *dest, char *title,int mode
36: ,uint subnum)
37: {
38: char str[512];
39: int file;
40:
41: xeditnum--;
42:
43: if(xedit[xeditnum]->misc&QUICKBBS) {
44: sprintf(str,"%sMSGINF",node_dir);
45: if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
46: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
47: return; }
48: sprintf(str,"%s\r\n%s\r\n%s\r\n%u\r\n%s\r\n%s\r\n"
49: ,(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_NAME) ? useron.name
50: : useron.alias
51: ,dest,title,1
52: ,mode&WM_NETMAIL ? "NetMail"
53: :mode&WM_EMAIL ? "Electronic Mail"
54: :subnum==INVALID_SUB ? nulstr
55: :sub[subnum]->sname
56: ,mode&WM_PRIVATE ? "YES":"NO");
57: write(file,str,strlen(str));
58: close(file); }
59: else {
60: sprintf(str,"%sEDITOR.INF",node_dir);
61: if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
62: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
63: return; }
64: sprintf(str,"%s\r\n%s\r\n%u\r\n%s\r\n%s\r\n%u\r\n"
65: ,title,dest,useron.number
66: ,(subnum!=INVALID_SUB && sub[subnum]->misc&SUB_NAME) ? useron.name
67: : useron.alias
68: ,useron.name,useron.level);
69: write(file,str,strlen(str));
70: close(file); }
71: }
72:
73: /****************************************************************************/
74: /* Creates a message (post or mail) using standard line editor. 'fname' is */
75: /* is name of file to create, 'top' is a buffer to place at beginning of */
76: /* message and 'title' is the title (70chars max) for the message. */
77: /* 'dest' contains a text description of where the message is going. */
78: /* Returns positive if successful or 0 if aborted. */
79: /****************************************************************************/
80: char writemsg(char *fname, char *top, char *title, int mode, int subnum
81: ,char *dest)
82: {
83: uchar str[256],quote[128],msgtmp[32],c,HUGE16 *buf,ex_mode=0,*p,*tp
84: ,useron_level;
85: int i,j,file,linesquoted=0;
86: long length,qlen,qtime;
87: ulong l;
88: FILE *stream;
89:
90: useron_level=useron.level;
91:
92: if((buf=(char HUGE16*)LMALLOC(level_linespermsg[useron_level]*MAX_LINE_LEN))
93: ==NULL) {
94: errormsg(WHERE,ERR_ALLOC,fname
95: ,level_linespermsg[useron_level]*MAX_LINE_LEN);
96: return(0); }
97:
98: if(mode&WM_NETMAIL ||
99: (!(mode&(WM_EMAIL|WM_NETMAIL)) && sub[subnum]->misc&SUB_PNET))
100: mode|=WM_NOTOP;
101:
102: if(useron.xedit && xedit[useron.xedit-1]->misc&QUICKBBS)
103: strcpy(msgtmp,"MSGTMP");
104: else
105: strcpy(msgtmp,"INPUT.MSG");
106:
107: if(mode&WM_QUOTE && !(useron.rest&FLAG('J'))
108: && ((mode&(WM_EMAIL|WM_NETMAIL) && sys_misc&SM_QUOTE_EM)
109: || (!(mode&(WM_EMAIL|WM_NETMAIL)) && (uint)subnum!=INVALID_SUB
110: && sub[subnum]->misc&SUB_QUOTE))) {
111:
112: /* Quote entire message to MSGTMP or INPUT.MSG */
113:
114: if(useron.xedit && xedit[useron.xedit-1]->misc"EALL) {
115: sprintf(str,"%sQUOTES.TXT",node_dir);
116: if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
117: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
118: LFREE(buf);
119: return(0); }
120:
121: sprintf(str,"%s%s",node_dir,msgtmp); /* file for quoted msg */
122: if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
123: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
124: LFREE(buf);
125: fclose(stream);
126: return(0); }
127:
128: while(!feof(stream) && !ferror(stream)) {
129: if(!fgets(str,255,stream))
130: break;
131: quotestr(str);
132: sprintf(tmp,qstr,str);
133: write(file,tmp,strlen(tmp));
134: linesquoted++; }
135: fclose(stream);
136: close(file); }
137:
138: /* Quote nothing to MSGTMP or INPUT.MSG automatically */
139:
140: else if(useron.xedit && xedit[useron.xedit-1]->misc"ENONE)
141: ;
142:
143: else if(yesno(text[QuoteMessageQ])) {
144: sprintf(str,"%sQUOTES.TXT",node_dir);
145: if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
146: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
147: LFREE(buf);
148: return(0); }
149:
150: sprintf(str,"%s%s",node_dir,msgtmp); /* file for quoted msg */
151: if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
152: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
153: LFREE(buf);
154: fclose(stream);
155: return(0); }
156:
157: l=ftell(stream); /* l now points to start of message */
158:
159: while(online) {
160: sprintf(str,text[QuoteLinesPrompt],linesquoted ? "Done":"All");
161: mnemonics(str);
162: i=getstr(quote,10,K_UPPER);
163: if(sys_status&SS_ABORT) {
164: fclose(stream);
165: close(file);
166: LFREE(buf);
167: return(0); }
168: if(!i && linesquoted)
169: break;
170: if(!i || quote[0]=='A') { /* Quote all */
171: fseek(stream,l,SEEK_SET);
172: while(!feof(stream) && !ferror(stream)) {
173: if(!fgets(str,255,stream))
174: break;
175: quotestr(str);
176: sprintf(tmp,qstr,str);
177: write(file,tmp,strlen(tmp));
178: linesquoted++; }
179: break; }
180: if(quote[0]=='L') {
181: fseek(stream,l,SEEK_SET);
182: i=1;
183: CRLF;
184: attr(LIGHTGRAY);
185: while(!feof(stream) && !ferror(stream) && !msgabort()) {
186: if(!fgets(str,255,stream))
187: break;
188: quotestr(str);
189: bprintf("%3d: %.74s\r\n",i,str);
190: i++; }
191: continue; }
192:
193: if(!isdigit(quote[0]))
194: break;
195: p=quote;
196: while(p) {
197: if(*p==',' || *p==SP)
198: p++;
199: i=atoi(p);
200: if(!i)
201: break;
202: fseek(stream,l,SEEK_SET);
203: j=1;
204: while(!feof(stream) && !ferror(stream) && j<i) {
205: if(!fgets(tmp,255,stream))
206: break;
207: j++; } /* skip beginning */
208: tp=strchr(p,'-'); /* tp for temp pointer */
209: if(tp) { /* range */
210: i=atoi(tp+1);
211: while(!feof(stream) && !ferror(stream) && j<=i) {
212: if(!fgets(str,255,stream))
213: break;
214: quotestr(str);
215: sprintf(tmp,qstr,str);
216: write(file,tmp,strlen(tmp));
217: linesquoted++;
218: j++; } }
219: else { /* one line */
220: if(fgets(str,255,stream)) {
221: quotestr(str);
222: sprintf(tmp,qstr,str);
223: write(file,tmp,strlen(tmp));
224: linesquoted++; } }
225: p=strchr(p,',');
226: // if(!p) p=strchr(p,SP); 02/05/96 huh?
227: } }
228:
229: fclose(stream);
230: close(file); } }
231: else {
232: sprintf(str,"%sQUOTES.TXT",node_dir);
233: remove(str); }
234:
235: if(!online || sys_status&SS_ABORT) {
236: LFREE(buf);
237: return(0); }
238:
239: if(!(mode&WM_EXTDESC)) {
240: if(mode&WM_FILE) {
241: c=12;
242: CRLF;
243: bputs(text[Filename]); }
244: else {
245: c=LEN_TITLE;
246: bputs(text[TitlePrompt]); }
247: if(!(mode&(WM_EMAIL|WM_NETMAIL)) && !(mode&WM_FILE)
248: && sub[subnum]->misc&(SUB_QNET /* |SUB_PNET */ ))
249: c=25;
250: if(mode&WM_QWKNET)
251: c=25;
252: if(!getstr(title,c,mode&WM_FILE ? K_LINE|K_UPPER : K_LINE|K_EDIT|K_AUTODEL)
253: && useron_level && useron.logons) {
254: LFREE(buf);
255: return(0); }
256: if(!(mode&(WM_EMAIL|WM_NETMAIL)) && sub[subnum]->misc&SUB_QNET
257: && !SYSOP
258: && (!stricmp(title,"DROP") || !stricmp(title,"ADD")
259: || !strnicmp(dest,"SBBS",4))) {
260: LFREE(buf); /* Users can't post DROP or ADD in QWK netted subs */
261: return(0); } } /* or messages to "SBBS" */
262:
263: if(!online || sys_status&SS_ABORT) {
264: LFREE(buf);
265: return(0); }
266:
267: /* Create WWIV compatible EDITOR.INF file */
268:
269: if(useron.xedit) {
270: editor_inf(useron.xedit,dest,title,mode,subnum);
271: if(xedit[useron.xedit-1]->type) {
272: gettimeleft();
273: xtrndat(useron.alias,node_dir,xedit[useron.xedit-1]->type,timeleft); }
274: }
275:
276: if(console&CON_RAW_IN) {
277: bprintf(text[EnterMsgNowRaw]
278: ,(ulong)level_linespermsg[useron_level]*MAX_LINE_LEN);
279: if(top[0] && !(mode&WM_NOTOP)) {
280: strcpy((char *)buf,top);
281: strcat((char *)buf,crlf);
282: l=strlen((char *)buf); }
283: else
284: l=0;
285: while(l<level_linespermsg[useron_level]*MAX_LINE_LEN) {
286: c=getkey(0);
287: if(sys_status&SS_ABORT) { /* Ctrl-C */
288: LFREE(buf);
289: return(0); }
290: if((c==ESC || c==1) && useron.rest&FLAG('A')) /* ANSI restriction */
291: continue;
292: #ifndef __OS2__
293: if(lclaes() && c=='"') c=7; /* convert keyboard reassignmnet to beep */
294: #endif
295: if(c==7 && useron.rest&FLAG('B')) /* Beep restriction */
296: continue;
297: if(!(console&CON_RAW_IN)) /* Ctrl-Z was hit */
298: break;
299: outchar(c);
300: buf[l++]=c; }
301: buf[l]=0;
302: if(l==level_linespermsg[useron_level]*MAX_LINE_LEN)
303: bputs(text[OutOfBytes]); }
304:
305:
306: else if((online==ON_LOCAL && node_misc&NM_LCL_EDIT && node_editor[0])
307: || useron.xedit) {
308:
309: if(useron.xedit && xedit[useron.xedit-1]->misc&IO_INTS) {
310: ex_mode|=EX_OUTL;
311: if(online==ON_REMOTE)
312: ex_mode|=(EX_OUTR|EX_INR);
313: if(xedit[useron.xedit-1]->misc&WWIVCOLOR)
314: ex_mode|=EX_WWIV; }
315:
316: sprintf(str,"%s%s",node_dir,msgtmp); /* temporary file for input */
317: if(!linesquoted && fexist(str))
318: remove(str);
319: if(linesquoted) {
320: qlen=flength(str);
321: qtime=fdate(str); }
322: if(online==ON_LOCAL) {
323: if(node_misc&NM_LCL_EDIT && node_editor[0])
324: external(cmdstr(node_editor,str,nulstr,NULL)
325: ,0); /* EX_CC removed and EX_OUTL removed */
326: else
327: external(cmdstr(xedit[useron.xedit-1]->lcmd,str,nulstr,NULL)
328: ,ex_mode); }
329:
330: else {
331: rioctl(IOCM|PAUSE|ABORT);
332: external(cmdstr(xedit[useron.xedit-1]->rcmd,str,nulstr,NULL),ex_mode);
333: rioctl(IOSM|PAUSE|ABORT); }
334: checkline();
335: if(!fexist(str) || !online
336: || (linesquoted && qlen==flength(str) && qtime==fdate(str))) {
337: LFREE(buf);
338: return(0); }
339: buf[0]=0;
340: if(!(mode&WM_NOTOP))
341: strcpy((char *)buf,top);
342: if((file=nopen(str,O_RDONLY))==-1) {
343: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
344: LFREE(buf);
345: return(0); }
346: length=filelength(file);
347: l=strlen((char *)buf); /* reserve space for top and terminating null */
348: /* truncate if too big */
349: if(length>(level_linespermsg[useron_level]*MAX_LINE_LEN)-(l+1)) {
350: length=(level_linespermsg[useron_level]*MAX_LINE_LEN)-(l+1);
351: bputs(text[OutOfBytes]); }
352: lread(file,buf+l,length);
353: close(file);
354: // remove(str); /* no need to save the temp input file */
355: buf[l+length]=0; }
356: else {
357: buf[0]=0;
358: if(linesquoted) {
359: sprintf(str,"%s%s",node_dir,msgtmp);
360: if((file=nopen(str,O_RDONLY))!=-1) {
361: length=filelength(file);
362: l=length>level_linespermsg[useron_level]*MAX_LINE_LEN
363: ? level_linespermsg[useron_level]*MAX_LINE_LEN : length;
364: lread(file,buf,l);
365: buf[l]=0;
366: close(file);
367: // remove(str);
368: } }
369: if(!(msgeditor((char *)buf,mode&WM_NOTOP ? nulstr : top,title))) {
370: LFREE(buf);
371: return(0); } }
372:
373: now=time(NULL);
374: bputs(text[Saving]);
375: if((stream=fnopen(&file,fname,O_WRONLY|O_CREAT|O_TRUNC))==NULL) {
376: errormsg(WHERE,ERR_OPEN,fname,O_WRONLY|O_CREAT|O_TRUNC);
377: LFREE(buf);
378: return(0); }
379: for(l=i=0;buf[l] && i<level_linespermsg[useron_level];l++) {
380: if(buf[l]==141 && useron.xedit && xedit[useron.xedit-1]->misc&QUICKBBS) {
381: fwrite(crlf,2,1,stream);
382: i++;
383: continue; }
384: if(buf[l]==LF && (!l || buf[l-1]!=CR) && useron.xedit
385: && xedit[useron.xedit-1]->misc&EXPANDLF) {
386: fwrite(crlf,2,1,stream);
387: i++;
388: continue; }
389: if(!(mode&(WM_EMAIL|WM_NETMAIL))
390: && (!l || buf[l-1]==LF)
391: && buf[l]=='-' && buf[l+1]=='-' && buf[l+2]=='-'
392: && (buf[l+3]==SP || buf[l+3]==TAB || buf[l+3]==CR))
393: buf[l+1]='+';
394: if(buf[l]==LF)
395: i++;
396: fputc(buf[l],stream); }
397:
398: if(buf[l])
399: bputs(text[NoMoreLines]);
400: fclose(stream);
401: LFREE((char *)buf);
402: bprintf(text[SavedNBytes],l,i);
403: return(1);
404: }
405:
406:
407: /****************************************************************************/
408: /* Removes from file 'str' every LF terminated line that starts with 'str2' */
409: /* That is divisable by num. Function skips first 'skip' number of lines */
410: /****************************************************************************/
411: void removeline(char *str, char *str2, char num, char skip)
412: {
413: char HUGE16 *buf;
414: char slen,c;
415: int i,file;
416: ulong l=0,m,flen;
417: FILE *stream;
418:
419: if((file=nopen(str,O_RDONLY))==-1) {
420: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
421: return; }
422: flen=filelength(file);
423: slen=strlen(str2);
424: if((buf=(char *)MALLOC(flen))==NULL) {
425: close(file);
426: errormsg(WHERE,ERR_ALLOC,str,flen);
427: return; }
428: if(lread(file,buf,flen)!=flen) {
429: close(file);
430: errormsg(WHERE,ERR_READ,str,flen);
431: FREE(buf);
432: return; }
433: close(file);
434: if((stream=fnopen(&file,str,O_WRONLY|O_TRUNC))==NULL) {
435: close(file);
436: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_TRUNC);
437: FREE(buf);
438: return; }
439: for(i=0;l<flen && i<skip;l++) {
440: fputc(buf[l],stream);
441: if(buf[l]==LF)
442: i++; }
443: while(l<flen) {
444: if(!strncmp((char *)buf+l,str2,slen)) {
445: for(i=0;i<num && l<flen;i++) {
446: while(l<flen && buf[l]!=LF) l++;
447: l++; } }
448: else {
449: for(i=0;i<num && l<flen;i++) {
450: while(l<flen && buf[l]!=LF) fputc(buf[l++],stream);
451: fputc(buf[l++],stream); } } }
452: fclose(stream);
453: FREE((char *)buf);
454: }
455:
456: /*****************************************************************************/
457: /* The Synchronet editor. */
458: /* Returns the number of lines edited. */
459: /*****************************************************************************/
460: ulong msgeditor(char *buf, char *top, char *title)
461: {
462: int i,j,line,lines=0,maxlines;
463: char strin[256],**str,done=0;
464: ulong l,m;
465:
466: if(online==ON_REMOTE) {
467: rioctl(IOCM|ABORT);
468: rioctl(IOCS|ABORT); }
469:
470: maxlines=level_linespermsg[useron.level];
471:
472: if((str=(char **)MALLOC(sizeof(char *)*(maxlines+1)))==NULL) {
473: errormsg(WHERE,ERR_ALLOC,"msgeditor",sizeof(char *)*(maxlines+1));
474: return(0); }
475: m=strlen(buf);
476: l=0;
477: while(l<m && lines<maxlines) {
478: msgabort(); /* to allow pausing */
479: if((str[lines]=MALLOC(MAX_LINE_LEN))==NULL) {
480: errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
481: for(i=0;i<lines;i++)
482: FREE(str[lines]);
483: FREE(str);
484: if(online==ON_REMOTE)
485: rioctl(IOSM|ABORT);
486: return(0); }
487: for(i=0;i<79 && l<m;i++,l++) {
488: if(buf[l]==CR) {
489: l+=2;
490: break; }
491: if(buf[l]==TAB) {
492: if(!(i%8)) /* hard-coded tabstop of 8 */
493: str[lines][i++]=SP; /* for expansion */
494: while(i%8 && i<79)
495: str[lines][i++]=SP;
496: i--;
497: /***
498: bprintf("\r\nMessage editor: Expanded tab on line #%d",lines+1);
499: ***/ }
500: else str[lines][i]=buf[l]; }
501: if(i==79) {
502: if(buf[l]==CR)
503: l+=2;
504: else
505: bprintf("\r\nMessage editor: Split line #%d",lines+1); }
506: str[lines][i]=0;
507: lines++; }
508: if(lines)
509: bprintf("\r\nMessage editor: Read in %d lines\r\n",lines);
510: bprintf(text[EnterMsgNow],maxlines);
511: for(i=0;i<79;i++)
512: if(i%TABSIZE || !i)
513: outchar('-');
514: else outchar('+');
515: CRLF;
516: putmsg(top,P_SAVEATR|P_NOATCODES);
517: for(line=0;line<lines && !msgabort();line++) { /* display lines in buf */
518: putmsg(str[line],P_SAVEATR|P_NOATCODES);
519: if(useron.misc&ANSI)
520: bputs("\x1b[K"); /* delete to end of line */
521: CRLF; }
522: SYNC;
523: if(online==ON_REMOTE)
524: rioctl(IOSM|ABORT);
525: while(online && !done) {
526: checkline();
527: if(line==lines) {
528: if((str[line]=MALLOC(MAX_LINE_LEN))==NULL) {
529: errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
530: for(i=0;i<lines;i++)
531: FREE(str[i]);
532: FREE(str);
533: return(0); }
534: str[line][0]=0; }
535: if(line>(maxlines-10)) {
536: if(line==maxlines)
537: bputs(text[NoMoreLines]);
538: else
539: bprintf(text[OnlyNLinesLeft],maxlines-line); }
540: strcpy(strin,str[line]);
541: do {
542: if(!line)
543: outchar(CR);
544: getstr(strin,79,K_WRAP|K_MSG|K_EDIT);
545: } while(console&CON_UPARROW && !line);
546:
547: if(sys_status&SS_ABORT) {
548: if(line==lines)
549: FREE(str[line]);
550: continue; }
551: if(strin[0]=='/' && strlen(strin)<8) {
552: if(!stricmp(strin,"/DEBUG") && SYSOP) {
553: if(line==lines)
554: FREE(str[line]);
555: bprintf("\r\nline=%d lines=%d rows=%d\r\n",line,lines,rows);
556: continue; }
557: else if(!stricmp(strin,"/ABT")) {
558: if(line==lines) /* delete a line */
559: FREE(str[line]);
560: for(i=0;i<lines;i++)
561: FREE(str[i]);
562: FREE(str);
563: return(0); }
564: else if(toupper(strin[1])=='D') {
565: if(line==lines) /* delete a line */
566: FREE(str[line]);
567: if(!lines)
568: continue;
569: i=atoi(strin+2)-1;
570: if(i==-1) /* /D means delete last line */
571: i=lines-1;
572: if(i>=lines || i<0)
573: bputs(text[InvalidLineNumber]);
574: else {
575: FREE(str[i]);
576: lines--;
577: while(i<lines) {
578: str[i]=str[i+1];
579: i++; }
580: if(line>lines)
581: line=lines; }
582: continue; }
583: else if(toupper(strin[1])=='I') {
584: if(line==lines) /* insert a line before number x */
585: FREE(str[line]);
586: if(line==maxlines || !lines)
587: continue;
588: i=atoi(strin+2)-1;
589: if(i==-1)
590: i=lines-1;
591: if(i>=lines || i<0)
592: bputs(text[InvalidLineNumber]);
593: else {
594: for(line=lines;line>i;line--) /* move the pointers */
595: str[line]=str[line-1];
596: if((str[i]=MALLOC(MAX_LINE_LEN))==NULL) {
597: errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
598: for(i=0;i<lines;i++)
599: FREE(str[i]);
600: FREE(str);
601: return(0); }
602: str[i][0]=0;
603: line=++lines; }
604: continue; }
605: else if(toupper(strin[1])=='E') {
606: if(line==lines) /* edit a line */
607: FREE(str[line]);
608: if(!lines)
609: continue;
610: i=atoi(strin+2)-1;
611: j=K_MSG|K_EDIT; /* use j for the getstr mode */
612: if(i==-1) { /* /E means edit last line */
613: i=lines-1;
614: j|=K_WRAP; } /* wrap when editing last line */
615: if(i>=lines || i<0)
616: bputs(text[InvalidLineNumber]);
617: else
618: getstr(str[i],79,j);
619: continue; }
620: else if(!stricmp(strin,"/CLR")) {
621: bputs(text[MsgCleared]);
622: if(line!=lines)
623: lines--;
624: for(i=0;i<=lines;i++)
625: FREE(str[i]);
626: line=0;
627: lines=0;
628: putmsg(top,P_SAVEATR|P_NOATCODES);
629: continue; }
630: else if(toupper(strin[1])=='L') { /* list message */
631: if(line==lines)
632: FREE(str[line]);
633: if(lines)
634: i=!noyes(text[WithLineNumbers]);
635: CRLF;
636: attr(LIGHTGRAY);
637: putmsg(top,P_SAVEATR|P_NOATCODES);
638: if(!lines) {
639: continue; }
640: j=atoi(strin+2);
641: if(j) j--; /* start from line j */
642: while(j<lines && !msgabort()) {
643: if(i) { /* line numbers */
644: sprintf(tmp,"%3d: %-.74s",j+1,str[j]);
645: putmsg(tmp,P_SAVEATR|P_NOATCODES); }
646: else
647: putmsg(str[j],P_SAVEATR|P_NOATCODES);
648: if(useron.misc&ANSI)
649: bputs("\x1b[K"); /* delete to end of line */
650: CRLF;
651: j++; }
652: SYNC;
653: continue; }
654: else if(!stricmp(strin,"/S")) { /* Save */
655: if(line==lines)
656: FREE(str[line]);
657: done=1;
658: continue;}
659: else if(!stricmp(strin,"/T")) { /* Edit title */
660: if(line==lines)
661: FREE(str[line]);
662: if(title[0]) {
663: bputs(text[TitlePrompt]);
664: getstr(title,LEN_TITLE,K_LINE|K_EDIT|K_AUTODEL);
665: SYNC;
666: CRLF; }
667: continue; }
668: else if(!stricmp(strin,"/?")) {
669: if(line==lines)
670: FREE(str[line]);
671: menu("EDITOR"); /* User Editor Commands */
672: SYNC;
673: continue; }
674: else if(!stricmp(strin,"/ATTR")) {
675: if(line==lines)
676: FREE(str[line]);
677: menu("ATTR"); /* User ANSI Commands */
678: SYNC;
679: continue; } }
680: strcpy(str[line],strin);
681: if(line<maxlines)
682: line++;
683: else
684: FREE(str[line]);
685: if(line>lines)
686: lines++;
687: if(console&CON_UPARROW) {
688: outchar(CR);
689: bprintf("\x1b[A\x1b[K"); /* up one line, clear to eol */
690: line-=2; }
691: }
692: if(!online) {
693: for(i=0;i<lines;i++)
694: FREE(str[i]);
695: FREE(str);
696: return(0); }
697: strcpy(buf,top);
698: for(i=0;i<lines;i++) {
699: strcat(buf,str[i]);
700: strcat(buf,crlf);
701: FREE(str[i]); }
702: FREE(str);
703: return(lines);
704: }
705:
706:
707: /****************************************************************************/
708: /* Edits an existing file or creates a new one in MSG format */
709: /****************************************************************************/
710: void editfile(char *str)
711: {
712: char *buf,str2[128],mode=0; /* EX_CC */
713: int file;
714: long length,maxlines,lines,l;
715:
716: maxlines=level_linespermsg[useron.level];
717: sprintf(str2,"%sQUOTES.TXT",node_dir);
718: remove(str2);
719: if(node_editor[0] && online==ON_LOCAL) {
720: external(cmdstr(node_editor,str,nulstr,NULL),0); /* EX_CC */
721: return; }
722: if(useron.xedit) {
723: editor_inf(useron.xedit,nulstr,nulstr,0,INVALID_SUB);
724: if(xedit[useron.xedit-1]->misc&IO_INTS) {
725: mode|=EX_OUTL;
726: if(online==ON_REMOTE)
727: mode|=(EX_OUTR|EX_INR);
728: if(xedit[useron.xedit-1]->misc&WWIVCOLOR)
729: mode|=EX_WWIV; }
730: if(online==ON_LOCAL)
731: external(cmdstr(xedit[useron.xedit-1]->lcmd,str,nulstr,NULL),mode);
732: else {
733: rioctl(IOCM|PAUSE|ABORT);
734: external(cmdstr(xedit[useron.xedit-1]->rcmd,str,nulstr,NULL),mode);
735: rioctl(IOSM|PAUSE|ABORT); }
736: return; }
737: if((buf=(char *)MALLOC(maxlines*MAX_LINE_LEN))==NULL) {
738: errormsg(WHERE,ERR_ALLOC,nulstr,maxlines*MAX_LINE_LEN);
739: return; }
740: if((file=nopen(str,O_RDONLY))!=-1) {
741: length=filelength(file);
742: if(length>(ulong)maxlines*MAX_LINE_LEN) {
743: attr(color[clr_err]);
744: bprintf("\7\r\nFile size (%lu bytes) is larger than (%lu).\r\n"
745: ,length,(ulong)maxlines*MAX_LINE_LEN);
746: close(file);
747: FREE(buf); }
748: if(read(file,buf,length)!=length) {
749: close(file);
750: FREE(buf);
751: errormsg(WHERE,ERR_READ,str,length);
752: return; }
753: buf[length]=0;
754: close(file); }
755: else {
756: buf[0]=0;
757: bputs(text[NewFile]); }
758: if(!msgeditor(buf,nulstr,nulstr)) {
759: FREE(buf);
760: return; }
761: bputs(text[Saving]);
762: if((file=nopen(str,O_CREAT|O_WRONLY|O_TRUNC))==-1) {
763: errormsg(WHERE,ERR_OPEN,str,O_CREAT|O_WRONLY|O_TRUNC);
764: FREE(buf);
765: return; }
766: if(write(file,buf,strlen(buf))!=strlen(buf)) {
767: close(file);
768: errormsg(WHERE,ERR_WRITE,str,strlen(buf));
769: FREE(buf);
770: return; }
771: for(l=lines=0;buf[l];l++)
772: if(buf[l]==LF)
773: lines++;
774: bprintf(text[SavedNBytes],l,lines);
775: close(file);
776: FREE(buf);
777: return;
778: }
779:
780: /*************************/
781: /* Copy file attachments */
782: /*************************/
783: void copyfattach(uint to, uint from, char *title)
784: {
785: char str[128],str2[128],str3[128],*tp,*sp,*p;
786: uint i;
787:
788: strcpy(str,title);
789: tp=str;
790: while(1) {
791: p=strchr(tp,SP);
792: if(p) *p=0;
793: sp=strrchr(tp,'/'); /* sp is slash pointer */
794: if(!sp) sp=strrchr(tp,'\\');
795: if(sp) tp=sp+1;
796: sprintf(str2,"%sFILE\\%04u.IN\\%s" /* str2 is path/fname */
797: ,data_dir,to,tp);
798: sprintf(str3,"%sFILE\\%04u.IN\\%s" /* str2 is path/fname */
799: ,data_dir,from,tp);
800: if(strcmp(str2,str3))
801: mv(str3,str2,1);
802: if(!p)
803: break;
804: tp=p+1; }
805: }
806:
807:
808: /****************************************************************************/
809: /* Forwards mail (fname) to usernumber */
810: /* Called from function readmail */
811: /****************************************************************************/
812: void forwardmail(smbmsg_t *msg, ushort usernumber)
813: {
814: char str[256],touser[128];
815: int i;
816: node_t node;
817: msghdr_t hdr=msg->hdr;
818: idxrec_t idx=msg->idx;
819:
820: if(useron.etoday>=level_emailperday[useron.level] && !SYSOP) {
821: bputs(text[TooManyEmailsToday]);
822: return; }
823: if(useron.rest&FLAG('F')) {
824: bputs(text[R_Forward]);
825: return; }
826: if(usernumber==1 && useron.rest&FLAG('S')) {
827: bprintf(text[R_Feedback],sys_op);
828: return; }
829: if(usernumber!=1 && useron.rest&FLAG('E')) {
830: bputs(text[R_Email]);
831: return; }
832:
833: msg->idx.attr&=~(MSG_READ|MSG_DELETE);
834: msg->hdr.attr=msg->idx.attr;
835:
836:
837: smb_hfield(msg,SENDER,strlen(useron.alias),useron.alias);
838: sprintf(str,"%u",useron.number);
839: smb_hfield(msg,SENDEREXT,strlen(str),str);
840:
841: username(usernumber,touser);
842: smb_hfield(msg,RECIPIENT,strlen(touser),touser);
843: sprintf(str,"%u",usernumber);
844: smb_hfield(msg,RECIPIENTEXT,sizeof(str),str);
845: msg->idx.to=usernumber;
846:
847: now=time(NULL);
848: smb_hfield(msg,FORWARDED,sizeof(time_t),&now);
849:
850:
851: if((i=smb_open_da(&smb))!=0) {
852: errormsg(WHERE,ERR_OPEN,smb.file,i);
853: return; }
854: if((i=smb_incdat(&smb,msg->hdr.offset,smb_getmsgdatlen(msg),1))!=0) {
855: errormsg(WHERE,ERR_WRITE,smb.file,i);
856: return; }
857: smb_close_da(&smb);
858:
859:
860: if((i=smb_addmsghdr(&smb,msg,SMB_SELFPACK))!=0) {
861: errormsg(WHERE,ERR_WRITE,smb.file,i);
862: return; }
863:
864: if(msg->hdr.auxattr&MSG_FILEATTACH)
865: copyfattach(usernumber,useron.number,msg->subj);
866:
867: bprintf(text[Forwarded],username(usernumber,str),usernumber);
868: sprintf(str,"Forwarded mail to %s #%d",username(usernumber,tmp)
869: ,usernumber);
870: logline("E",str);
871: msg->idx=idx;
872: msg->hdr=hdr;
873:
874:
875: if(usernumber==1) {
876: useron.fbacks++;
877: logon_fbacks++;
878: putuserrec(useron.number,U_FBACKS,5,itoa(useron.fbacks,tmp,10)); }
879: else {
880: useron.emails++;
881: logon_emails++;
882: putuserrec(useron.number,U_EMAILS,5,itoa(useron.emails,tmp,10)); }
883: useron.etoday++;
884: putuserrec(useron.number,U_ETODAY,5,itoa(useron.etoday,tmp,10));
885:
886: for(i=1;i<=sys_nodes;i++) { /* Tell user, if online */
887: getnodedat(i,&node,0);
888: if(node.useron==usernumber && !(node.misc&NODE_POFF)
889: && (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
890: sprintf(str,text[EmailNodeMsg],node_num,useron.alias);
891: putnmsg(i,str);
892: break; } }
893: if(i>sys_nodes) { /* User wasn't online, so leave short msg */
894: sprintf(str,text[UserSentYouMail],useron.alias);
895: putsmsg(usernumber,str); }
896: }
897:
898: /****************************************************************************/
899: /* Auto-Message Routine ('A' from the main menu) */
900: /****************************************************************************/
901: void automsg()
902: {
903: char str[256],buf[300],anon=0;
904: int file;
905: struct ffblk ff;
906:
907: while(online) {
908: SYNC;
909: mnemonics(text[AutoMsg]);
910: switch(getkeys("RWQ",0)) {
911: case 'R':
912: sprintf(str,"%sMSGS\\AUTO.MSG",data_dir);
913: printfile(str,P_NOABORT|P_NOATCODES);
914: break;
915: case 'W':
916: if(useron.rest&FLAG('W')) {
917: bputs(text[R_AutoMsg]);
918: break; }
919: action=NODE_AMSG;
920: SYNC;
921: bputs("\r\n3 lines:\r\n");
922: if(!getstr(str,68,K_WRAP|K_MSG))
923: break;
924: strcpy(buf,str);
925: strcat(buf,"\r\n ");
926: getstr(str,68,K_WRAP|K_MSG);
927: strcat(buf,str);
928: strcat(buf,"\r\n ");
929: getstr(str,68,K_MSG);
930: strcat(str,crlf);
931: strcat(buf,str);
932: if(yesno(text[OK])) {
933: if(useron.exempt&FLAG('A')) {
934: if(!noyes(text[AnonymousQ]))
935: anon=1; }
936: sprintf(str,"%sMSGS\\AUTO.MSG",data_dir);
937: if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
938: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
939: return; }
940: if(anon)
941: sprintf(tmp,"%.80s",text[Anonymous]);
942: else
943: sprintf(tmp,"%s #%d",useron.alias,useron.number);
944: sprintf(str,text[AutoMsgBy],tmp);
945: strcat(str," ");
946: write(file,str,strlen(str));
947: write(file,buf,strlen(buf));
948: close(file); }
949: break;
950: case 'Q':
951: return; } }
952: }
953:
954: /****************************************************************************/
955: /* Edits messages */
956: /****************************************************************************/
957: void editmsg(smbmsg_t *msg, uint subnum)
958: {
959: char str[256],buf[SDT_BLOCK_LEN];
960: ushort xlat;
961: int file,i,j,x;
962: ulong length,offset;
963: FILE *instream;
964:
965: if(!msg->hdr.total_dfields)
966: return;
967: sprintf(str,"%sINPUT.MSG",node_dir);
968: remove(str);
969: msgtotxt(*msg,str,0,1);
970: editfile(str);
971: length=flength(str)+2; /* +2 for translation string */
972: if(length<1L)
973: return;
974:
975: if((i=smb_locksmbhdr(&smb))!=0) {
976: errormsg(WHERE,ERR_LOCK,smb.file,i);
977: return; }
978:
979: if((i=smb_getstatus(&smb))!=0) {
980: errormsg(WHERE,ERR_READ,smb.file,i);
981: return; }
982:
983: if(!(smb.status.attr&SMB_HYPERALLOC)) {
984: if((i=smb_open_da(&smb))!=0) {
985: errormsg(WHERE,ERR_OPEN,smb.file,i);
986: return; }
987: for(x=0;x<msg->hdr.total_dfields;x++)
988: if((i=smb_freemsgdat(&smb,msg->hdr.offset+msg->dfield[x].offset
989: ,msg->dfield[x].length,1))!=0)
990: errormsg(WHERE,ERR_WRITE,smb.file,i); }
991:
992: msg->dfield[0].type=TEXT_BODY; /* Make one single data field */
993: msg->dfield[0].length=length;
994: msg->dfield[0].offset=0;
995: for(x=1;x<msg->hdr.total_dfields;x++) { /* Clear the other data fields */
996: msg->dfield[x].type=UNUSED; /* so we leave the header length */
997: msg->dfield[x].length=0; /* unchanged */
998: msg->dfield[x].offset=0; }
999:
1000:
1001: if(smb.status.attr&SMB_HYPERALLOC) {
1002: offset=smb_hallocdat(&smb); }
1003: else {
1004: if((subnum!=INVALID_SUB && sub[subnum]->misc&SUB_FAST)
1005: || (subnum==INVALID_SUB && sys_misc&SM_FASTMAIL))
1006: offset=smb_fallocdat(&smb,length,1);
1007: else
1008: offset=smb_allocdat(&smb,length,1);
1009: smb_close_da(&smb); }
1010:
1011: msg->hdr.offset=offset;
1012: if((file=open(str,O_RDONLY|O_BINARY))==-1
1013: || (instream=fdopen(file,"rb"))==NULL) {
1014: smb_unlocksmbhdr(&smb);
1015: smb_freemsgdat(&smb,offset,length,1);
1016: errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_BINARY);
1017: return; }
1018:
1019: setvbuf(instream,NULL,_IOFBF,2*1024);
1020: fseek(smb.sdt_fp,offset,SEEK_SET);
1021: xlat=XLAT_NONE;
1022: fwrite(&xlat,2,1,smb.sdt_fp);
1023: x=SDT_BLOCK_LEN-2; /* Don't read/write more than 255 */
1024: while(!feof(instream)) {
1025: memset(buf,0,x);
1026: j=fread(buf,1,x,instream);
1027: if((j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
1028: buf[j-1]=buf[j-2]=0; /* Convert to NULL */
1029: fwrite(buf,j,1,smb.sdt_fp);
1030: x=SDT_BLOCK_LEN; }
1031: fflush(smb.sdt_fp);
1032: fclose(instream);
1033:
1034: smb_unlocksmbhdr(&smb);
1035: msg->hdr.length=smb_getmsghdrlen(msg);
1036: if((i=smb_putmsghdr(&smb,msg))!=0)
1037: errormsg(WHERE,ERR_WRITE,smb.file,i);
1038: }
1039:
1040: /****************************************************************************/
1041: /* Moves a message from one message base to another */
1042: /****************************************************************************/
1043: char movemsg(smbmsg_t msg, uint subnum)
1044: {
1045: char str[256],*buf;
1046: int i,j,x,file,newgrp,newsub,storage;
1047: long l;
1048: ulong offset,length;
1049:
1050: for(i=0;i<usrgrps;i++) /* Select New Group */
1051: uselect(1,i,"Message Group",grp[usrgrp[i]]->lname,0);
1052: if((newgrp=uselect(0,0,0,0,0))<0)
1053: return(0);
1054:
1055: for(i=0;i<usrsubs[newgrp];i++) /* Select New Sub-Board */
1056: uselect(1,i,"Sub-Board",sub[usrsub[newgrp][i]]->lname,0);
1057: if((newsub=uselect(0,0,0,0,0))<0)
1058: return(0);
1059: newsub=usrsub[newgrp][newsub];
1060:
1061: length=smb_getmsgdatlen(&msg);
1062: if((buf=(char *)MALLOC(length))==NULL) {
1063: errormsg(WHERE,ERR_ALLOC,smb.file,length);
1064: return(0); }
1065:
1066: fseek(smb.sdt_fp,msg.hdr.offset,SEEK_SET);
1067: fread(buf,length,1,smb.sdt_fp);
1068:
1069: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
1070: FREE(buf);
1071: errormsg(WHERE,ERR_OPEN,sub[newsub]->code,i);
1072: return(0); }
1073:
1074: sprintf(smb.file,"%s%s",sub[newsub]->data_dir,sub[newsub]->code);
1075: smb.retry_time=smb_retry_time;
1076: if((i=smb_open(&smb))!=0) {
1077: FREE(buf);
1078: smb_stack(&smb,SMB_STACK_POP);
1079: errormsg(WHERE,ERR_OPEN,smb.file,i);
1080: return(0); }
1081:
1082: if(filelength(fileno(smb.shd_fp))<1) { /* Create it if it doesn't exist */
1083: smb.status.max_crcs=sub[newsub]->maxcrcs;
1084: smb.status.max_msgs=sub[newsub]->maxmsgs;
1085: smb.status.max_age=sub[newsub]->maxage;
1086: smb.status.attr=sub[newsub]->misc&SUB_HYPER ? SMB_HYPERALLOC :0;
1087: if((i=smb_create(&smb))!=0) {
1088: FREE(buf);
1089: smb_close(&smb);
1090: smb_stack(&smb,SMB_STACK_POP);
1091: errormsg(WHERE,ERR_CREATE,smb.file,i);
1092: return(0); } }
1093:
1094: if((i=smb_locksmbhdr(&smb))!=0) {
1095: FREE(buf);
1096: smb_close(&smb);
1097: smb_stack(&smb,SMB_STACK_POP);
1098: errormsg(WHERE,ERR_LOCK,smb.file,i);
1099: return(0); }
1100:
1101: if((i=smb_getstatus(&smb))!=0) {
1102: FREE(buf);
1103: smb_close(&smb);
1104: smb_stack(&smb,SMB_STACK_POP);
1105: errormsg(WHERE,ERR_READ,smb.file,i);
1106: return(0); }
1107:
1108: if(smb.status.attr&SMB_HYPERALLOC) {
1109: offset=smb_hallocdat(&smb);
1110: storage=SMB_HYPERALLOC; }
1111: else {
1112: if((i=smb_open_da(&smb))!=0) {
1113: FREE(buf);
1114: smb_close(&smb);
1115: smb_stack(&smb,SMB_STACK_POP);
1116: errormsg(WHERE,ERR_OPEN,smb.file,i);
1117: return(0); }
1118: if(sub[newsub]->misc&SUB_FAST) {
1119: offset=smb_fallocdat(&smb,length,1);
1120: storage=SMB_FASTALLOC; }
1121: else {
1122: offset=smb_allocdat(&smb,length,1);
1123: storage=SMB_SELFPACK; }
1124: smb_close_da(&smb); }
1125:
1126: msg.hdr.offset=offset;
1127:
1128: memcpy(msg.hdr.id,"SHD\x1a",4);
1.1.1.2 ! root 1129: msg.hdr.version=smb_ver();
1.1 root 1130:
1131: smb_unlocksmbhdr(&smb);
1132:
1133: fseek(smb.sdt_fp,offset,SEEK_SET);
1134: fwrite(buf,length,1,smb.sdt_fp);
1135: fflush(smb.sdt_fp);
1136: FREE(buf);
1137:
1138: i=smb_addmsghdr(&smb,&msg,storage);
1139: smb_close(&smb);
1140: smb_stack(&smb,SMB_STACK_POP);
1141:
1142: if(i) {
1143: smb_freemsgdat(&smb,offset,length,1);
1144: errormsg(WHERE,ERR_WRITE,smb.file,i);
1145: return(0); }
1146:
1147: bprintf("\r\nMoved to %s %s\r\n\r\n"
1148: ,grp[usrgrp[newgrp]]->sname,sub[newsub]->lname);
1149: sprintf(str,"Moved message from %s %s to %s %s"
1150: ,grp[newgrp]->sname,sub[newsub]->sname
1151: ,grp[sub[subnum]->grp]->sname,sub[subnum]->sname);
1152: logline("M+",str);
1153: if(sub[newsub]->misc&SUB_FIDO && sub[newsub]->echomail_sem[0])
1154: if((file=nopen(sub[newsub]->echomail_sem
1155: ,O_WRONLY|O_CREAT|O_TRUNC))!=-1)
1156: close(file);
1157: return(1);
1158: }
1159:
1160: ushort chmsgattr(ushort attr)
1161: {
1162: int ch;
1163:
1164: while(online && !(sys_status&SS_ABORT)) {
1165: CRLF;
1166: show_msgattr(attr);
1167: menu("MSGATTR");
1168: ch=getkey(K_UPPER);
1169: if(ch)
1170: bprintf("%c\r\n",ch);
1171: switch(ch) {
1172: case 'P':
1173: attr^=MSG_PRIVATE;
1174: break;
1175: case 'R':
1176: attr^=MSG_READ;
1177: break;
1178: case 'K':
1179: attr^=MSG_KILLREAD;
1180: break;
1181: case 'A':
1182: attr^=MSG_ANONYMOUS;
1183: break;
1184: case 'N': /* Non-purgeable */
1185: attr^=MSG_PERMANENT;
1186: break;
1187: case 'M':
1188: attr^=MSG_MODERATED;
1189: break;
1190: case 'V':
1191: attr^=MSG_VALIDATED;
1192: break;
1193: case 'D':
1194: attr^=MSG_DELETE;
1195: break;
1196: case 'L':
1197: attr^=MSG_LOCKED;
1198: break;
1199: default:
1200: return(attr); } }
1201: return(attr);
1202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.