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

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

unix.superglobalmegacorp.com

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