Annotation of sbbs/src/sbbs3/chat.cpp, revision 1.1.1.1

1.1       root        1: /* chat.cpp */
                      2: 
                      3: /* Synchronet real-time chat functions */
                      4: 
                      5: /* $Id: chat.cpp,v 1.47 2006/08/23 01:45:05 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 2006 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 PCHAT_LEN 1000         /* Size of Private chat file */
                     41: 
                     42: const char *weekday[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"
                     43:                                ,"Saturday"};
                     44: const char *month[]={"January","February","March","April","May","June"
                     45:                                ,"July","August","September","October","November","December"};
                     46: 
                     47: /****************************************************************************/
                     48: /****************************************************************************/
                     49: void sbbs_t::multinodechat(int channel)
                     50: {
                     51:        char    line[256],str[256],ch,done
                     52:                        ,usrs,preusrs,qusrs,*gurubuf=NULL,savch,*p
                     53:                        ,pgraph[400],buf[400]
                     54:                        ,usr[MAX_NODES],preusr[MAX_NODES],qusr[MAX_NODES];
                     55:        char    guru_lastanswer[512];
                     56:        char    tmp[512];
                     57:        int     file;
                     58:        long    i,j,k,n;
                     59:        node_t  node;
                     60: 
                     61:        if(useron.rest&FLAG('C')) {
                     62:                bputs(text[R_Chat]);
                     63:                return; 
                     64:        }
                     65: 
                     66:        if(channel<1 || channel>cfg.total_chans)
                     67:                channel=1;
                     68: 
                     69:        if(!chan_access(channel-1))
                     70:                return;
                     71:        if(useron.misc&(RIP|WIP|HTML) ||!(useron.misc&EXPERT))
                     72:                menu("multchat");
                     73:        bputs(text[WelcomeToMultiChat]);
                     74:        if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                     75:                thisnode.aux=channel;           
                     76:                putnodedat(cfg.node_num,&thisnode);
                     77:        }
                     78:        bprintf(text[WelcomeToChannelN],channel,cfg.chan[channel-1]->name);
                     79:        if(gurubuf) {
                     80:                free(gurubuf);
                     81:                gurubuf=NULL; }
                     82:        if(cfg.chan[channel-1]->misc&CHAN_GURU && cfg.chan[channel-1]->guru<cfg.total_gurus
                     83:                && chk_ar(cfg.guru[cfg.chan[channel-1]->guru]->ar,&useron)) {
                     84:                sprintf(str,"%s%s.dat",cfg.ctrl_dir,cfg.guru[cfg.chan[channel-1]->guru]->code);
                     85:                if((file=nopen(str,O_RDONLY))==-1) {
                     86:                        errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
                     87:                        return; }
                     88:                if((gurubuf=(char *)malloc(filelength(file)+1))==NULL) {
                     89:                        close(file);
                     90:                        errormsg(WHERE,ERR_ALLOC,str,filelength(file)+1);
                     91:                        return; }
                     92:                read(file,gurubuf,filelength(file));
                     93:                gurubuf[filelength(file)]=0;
                     94:                close(file); }
                     95:        usrs=0;
                     96:        for(i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
                     97:                if(i==cfg.node_num)
                     98:                        continue;
                     99:                getnodedat(i,&node,0);
                    100:                if(node.action!=NODE_MCHT || node.status!=NODE_INUSE)
                    101:                        continue;
                    102:                if(node.aux && (node.aux&0xff)!=channel)
                    103:                        continue;
                    104:                printnodedat(i,&node);
                    105:                preusr[usrs]=usr[usrs++]=(char)i; }
                    106:        preusrs=usrs;
                    107:        if(gurubuf)
                    108:                bprintf(text[NodeInMultiChatLocally]
                    109:                        ,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name,channel);
                    110:        bputs(text[YoureOnTheAir]);
                    111:        done=0;
                    112:        while(online && !done) {
                    113:                checkline();
                    114:                gettimeleft();
                    115:                action=NODE_MCHT;
                    116:                qusrs=usrs=0;
                    117:         for(i=1;i<=cfg.sys_nodes;i++) {
                    118:                        if(i==cfg.node_num)
                    119:                                continue;
                    120:                        getnodedat(i,&node,0);
                    121:                        if(node.action!=NODE_MCHT
                    122:                                || (node.aux && channel && (node.aux&0xff)!=channel))
                    123:                                continue;
                    124:                        if(node.status==NODE_QUIET)
                    125:                                qusr[qusrs++]=(char)i;
                    126:                        else if(node.status==NODE_INUSE)
                    127:                                usr[usrs++]=(char)i; }
                    128:                if(preusrs>usrs) {
                    129:                        if(!usrs && channel && cfg.chan[channel-1]->misc&CHAN_GURU
                    130:                                && cfg.chan[channel-1]->guru<cfg.total_gurus)
                    131:                                bprintf(text[NodeJoinedMultiChat]
                    132:                                        ,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name
                    133:                                        ,channel);
                    134:                        outchar(BEL);
                    135:                        for(i=0;i<preusrs;i++) {
                    136:                                for(j=0;j<usrs;j++)
                    137:                                        if(preusr[i]==usr[j])
                    138:                                                break;
                    139:                                if(j==usrs) {
                    140:                                        getnodedat(preusr[i],&node,0);
                    141:                                        if(node.misc&NODE_ANON)
                    142:                                                sprintf(str,"%.80s",text[UNKNOWN_USER]);
                    143:                                        else
                    144:                                                username(&cfg,node.useron,str);
                    145:                                        bprintf(text[NodeLeftMultiChat]
                    146:                                                ,preusr[i],str,channel); } } }
                    147:                else if(preusrs<usrs) {
                    148:                        if(!preusrs && channel && cfg.chan[channel-1]->misc&CHAN_GURU
                    149:                                && cfg.chan[channel-1]->guru<cfg.total_gurus)
                    150:                                bprintf(text[NodeLeftMultiChat]
                    151:                                        ,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name
                    152:                                        ,channel);
                    153:                        outchar(BEL);
                    154:                        for(i=0;i<usrs;i++) {
                    155:                                for(j=0;j<preusrs;j++)
                    156:                                        if(usr[i]==preusr[j])
                    157:                                                break;
                    158:                                if(j==preusrs) {
                    159:                                        getnodedat(usr[i],&node,0);
                    160:                                        if(node.misc&NODE_ANON)
                    161:                                                sprintf(str,"%.80s",text[UNKNOWN_USER]);
                    162:                                        else
                    163:                                                username(&cfg,node.useron,str);
                    164:                                        bprintf(text[NodeJoinedMultiChat]
                    165:                                                ,usr[i],str,channel); } } }
                    166:                preusrs=usrs;
                    167:                for(i=0;i<usrs;i++)
                    168:                        preusr[i]=usr[i];
                    169:                attr(cfg.color[clr_multichat]);
                    170:                SYNC;
                    171:                sys_status&=~SS_ABORT;
                    172:                if((ch=inkey(K_NONE,250))!=0 || wordwrap[0]) {
                    173:                        if(ch=='/') {
                    174:                                bputs(text[MultiChatCommandPrompt]);
                    175:                                strcpy(str,"ACELWQ?*");
                    176:                                if(SYSOP)
                    177:                                        strcat(str,"0");
                    178:                                i=getkeys(str,cfg.total_chans);
                    179:                                if(i&0x80000000L) {  /* change channel */
                    180:                                        savch=(char)(i&~0x80000000L);
                    181:                                        if(savch==channel)
                    182:                                                continue;
                    183:                                        if(!chan_access(savch-1))
                    184:                                                continue;
                    185:                                        bprintf(text[WelcomeToChannelN]
                    186:                                                ,savch,cfg.chan[savch-1]->name);
                    187: 
                    188:                                        usrs=0;
                    189:                                        for(i=1;i<=cfg.sys_nodes;i++) {
                    190:                                                if(i==cfg.node_num)
                    191:                                                        continue;
                    192:                                                getnodedat(i,&node,0);
                    193:                                                if(node.action!=NODE_MCHT
                    194:                                                        || node.status!=NODE_INUSE)
                    195:                                                        continue;
                    196:                                                if(node.aux && (node.aux&0xff)!=savch)
                    197:                                                        continue;
                    198:                                                printnodedat(i,&node);
                    199:                                                if(node.aux&0x1f00) {   /* password */
                    200:                                                        bprintf(text[PasswordProtected]
                    201:                                                                ,node.misc&NODE_ANON
                    202:                                                                ? text[UNKNOWN_USER]
                    203:                                                                : username(&cfg,node.useron,tmp));
                    204:                                                        if(!getstr(str,8,K_UPPER|K_ALPHA|K_LINE))
                    205:                                                                break;
                    206:                                                        if(strcmp(str,unpackchatpass(tmp,&node)))
                    207:                                                                break;
                    208:                                                                bputs(text[CorrectPassword]);  }
                    209:                                                preusr[usrs]=usr[usrs++]=(char)i; }
                    210:                                        if(i<=cfg.sys_nodes) {  /* failed password */
                    211:                                                bputs(text[WrongPassword]);
                    212:                                                continue; }
                    213:                                        if(gurubuf) {
                    214:                                                free(gurubuf);
                    215:                                                gurubuf=NULL; }
                    216:                                        if(cfg.chan[savch-1]->misc&CHAN_GURU
                    217:                                                && cfg.chan[savch-1]->guru<cfg.total_gurus
                    218:                                                && chk_ar(cfg.guru[cfg.chan[savch-1]->guru]->ar,&useron
                    219:                                                )) {
                    220:                                                sprintf(str,"%s%s.dat",cfg.ctrl_dir
                    221:                                                        ,cfg.guru[cfg.chan[savch-1]->guru]->code);
                    222:                                                if((file=nopen(str,O_RDONLY))==-1) {
                    223:                                                        errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
                    224:                                                        break; }
                    225:                                                if((gurubuf=(char *)malloc(filelength(file)+1))==NULL) {
                    226:                                                        close(file);
                    227:                                                        errormsg(WHERE,ERR_ALLOC,str
                    228:                                                                ,filelength(file)+1);
                    229:                                                        break; }
                    230:                                                read(file,gurubuf,filelength(file));
                    231:                                                gurubuf[filelength(file)]=0;
                    232:                                                close(file); }
                    233:                                        preusrs=usrs;
                    234:                                        if(gurubuf)
                    235:                                                bprintf(text[NodeInMultiChatLocally]
                    236:                                                        ,cfg.sys_nodes+1
                    237:                                                        ,cfg.guru[cfg.chan[savch-1]->guru]->name
                    238:                                                        ,savch);
                    239:                                        channel=savch;
                    240:                                        if(!usrs && cfg.chan[savch-1]->misc&CHAN_PW
                    241:                                                && !noyes(text[PasswordProtectChanQ])) {
                    242:                                                bputs(text[PasswordPrompt]);
                    243:                                                if(getstr(str,8,K_UPPER|K_ALPHA|K_LINE)) {
                    244:                                                        getnodedat(cfg.node_num,&thisnode,true);
                    245:                                                        thisnode.aux=channel;
                    246:                                                        packchatpass(str,&thisnode); }
                    247:                                                else {
                    248:                                                        getnodedat(cfg.node_num,&thisnode,true);
                    249:                                                        thisnode.aux=channel; } }
                    250:                                        else {
                    251:                                                getnodedat(cfg.node_num,&thisnode,true);
                    252:                                                thisnode.aux=channel; }
                    253:                                        putnodedat(cfg.node_num,&thisnode);
                    254:                                        bputs(text[YoureOnTheAir]);
                    255:                                        if(cfg.chan[channel-1]->cost
                    256:                                                && !(useron.exempt&FLAG('J')))
                    257:                                                subtract_cdt(&cfg,&useron,cfg.chan[channel-1]->cost); }
                    258:                                else switch(i) {        /* other command */
                    259:                                        case '0':       /* Global channel */
                    260:                                                if(!SYSOP)
                    261:                                                        break;
                    262:                         usrs=0;
                    263:                                                for(i=1;i<=cfg.sys_nodes;i++) {
                    264:                                                        if(i==cfg.node_num)
                    265:                                                                continue;
                    266:                                                        getnodedat(i,&node,0);
                    267:                                                        if(node.action!=NODE_MCHT
                    268:                                                                || node.status!=NODE_INUSE)
                    269:                                                                continue;
                    270:                                                        printnodedat(i,&node);
                    271:                                                        preusr[usrs]=usr[usrs++]=(char)i; }
                    272:                                                preusrs=usrs;
                    273:                                                if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                    274:                                                        thisnode.aux=channel=0;
                    275:                                                        putnodedat(cfg.node_num,&thisnode);
                    276:                                                }
                    277:                                                break;
                    278:                                        case 'A':   /* Action commands */
                    279:                                                useron.chat^=CHAT_ACTION;
                    280:                                                bprintf("\r\nAction commands are now %s\r\n"
                    281:                                                        ,useron.chat&CHAT_ACTION
                    282:                                                        ? text[ON]:text[OFF]);
                    283:                                                putuserrec(&cfg,useron.number,U_CHAT,8
                    284:                                                        ,ultoa(useron.chat,str,16));
                    285:                                                break;
                    286:                                        case 'C':   /* List of action commands */
                    287:                                                CRLF;
                    288:                                                for(i=0;channel && i<cfg.total_chatacts;i++) {
                    289:                                                        if(cfg.chatact[i]->actset
                    290:                                                                !=cfg.chan[channel-1]->actset)
                    291:                                                                continue;
                    292:                                                        bprintf("%-*.*s",LEN_CHATACTCMD
                    293:                                                                ,LEN_CHATACTCMD,cfg.chatact[i]->cmd);
                    294:                                                        if(!((i+1)%8)) {
                    295:                                                                CRLF; }
                    296:                                                        else
                    297:                                                                bputs(" "); }
                    298:                                                CRLF;
                    299:                                                break;
                    300:                                        case 'E':   /* Toggle echo */
                    301:                                                useron.chat^=CHAT_ECHO;
                    302:                                                bprintf(text[EchoIsNow]
                    303:                                                        ,useron.chat&CHAT_ECHO
                    304:                                                        ? text[ON]:text[OFF]);
                    305:                                                putuserrec(&cfg,useron.number,U_CHAT,8
                    306:                                                        ,ultoa(useron.chat,str,16));
                    307:                                                break;
                    308:                                        case 'L':       /* list nodes */
                    309:                                                CRLF;
                    310:                                                for(i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
                    311:                                                        getnodedat(i,&node,0);
                    312:                                                        printnodedat(i,&node); }
                    313:                                                CRLF;
                    314:                                                break;
                    315:                                        case 'W':   /* page node(s) */
                    316:                                                j=getnodetopage(0,0);
                    317:                                                if(!j)
                    318:                                                        break;
                    319:                                                for(i=0;i<usrs;i++)
                    320:                                                        if(usr[i]==j)
                    321:                                                                break;
                    322:                                                if(i>=usrs) {
                    323:                                                        bputs(text[UserNotFound]);
                    324:                                                        break; }
                    325: 
                    326:                                                bputs(text[NodeMsgPrompt]);
                    327:                                                if(!getstr(line,66,K_LINE|K_MSG))
                    328:                                                        break;
                    329: 
                    330:                                                sprintf(buf,text[ChatLineFmt]
                    331:                                                        ,thisnode.misc&NODE_ANON
                    332:                                                        ? text[AnonUserChatHandle]
                    333:                                                        : useron.handle
                    334:                                                        ,cfg.node_num,'*',line);
                    335:                                                strcat(buf,crlf);
                    336:                                                if(useron.chat&CHAT_ECHO)
                    337:                                                        bputs(buf);
                    338:                                                putnmsg(&cfg,j,buf);
                    339:                                                break;
                    340:                                        case 'Q':       /* quit */
                    341:                                                done=1;
                    342:                                                break;
                    343:                                        case '*':
                    344:                                                sprintf(str,"%smenu/chan.*",cfg.text_dir);
                    345:                                                if(fexist(str))
                    346:                                                        menu("chan");
                    347:                                                else {
                    348:                                                        bputs(text[ChatChanLstHdr]);
                    349:                                                        bputs(text[ChatChanLstTitles]);
                    350:                                                        if(cfg.total_chans>=10) {
                    351:                                                                bputs("     ");
                    352:                                                                bputs(text[ChatChanLstTitles]); }
                    353:                                                        CRLF;
                    354:                                                        bputs(text[ChatChanLstUnderline]);
                    355:                                                        if(cfg.total_chans>=10) {
                    356:                                                                bputs("     ");
                    357:                                                                bputs(text[ChatChanLstUnderline]); }
                    358:                                                        CRLF;
                    359:                                                        if(cfg.total_chans>=10)
                    360:                                                                j=(cfg.total_chans/2)+(cfg.total_chans&1);
                    361:                                                        else
                    362:                                                                j=cfg.total_chans;
                    363:                                                        for(i=0;i<j && !msgabort();i++) {
                    364:                                                                bprintf(text[ChatChanLstFmt],i+1
                    365:                                                                        ,cfg.chan[i]->name
                    366:                                                                        ,cfg.chan[i]->cost);
                    367:                                                                if(cfg.total_chans>=10) {
                    368:                                                                        k=(cfg.total_chans/2)
                    369:                                                                                +i+(cfg.total_chans&1);
                    370:                                                                        if(k<cfg.total_chans) {
                    371:                                                                                bputs("     ");
                    372:                                                                                bprintf(text[ChatChanLstFmt]
                    373:                                                                                        ,k+1
                    374:                                                                                        ,cfg.chan[k]->name
                    375:                                                                                        ,cfg.chan[k]->cost); } }
                    376:                                                                CRLF; }
                    377:                                                        CRLF; }
                    378:                                                break;
                    379:                                        case '?':       /* menu */
                    380:                                                menu("multchat");
                    381:                                                break;  
                    382:                                } 
                    383:                        } else {
                    384:                                ungetkey(ch);
                    385:                                j=0;
                    386:                                pgraph[0]=0;
                    387:                                while(j<5) {
                    388:                                        if(!getstr(line,66,K_WRAP|K_MSG|K_CHAT))
                    389:                                                break;
                    390:                                        if(j) {
                    391:                                                sprintf(str,text[ChatLineFmt]
                    392:                                                        ,thisnode.misc&NODE_ANON
                    393:                                                        ? text[AnonUserChatHandle]
                    394:                                                        : useron.handle
                    395:                                                        ,cfg.node_num,':',nulstr);
                    396:                                                sprintf(tmp,"%*s",bstrlen(str),nulstr);
                    397:                                                strcat(pgraph,tmp); }
                    398:                                        strcat(pgraph,line);
                    399:                                        strcat(pgraph,crlf);
                    400:                                        if(!wordwrap[0])
                    401:                                                break;
                    402:                                        j++; }
                    403:                                if(pgraph[0]) {
                    404:                                        if(channel && useron.chat&CHAT_ACTION) {
                    405:                                                for(i=0;i<cfg.total_chatacts;i++) {
                    406:                                                        if(cfg.chatact[i]->actset
                    407:                                                                !=cfg.chan[channel-1]->actset)
                    408:                                                                continue;
                    409:                                                        sprintf(str,"%s ",cfg.chatact[i]->cmd);
                    410:                                                        if(!strnicmp(str,pgraph,strlen(str)))
                    411:                                                                break;
                    412:                                                        sprintf(str,"%.*s"
                    413:                                                                ,LEN_CHATACTCMD+2,pgraph);
                    414:                                                        str[strlen(str)-2]=0;
                    415:                                                        if(!stricmp(cfg.chatact[i]->cmd,str))
                    416:                                                                break; }
                    417: 
                    418:                                                if(i<cfg.total_chatacts) {
                    419:                                                        p=pgraph+strlen(str);
                    420:                                                        n=atoi(p);
                    421:                                                        for(j=0;j<usrs;j++) {
                    422:                                                                getnodedat(usr[j],&node,0);
                    423:                                                                if(usrs==1) /* no need to search */
                    424:                                                                        break;
                    425:                                                                if(n) {
                    426:                                                                        if(usr[j]==n)
                    427:                                                                                break;
                    428:                                                                        continue; }
                    429:                                                                username(&cfg,node.useron,str);
                    430:                                                                if(!strnicmp(str,p,strlen(str)))
                    431:                                                                        break;
                    432:                                                                getuserrec(&cfg,node.useron,U_HANDLE
                    433:                                                                        ,LEN_HANDLE,str);
                    434:                                                                if(!strnicmp(str,p,strlen(str)))
                    435:                                                                        break; }
                    436:                                                        if(!usrs
                    437:                                                                && cfg.chan[channel-1]->guru<cfg.total_gurus)
                    438:                                                                strcpy(str
                    439:                                                                ,cfg.guru[cfg.chan[channel-1]->guru]->name);
                    440:                                                        else if(j>=usrs)
                    441:                                                                strcpy(str,"everyone");
                    442:                                                        else if(node.misc&NODE_ANON)
                    443:                                                                strcpy(str,text[UNKNOWN_USER]);
                    444:                                                        else
                    445:                                                                username(&cfg,node.useron,str);
                    446: 
                    447:                                                        /* Display on same node */
                    448:                                                        bprintf(cfg.chatact[i]->out
                    449:                                                                ,thisnode.misc&NODE_ANON
                    450:                                                                ? text[UNKNOWN_USER] : useron.alias
                    451:                                                                ,str);
                    452:                                                        CRLF;
                    453: 
                    454:                                                        if(usrs && j<usrs) {
                    455:                                                                /* Display to dest user */
                    456:                                                                sprintf(buf,cfg.chatact[i]->out
                    457:                                                                        ,thisnode.misc&NODE_ANON
                    458:                                                                        ? text[UNKNOWN_USER] : useron.alias
                    459:                                                                        ,"you");
                    460:                                                                strcat(buf,crlf);
                    461:                                                                putnmsg(&cfg,usr[j],buf); }
                    462: 
                    463: 
                    464:                                                        /* Display to all other users */
                    465:                                                        sprintf(buf,cfg.chatact[i]->out
                    466:                                                                ,thisnode.misc&NODE_ANON
                    467:                                                                ? text[UNKNOWN_USER] : useron.alias
                    468:                                                                ,str);
                    469:                                                        strcat(buf,crlf);
                    470: 
                    471:                                                        for(i=0;i<usrs;i++) {
                    472:                                                                if(i==j)
                    473:                                                                        continue;
                    474:                                                                getnodedat(usr[i],&node,0);
                    475:                                                                putnmsg(&cfg,usr[i],buf); }
                    476:                                                        for(i=0;i<qusrs;i++) {
                    477:                                                                getnodedat(qusr[i],&node,0);
                    478:                                                                putnmsg(&cfg,qusr[i],buf); }
                    479:                                                        continue; } }
                    480: 
                    481:                                        sprintf(buf,text[ChatLineFmt]
                    482:                                                ,thisnode.misc&NODE_ANON
                    483:                                                ? text[AnonUserChatHandle]
                    484:                                                : useron.handle
                    485:                                                ,cfg.node_num,':',pgraph);
                    486:                                        if(useron.chat&CHAT_ECHO)
                    487:                                                bputs(buf);
                    488:                                        for(i=0;i<usrs;i++) {
                    489:                                                getnodedat(usr[i],&node,0);
                    490:                                                putnmsg(&cfg,usr[i],buf); 
                    491:                                        }
                    492:                                        for(i=0;i<qusrs;i++) {
                    493:                                                getnodedat(qusr[i],&node,0);
                    494:                                                putnmsg(&cfg,qusr[i],buf); 
                    495:                                        }
                    496:                                        if(!usrs && channel && gurubuf
                    497:                                                && cfg.chan[channel-1]->misc&CHAN_GURU)
                    498:                                                guruchat(pgraph,gurubuf,cfg.chan[channel-1]->guru,guru_lastanswer);
                    499:                                } 
                    500:                        } 
                    501:                }
                    502:                if(sys_status&SS_ABORT)
                    503:                        break; 
                    504:        }
                    505:        lncntr=0;
                    506: }
                    507: 
                    508: /****************************************************************************/
                    509: /****************************************************************************/
                    510: bool sbbs_t::guru_page(void)
                    511: {
                    512:        char    path[MAX_PATH+1];
                    513:        char*   gurubuf;
                    514:        int     file;
                    515:        long    i;
                    516: 
                    517:        if(useron.rest&FLAG('C')) {
                    518:                bputs(text[R_Chat]);
                    519:                return(false); 
                    520:        }
                    521: 
                    522:        if(!cfg.total_gurus) {
                    523:                bprintf(text[SysopIsNotAvailable],"The Guru");
                    524:                return(false); 
                    525:        }
                    526:        if(cfg.total_gurus==1 && chk_ar(cfg.guru[0]->ar,&useron))
                    527:                i=0;
                    528:        else {
                    529:                for(i=0;i<cfg.total_gurus;i++)
                    530:                        uselect(1,i,nulstr,cfg.guru[i]->name,cfg.guru[i]->ar);
                    531:                i=uselect(0,0,0,0,0);
                    532:                if(i<0)
                    533:                        return(false); 
                    534:        }
                    535:        sprintf(path,"%s%s.dat",cfg.ctrl_dir,cfg.guru[i]->code);
                    536:        if((file=nopen(path,O_RDONLY))==-1) {
                    537:                errormsg(WHERE,ERR_OPEN,path,O_RDONLY);
                    538:                return(false); 
                    539:        }
                    540:        if((gurubuf=(char *)malloc(filelength(file)+1))==NULL) {
                    541:                close(file);
                    542:                errormsg(WHERE,ERR_ALLOC,path,filelength(file)+1);
                    543:                return(false); 
                    544:        }
                    545:        read(file,gurubuf,filelength(file));
                    546:        gurubuf[filelength(file)]=0;
                    547:        close(file);
                    548:        localguru(gurubuf,i);
                    549:        free(gurubuf);
                    550:        return(true);
                    551: }
                    552: 
                    553: /****************************************************************************/
                    554: /* The chat section                                                         */
                    555: /****************************************************************************/
                    556: void sbbs_t::chatsection()
                    557: {
                    558:        char    str[256],ch,no_rip_menu;
                    559: 
                    560:        if(useron.rest&FLAG('C')) {
                    561:                bputs(text[R_Chat]);
                    562:                return; 
                    563:        }
                    564: 
                    565:        action=NODE_CHAT;
                    566:        if(useron.misc&(RIP|WIP|HTML) || !(useron.misc&EXPERT))
                    567:                menu("chat");
                    568:        ASYNC;
                    569:        bputs(text[ChatPrompt]);
                    570:        while(online) {
                    571:                no_rip_menu=0;
                    572:                ch=(char)getkeys("ACDJPQST?\r",0);
                    573:                if(ch>' ')
                    574:                        logch(ch,0);
                    575:                switch(ch) {
                    576:                        case 'S':
                    577:                                useron.chat^=CHAT_SPLITP;
                    578:                                putuserrec(&cfg,useron.number,U_CHAT,8
                    579:                                        ,ultoa(useron.chat,str,16));
                    580:                                bprintf("\r\nPrivate split-screen chat is now: %s\r\n"
                    581:                                        ,useron.chat&CHAT_SPLITP ? text[ON]:text[OFF]);
                    582:                                break;
                    583:                        case 'A':
                    584:                                CRLF;
                    585:                                useron.chat^=CHAT_NOACT;
                    586:                                putuserrec(&cfg,useron.number,U_CHAT,8
                    587:                                        ,ultoa(useron.chat,str,16));
                    588:                                if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                    589:                                        thisnode.misc^=NODE_AOFF;
                    590:                                        printnodedat(cfg.node_num,&thisnode);
                    591:                                }
                    592:                                putnodedat(cfg.node_num,&thisnode);
                    593:                                no_rip_menu=true;
                    594:                                break;
                    595:                        case 'D':
                    596:                                CRLF;
                    597:                                useron.chat^=CHAT_NOPAGE;
                    598:                                putuserrec(&cfg,useron.number,U_CHAT,8
                    599:                                        ,ultoa(useron.chat,str,16));
                    600:                                if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                    601:                                        thisnode.misc^=NODE_POFF;
                    602:                                        printnodedat(cfg.node_num,&thisnode);
                    603:                                }
                    604:                                putnodedat(cfg.node_num,&thisnode);
                    605:                                no_rip_menu=true;
                    606:                                break;
                    607:                        case 'J':
                    608:                                multinodechat();
                    609:                                break;
                    610:                        case 'P':   /* private node-to-node chat */
                    611:                                privchat();
                    612:                                break;
                    613:                        case 'C':
                    614:                                no_rip_menu=1;
                    615:                                if(sysop_page())
                    616:                                        break;
                    617:                                if(cfg.total_gurus && chk_ar(cfg.guru[0]->ar,&useron)) {
                    618:                                        sprintf(str,text[ChatWithGuruInsteadQ],cfg.guru[0]->name);
                    619:                                        if(!yesno(str))
                    620:                                                break; }
                    621:                                else
                    622:                                        break;
                    623:                                /* FALL-THROUGH */
                    624:                        case 'T':
                    625:                                guru_page();
                    626:                                no_rip_menu=1;
                    627:                                break;
                    628:                        case '?':
                    629:                                if(useron.misc&EXPERT)
                    630:                                        menu("chat");
                    631:                                break;
                    632:                        default:        /* 'Q' or <CR> */
                    633:                                lncntr=0;
                    634: //                             if(gurubuf)
                    635: //                                     free(gurubuf);
                    636:                                return; }
                    637:                action=NODE_CHAT;
                    638:                if(!(useron.misc&EXPERT) || useron.misc&(WIP|HTML)
                    639:                        || (useron.misc&RIP && !no_rip_menu)) {
                    640:                        menu("chat"); 
                    641:                }
                    642:                ASYNC;
                    643:                bputs(text[ChatPrompt]); }
                    644: //     if(gurubuf)
                    645: //             free(gurubuf);
                    646: }
                    647: 
                    648: /****************************************************************************/
                    649: /****************************************************************************/
                    650: bool sbbs_t::sysop_page(void)
                    651: {
                    652:        char    str[256];
                    653:        int             i;
                    654: 
                    655:        if(useron.rest&FLAG('C')) {
                    656:                bputs(text[R_Chat]);
                    657:                return(false); 
                    658:        }
                    659: 
                    660:        if(startup->options&BBS_OPT_SYSOP_AVAILABLE 
                    661:                || (cfg.sys_chat_ar[0] && chk_ar(cfg.sys_chat_ar,&useron))
                    662:                || useron.exempt&FLAG('C')) {
                    663: 
                    664:                sprintf(str,"%s paged sysop for chat",useron.alias);
                    665:                logline("C",str);
                    666: 
                    667:                for(i=0;i<cfg.total_pages;i++)
                    668:                        if(chk_ar(cfg.page[i]->ar,&useron))
                    669:                                break;
                    670:                if(i<cfg.total_pages) {
                    671:                        bprintf(text[PagingGuru],cfg.sys_op);
                    672:                        external(cmdstr(cfg.page[i]->cmd,nulstr,nulstr,NULL)
                    673:                                ,cfg.page[i]->misc&IO_INTS ? EX_OUTL|EX_OUTR|EX_INR
                    674:                                        : EX_OUTL); }
                    675:                else if(cfg.sys_misc&SM_SHRTPAGE) {
                    676:                        bprintf(text[PagingGuru],cfg.sys_op);
                    677:                        for(i=0;i<10 && !lkbrd(1);i++) {
                    678:                                sbbs_beep(1000,200);
                    679:                                mswait(200);
                    680:                                outchar('.'); }
                    681:                        CRLF; }
                    682:                else {
                    683:                        sys_status^=SS_SYSPAGE;
                    684:                        bprintf(text[SysopPageIsNow]
                    685:                                ,sys_status&SS_SYSPAGE ? text[ON] : text[OFF]);
                    686:                        nosound();      
                    687:                }
                    688: 
                    689:                return(true);
                    690:        }
                    691: 
                    692:        bprintf(text[SysopIsNotAvailable],cfg.sys_op);
                    693: 
                    694:        return(false);
                    695: }
                    696: 
                    697: /****************************************************************************/
                    698: /* Returns 1 if user online has access to channel "channum"                 */
                    699: /****************************************************************************/
                    700: bool sbbs_t::chan_access(uint cnum)
                    701: {
                    702: 
                    703:        if(!cfg.total_chans || cnum>=cfg.total_chans || !chk_ar(cfg.chan[cnum]->ar,&useron)) {
                    704:                bputs(text[CantAccessThatChannel]);
                    705:                return(false); }
                    706:        if(!(useron.exempt&FLAG('J')) && cfg.chan[cnum]->cost>useron.cdt+useron.freecdt) {
                    707:                bputs(text[NotEnoughCredits]);
                    708:                return(false); }
                    709:        return(true);
                    710: }
                    711: 
                    712: /****************************************************************************/
                    713: /* Private split-screen (or interspersed) chat with node or local sysop                */
                    714: /****************************************************************************/
                    715: void sbbs_t::privchat(bool local)
                    716: {
                    717:        char    str[128],c,*p,localbuf[5][81],remotebuf[5][81]
                    718:                        ,localline=0,remoteline=0,localchar=0,remotechar=0
                    719:                        ,*sep=text[PrivateChatSeparator]
                    720:                        ,*local_sep=text[SysopChatSeparator]
                    721:                        ;
                    722:        char    tmp[512];
                    723:        char    outpath[MAX_PATH+1];
                    724:        char    inpath[MAX_PATH+1];
                    725:        uchar   ch;
                    726:        int     in,out,i,n,echo=1,x,y,activity,remote_activity;
                    727:     int                local_y=1,remote_y=1;
                    728:        node_t  node;
                    729:        time_t  last_nodechk=0;
                    730: 
                    731:        if(useron.rest&FLAG('C')) {
                    732:                bputs(text[R_Chat]);
                    733:                return; 
                    734:        }
                    735: 
                    736:        if(local) 
                    737:                n=0;
                    738:        else {
                    739:                n=getnodetopage(0,0);
                    740:                if(!n)
                    741:                        return;
                    742:                if(n==cfg.node_num) {
                    743:                        bputs(text[NoNeedToPageSelf]);
                    744:                        return; }
                    745:                getnodedat(n,&node,0);
                    746:                if(node.action==NODE_PCHT && node.aux!=cfg.node_num) {
                    747:                        bprintf(text[NodeNAlreadyInPChat],n);
                    748:                        return; }
                    749:                if((node.action!=NODE_PAGE || node.aux!=cfg.node_num)
                    750:                        && node.misc&NODE_POFF && !SYSOP) {
                    751:                        bprintf(text[CantPageNode],node.misc&NODE_ANON
                    752:                                ? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
                    753:                        return; }
                    754:                if(node.action!=NODE_PAGE) {
                    755:                        bprintf(text[PagingUser]
                    756:                                ,node.misc&NODE_ANON ? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp)
                    757:                                ,node.misc&NODE_ANON ? 0 : node.useron);
                    758:                        sprintf(str,text[NodePChatPageMsg]
                    759:                                ,cfg.node_num,thisnode.misc&NODE_ANON
                    760:                                        ? text[UNKNOWN_USER] : useron.alias);
                    761:                        putnmsg(&cfg,n,str);
                    762:                        sprintf(str,"%s paged %s on node %d to private chat"
                    763:                                ,useron.alias,username(&cfg,node.useron,tmp),n);
                    764:                        logline("C",str); }
                    765: 
                    766:                if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                    767:                        thisnode.action=action=NODE_PAGE;
                    768:                        thisnode.aux=n;
                    769:                        putnodedat(cfg.node_num,&thisnode);
                    770:                }
                    771: 
                    772:                if(node.action!=NODE_PAGE || node.aux!=cfg.node_num) {
                    773:                        bprintf(text[WaitingForNodeInPChat],n);
                    774:                        while(online && !(sys_status&SS_ABORT)) {
                    775:                                getnodedat(n,&node,0);
                    776:                                if((node.action==NODE_PAGE || node.action==NODE_PCHT)
                    777:                                        && node.aux==cfg.node_num) {
                    778:                                        bprintf(text[NodeJoinedPrivateChat]
                    779:                                                ,n,node.misc&NODE_ANON ? text[UNKNOWN_USER]
                    780:                                                        : username(&cfg,node.useron,tmp));
                    781:                                        break; 
                    782:                                }
                    783:                                action=NODE_PAGE;
                    784:                                checkline();
                    785:                                gettimeleft();
                    786:                                SYNC; 
                    787:                                inkey(K_NONE,500);
                    788:                        } 
                    789:                }
                    790:        }
                    791: 
                    792:        gettimeleft();
                    793: 
                    794:        if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                    795:                thisnode.action=action=NODE_PCHT;
                    796:                thisnode.aux=n;
                    797:                thisnode.misc&=~NODE_LCHAT;
                    798:                putnodedat(cfg.node_num,&thisnode);
                    799:        }
                    800: 
                    801:        if(!online || sys_status&SS_ABORT)
                    802:                return;
                    803: 
                    804:        if(((sys_status&SS_USERON && useron.chat&CHAT_SPLITP) || !(sys_status&SS_USERON))
                    805:                && term_supports(ANSI) && rows>=24)
                    806:                sys_status|=SS_SPLITP;
                    807:        else
                    808:                sys_status&=~SS_SPLITP;
                    809:        /*
                    810:        if(!(useron.misc&EXPERT))
                    811:                menu("privchat");
                    812:        */
                    813: 
                    814:        if(!(sys_status&SS_SPLITP)) {
                    815:                if(local)
                    816:                        bprintf(text[SysopIsHere],cfg.sys_op);
                    817:                else
                    818:                        bputs(text[WelcomeToPrivateChat]);
                    819:        }
                    820: 
                    821:        sprintf(outpath,"%schat.dab",cfg.node_dir);
                    822:        if((out=sopen(outpath,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IREAD|S_IWRITE))==-1) {
                    823:                errormsg(WHERE,ERR_OPEN,outpath,O_RDWR|O_DENYNONE|O_CREAT);
                    824:                return; 
                    825:        }
                    826: 
                    827:        if(local)
                    828:                sprintf(inpath,"%slchat.dab",cfg.node_dir);
                    829:        else
                    830:                sprintf(inpath,"%schat.dab",cfg.node_path[n-1]);
                    831:        if(!fexist(inpath))             /* Wait while it's created for the first time */
                    832:                mswait(2000);
                    833:        if((in=sopen(inpath,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IREAD|S_IWRITE))==-1) {
                    834:                close(out);
                    835:                errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_DENYNONE|O_CREAT);
                    836:                return; }
                    837: 
                    838:        if((p=(char *)malloc(PCHAT_LEN))==NULL) {
                    839:                close(in);
                    840:                close(out);
                    841:                errormsg(WHERE,ERR_ALLOC,str,PCHAT_LEN);
                    842:                return; }
                    843:        memset(p,0,PCHAT_LEN);
                    844:        write(in,p,PCHAT_LEN);
                    845:        write(out,p,PCHAT_LEN);
                    846:        free(p);
                    847:        lseek(in,0L,SEEK_SET);
                    848:        lseek(out,0L,SEEK_SET);
                    849: 
                    850:        if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                    851:                thisnode.misc&=~NODE_RPCHT;             /* Clear "reset pchat flag" */
                    852:                putnodedat(cfg.node_num,&thisnode);
                    853:        }
                    854: 
                    855:        if(!local) {
                    856:                if(getnodedat(n,&node,true)==0) {
                    857:                        node.misc|=NODE_RPCHT;                          /* Set "reset pchat flag" */
                    858:                        putnodedat(n,&node);                            /* on other node */
                    859:                }
                    860: 
                    861:                                                                                        /* Wait for other node */
                    862:                                                                                        /* to acknowledge and reset */
                    863:                while(online && !(sys_status&SS_ABORT)) {
                    864:                        getnodedat(n,&node,0);
                    865:                        if(!(node.misc&NODE_RPCHT))
                    866:                                break;
                    867:                        getnodedat(cfg.node_num,&thisnode,0);
                    868:                        if(thisnode.misc&NODE_RPCHT)
                    869:                                break;
                    870:                        checkline();
                    871:                        gettimeleft();
                    872:                        SYNC;
                    873:                        SLEEP(500); 
                    874:                }
                    875:        }
                    876: 
                    877:        action=NODE_PCHT;
                    878:        SYNC;
                    879: 
                    880:        if(sys_status&SS_SPLITP) {
                    881:                lncntr=0;
                    882:                CLS;
                    883:                ANSI_SAVE();
                    884: #if 0
                    885:                if(local)
                    886:                        bprintf(text[SysopIsHere],cfg.sys_op);
                    887: #endif
                    888:                GOTOXY(1,13);
                    889:                remote_y=1;
                    890:                bprintf(local ? local_sep : sep
                    891:                        ,thisnode.misc&NODE_MSGW ? 'T':' '
                    892:                        ,sectostr(timeleft,tmp)
                    893:                        ,thisnode.misc&NODE_NMSG ? 'M':' ');
                    894:                CRLF;
                    895:                local_y=14; }
                    896: 
                    897:        while(online && (local || !(sys_status&SS_ABORT))) {
                    898:                lncntr=0;
                    899:                if(sys_status&SS_SPLITP)
                    900:                        lbuflen=0;
                    901:                action=NODE_PCHT;
                    902:                activity=0;
                    903:                remote_activity=0;
                    904:                if((ch=inkey(K_GETSTR,100))!=0) {
                    905:                        activity=1;
                    906:                        if(echo)
                    907:                                attr(cfg.color[clr_chatlocal]);
                    908:                        if(ch==BS || ch==DEL) {
                    909:                                if(localchar) {
                    910:                                        if(echo)
                    911:                                                backspace();
                    912:                                        localchar--;
                    913:                                        localbuf[localline][localchar]=0; } }
                    914:                        else if(ch==TAB) {
                    915:                                if(echo)
                    916:                                        outchar(' ');
                    917:                                localbuf[localline][localchar]=' ';
                    918:                                localchar++;
                    919:                                while(localchar<78 && localchar%8) {
                    920:                                        if(echo)
                    921:                                                outchar(' ');
                    922:                                        localbuf[localline][localchar++]=' '; } }
                    923:                        else if(ch==CTRL_R) {
                    924:                                if(sys_status&SS_SPLITP) {
                    925:                                        CLS;
                    926:                                        attr(cfg.color[clr_chatremote]);
                    927:                                        remotebuf[remoteline][remotechar]=0;
                    928:                                        for(i=0;i<=remoteline;i++) {
                    929:                                                bputs(remotebuf[i]); 
                    930:                                                if(i!=remoteline) 
                    931:                                                        bputs(crlf);
                    932:                                        }
                    933:                                        remote_y=1+remoteline;
                    934:                                        bputs("\1i_\1n");  /* Fake cursor */
                    935:                                        ANSI_SAVE();
                    936:                                        GOTOXY(1,13);
                    937:                                        bprintf(local ? local_sep : sep
                    938:                                                ,thisnode.misc&NODE_MSGW ? 'T':' '
                    939:                                                ,sectostr(timeleft,tmp)
                    940:                                                ,thisnode.misc&NODE_NMSG ? 'M':' ');
                    941:                                        CRLF;
                    942:                                        attr(cfg.color[clr_chatlocal]);
                    943:                                        localbuf[localline][localchar]=0;
                    944:                                        for(i=0;i<=localline;i++) {
                    945:                                                bputs(localbuf[i]);
                    946:                                                if(i!=localline) 
                    947:                                                        bputs(crlf);
                    948:                                        }
                    949:                                        local_y=15+localline;
                    950:                                }
                    951:                                continue;
                    952:                        }
                    953:                        else if(ch>=' ' || ch==CR) {
                    954:                                if(ch!=CR) {
                    955:                                        if(echo)
                    956:                                                outchar(ch);
                    957:                                        localbuf[localline][localchar]=ch; }
                    958: 
                    959:                                if(ch==CR || (localchar>68 && ch==' ') || ++localchar>78) {
                    960: 
                    961:                                        localbuf[localline][localchar]=0;
                    962:                                        localchar=0;
                    963: 
                    964:                                        if(sys_status&SS_SPLITP && local_y==24) {
                    965:                                                GOTOXY(1,13);
                    966:                                                bprintf(local ? local_sep : sep
                    967:                                                        ,thisnode.misc&NODE_MSGW ? 'T':' '
                    968:                                                        ,sectostr(timeleft,tmp)
                    969:                                                        ,thisnode.misc&NODE_NMSG ? 'M':' ');
                    970:                                                attr(cfg.color[clr_chatlocal]);
                    971:                                                for(x=13,y=0;x<rows;x++,y++) {
                    972:                                                        rprintf("\x1b[%d;1H\x1b[K",x+1);
                    973:                                                        if(y<=localline)
                    974:                                                                bprintf("%s\r\n",localbuf[y]); }
                    975:                                                GOTOXY(1,local_y=(15+localline));
                    976:                                                localline=0; }
                    977:                                        else {
                    978:                                                if(localline>=4)
                    979:                                                        for(i=0;i<4;i++)
                    980:                                                                memcpy(localbuf[i],localbuf[i+1],81);
                    981:                                                else
                    982:                                                        localline++;
                    983:                                                if(echo) {
                    984:                                                        CRLF;
                    985:                                        local_y++;
                    986:                                                        if(sys_status&SS_SPLITP)
                    987:                                                                cleartoeol(); 
                    988:                                                } 
                    989:                                        }
                    990:                                        // SYNC;
                    991:                                } 
                    992:                        }
                    993: 
                    994:                        read(out,&c,1);
                    995:                        lseek(out,-1L,SEEK_CUR);
                    996:                        if(!c)          /* hasn't wrapped */
                    997:                                write(out,&ch,1);
                    998:                        else {
                    999:                                if(!tell(out))
                   1000:                                        lseek(out,0L,SEEK_END);
                   1001:                                lseek(out,-1L,SEEK_CUR);
                   1002:                                ch=0;
                   1003:                                write(out,&ch,1);
                   1004:                                lseek(out,-1L,SEEK_CUR); 
                   1005:                        }
                   1006:                        utime(outpath,NULL);    /* update mod time for NFS/smbfs nodes */
                   1007:                        if(tell(out)>=PCHAT_LEN)
                   1008:                                lseek(out,0L,SEEK_SET);
                   1009:                }
                   1010:                else while(online) {
                   1011:                        if(!(sys_status&SS_SPLITP))
                   1012:                                remotechar=localchar;
                   1013:                        if(tell(in)>=PCHAT_LEN)
                   1014:                                lseek(in,0L,SEEK_SET);
                   1015:                        ch=0;
                   1016:                        utime(inpath,NULL);
                   1017:                        read(in,&ch,1);
                   1018:                        lseek(in,-1L,SEEK_CUR);
                   1019:                        if(!ch) break;                                    /* char from other node */
                   1020:                        activity=1;
                   1021:                        if(sys_status&SS_SPLITP && !remote_activity) {
                   1022:                                ansi_getxy(&x,&y);
                   1023:                                ANSI_RESTORE();
                   1024:                        }
                   1025:                        attr(cfg.color[clr_chatremote]);
                   1026:                        if(sys_status&SS_SPLITP && !remote_activity)
                   1027:                                backspace();             /* Delete fake cursor */
                   1028:                        remote_activity=1;
                   1029:                        if(ch==BS || ch==DEL) {
                   1030:                                if(remotechar) {
                   1031:                                        backspace();
                   1032:                                        remotechar--;
                   1033:                                        remotebuf[remoteline][remotechar]=0; } }
                   1034:                        else if(ch==TAB) {
                   1035:                                outchar(' ');
                   1036:                                remotebuf[remoteline][remotechar]=' ';
                   1037:                                remotechar++;
                   1038:                                while(remotechar<78 && remotechar%8) {
                   1039:                                        outchar(' ');
                   1040:                                        remotebuf[remoteline][remotechar++]=' '; } }
                   1041:                        else if(ch>=' ' || ch==CR) {
                   1042:                                if(ch!=CR) {
                   1043:                                        outchar(ch);
                   1044:                                        remotebuf[remoteline][remotechar]=ch; }
                   1045: 
                   1046:                                if(ch==CR || (remotechar>68 && ch==' ') || ++remotechar>78) {
                   1047: 
                   1048:                                        remotebuf[remoteline][remotechar]=0;
                   1049:                                        remotechar=0;
                   1050: 
                   1051:                                        if(sys_status&SS_SPLITP && remote_y==12) {
                   1052:                                                CRLF;
                   1053:                                                bprintf(local ? local_sep : sep
                   1054:                                                        ,thisnode.misc&NODE_MSGW ? 'T':' '
                   1055:                                                        ,sectostr(timeleft,tmp)
                   1056:                                                        ,thisnode.misc&NODE_NMSG ? 'M':' ');
                   1057:                                                attr(cfg.color[clr_chatremote]);
                   1058:                                                for(i=0;i<12;i++) {
                   1059:                                                        bprintf("\x1b[%d;1H\x1b[K",i+1);
                   1060:                                                        if(i<=remoteline)
                   1061:                                                                bprintf("%s\r\n",remotebuf[i]); }
                   1062:                                                remoteline=0;
                   1063:                                                GOTOXY(1, remote_y=6); }
                   1064:                                        else {
                   1065:                                                if(remoteline>=4)
                   1066:                                                        for(i=0;i<4;i++)
                   1067:                                                                memcpy(remotebuf[i],remotebuf[i+1],81);
                   1068:                                                else
                   1069:                                                        remoteline++;
                   1070:                                                if(echo) {
                   1071:                                                        CRLF;
                   1072:                                        remote_y++;
                   1073:                                                        if(sys_status&SS_SPLITP)
                   1074:                                                                cleartoeol(); 
                   1075:                                                } 
                   1076:                                        } 
                   1077:                                } 
                   1078:                        }
                   1079:                        ch=0;
                   1080:                        write(in,&ch,1);
                   1081: 
                   1082:                        if(!(sys_status&SS_SPLITP))
                   1083:                                localchar=remotechar;
                   1084:                        }
                   1085: 
                   1086:                if(sys_status&SS_SPLITP && remote_activity) {
                   1087:                        bputs("\1i_\1n");  /* Fake cursor */
                   1088:                        ANSI_SAVE();
                   1089:                        GOTOXY(x,y); 
                   1090:                }
                   1091: 
                   1092:                now=time(NULL);
                   1093:                if(!activity && now!=last_nodechk) {    /* no activity so chk node.dab */
                   1094: 
                   1095:                        if(!localchar) {
                   1096:                                if(sys_status&SS_SPLITP) {
                   1097:                                        getnodedat(cfg.node_num,&thisnode,0);
                   1098:                                        if(thisnode.misc&NODE_INTR)
                   1099:                                                break;
                   1100:                                        if(thisnode.misc&NODE_UDAT && !(useron.rest&FLAG('G'))) {
                   1101:                                                getuserdat(&cfg,&useron);
                   1102:                                                if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                   1103:                                                        thisnode.misc&=~NODE_UDAT;
                   1104:                                                        putnodedat(cfg.node_num,&thisnode); 
                   1105:                                                }
                   1106:                                        } 
                   1107:                                }
                   1108:                                else
                   1109:                                        nodesync(); 
                   1110:                        }
                   1111: 
                   1112:                        if(!local) {
                   1113:                                getnodedat(n,&node,0);
                   1114:                                if((node.action!=NODE_PCHT && node.action!=NODE_PAGE)
                   1115:                                        || node.aux!=cfg.node_num) {
                   1116:                                        bprintf(text[NodeLeftPrivateChat]
                   1117:                                                ,n,node.misc&NODE_ANON ? text[UNKNOWN_USER]
                   1118:                                                : username(&cfg,node.useron,tmp));
                   1119:                                        break; 
                   1120:                                }
                   1121:                        }
                   1122:                        getnodedat(cfg.node_num,&thisnode,0);
                   1123:                        if(thisnode.action!=NODE_PCHT) {
                   1124:                                action=thisnode.action;
                   1125:                                bputs(text[EndOfChat]);
                   1126:                                break;
                   1127:                        }
                   1128:                        if(thisnode.misc&NODE_RPCHT) {          /* pchat has been reset */
                   1129:                                lseek(in,0L,SEEK_SET);                  /* so seek to beginning */
                   1130:                                lseek(out,0L,SEEK_SET);
                   1131:                                if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                   1132:                                        thisnode.misc&=~NODE_RPCHT;
                   1133:                                        putnodedat(cfg.node_num,&thisnode); 
                   1134:                                }
                   1135:                        }
                   1136:                        last_nodechk=now;
                   1137:                        gettimeleft(); 
                   1138:                }
                   1139:        }
                   1140:        if(sys_status&SS_SPLITP)
                   1141:                CLS;
                   1142:        sys_status&=~(SS_SPLITP|SS_ABORT);
                   1143:        close(in);
                   1144:        close(out);
                   1145: }
                   1146: 
                   1147: 
                   1148: int sbbs_t::getnodetopage(int all, int telegram)
                   1149: {
                   1150:        char    str[128];
                   1151:        char    tmp[512];
                   1152:        uint    i,j;
                   1153:        ulong   l;
                   1154:        node_t  node;
                   1155: 
                   1156:        if(!lastnodemsg)
                   1157:                lastnodemsguser[0]=0;
                   1158:        if(lastnodemsg) {
                   1159:                getnodedat(lastnodemsg,&node,0);
                   1160:                if(node.status!=NODE_INUSE && !SYSOP)
                   1161:                        lastnodemsg=1; }
                   1162:        for(j=0,i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
                   1163:                getnodedat(i,&node,0);
                   1164:                if(i==cfg.node_num)
                   1165:                        continue;
                   1166:                if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) {
                   1167:                        if(!lastnodemsg)
                   1168:                                lastnodemsg=i;
                   1169:                        j++; } }
                   1170: 
                   1171:        if(!lastnodemsguser[0])
                   1172:                sprintf(lastnodemsguser,"%u",lastnodemsg);
                   1173: 
                   1174:        if(!j && !telegram) {
                   1175:                bputs(text[NoOtherActiveNodes]);
                   1176:                return(0); }
                   1177: 
                   1178:        if(all)
                   1179:                sprintf(str,text[NodeToSendMsgTo],lastnodemsg);
                   1180:        else
                   1181:                sprintf(str,text[NodeToPrivateChat],lastnodemsg);
                   1182:        mnemonics(str);
                   1183: 
                   1184:        strcpy(str,lastnodemsguser);
                   1185:        getstr(str,LEN_ALIAS,K_UPRLWR|K_LINE|K_EDIT|K_AUTODEL);
                   1186:        if(sys_status&SS_ABORT)
                   1187:                return(0);
                   1188:        if(!str[0])
                   1189:                return(0);
                   1190: 
                   1191:        j=atoi(str);
                   1192:        if(j && j<=cfg.sys_lastnode && j<=cfg.sys_nodes) {
                   1193:                getnodedat(j,&node,0);
                   1194:                if(node.status!=NODE_INUSE && !SYSOP) {
                   1195:                        bprintf(text[NodeNIsNotInUse],j);
                   1196:                        return(0); }
                   1197:                if(telegram && node.misc&(NODE_POFF|NODE_ANON) && !SYSOP) {
                   1198:                        bprintf(text[CantPageNode],node.misc&NODE_ANON
                   1199:                                ? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
                   1200:                        return(0); }
                   1201:                strcpy(lastnodemsguser,str);
                   1202:                if(telegram)
                   1203:                        return(node.useron);
                   1204:                return(j); }
                   1205:        if(all && !stricmp(str,"ALL"))
                   1206:                return(-1);
                   1207: 
                   1208:        if(str[0]=='\'') {
                   1209:                j=userdatdupe(0,U_HANDLE,LEN_HANDLE,str+1,0);
                   1210:                if(!j) {
                   1211:                        bputs(text[UnknownUser]);
                   1212:                        return(0); } }
                   1213:        else if(str[0]=='#')
                   1214:                j=atoi(str+1);
                   1215:        else
                   1216:                j=finduser(str);
                   1217:        if(!j)
                   1218:                return(0);
                   1219:        if(j>lastuser(&cfg))
                   1220:                return(0);
                   1221:        getuserrec(&cfg,j,U_MISC,8,tmp);
                   1222:        l=ahtoul(tmp);
                   1223:        if(l&(DELETED|INACTIVE)) {              /* Deleted or Inactive User */
                   1224:                bputs(text[UnknownUser]);
                   1225:                return(0); }
                   1226: 
                   1227:        for(i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
                   1228:                getnodedat(i,&node,0);
                   1229:                if((node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET))
                   1230:                        && node.useron==j) {
                   1231:                        if(telegram && node.misc&NODE_POFF && !SYSOP) {
                   1232:                                bprintf(text[CantPageNode],node.misc&NODE_ANON
                   1233:                                        ? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
                   1234:                                return(0); }
                   1235:                        if(telegram)
                   1236:                                return(j);
                   1237:                        strcpy(lastnodemsguser,str);
                   1238:                        return(i); } }
                   1239:        if(telegram) {
                   1240:                strcpy(lastnodemsguser,str);
                   1241:                return(j); }
                   1242:        bputs(text[UserNotFound]);
                   1243:        return(0);
                   1244: }
                   1245: 
                   1246: 
                   1247: /****************************************************************************/
                   1248: /* Sending single line messages between nodes                               */
                   1249: /****************************************************************************/
                   1250: void sbbs_t::nodemsg()
                   1251: {
                   1252:        char    str[256],line[256],buf[512],logbuf[512],ch=0;
                   1253:        char    tmp[512];
                   1254:        int     i,usernumber,done=0;
                   1255:        node_t  node,savenode;
                   1256: 
                   1257:        if(nodemsg_inside>1)    /* nested once only */
                   1258:                return;
                   1259:        sys_status|=SS_IN_CTRLP;
                   1260:        getnodedat(cfg.node_num,&savenode,0);
                   1261:        nodemsg_inside++;
                   1262:        wordwrap[0]=0;
                   1263:        while(online && !done) {
                   1264:                if(useron.rest&FLAG('C')) {
                   1265:                        bputs(text[R_SendMessages]);
                   1266:                        break; 
                   1267:                }
                   1268:                SYNC;
                   1269:                mnemonics(text[PrivateMsgPrompt]);
                   1270:                sys_status&=~SS_ABORT;
                   1271:                while(online) {          /* Watch for incoming messages */
                   1272:                        ch=toupper(inkey(K_NONE,1000));
                   1273:                        if(ch && strchr("TMCQ\r",ch))
                   1274:                                break;
                   1275:                        if(sys_status&SS_ABORT)
                   1276:                                break;
                   1277:                        if(getnodedat(cfg.node_num,&thisnode,false)==0) {
                   1278:                                if(thisnode.misc&(NODE_MSGW|NODE_NMSG)) {
                   1279:                                        lncntr=0;       /* prevent pause prompt */
                   1280:                                        SAVELINE;
                   1281:                                        CRLF;
                   1282:                                        if(thisnode.misc&NODE_NMSG)
                   1283:                                                getnmsg();
                   1284:                                        if(thisnode.misc&NODE_MSGW)
                   1285:                                                getsmsg(useron.number);
                   1286:                                        CRLF;
                   1287:                                        RESTORELINE; }
                   1288:                                else
                   1289:                                        nodesync();
                   1290:                        }
                   1291:                        gettimeleft();
                   1292:                }
                   1293: 
                   1294:                if(!online || sys_status&SS_ABORT) {
                   1295:                        sys_status&=~SS_ABORT;
                   1296:                        CRLF;
                   1297:                        break; 
                   1298:                }
                   1299: 
                   1300:                switch(toupper(ch)) {
                   1301:                        case 'T':   /* Telegram */
                   1302:                                bputs("Telegram\r\n");
                   1303:                                usernumber=getnodetopage(0,1);
                   1304:                                if(!usernumber)
                   1305:                                        break;
                   1306: 
                   1307:                                if(usernumber==1 && useron.rest&FLAG('S')) { /* ! val fback */
                   1308:                                        bprintf(text[R_Feedback],cfg.sys_op);
                   1309:                                        break; }
                   1310:                                if(usernumber!=1 && useron.rest&FLAG('E')) {
                   1311:                                        bputs(text[R_Email]);
                   1312:                                        break; }
                   1313:                                now=time(NULL);
                   1314:                                bprintf(text[SendingTelegramToUser]
                   1315:                                        ,username(&cfg,usernumber,tmp),usernumber);
                   1316:                                sprintf(buf,text[TelegramFmt]
                   1317:                                        ,thisnode.misc&NODE_ANON ? text[UNKNOWN_USER] : useron.alias
                   1318:                                        ,timestr(&now));
                   1319:                                i=0;
                   1320:                                logbuf[0]=0;
                   1321:                                while(online && i<5) {
                   1322:                                        bprintf("%4s",nulstr);
                   1323:                                        if(!getstr(line,70,K_WRAP|K_MSG))
                   1324:                                                break;
                   1325:                                        sprintf(str,"%4s%s\r\n",nulstr,line);
                   1326:                                        strcat(buf,str);
                   1327:                                        if(line[0]) {
                   1328:                                                if(i)
                   1329:                                                        strcat(logbuf,"   ");
                   1330:                                                strcat(logbuf,line);
                   1331:                                        }
                   1332:                                        i++; }
                   1333:                                if(!i)
                   1334:                                        break;
                   1335:                                if(sys_status&SS_ABORT) {
                   1336:                                        CRLF;
                   1337:                                        break; }
                   1338:                                putsmsg(&cfg,usernumber,buf);
                   1339:                                sprintf(str,"%s sent telegram to %s #%u"
                   1340:                                        ,useron.alias,username(&cfg,usernumber,tmp),usernumber);
                   1341:                                logline("C",str);
                   1342:                                logline(nulstr,logbuf);
                   1343:                                bprintf(text[MsgSentToUser],"Telegram"
                   1344:                                        ,username(&cfg,usernumber,tmp),usernumber);
                   1345:                                break;
                   1346:                        case 'M':   /* Message */
                   1347:                                bputs("Message\r\n");
                   1348:                                i=getnodetopage(1,0);
                   1349:                                if(!i)
                   1350:                                        break;
                   1351:                                if(i!=-1) {
                   1352:                                        getnodedat(i,&node,0);
                   1353:                                        usernumber=node.useron;
                   1354:                                        if(node.misc&NODE_POFF && !SYSOP)
                   1355:                                                bprintf(text[CantPageNode],node.misc&NODE_ANON
                   1356:                                                        ? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
                   1357:                                        else {
                   1358:                                                bprintf(text[SendingMessageToUser]
                   1359:                                                        ,node.misc&NODE_ANON ? text[UNKNOWN_USER]
                   1360:                                                        : username(&cfg,node.useron,tmp)
                   1361:                                                        ,node.misc&NODE_ANON ? 0 : node.useron);
                   1362:                                                bputs(text[NodeMsgPrompt]);
                   1363:                                                if(!getstr(line,69,K_LINE))
                   1364:                                                        break;
                   1365:                                                sprintf(buf,text[NodeMsgFmt],cfg.node_num
                   1366:                                                        ,thisnode.misc&NODE_ANON
                   1367:                                                                ? text[UNKNOWN_USER] : useron.alias,line);
                   1368:                                                putnmsg(&cfg,i,buf);
                   1369:                                                if(!(node.misc&NODE_ANON))
                   1370:                                                        bprintf(text[MsgSentToUser],"Message"
                   1371:                                                                ,username(&cfg,usernumber,tmp),usernumber);
                   1372:                                                sprintf(str,"%s sent message to %s on node %d:"
                   1373:                                                        ,useron.alias,username(&cfg,usernumber,tmp),i);
                   1374:                                                logline("C",str);
                   1375:                                                logline(nulstr,line); } }
                   1376:                                else {  /* ALL */
                   1377:                                        bputs(text[NodeMsgPrompt]);
                   1378:                                        if(!getstr(line,70,K_LINE))
                   1379:                                                break;
                   1380:                                        sprintf(buf,text[AllNodeMsgFmt],cfg.node_num
                   1381:                                                ,thisnode.misc&NODE_ANON
                   1382:                                                        ? text[UNKNOWN_USER] : useron.alias,line);
                   1383:                                        for(i=1;i<=cfg.sys_nodes;i++) {
                   1384:                                                if(i==cfg.node_num)
                   1385:                                                        continue;
                   1386:                                                getnodedat(i,&node,0);
                   1387:                                                if((node.status==NODE_INUSE
                   1388:                                                        || (SYSOP && node.status==NODE_QUIET))
                   1389:                                                        && (SYSOP || !(node.misc&NODE_POFF)))
                   1390:                                                        putnmsg(&cfg,i,buf); }
                   1391:                                        sprintf(str,"%s sent message to all nodes",useron.alias);
                   1392:                                        logline("C",str);
                   1393:                                        logline(nulstr,line); 
                   1394:                                }
                   1395:                                break;
                   1396:                        case 'C':   /* Chat */
                   1397:                                bputs("Chat\r\n");
                   1398:                                if(action==NODE_PCHT) { /* already in pchat */
                   1399:                                        done=1;
                   1400:                                        break; }
                   1401:                                privchat();
                   1402:                                action=savenode.action;
                   1403:                                break;
                   1404:                        default:
                   1405:                                bputs("Quit\r\n");
                   1406:                                done=1;
                   1407:                                break; } }
                   1408:        nodemsg_inside--;
                   1409:        if(!nodemsg_inside)
                   1410:                sys_status&=~SS_IN_CTRLP;
                   1411:        if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                   1412:                thisnode.action=action=savenode.action;
                   1413:                thisnode.aux=savenode.aux;
                   1414:                thisnode.extaux=savenode.extaux;
                   1415:                putnodedat(cfg.node_num,&thisnode);
                   1416:        }
                   1417: }
                   1418: 
                   1419: /****************************************************************************/
                   1420: /* The guru will respond from the 'guru' buffer to 'line'                   */
                   1421: /****************************************************************************/
                   1422: void sbbs_t::guruchat(char* line, char* gurubuf, int gurunum, char* last_answer)
                   1423: {
                   1424:        char    str[512],cstr[512],*ptr,*answer[100],theanswer[1024]
                   1425:                        ,mistakes=1,hu=0;
                   1426:        char    tmp[512];
                   1427:        int             file;
                   1428:        uint    c,i,j,k,answers;
                   1429:        long    len;
                   1430:        struct  tm tm;
                   1431: 
                   1432:        now=time(NULL);
                   1433:        localtime_r(&now,&tm);
                   1434: 
                   1435:        for(i=0;i<100;i++) {
                   1436:                if((answer[i]=(char *)malloc(512))==NULL) {
                   1437:                        errormsg(WHERE,ERR_ALLOC,nulstr,512);
                   1438:                        while(i) {
                   1439:                                i--;
                   1440:                                free(answer[i]); }
                   1441:                        sys_status&=~SS_GURUCHAT;
                   1442:                        return; } }
                   1443:        ptr=gurubuf;
                   1444:        len=strlen(gurubuf);
                   1445:        strupr(line);
                   1446:        j=strlen(line);
                   1447:        k=0;
                   1448:        for(i=0;i<j;i++) {
                   1449:                if(!isalnum(line[i]) && !k)     /* beginning non-alphanumeric */
                   1450:                        continue;
                   1451:                if(!isalnum(line[i]) && line[i]==line[i+1])     /* redundant non-alnum */
                   1452:                        continue;
                   1453:                if(!isalnum(line[i]) && line[i+1]=='?') /* fix "WHAT ?" */
                   1454:                        continue;
                   1455:                cstr[k++]=line[i]; }
                   1456:        cstr[k]=0;
                   1457:        while(k) {
                   1458:                k--;
                   1459:                if(!isalnum(cstr[k]))
                   1460:                        continue;
                   1461:                break; }
                   1462:        if(k<1) {
                   1463:                for(i=0;i<100;i++)
                   1464:                        free(answer[i]);
                   1465:                return; }
                   1466:        if(cstr[k+1]=='?')
                   1467:                k++;
                   1468:        cstr[k+1]=0;
                   1469:        while(*ptr && ptr<gurubuf+len) {
                   1470:                if(*ptr=='(') {
                   1471:                        ptr++;
                   1472:                        if(!guruexp(&ptr,cstr)) {
                   1473:                                while(*ptr && *ptr!='(' && ptr<gurubuf+len)
                   1474:                                        ptr++;
                   1475:                                continue; } }
                   1476:                else {
                   1477:                        while(*ptr && *ptr!=LF && ptr<gurubuf+len) /* skip LF after ')' */
                   1478:                                ptr++;
                   1479:                        ptr++;
                   1480:                        answers=0;
                   1481:                        while(*ptr && answers<100 && ptr<gurubuf+len) {
                   1482:                                i=0;
                   1483:                                while(*ptr && *ptr!=CR && *ptr!=LF && i<511 && ptr<gurubuf+len) {
                   1484:                                        answer[answers][i]=*ptr;
                   1485:                                        ptr++;
                   1486:                                        i++;
                   1487:                                        /* multi-line answer */
                   1488:                                        if(*ptr=='\\' && (*(ptr+1)==CR || *(ptr+1)==LF)) {
                   1489:                                                ptr++;  /* skip \ */
                   1490:                                                while(*ptr && *ptr<' ') ptr++;  /* skip [CR]LF */
                   1491:                                                answer[answers][i++]=CR;
                   1492:                                                answer[answers][i++]=LF; } }
                   1493:                                answer[answers][i]=0;
                   1494:                                if(!strlen(answer[answers]) || answer[answers][0]=='(') {
                   1495:                                        ptr-=strlen(answer[answers]);
                   1496:                                        break; }
                   1497:                                while(*ptr && *ptr<' ') ptr++;  /* skip [CR]LF */
                   1498:                                answers++; }
                   1499:                        if(answers==100)
                   1500:                                while(*ptr && *ptr!='(' && ptr<gurubuf+len)
                   1501:                                        ptr++;
                   1502:                        /* Try to not repeat yourself */
                   1503:                        for(j=0;j<answers;j++) {
                   1504:                                i=sbbs_random(answers);
                   1505:                                if(stricmp(answer[i],last_answer))
                   1506:                                        break;
                   1507:                        }
                   1508:                        strcpy(last_answer,answer[i]);
                   1509:                        for(j=0,k=0;answer[i][j];j++) {
                   1510:                                if(answer[i][j]=='`') {
                   1511:                                        j++;
                   1512:                                        theanswer[k]=0;
                   1513:                                        switch(toupper(answer[i][j])) {
                   1514:                                                case 'A':
                   1515:                                                        if(sys_status&SS_USERON)
                   1516:                                                                strcat(theanswer,useron.alias);
                   1517:                                                        else
                   1518:                                                                strcat(theanswer,text[UNKNOWN_USER]);
                   1519:                                                        break;
                   1520:                                                case 'B':
                   1521:                                                        if(sys_status&SS_USERON)
                   1522:                                                                strcat(theanswer,useron.birth);
                   1523:                                                        else
                   1524:                                                                strcat(theanswer,"00/00/00");
                   1525:                                                        break;
                   1526:                                                case 'C':
                   1527:                                if(sys_status&SS_USERON)
                   1528:                                                                strcat(theanswer,useron.comp);
                   1529:                                                        else
                   1530:                                                                strcat(theanswer,"PC Jr.");
                   1531:                                                        break;
                   1532:                                                case 'D':
                   1533:                                if(sys_status&SS_USERON)
                   1534:                                                                strcat(theanswer,ultoac(useron.dlb,tmp));
                   1535:                                                        else
                   1536:                                                                strcat(theanswer,"0");
                   1537:                                                        break;
                   1538:                                                case 'G':
                   1539:                                                        strcat(theanswer,cfg.guru[gurunum]->name);
                   1540:                                                        break;
                   1541:                                                case 'H':
                   1542:                                                        hu=1;
                   1543:                                                        break;
                   1544:                                                case 'I':
                   1545:                                                        strcat(theanswer,cfg.sys_id);
                   1546:                                                        break;
                   1547:                                                case 'J':
                   1548:                                                        sprintf(tmp,"%u",tm.tm_mday);
                   1549:                                                        break;
                   1550:                                                case 'L':
                   1551:                                if(sys_status&SS_USERON)
                   1552:                                                                strcat(theanswer,ultoa(useron.level,tmp,10));
                   1553:                                                        else
                   1554:                                                                strcat(theanswer,"0");
                   1555:                                                        break;
                   1556:                                                case 'M':
                   1557:                                                        strcat(theanswer,month[tm.tm_mon]);
                   1558:                                                        break;
                   1559:                                                case 'N':   /* Note */
                   1560:                                if(sys_status&SS_USERON)
                   1561:                                                                strcat(theanswer,useron.note);
                   1562:                                                        else
                   1563:                                                                strcat(theanswer,text[UNKNOWN_USER]);
                   1564:                                                        break;
                   1565:                                                case 'O':
                   1566:                                                        strcat(theanswer,cfg.sys_op);
                   1567:                                                        break;
                   1568:                                                case 'P':
                   1569:                                if(sys_status&SS_USERON)
                   1570:                                                                strcat(theanswer,useron.phone);
                   1571:                                                        else
                   1572:                                                                strcat(theanswer,"000-000-0000");
                   1573:                                                        break;
                   1574:                                                case 'Q':
                   1575:                                                                sys_status&=~SS_GURUCHAT;
                   1576:                                                        break;
                   1577:                                                case 'R':
                   1578:                                if(sys_status&SS_USERON)
                   1579:                                                                strcat(theanswer,useron.name);
                   1580:                                                        else
                   1581:                                                                strcat(theanswer,text[UNKNOWN_USER]);
                   1582:                                                        break;
                   1583:                                                case 'S':
                   1584:                                                        strcat(theanswer,cfg.sys_name);
                   1585:                                                        break;
                   1586:                                                case 'T':
                   1587:                                                        sprintf(tmp,"%u:%02u",tm.tm_hour>12 ? tm.tm_hour-12
                   1588:                                                                : tm.tm_hour,tm.tm_min);
                   1589:                                                        strcat(theanswer,tmp);
                   1590:                                                        break;
                   1591:                                                case 'U':
                   1592:                                if(sys_status&SS_USERON)
                   1593:                                                                strcat(theanswer,ultoac(useron.ulb,tmp));
                   1594:                                                        else
                   1595:                                                                strcat(theanswer,"0");
                   1596:                                                        break;
                   1597:                                                case 'W':
                   1598:                                                        strcat(theanswer,weekday[tm.tm_wday]);
                   1599:                                                        break;
                   1600:                                                case 'Y':   /* Current year */
                   1601:                                                        sprintf(tmp,"%u",1900+tm.tm_year);
                   1602:                                                        strcat(theanswer,tmp);
                   1603:                                                        break;
                   1604:                                                case 'Z':
                   1605:                                                        if(sys_status&SS_USERON)
                   1606:                                                                strcat(theanswer,useron.zipcode);
                   1607:                                                        else
                   1608:                                                                strcat(theanswer,"90210");
                   1609:                                                        break;
                   1610:                                                case '$':   /* Credits */
                   1611:                                if(sys_status&SS_USERON)
                   1612:                                                                strcat(theanswer,ultoac(useron.cdt,tmp));
                   1613:                                                        else
                   1614:                                                                strcat(theanswer,"0");
                   1615:                                                        break;
                   1616:                                                case '#':
                   1617:                                if(sys_status&SS_USERON)
                   1618:                                                                strcat(theanswer,ultoa(getage(&cfg,useron.birth)
                   1619:                                                                        ,tmp,10));
                   1620:                                                        else
                   1621:                                                                strcat(theanswer,"0");
                   1622:                                                        break;
                   1623:                                                case '!':
                   1624:                                                        mistakes=!mistakes;
                   1625:                                                        break;
                   1626:                                                case '_':
                   1627:                                                        mswait(500);
                   1628:                                                        break; }
                   1629:                                        k=strlen(theanswer); }
                   1630:                                else
                   1631:                                        theanswer[k++]=answer[i][j]; }
                   1632:                        theanswer[k]=0;
                   1633:                        mswait(500+sbbs_random(1000));   /* thinking time */
                   1634:                        if(action!=NODE_MCHT) {
                   1635:                                for(i=0;i<k;i++) {
                   1636:                                        if(mistakes && theanswer[i]!=theanswer[i-1] &&
                   1637:                                                ((!isalnum(theanswer[i]) && !sbbs_random(100))
                   1638:                                                || (isalnum(theanswer[i]) && !sbbs_random(30)))) {
                   1639:                                                c=j=((uint)sbbs_random(3)+1);   /* 1 to 3 chars */
                   1640:                                                if(c<strcspn(theanswer+(i+1),"\0., "))
                   1641:                                                        c=j=1;
                   1642:                                                while(j) {
                   1643:                                                        outchar(97+sbbs_random(26));
                   1644:                                                        mswait(25+sbbs_random(150));
                   1645:                                                        j--; }
                   1646:                                                if(sbbs_random(100)) {
                   1647:                                                        mswait(100+sbbs_random(300));
                   1648:                                                        while(c) {
                   1649:                                                                backspace();
                   1650:                                                                mswait(50+sbbs_random(50));
                   1651:                                                                c--; } } }
                   1652:                                        outchar(theanswer[i]);
                   1653:                                        if(theanswer[i]==theanswer[i+1])
                   1654:                                                mswait(25+sbbs_random(50));
                   1655:                                        else
                   1656:                                                mswait(25+sbbs_random(150));
                   1657:                                        if(theanswer[i]==' ')
                   1658:                                                mswait(sbbs_random(50)); 
                   1659:                                        } }
                   1660:                        else {
                   1661:                                mswait(strlen(theanswer)*100);
                   1662:                                bprintf(text[ChatLineFmt],cfg.guru[gurunum]->name
                   1663:                                        ,cfg.sys_nodes+1,':',theanswer); }
                   1664:                        CRLF;
                   1665:                        sprintf(str,"%sguru.log",cfg.logs_dir);
                   1666:                        if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1)
                   1667:                                errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
                   1668:                        else {
                   1669:                                if(action==NODE_MCHT) {
                   1670:                                        sprintf(str,"[Multi] ");
                   1671:                                        write(file,str,strlen(str)); }
                   1672:                                sprintf(str,"%s:\r\n",sys_status&SS_USERON
                   1673:                                        ? useron.alias : "UNKNOWN");
                   1674:                                write(file,str,strlen(str));
                   1675:                                write(file,line,strlen(line));
                   1676:                                if(action!=NODE_MCHT)
                   1677:                                        write(file,crlf,2);
                   1678:                                sprintf(str,"%s:\r\n",cfg.guru[gurunum]->name);
                   1679:                                write(file,str,strlen(str));
                   1680:                                write(file,theanswer,strlen(theanswer));
                   1681:                                write(file,crlf,2);
                   1682:                                close(file); }
                   1683:                        if(hu)
                   1684:                                hangup();
                   1685:                        break; } }
                   1686:        for(i=0;i<100;i++)
                   1687:                free(answer[i]);
                   1688: }
                   1689: 
                   1690: /****************************************************************************/
                   1691: /* An expression from the guru's buffer 'ptrptr' is evaluated and true or   */
                   1692: /* false is returned.                                                       */
                   1693: /****************************************************************************/
                   1694: bool sbbs_t::guruexp(char **ptrptr, char *line)
                   1695: {
                   1696:        char    c,*cp,str[256];
                   1697:        int             nest;
                   1698:        bool    result=false,_and=false,_or=false;
                   1699:        uchar   *ar;
                   1700: 
                   1701:        if((**ptrptr)==')') {   /* expressions of () are always result */
                   1702:                (*ptrptr)++;
                   1703:                return(true); }
                   1704:        while((**ptrptr)!=')' && (**ptrptr)) {
                   1705:                if((**ptrptr)=='[') {
                   1706:                        (*ptrptr)++;
                   1707:                        SAFECOPY(str,*ptrptr);
                   1708:                        while(**ptrptr && (**ptrptr)!=']')
                   1709:                                (*ptrptr)++;
                   1710:                        (*ptrptr)++;
                   1711:                        cp=strchr(str,']');
                   1712:                        if(cp) *cp=0;
                   1713:                        ar=arstr(NULL,str,&cfg);
                   1714:                        c=chk_ar(ar,&useron);
                   1715:                        if(ar[0]!=AR_NULL)
                   1716:                                free(ar);
                   1717:                        if(!c && _and) {
                   1718:                                result=false;
                   1719:                                break; }
                   1720:                        if(c && _or) {
                   1721:                                result=true;
                   1722:                                break; }
                   1723:                        if(c)
                   1724:                                result=true;
                   1725:                        continue; }
                   1726:                if((**ptrptr)=='(') {
                   1727:                        (*ptrptr)++;
                   1728:                        c=guruexp(&(*ptrptr),line);
                   1729:                        if(!c && _and) {
                   1730:                                result=false;
                   1731:                                break; }
                   1732:                        if(c && _or) {
                   1733:                                result=true;
                   1734:                                break; }
                   1735:                        if(c)
                   1736:                                result=true; }
                   1737:                if((**ptrptr)==')')
                   1738:                        break;
                   1739:                c=0;
                   1740:                while((**ptrptr) && isspace(**ptrptr))
                   1741:                        (*ptrptr)++;
                   1742:                while((**ptrptr)!='|' && (**ptrptr)!='&' && (**ptrptr)!=')' &&(**ptrptr)) {
                   1743:                        str[c++]=(**ptrptr);
                   1744:                        (*ptrptr)++; }
                   1745:                str[c]=0;
                   1746:                if((**ptrptr)=='|') {
                   1747:                        if(!c && result)
                   1748:                                break;
                   1749:                        _and=false;
                   1750:                        _or=true; }
                   1751:                else if((**ptrptr)=='&') {
                   1752:                        if(!c && !result)
                   1753:                                break;
                   1754:                        _and=true;
                   1755:                        _or=false; }
                   1756:                if(!c) {                                /* support ((exp)op(exp)) */
                   1757:                        (*ptrptr)++;
                   1758:                        continue; }
                   1759:                if((**ptrptr)!=')')
                   1760:                        (*ptrptr)++;
                   1761:                c=0;                                    /* c now used for start line flag */
                   1762:                if(str[strlen(str)-1]=='^') {   /* ^signifies start of line only */
                   1763:                        str[strlen(str)-1]=0;
                   1764:                        c=true; }
                   1765:                if(str[strlen(str)-1]=='~') {   /* ~signifies non-isolated word */
                   1766:                        str[strlen(str)-1]=0;
                   1767:                        cp=strstr(line,str);
                   1768:                        if(c && cp!=line)
                   1769:                                cp=0; }
                   1770:                else {
                   1771:                        cp=strstr(line,str);
                   1772:                        if(cp && c) {
                   1773:                                if(cp!=line || isalnum(*(cp+strlen(str))))
                   1774:                                        cp=0; }
                   1775:                        else {  /* must be isolated word */
                   1776:                                while(cp)
                   1777:                                        if((cp!=line && isalnum(*(cp-1)))
                   1778:                                                || isalnum(*(cp+strlen(str))))
                   1779:                                                cp=strstr(cp+strlen(str),str);
                   1780:                                        else
                   1781:                                                break; } }
                   1782:                if(!cp && _and) {
                   1783:                        result=false;
                   1784:                        break; }
                   1785:                if(cp && _or) {
                   1786:                        result=true;
                   1787:                        break; }
                   1788:                if(cp)
                   1789:                        result=true; }
                   1790:        nest=0;
                   1791:        while((**ptrptr)!=')' && (**ptrptr)) {          /* handle nested exp */
                   1792:                if((**ptrptr)=='(')                                             /* (TRUE|(IGNORE)) */
                   1793:                        nest++;
                   1794:                (*ptrptr)++;
                   1795:                while((**ptrptr)==')' && nest && (**ptrptr)) {
                   1796:                        nest--;
                   1797:                        (*ptrptr)++; } }
                   1798:        (*ptrptr)++;    /* skip over ')' */
                   1799:        return(result);
                   1800: }
                   1801: 
                   1802: /****************************************************************************/
                   1803: /* Guru chat with the appearance of Local chat with sysop.                  */
                   1804: /****************************************************************************/
                   1805: void sbbs_t::localguru(char *gurubuf, int gurunum)
                   1806: {
                   1807:        char    ch,str[256];
                   1808:        int     con=console;             /* save console state */
                   1809:        char    lastanswer[512];
                   1810: 
                   1811:        if(sys_status&SS_GURUCHAT || !cfg.total_gurus)
                   1812:                return;
                   1813:        sys_status|=SS_GURUCHAT;
                   1814:        console&=~(CON_L_ECHOX|CON_R_ECHOX);    /* turn off X's */
                   1815:        console|=(CON_L_ECHO|CON_R_ECHO);                                       /* make sure echo is on */
                   1816:        if(action==NODE_CHAT) { /* only page if from chat section */
                   1817:                bprintf(text[PagingGuru],cfg.guru[gurunum]->name);
                   1818:                ch=sbbs_random(25)+25;
                   1819:                while(ch--) {
                   1820:                        mswait(200);
                   1821:                        outchar('.'); } }
                   1822:        bprintf(text[SysopIsHere],cfg.guru[gurunum]->name);
                   1823:        if(getnodedat(cfg.node_num,&thisnode,true)==0) {
                   1824:                thisnode.aux=gurunum;
                   1825:                putnodedat(cfg.node_num,&thisnode);
                   1826:        }
                   1827:        attr(cfg.color[clr_chatlocal]);
                   1828:        strcpy(str,"HELLO");
                   1829:        guruchat(str,gurubuf,gurunum,lastanswer);
                   1830:        str[0]=0;
                   1831:        while(online && (sys_status&SS_GURUCHAT)) {
                   1832:                checkline();
                   1833:                action=NODE_GCHT;
                   1834:                SYNC;
                   1835:                if(wordwrap[0]==0) {
                   1836:                        if((ch=inkey(K_NONE,1000))==0) {
                   1837:                                if(str[0]) {
                   1838:                                        attr(cfg.color[clr_chatlocal]);
                   1839:                                        guruchat(str,gurubuf,gurunum,lastanswer); 
                   1840:                                        str[0]=0;
                   1841:                                }
                   1842:                                continue;
                   1843:                        }
                   1844:                        ungetkey(ch);
                   1845:                }
                   1846:                attr(cfg.color[clr_chatremote]);
                   1847:                getstr(str,78,K_WRAP|K_CHAT);
                   1848:        }
                   1849:        bputs(text[EndOfChat]);
                   1850:        sys_status&=~SS_GURUCHAT;
                   1851:        console=con;                            /* restore console state */
                   1852: }
                   1853: 
                   1854: 

unix.superglobalmegacorp.com

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