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