Annotation of sbbs/sbbs3/writemsg.cpp, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.