Newer
Older
/* Synchronet real-time chat functions */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
#define PCHAT_LEN 1000 /* Size of Private chat file */
const char *weekday[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"
,"Saturday"};
const char *month[]={"January","February","March","April","May","June"
,"July","August","September","October","November","December"};
/****************************************************************************/
/****************************************************************************/
char line[256],str[256],ch,done
,usrs,preusrs,qusrs,*gurubuf=NULL,savch,*p
,pgraph[400],buf[400]
,usr[MAX_NODES],preusr[MAX_NODES],qusr[MAX_NODES];
int file;
long i,j,k,n;
node_t node;
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
if(channel<1 || channel>cfg.total_chans)
channel=1;
if(!chan_access(channel-1))
return;
if(useron.misc&(RIP|WIP|HTML) ||!(useron.misc&EXPERT))
menu("multchat");
bputs(text[WelcomeToMultiChat]);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
putnodedat(cfg.node_num,&thisnode);
}
bprintf(text[WelcomeToChannelN],channel,cfg.chan[channel-1]->name);
if(cfg.chan[channel-1]->misc&CHAN_GURU && cfg.chan[channel-1]->guru<cfg.total_gurus
&& chk_ar(cfg.guru[cfg.chan[channel-1]->guru]->ar,&useron,&client)) {
sprintf(str,"%s%s.dat",cfg.ctrl_dir,cfg.guru[cfg.chan[channel-1]->guru]->code);
if((file=nopen(str,O_RDONLY))==-1) {
errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
if((gurubuf=(char *)malloc((size_t)filelength(file)+1))==NULL) {
errormsg(WHERE,ERR_ALLOC,str,(size_t)filelength(file)+1);
(void)read(file,gurubuf,(size_t)filelength(file));
usrs=0;
for(i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if(node.action!=NODE_MCHT || node.status!=NODE_INUSE)
continue;
if(node.aux && (node.aux&0xff)!=channel)
continue;
printnodedat(i,&node);
preusrs=usrs;
if(gurubuf)
bprintf(text[NodeInMultiChatLocally]
,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name,channel);
bputs(text[YoureOnTheAir]);
done=0;
while(online && !done) {
checkline();
gettimeleft();
action=NODE_MCHT;
qusrs=usrs=0;
for(i=1;i<=cfg.sys_nodes;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if(node.action!=NODE_MCHT
|| (node.aux && channel && (node.aux&0xff)!=channel))
continue;
if(node.status==NODE_QUIET)
qusr[qusrs++]=(char)i;
else if(node.status==NODE_INUSE)
if(preusrs>usrs) {
if(!usrs && channel && cfg.chan[channel-1]->misc&CHAN_GURU
&& cfg.chan[channel-1]->guru<cfg.total_gurus)
bprintf(text[NodeJoinedMultiChat]
,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name
,channel);
outchar(BEL);
for(i=0;i<preusrs;i++) {
for(j=0;j<usrs;j++)
if(preusr[i]==usr[j])
break;
if(j==usrs) {
getnodedat(preusr[i],&node,0);
if(node.misc&NODE_ANON)
sprintf(str,"%.80s",text[UNKNOWN_USER]);
else
username(&cfg,node.useron,str);
bprintf(text[NodeLeftMultiChat]
,preusr[i],str,channel);
}
}
else if(preusrs<usrs) {
if(!preusrs && channel && cfg.chan[channel-1]->misc&CHAN_GURU
&& cfg.chan[channel-1]->guru<cfg.total_gurus)
bprintf(text[NodeLeftMultiChat]
,cfg.sys_nodes+1,cfg.guru[cfg.chan[channel-1]->guru]->name
,channel);
outchar(BEL);
for(i=0;i<usrs;i++) {
for(j=0;j<preusrs;j++)
if(usr[i]==preusr[j])
break;
if(j==preusrs) {
getnodedat(usr[i],&node,0);
if(node.misc&NODE_ANON)
sprintf(str,"%.80s",text[UNKNOWN_USER]);
else
username(&cfg,node.useron,str);
bprintf(text[NodeJoinedMultiChat]
,usr[i],str,channel);
}
}
preusrs=usrs;
for(i=0;i<usrs;i++)
preusr[i]=usr[i];
attr(cfg.color[clr_multichat]);
SYNC;
sys_status&=~SS_ABORT;
if((ch=inkey(K_NONE,250))!=0 || wordwrap[0]) {
if(ch=='/') {
bputs(text[MultiChatCommandPrompt]);
strcpy(str,"ACELWQ?*");
if(SYSOP)
SAFECAT(str,"0");
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
i=getkeys(str,cfg.total_chans);
if(i&0x80000000L) { /* change channel */
savch=(char)(i&~0x80000000L);
if(savch==channel)
continue;
if(!chan_access(savch-1))
continue;
bprintf(text[WelcomeToChannelN]
,savch,cfg.chan[savch-1]->name);
usrs=0;
for(i=1;i<=cfg.sys_nodes;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if(node.action!=NODE_MCHT
|| node.status!=NODE_INUSE)
continue;
if(node.aux && (node.aux&0xff)!=savch)
continue;
printnodedat(i,&node);
if(node.aux&0x1f00) { /* password */
bprintf(text[PasswordProtected]
,node.misc&NODE_ANON
? text[UNKNOWN_USER]
: username(&cfg,node.useron,tmp));
if(!getstr(str,8,K_UPPER|K_ALPHA|K_LINE))
break;
if(strcmp(str,unpackchatpass(tmp,&node)))
break;
bputs(text[CorrectPassword]);
}
if(i<=cfg.sys_nodes) { /* failed password */
bputs(text[WrongPassword]);
if(cfg.chan[savch-1]->misc&CHAN_GURU
&& cfg.chan[savch-1]->guru<cfg.total_gurus
&& chk_ar(cfg.guru[cfg.chan[savch-1]->guru]->ar,&useron,&client
)) {
sprintf(str,"%s%s.dat",cfg.ctrl_dir
,cfg.guru[cfg.chan[savch-1]->guru]->code);
if((file=nopen(str,O_RDONLY))==-1) {
errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
if((gurubuf=(char *)malloc((size_t)filelength(file)+1))==NULL) {
close(file);
errormsg(WHERE,ERR_ALLOC,str
,(size_t)filelength(file)+1);
(void)read(file,gurubuf,(size_t)filelength(file));
preusrs=usrs;
if(gurubuf)
bprintf(text[NodeInMultiChatLocally]
,cfg.sys_nodes+1
,cfg.guru[cfg.chan[savch-1]->guru]->name
,savch);
channel=savch;
if(!usrs && cfg.chan[savch-1]->misc&CHAN_PW
&& !noyes(text[PasswordProtectChanQ])) {
bputs(text[PasswordPrompt]);
if(getstr(str,8,K_UPPER|K_ALPHA|K_LINE)) {
getnodedat(cfg.node_num,&thisnode,true);
packchatpass(str,&thisnode);
getnodedat(cfg.node_num,&thisnode,true);
thisnode.aux=channel;
}
getnodedat(cfg.node_num,&thisnode,true);
putnodedat(cfg.node_num,&thisnode);
bputs(text[YoureOnTheAir]);
if(cfg.chan[channel-1]->cost
&& !(useron.exempt&FLAG('J')))
subtract_cdt(&cfg,&useron,cfg.chan[channel-1]->cost);
else switch(i) { /* other command */
case '0': /* Global channel */
if(!SYSOP)
break;
usrs=0;
for(i=1;i<=cfg.sys_nodes;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if(node.action!=NODE_MCHT
|| node.status!=NODE_INUSE)
continue;
printnodedat(i,&node);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.aux=channel=0;
putnodedat(cfg.node_num,&thisnode);
}
break;
case 'A': /* Action commands */
useron.chat^=CHAT_ACTION;
bprintf("\r\nAction commands are now %s\r\n"
,useron.chat&CHAT_ACTION
? text[ON]:text[OFF]);
putuserchat(useron.number, useron.chat);
break;
case 'C': /* List of action commands */
CRLF;
for(i=0;channel && i<cfg.total_chatacts;i++) {
if(cfg.chatact[i]->actset
!=cfg.chan[channel-1]->actset)
continue;
bprintf("%-*.*s",LEN_CHATACTCMD
,LEN_CHATACTCMD,cfg.chatact[i]->cmd);
if(!((i+1)%8)) {
CRLF;
break;
case 'E': /* Toggle echo */
useron.chat^=CHAT_ECHO;
bprintf(text[EchoIsNow]
,useron.chat&CHAT_ECHO
? text[ON]:text[OFF]);
putuserchat(useron.number, useron.chat);
break;
case 'L': /* list nodes */
CRLF;
for(i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
getnodedat(i,&node,0);
CRLF;
break;
case 'W': /* page node(s) */
j=getnodetopage(0,0);
if(!j)
break;
for(i=0;i<usrs;i++)
if(usr[i]==j)
break;
if(i>=usrs) {
bputs(text[UserNotFound]);
bputs(text[NodeMsgPrompt]);
if(!getstr(line,66,K_LINE|K_MSG))
break;
sprintf(buf,text[ChatLineFmt]
,thisnode.misc&NODE_ANON
? text[AnonUserChatHandle]
: useron.handle
,cfg.node_num,'*',line);
SAFECAT(buf,crlf);
if(useron.chat&CHAT_ECHO)
bputs(buf);
putnmsg(&cfg,j,buf);
break;
case 'Q': /* quit */
done=1;
break;
case '*':
if(!menu("chan", P_NOERROR)) {
bputs(text[ChatChanLstHdr]);
bputs(text[ChatChanLstTitles]);
if(cfg.total_chans>=10) {
bputs(" ");
bputs(text[ChatChanLstTitles]);
CRLF;
bputs(text[ChatChanLstUnderline]);
if(cfg.total_chans>=10) {
bputs(" ");
bputs(text[ChatChanLstUnderline]);
CRLF;
if(cfg.total_chans>=10)
j=(cfg.total_chans/2)+(cfg.total_chans&1);
else
j=cfg.total_chans;
for(i=0;i<j && !msgabort();i++) {
bprintf(text[ChatChanLstFmt],i+1
,cfg.chan[i]->name
,cfg.chan[i]->cost);
if(cfg.total_chans>=10) {
k=(cfg.total_chans/2)
+i+(cfg.total_chans&1);
if(k<cfg.total_chans) {
bputs(" ");
bprintf(text[ChatChanLstFmt]
,k+1
,cfg.chan[k]->name
,cfg.chan[k]->cost);
}
break;
case '?': /* menu */
menu("multchat");
ungetkey(ch);
j=0;
pgraph[0]=0;
while(j<5) {
if(!getstr(line,66,K_WRAP|K_MSG|K_CHAT))
break;
if(j) {
sprintf(str,text[ChatLineFmt]
,thisnode.misc&NODE_ANON
? text[AnonUserChatHandle]
: useron.handle
,cfg.node_num,':',nulstr);
SAFECAT(pgraph,tmp);
SAFECAT(pgraph,line);
SAFECAT(pgraph,crlf);
if(channel && useron.chat&CHAT_ACTION) {
for(i=0;i<cfg.total_chatacts;i++) {
if(cfg.chatact[i]->actset
!=cfg.chan[channel-1]->actset)
continue;
sprintf(str,"%s ",cfg.chatact[i]->cmd);
if(!strnicmp(str,pgraph,strlen(str)))
break;
sprintf(str,"%.*s"
,LEN_CHATACTCMD+2,pgraph);
str[strlen(str)-2]=0;
if(!stricmp(cfg.chatact[i]->cmd,str))
if(i<cfg.total_chatacts) {
p=pgraph+strlen(str);
n=atoi(p);
for(j=0;j<usrs;j++) {
getnodedat(usr[j],&node,0);
if(usrs==1) /* no need to search */
break;
if(n) {
if(usr[j]==n)
break;
username(&cfg,node.useron,str);
if(!strnicmp(str,p,strlen(str)))
break;
getuserstr(&cfg, node.useron, USER_HANDLE, str, sizeof(str));
if(!usrs
&& cfg.chan[channel-1]->guru<cfg.total_gurus)
strcpy(str
,cfg.guru[cfg.chan[channel-1]->guru]->name);
else if(j>=usrs)
strcpy(str,"everyone");
else if(node.misc&NODE_ANON)
strcpy(str,text[UNKNOWN_USER]);
else
username(&cfg,node.useron,str);
/* Display on same node */
bprintf(cfg.chatact[i]->out
,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias
,str);
CRLF;
if(usrs && j<usrs) {
/* Display to dest user */
sprintf(buf,cfg.chatact[i]->out
,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias
,"you");
SAFECAT(buf,crlf);
putnmsg(&cfg,usr[j],buf);
/* Display to all other users */
sprintf(buf,cfg.chatact[i]->out
,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias
,str);
SAFECAT(buf,crlf);
for(i=0;i<usrs;i++) {
if(i==j)
continue;
getnodedat(usr[i],&node,0);
putnmsg(&cfg,usr[i],buf);
for(i=0;i<qusrs;i++) {
getnodedat(qusr[i],&node,0);
putnmsg(&cfg,qusr[i],buf);
sprintf(buf,text[ChatLineFmt]
,thisnode.misc&NODE_ANON
? text[AnonUserChatHandle]
: useron.handle
,cfg.node_num,':',pgraph);
if(useron.chat&CHAT_ECHO)
bputs(buf);
for(i=0;i<usrs;i++) {
getnodedat(usr[i],&node,0);
putnmsg(&cfg,usr[i],buf);
for(i=0;i<qusrs;i++) {
getnodedat(qusr[i],&node,0);
putnmsg(&cfg,qusr[i],buf);
if(!usrs && channel && gurubuf
&& cfg.chan[channel-1]->misc&CHAN_GURU)
guruchat(pgraph,gurubuf,cfg.chan[channel-1]->guru,guru_lastanswer);
if(gurubuf != NULL)
free(gurubuf);
/****************************************************************************/
/****************************************************************************/
bool sbbs_t::guru_page(void)
{
char path[MAX_PATH+1];
char* gurubuf;
int file;
long i;
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
if(!cfg.total_gurus) {
bprintf(text[SysopIsNotAvailable],"The Guru");
if(cfg.total_gurus==1 && chk_ar(cfg.guru[0]->ar,&useron,&client))
i=0;
else {
for(i=0;i<cfg.total_gurus;i++)
uselect(1,i,nulstr,cfg.guru[i]->name,cfg.guru[i]->ar);
i=uselect(0,0,0,0,0);
if(i<0)
}
sprintf(path,"%s%s.dat",cfg.ctrl_dir,cfg.guru[i]->code);
if((file=nopen(path,O_RDONLY))==-1) {
errormsg(WHERE,ERR_OPEN,path,O_RDONLY);
long length = (long)filelength(file);
if(length < 0) {
errormsg(WHERE ,ERR_CHK, path, length);
close(file);
return false;
}
if((gurubuf=(char *)malloc(length + 1))==NULL) {
errormsg(WHERE, ERR_ALLOC, path, length + 1);
if(read(file,gurubuf,length) != length)
errormsg(WHERE, ERR_READ, path, length);
gurubuf[length]=0;
return(true);
}
/****************************************************************************/
/* The chat section */
/****************************************************************************/
void sbbs_t::chatsection()
{
exec_bin(cfg.chatsec_mod, &main_csi);
/****************************************************************************/
/****************************************************************************/
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
return(false);
}
if(sysop_available(&cfg)
|| (cfg.sys_chat_ar[0] && chk_ar(cfg.sys_chat_ar,&useron,&client))
if(!(sys_status&SS_SYSPAGE)) {
logline("C", "paged sysop for chat");
sprintf(str, "%s paged you to chat", useron.alias);
notify(&cfg, 1, str, NULL);
ftouch(syspage_semfile);
char topic[128];
SAFEPRINTF(topic, "page/node/%u", cfg.node_num);
snprintf(str, sizeof(str), "%u\t%s", useron.number, useron.alias);
mqtt_pub_timestamped_msg(mqtt, TOPIC_BBS_ACTION, topic, time(NULL), str);
break;
if(i<cfg.total_pages) {
bprintf(text[PagingGuru],cfg.sys_op);
long mode = 0;
if(cfg.page[i]->misc&XTRN_STDIO)
mode |= EX_STDIO;
if(cfg.page[i]->misc&XTRN_NATIVE)
mode|= EX_NATIVE;
if(cfg.page[i]->misc&XTRN_SH)
mode |= EX_SH;
external(cmdstr(cfg.page[i]->cmd,nulstr,nulstr,NULL,mode), mode);
else if(cfg.sys_misc&SM_SHRTPAGE) {
bprintf(text[PagingGuru],cfg.sys_op);
outchar('.');
}
CRLF;
}
else {
sys_status^=SS_SYSPAGE;
bprintf(text[SysopPageIsNow]
,sys_status&SS_SYSPAGE ? text[ON] : text[OFF]);
nosound();
}
if(!(sys_status&SS_SYSPAGE))
remove(syspage_semfile);
return(true);
}
bprintf(text[SysopIsNotAvailable],cfg.sys_op);
return(false);
}
/****************************************************************************/
/* Returns 1 if user online has access to channel "channum" */
/****************************************************************************/
bool sbbs_t::chan_access(uint cnum)
{
if(!cfg.total_chans || cnum>=cfg.total_chans || !chk_ar(cfg.chan[cnum]->ar,&useron,&client)) {
bputs(text[CantAccessThatChannel]);
return(false);
}
if(!(useron.exempt&FLAG('J')) && cfg.chan[cnum]->cost>user_available_credits(&useron)) {
bputs(text[NotEnoughCredits]);
return(false);
}
/****************************************************************************/
/* Private split-screen (or interspersed) chat with node or local sysop */
/****************************************************************************/

Rob Swindell
committed
void sbbs_t::privchat(bool forced, int node_num)
{
char str[128],c,*p,localbuf[5][81],remotebuf[5][81]
,localline=0,remoteline=0,localchar=0,remotechar=0
,*sep=text[PrivateChatSeparator]
,*local_sep=text[SysopChatSeparator]
;
char outpath[MAX_PATH+1];
char inpath[MAX_PATH+1];
int in,out,i,n,echo=1,x,y,activity,remote_activity;
int local_y=1,remote_y=1;
time_t last_nodechk=0;

Rob Swindell
committed
if(forced)
n = node_num;
if(useron.rest&FLAG('C')) {
bputs(text[R_Chat]);
return;
}
n=getnodetopage(0,0);
if(!n)
return;
if(n==cfg.node_num) {
bputs(text[NoNeedToPageSelf]);
getnodedat(n,&node,0);
if(node.action==NODE_PCHT && node.aux!=cfg.node_num) {
bprintf(text[NodeNAlreadyInPChat],n);

Rob Swindell
committed
if(SYSOP && getnodedat(n, &node, true) == 0) {
node.misc |= NODE_FCHAT;
putnodedat(n, &node);
} else {
if((node.action!=NODE_PAGE || node.aux!=cfg.node_num)
&& node.misc&NODE_POFF) {
bprintf(text[CantPageNode],node.misc&NODE_ANON
? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
return;
}
if(node.action!=NODE_PAGE) {
bprintf(text[PagingUser]
,node.misc&NODE_ANON ? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp)
,node.misc&NODE_ANON ? 0 : node.useron);
sprintf(str,text[NodePChatPageMsg]
,cfg.node_num,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias);
putnmsg(&cfg,n,str);
sprintf(str,"paged %s on node %d to private chat"
,username(&cfg,node.useron,tmp),n);
logline("C",str);
}
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.action=action=NODE_PAGE;
thisnode.aux=n;
putnodedat(cfg.node_num,&thisnode);
}
if(node.action!=NODE_PAGE || node.aux!=cfg.node_num) {
bprintf(text[WaitingForNodeInPChat],n);
while(online && !(sys_status&SS_ABORT)) {
getnodedat(n,&node,0);
if((node.action==NODE_PAGE || node.action==NODE_PCHT)
&& node.aux==cfg.node_num) {
bprintf(text[NodeJoinedPrivateChat]
,n,node.misc&NODE_ANON ? text[UNKNOWN_USER]
: username(&cfg,node.useron,tmp));
action=NODE_PAGE;
checkline();
gettimeleft();
inkey(K_NONE,500);
gettimeleft();
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.action=action=NODE_PCHT;
thisnode.aux=n;

Rob Swindell
committed
thisnode.misc&=~ (NODE_LCHAT|NODE_FCHAT);
putnodedat(cfg.node_num,&thisnode);
}

Rob Swindell
committed
if(!online || (!forced && (sys_status&SS_ABORT)))

Rob Swindell
committed
if(forced && n == 0) {
/* If an external sysop chat event handler is installed, just run that and do nothing else */
if(user_event(EVENT_LOCAL_CHAT))
return;
}
if(((sys_status&SS_USERON && useron.chat&CHAT_SPLITP) || !(sys_status&SS_USERON))
&& term_supports(ANSI) && rows>=24 && cols>=80)
else
sys_status&=~SS_SPLITP;
/*
if(!(useron.misc&EXPERT))

rswindell
committed
menu("privchat");
*/
if(!(sys_status&SS_SPLITP)) {

Rob Swindell
committed
if(forced)
bprintf(text[SysopIsHere],cfg.sys_op);
else
bputs(text[WelcomeToPrivateChat]);
}
sprintf(outpath,"%schat.dab",cfg.node_dir);
if((out=sopen(outpath,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,DEFFILEMODE))==-1) {
errormsg(WHERE,ERR_OPEN,outpath,O_RDWR|O_DENYNONE|O_CREAT);
return;
}

Rob Swindell
committed
if(forced && n == 0)
sprintf(inpath,"%slchat.dab",cfg.node_dir);
sprintf(inpath,"%schat.dab",cfg.node_path[n-1]);
if(!fexist(inpath)) /* Wait while it's created for the first time */
if((in=sopen(inpath,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,DEFFILEMODE))==-1) {
errormsg(WHERE,ERR_OPEN,inpath,O_RDWR|O_DENYNONE|O_CREAT);
errormsg(WHERE,ERR_ALLOC,nulstr,PCHAT_LEN);
memset(p,0,PCHAT_LEN);
write(in,p,PCHAT_LEN);
write(out,p,PCHAT_LEN);
lseek(in,0L,SEEK_SET);
lseek(out,0L,SEEK_SET);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.misc&=~NODE_RPCHT; /* Clear "reset pchat flag" */
putnodedat(cfg.node_num,&thisnode);
}

Rob Swindell
committed
if(n) { // not local
if(getnodedat(n,&node,true)==0) {
node.misc|=NODE_RPCHT; /* Set "reset pchat flag" */
putnodedat(n,&node); /* on other node */
}
/* Wait for other node */
/* to acknowledge and reset */
while(online && !(sys_status&SS_ABORT)) {
getnodedat(n,&node,0);
if(!(node.misc&NODE_RPCHT))
break;
getnodedat(cfg.node_num,&thisnode,0);
if(thisnode.misc&NODE_RPCHT)
break;
checkline();
gettimeleft();
SYNC;
}
action=NODE_PCHT;
SYNC;
if(sys_status&SS_SPLITP) {
lncntr=0;
CLS;
ansi_save();
ansi_gotoxy(1,13);

Rob Swindell
committed
bprintf(forced ? local_sep : sep
,thisnode.misc&NODE_MSGW ? 'T':' '
,thisnode.misc&NODE_NMSG ? 'M':' ');
ansi_gotoxy(1,14);

Rob Swindell
committed
while(online && (forced || !(sys_status&SS_ABORT))) {
lncntr=0;
if(sys_status&SS_SPLITP)
lbuflen=0;
action=NODE_PCHT;
activity=0;
remote_activity=0;
if((ch=inkey(K_GETSTR,100))!=0) {
activity=1;
if(echo)
attr(cfg.color[clr_chatlocal]);
if(ch==BS || ch==DEL) {
localbuf[localline][localchar]=0;
}
}
else if(ch==TAB) {
if(echo)
outchar(' ');
localbuf[localline][localchar]=' ';
localchar++;
while(localchar<78 && localchar%8) {
if(echo)
localbuf[localline][localchar++]=' ';
}
}
if(sys_status&SS_SPLITP) {
CLS;
attr(cfg.color[clr_chatremote]);
remotebuf[remoteline][remotechar]=0;
for(i=0;i<=remoteline;i++) {
bputs(remotebuf[i]);
if(i!=remoteline)
bputs(crlf);
}
remote_y=1+remoteline;
bputs("\1i_\1n"); /* Fake cursor */
ansi_save();
ansi_gotoxy(1,13);

Rob Swindell
committed
bprintf(forced ? local_sep : sep
,thisnode.misc&NODE_MSGW ? 'T':' '
,sectostr(timeleft,tmp)
,thisnode.misc&NODE_NMSG ? 'M':' ');
ansi_gotoxy(1,14);
attr(cfg.color[clr_chatlocal]);
localbuf[localline][localchar]=0;
for(i=0;i<=localline;i++) {
bputs(localbuf[i]);
if(i!=localline)
bputs(crlf);
}
local_y=15+localline;
}
else if(ch>=' ' || ch==CR) {
if(ch!=CR) {
if(echo)
outchar(ch);
localbuf[localline][localchar]=ch;
}
if(ch==CR || (localchar>68 && ch==' ') || ++localchar>78) {
lprintf(LOG_DEBUG, "chat line wrapped, localchar=%d, ch=%x", localchar, ch);
localbuf[localline][localchar]=0;
localchar=0;
if(sys_status&SS_SPLITP && local_y >= rows) {
ansi_gotoxy(1,13);

Rob Swindell
committed
bprintf(forced ? local_sep : sep
,thisnode.misc&NODE_MSGW ? 'T':' '
,thisnode.misc&NODE_NMSG ? 'M':' ');
attr(cfg.color[clr_chatlocal]);
for(x=13,y=0;x<rows;x++,y++) {

rswindell
committed
comprintf("\x1b[%d;1H\x1b[K",x+1);
bprintf("%s\r\n",localbuf[y]);
}
ansi_gotoxy(1,local_y=(15+localline));
localline=0;
}
else {
if(localline>=4)
for(i=0;i<4;i++)
memcpy(localbuf[i],localbuf[i+1],81);
else
localline++;
if(echo) {
CRLF;
local_y++;
if(sys_status&SS_SPLITP)
cleartoeol();
}
}
}
} else { // illegal key
continue;
}
(void)read(out,&c,1);
(void)lseek(out,-1L,SEEK_CUR);
wr = write(out,&ch,1);
else {
if(!tell(out))
lseek(out,0L,SEEK_END);
lseek(out,-1L,SEEK_CUR);
ch=0;
wr = write(out,&ch,1);
lseek(out,-1L,SEEK_CUR);
}
if(wr != 1)
lprintf(LOG_ERR, "write of character 0x%02X to %s returned %d", ch, outpath, wr);
else if(ch < ' ')
lprintf(LOG_DEBUG, "wrote control character %u (%s) to %s", ch, c_escape_char(ch), outpath);
else
lprintf(LOG_DEBUG, "wrote character '%c' to %s", ch, outpath);
utime(outpath,NULL); /* update mod time for NFS/smbfs nodes */
if(tell(out)>=PCHAT_LEN)
lseek(out,0L,SEEK_SET);
}
else while(online) {
if(!(sys_status&SS_SPLITP))
remotechar=localchar;
if(tell(in)>=PCHAT_LEN)
lseek(in,0L,SEEK_SET);
ch=0;
utime(inpath,NULL);
int rd = read(in,&ch,1);
if(rd != 1) {
lprintf(LOG_ERR, "read character from %s returned %d instead of 1", inpath, rd);
if(!ch) break; /* char from other node */
if(ch < ' ')
lprintf(LOG_DEBUG, "read control character %u (%s) from %s", ch, c_escape_char(ch), inpath);
else
lprintf(LOG_DEBUG, "read character '%c' from %s", ch, inpath);
activity=1;
if(sys_status&SS_SPLITP && !remote_activity) {
ansi_getxy(&x,&y);
ansi_restore();
}
attr(cfg.color[clr_chatremote]);
if(sys_status&SS_SPLITP && !remote_activity)
backspace(); /* Delete fake cursor */
if(ch==BS || ch==DEL) {
remotebuf[remoteline][remotechar]=0;
}
}
outchar(' ');
remotebuf[remoteline][remotechar]=' ';
remotechar++;
while(remotechar<78 && remotechar%8) {
remotebuf[remoteline][remotechar++]=' ';
}
}
else if(ch>=' ' || ch==CR) {
if(ch!=CR) {
outchar(ch);
remotebuf[remoteline][remotechar]=ch;
}
if(ch==CR || (remotechar>68 && ch==' ') || ++remotechar>78) {
remotebuf[remoteline][remotechar]=0;
remotechar=0;
if(sys_status&SS_SPLITP && remote_y==12) {
CRLF;

Rob Swindell
committed
bprintf(forced ? local_sep : sep
,thisnode.misc&NODE_MSGW ? 'T':' '
,thisnode.misc&NODE_NMSG ? 'M':' ');
attr(cfg.color[clr_chatremote]);
for(i=0;i<12;i++) {
bprintf("\x1b[%d;1H\x1b[K",i+1);
if(i<=remoteline)
bprintf("%s\r\n",remotebuf[i]);
}
ansi_gotoxy(1, remote_y=6);
}
else {
if(remoteline>=4)
for(i=0;i<4;i++)
memcpy(remotebuf[i],remotebuf[i+1],81);
else
remoteline++;
if(echo) {
CRLF;
remote_y++;
if(sys_status&SS_SPLITP)
cleartoeol();
}
}
}
}
if(write(in,&ch,1) != 1)
lprintf(LOG_ERR, "write of NUL to %s returned %d", inpath, wr);
if(!(sys_status&SS_SPLITP))
localchar=remotechar;
}
if(sys_status&SS_SPLITP && remote_activity) {
bputs("\1i_\1n"); /* Fake cursor */
ansi_save();
ansi_gotoxy(x,y);
now=time(NULL);
if(!activity && now!=last_nodechk) { /* no activity so chk node.dab */
if(!localchar) {
if(sys_status&SS_SPLITP) {
getnodedat(cfg.node_num,&thisnode,0);
if(thisnode.misc&NODE_INTR)
break;
if(thisnode.misc&NODE_UDAT && !(useron.rest&FLAG('G'))) {
getuserdat(&cfg,&useron);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.misc&=~NODE_UDAT;
putnodedat(cfg.node_num,&thisnode);
}
}
}
else
nodesync();
}

Rob Swindell
committed
if(n != 0) {
getnodedat(n,&node,0);
if((node.action!=NODE_PCHT && node.action!=NODE_PAGE)
|| node.aux!=cfg.node_num) {
bprintf(text[NodeLeftPrivateChat]
,n,node.misc&NODE_ANON ? text[UNKNOWN_USER]
: username(&cfg,node.useron,tmp));
break;
}
}
getnodedat(cfg.node_num,&thisnode,0);
if(thisnode.action!=NODE_PCHT) {
action=thisnode.action;
bputs(text[EndOfChat]);
break;
}
if(thisnode.misc&NODE_RPCHT) { /* pchat has been reset */
lseek(in,0L,SEEK_SET); /* so seek to beginning */
lseek(out,0L,SEEK_SET);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.misc&=~NODE_RPCHT;
putnodedat(cfg.node_num,&thisnode);
}
last_nodechk=now;
gettimeleft();
if(sys_status&SS_SPLITP)
CLS;
sys_status&=~(SS_SPLITP|SS_ABORT);
close(in);
close(out);
}
int sbbs_t::getnodetopage(int all, int telegram)
{
char str[128];
node_t node;
if(!lastnodemsg)
lastnodemsguser[0]=0;
if(lastnodemsg) {
getnodedat(lastnodemsg,&node,0);
if(node.status!=NODE_INUSE && !SYSOP)
lastnodemsg=1;
}
for(j=0,i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
getnodedat(i,&node,0);
if(i==cfg.node_num)
continue;
if(node.status==NODE_INUSE || (SYSOP && node.status >= NODE_LOGON && node.status <= NODE_QUIET)) {
if(!lastnodemsg)
lastnodemsg=i;
j++;
}
}
if(!lastnodemsguser[0])
sprintf(lastnodemsguser,"%u",lastnodemsg);
if(!j && !telegram) {
bputs(text[NoOtherActiveNodes]);
return(0);
}
if(all)
sprintf(str,text[NodeToSendMsgTo],lastnodemsg);
else
sprintf(str,text[NodeToPrivateChat],lastnodemsg);
mnemonics(str);
getstr(str,LEN_ALIAS,K_LINE|K_EDIT|K_AUTODEL);
if(sys_status&SS_ABORT) {
sys_status&= ~SS_ABORT;
if(!str[0])
return(0);
j=atoi(str);
if(j && j<=cfg.sys_lastnode && j<=cfg.sys_nodes) {
getnodedat(j,&node,0);
if(node.status!=NODE_INUSE && !SYSOP) {
bprintf(text[NodeNIsNotInUse],j);
return(0);
}
if(telegram && node.misc&(NODE_POFF|NODE_ANON) && !SYSOP) {
bprintf(text[CantPageNode],node.misc&NODE_ANON
? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
return(0);
}
if(telegram)
return(node.useron);
return(j);
}
if(all && !stricmp(str,"ALL"))
return(-1);
if(str[0]=='\'') {
j=finduserstr(0, USER_HANDLE, str+1);
if(!j) {
bputs(text[UnknownUser]);
return(0);
}
}
else if(str[0]=='#')
j=atoi(str+1);
else
j=finduser(str);
if(!j)
return(0);
if(j>lastuser(&cfg))
return(0);
if(getusermisc(&cfg, j) & (DELETED|INACTIVE)) { /* Deleted or Inactive User */
return(0);
}
for(i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
getnodedat(i,&node,0);
if((node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET))
&& node.useron==j) {
if(telegram && node.misc&NODE_POFF && !SYSOP) {
bprintf(text[CantPageNode],node.misc&NODE_ANON
? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
return(0);
}
return(i);
}
}
SAFECOPY(lastnodemsguser,str);
return(j);
}
bputs(text[UserNotFound]);
return(0);
}
/****************************************************************************/
/* Sending single line messages between nodes */
/****************************************************************************/
void sbbs_t::nodemsg()
{
char str[256],line[256],buf[512],logbuf[512],ch=0;
int i,usernumber,done=0;
node_t node,savenode;
if(nodemsg_inside>1) /* nested once only */
return;
nodemsg_inside++;
if(cfg.privatemsg_mod[0] != '\0') {
exec_bin(cfg.privatemsg_mod, &main_csi);
nodemsg_inside--;
return;
}
sys_status|=SS_IN_CTRLP;
getnodedat(cfg.node_num,&savenode,0);
wordwrap[0]=0;
while(online && !done) {
if(useron.rest&FLAG('C')) {
bputs(text[R_SendMessages]);
SYNC;
mnemonics(text[PrivateMsgPrompt]);
sys_status&=~SS_ABORT;
while(online) { /* Watch for incoming messages */
if(ch && strchr("TMCQ\r",ch))
break;
if(sys_status&SS_ABORT)
break;
if(getnodedat(cfg.node_num,&thisnode,false)==0) {
if(thisnode.misc&(NODE_MSGW|NODE_NMSG)) {
lncntr=0; /* prevent pause prompt */
SAVELINE;
CRLF;
if(thisnode.misc&NODE_NMSG)
getnmsg();
if(thisnode.misc&NODE_MSGW)
getsmsg(useron.number);
CRLF;
RESTORELINE;
}
else
nodesync();
}
}
if(!online || sys_status&SS_ABORT) {
sys_status&=~SS_ABORT;
CRLF;
break;
}
switch(toupper(ch)) {
case 'T': /* Telegram */
bputs("Telegram\r\n");
usernumber=getnodetopage(0,1);
if(!usernumber)
break;
if(usernumber==1 && useron.rest&FLAG('S')) { /* ! val fback */
bprintf(text[R_Feedback],cfg.sys_op);
if(usernumber!=1 && useron.rest&FLAG('E')) {
bputs(text[R_Email]);
bprintf(text[SendingTelegramToUser]
,username(&cfg,usernumber,tmp),usernumber);
sprintf(buf,text[TelegramFmt]
,thisnode.misc&NODE_ANON ? text[UNKNOWN_USER] : useron.alias
,timestr(now));
i=0;
logbuf[0]=0;
while(online && i<5) {
bprintf("%4s",nulstr);
if(!getstr(line,70,K_WRAP|K_MSG))
break;
SAFEPRINTF2(str,"%4s%s\r\n",nulstr,line);
SAFECAT(buf,str);
SAFECAT(logbuf," ");
SAFECAT(logbuf,line);
if(!i)
break;
if(sys_status&SS_ABORT) {
CRLF;
putsmsg(&cfg,usernumber,buf);
sprintf(str,"sent telegram to %s #%u"
,username(&cfg,usernumber,tmp),usernumber);
logline("C",str);
logline(nulstr,logbuf);
bprintf(text[MsgSentToUser],"Telegram"
,username(&cfg,usernumber,tmp),usernumber);
break;
case 'M': /* Message */
bputs("Message\r\n");
i=getnodetopage(1,0);
if(!i)
break;
if(i!=-1) {
getnodedat(i,&node,0);
usernumber=node.useron;
if(node.misc&NODE_POFF && !SYSOP)
bprintf(text[CantPageNode],node.misc&NODE_ANON
? text[UNKNOWN_USER] : username(&cfg,node.useron,tmp));
else {
bprintf(text[SendingMessageToUser]
,node.misc&NODE_ANON ? text[UNKNOWN_USER]
: username(&cfg,node.useron,tmp)
,node.misc&NODE_ANON ? 0 : node.useron);
bputs(text[NodeMsgPrompt]);
if(!getstr(line,69,K_LINE))
break;
sprintf(buf,text[NodeMsgFmt],cfg.node_num
,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias,line);
putnmsg(&cfg,i,buf);
bprintf(text[MsgSentToUser],"Message"
,username(&cfg,usernumber,tmp),usernumber);
sprintf(str,"sent message to %s on node %d:"
,username(&cfg,usernumber,tmp),i);
logline(nulstr,line);
}
}
else { /* ALL */
bputs(text[NodeMsgPrompt]);
if(!getstr(line,70,K_LINE))
break;
sprintf(buf,text[AllNodeMsgFmt],cfg.node_num
,thisnode.misc&NODE_ANON
? text[UNKNOWN_USER] : useron.alias,line);
for(i=1;i<=cfg.sys_nodes;i++) {
if(i==cfg.node_num)
continue;
getnodedat(i,&node,0);
if((node.status==NODE_INUSE
|| (SYSOP && node.status==NODE_QUIET))
&& (SYSOP || !(node.misc&NODE_POFF)))
putnmsg(&cfg,i,buf);
}
SAFECOPY(str,"sent message to all nodes");
logline("C",str);
logline(nulstr,line);
}
break;
case 'C': /* Chat */
bputs("Chat\r\n");
if(action==NODE_PCHT) { /* already in pchat */
done=1;
privchat();
action=savenode.action;
break;
default:
bputs("Quit\r\n");
done=1;
break;
}
}
nodemsg_inside--;
if(!nodemsg_inside)
sys_status&=~SS_IN_CTRLP;
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.action=action=savenode.action;
thisnode.aux=savenode.aux;
thisnode.extaux=savenode.extaux;
putnodedat(cfg.node_num,&thisnode);
}
}
/****************************************************************************/
/* The guru will respond from the 'guru' buffer to 'line' */
/****************************************************************************/
void sbbs_t::guruchat(char* line, char* gurubuf, int gurunum, char* last_answer)
char str[512],cstr[512],*ptr,*answer[100],theanswer[1024]
long len;
struct tm tm;
now=time(NULL);
localtime_r(&now,&tm);
if((answer[i]=(char *)malloc(512))==NULL) {
errormsg(WHERE,ERR_ALLOC,nulstr,512);
free(answer[i]);
}
return;
}
}
ptr=gurubuf;
len=strlen(gurubuf);
strupr(line);
j=strlen(line);
k=0;
for(i=0;i<j;i++) {
if(line[i]<0 || !IS_ALPHANUMERIC(line[i])) {
if(!k) /* beginning non-alphanumeric */
continue;
if(line[i]==line[i+1]) /* redundant non-alnum */
continue;
if(line[i+1]=='?') /* fix "WHAT ?" */
continue;
}
cstr[k++]=line[i];
}
if(!IS_ALPHANUMERIC(cstr[k]))
if(k<1) {
for(i=0;i<100;i++)
if(cstr[k+1]=='?')
k++;
cstr[k+1]=0;
while(*ptr && ptr<gurubuf+len) {
if(*ptr=='(') {
ptr++;
if(!guruexp(&ptr,cstr)) {
while(*ptr && *ptr!='(' && ptr<gurubuf+len)
ptr++;
continue;
}
}
else {
while(*ptr && *ptr!=LF && ptr<gurubuf+len) /* skip LF after ')' */
ptr++;
ptr++;
answers=0;
while(*ptr && answers<100 && ptr<gurubuf+len) {
i=0;
while(*ptr && *ptr!=CR && *ptr!=LF && i<511 && ptr<gurubuf+len) {
answer[answers][i]=*ptr;
ptr++;
i++;
/* multi-line answer */
if(*ptr=='\\' && (*(ptr+1)==CR || *(ptr+1)==LF)) {
ptr++; /* skip \ */
while(*ptr && *ptr<' ') ptr++; /* skip [CR]LF */
answer[answers][i++]=LF;
}
}
answer[answers][i]=0;
if(!strlen(answer[answers]) || answer[answers][0]=='(') {
ptr-=strlen(answer[answers]);
while(*ptr && *ptr<' ') ptr++; /* skip [CR]LF */
answers++;
}
if(answers==100)
while(*ptr && *ptr!='(' && ptr<gurubuf+len)
ptr++;
i=0;
/* Try to not repeat yourself */
for(j=0;j<answers;j++) {
i=sbbs_random(answers);
if(stricmp(answer[i],last_answer))
break;
}
strcpy(last_answer,answer[i]);
for(j=0,k=0;answer[i][j];j++) {
if(answer[i][j]=='`') {
j++;
theanswer[k]=0;
switch(toupper(answer[i][j])) {
case 'A':
if(sys_status&SS_USERON) {
SAFECAT(theanswer,useron.alias);
} else {
SAFECAT(theanswer,text[UNKNOWN_USER]);
}
if(sys_status&SS_USERON) {
getbirthdstr(&cfg, useron.birth, theanswer, sizeof(theanswer));
} else {
SAFECAT(theanswer,"00/00/00");
}
if(sys_status&SS_USERON) {
SAFECAT(theanswer,useron.comp);
} else {
SAFECAT(theanswer,"PC Jr.");
}
if(sys_status&SS_USERON) {
SAFECAT(theanswer,u64toac(useron.dlb,tmp));
} else {
SAFECAT(theanswer,"0");
}
SAFECAT(theanswer,cfg.guru[gurunum]->name);
break;
case 'H':
hu=1;
break;
case 'I':
SAFECAT(theanswer,cfg.sys_id);
break;
case 'J':
sprintf(tmp,"%u",tm.tm_mday);
break;
case 'L':
if(sys_status&SS_USERON) {
SAFECAT(theanswer,ultoa(useron.level,tmp,10));
} else {
SAFECAT(theanswer,"0");
}
SAFECAT(theanswer,month[tm.tm_mon]);
break;
case 'N': /* Note */
if(sys_status&SS_USERON) {
SAFECAT(theanswer,useron.note);
} else {
SAFECAT(theanswer,text[UNKNOWN_USER]);
}
SAFECAT(theanswer,cfg.sys_op);
if(sys_status&SS_USERON) {
SAFECAT(theanswer,useron.phone);
} else {
SAFECAT(theanswer,"000-000-0000");
}
break;
case 'Q':
sys_status&=~SS_GURUCHAT;
break;
case 'R':
if(sys_status&SS_USERON) {
SAFECAT(theanswer,useron.name);
} else {
SAFECAT(theanswer,text[UNKNOWN_USER]);
}
SAFECAT(theanswer,cfg.sys_name);
break;
case 'T':
sprintf(tmp,"%u:%02u",tm.tm_hour>12 ? tm.tm_hour-12
: tm.tm_hour,tm.tm_min);
SAFECAT(theanswer,tmp);
if(sys_status&SS_USERON) {
SAFECAT(theanswer,u64toac(useron.ulb,tmp));
} else {
SAFECAT(theanswer,"0");
}
SAFECAT(theanswer,weekday[tm.tm_wday]);
break;
case 'Y': /* Current year */
sprintf(tmp,"%u",1900+tm.tm_year);
SAFECAT(theanswer,tmp);
if(sys_status&SS_USERON) {
SAFECAT(theanswer,useron.zipcode);
} else {
SAFECAT(theanswer,"90210");
}
break;
case '$': /* Credits */
if(sys_status&SS_USERON) {
SAFECAT(theanswer,u64toac(useron.cdt,tmp));
} else {
SAFECAT(theanswer,"0");
}
if(sys_status&SS_USERON) {
SAFECAT(theanswer,ultoa(getage(&cfg,useron.birth)
} else {
SAFECAT(theanswer,"0");
}
break;
case '!':
mistakes=!mistakes;
break;
case '_':
mswait(500);
break;
}
k=strlen(theanswer);
}
theanswer[k++]=answer[i][j];
}
mswait(500+sbbs_random(1000)); /* thinking time */
if(action!=NODE_MCHT) {
for(i=0;i<k;i++) {
if(i && mistakes && theanswer[i]!=theanswer[i-1] &&
((!IS_ALPHANUMERIC(theanswer[i]) && !sbbs_random(100))
|| (IS_ALPHANUMERIC(theanswer[i]) && !sbbs_random(30)))) {
c=j=((uint)sbbs_random(3)+1); /* 1 to 3 chars */
if(c<strcspn(theanswer+(i+1),"\0., "))
c=j=1;
while(j) {
outchar(97+sbbs_random(26));
mswait(25+sbbs_random(150));
if(sbbs_random(100)) {
mswait(100+sbbs_random(300));
mswait(50+sbbs_random(50));
c--;
}
}
}
outchar(theanswer[i]);
if(theanswer[i]==theanswer[i+1])
mswait(25+sbbs_random(50));
mswait(25+sbbs_random(150));
mswait(sbbs_random(50));
else {
mswait(strlen(theanswer)*100);
bprintf(text[ChatLineFmt],cfg.guru[gurunum]->name
,cfg.sys_nodes+1,':',theanswer);
}
sprintf(str,"%sguru.log",cfg.logs_dir);
if((fp = fopenlog(&cfg, str)) == NULL)
errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
else {
xpDateTime_to_isoDateTimeStr(xpDateTime_now(), "-", " ", ":", 0, str, sizeof(str)-3);
fprintf(fp, "%s\r\n", str);
fprintf(fp, "[Multi] ");
fprintf(fp,"%s:\r\n",sys_status&SS_USERON
fprintf(fp,"%s",line);
fprintf(fp,"\r\n");
fprintf(fp,"%s:\r\n",cfg.guru[gurunum]->name);
fprintf(fp,"%s\r\n",theanswer);
fcloselog(fp);
break;
}
}
}
/****************************************************************************/
/* An expression from the guru's buffer 'ptrptr' is evaluated and true or */
/* false is returned. */
/****************************************************************************/
bool sbbs_t::guruexp(char **ptrptr, char *line)
{
char *cp,str[256];
unsigned c;
bool result=false,_and=false,_or=false;
uchar *ar;
if((**ptrptr)==')') { /* expressions of () are always result */
(*ptrptr)++;
return(true);
}
while((**ptrptr)!=')' && (**ptrptr)) {
if((**ptrptr)=='[') {
(*ptrptr)++;
while(**ptrptr && (**ptrptr)!=']')
(*ptrptr)++;
(*ptrptr)++;
cp=strchr(str,']');
if(cp) *cp=0;

rswindell
committed
ar=arstr(NULL,str,&cfg,NULL);

rswindell
committed
free(ar);
if(!c && _and) {
if(c && _or) {
if((**ptrptr)=='(') {
(*ptrptr)++;
c=guruexp(&(*ptrptr),line);
if(!c && _and) {
if(c && _or) {
result=true;
}
if((**ptrptr)==')')
break;
c=0;
while((**ptrptr) && IS_WHITESPACE(**ptrptr))
(*ptrptr)++;
while((**ptrptr)!='|' && (**ptrptr)!='&' && (**ptrptr)!=')' &&(**ptrptr)) {
str[c++]=(**ptrptr);
(*ptrptr)++;
}
str[c]=0;
if((**ptrptr)=='|') {
if(!c && result)
break;
_and=false;
else if((**ptrptr)=='&') {
if(!c && !result)
break;
_and=true;
_or=false;
}
if(!c) { /* support ((exp)op(exp)) */
(*ptrptr)++;
if((**ptrptr)!=')')
(*ptrptr)++;
c=0; /* c now used for start line flag */
if(str[strlen(str)-1]=='^') { /* ^signifies start of line only */
str[strlen(str)-1]=0;
if(str[strlen(str)-1]=='~') { /* ~signifies non-isolated word */
str[strlen(str)-1]=0;
cp=strstr(line,str);
if(c && cp!=line)
else {
cp=strstr(line,str);
if(cp && c) {
if(cp!=line || IS_ALPHANUMERIC(*(cp+strlen(str))))
else { /* must be isolated word */
while(cp)
if((cp!=line && IS_ALPHANUMERIC(*(cp-1)))
|| IS_ALPHANUMERIC(*(cp+strlen(str))))
cp=strstr(cp+strlen(str),str);
else
break;
}
}
if(!cp && _and) {
if(cp && _or) {
result=true;
}
nest=0;
while((**ptrptr)!=')' && (**ptrptr)) { /* handle nested exp */
if((**ptrptr)=='(') /* (TRUE|(IGNORE)) */
nest++;
(*ptrptr)++;
while((**ptrptr)==')' && nest && (**ptrptr)) {
nest--;
(*ptrptr)++;
}
}
(*ptrptr)++; /* skip over ')' */
return(result);
}
/****************************************************************************/
/* Guru chat with the appearance of Local chat with sysop. */
/****************************************************************************/
void sbbs_t::localguru(char *gurubuf, int gurunum)
{
char ch,str[256];
int con=console; /* save console state */
if(sys_status&SS_GURUCHAT || !cfg.total_gurus)
return;
sys_status|=SS_GURUCHAT;
console&=~(CON_L_ECHOX|CON_R_ECHOX); /* turn off X's */
console|=(CON_L_ECHO|CON_R_ECHO); /* make sure echo is on */
if(action==NODE_CHAT) { /* only page if from chat section */
bprintf(text[PagingGuru],cfg.guru[gurunum]->name);
ch=sbbs_random(25)+25;
while(ch--) {
mswait(200);
outchar('.');
}
}
bprintf(text[SysopIsHere],cfg.guru[gurunum]->name);
if(getnodedat(cfg.node_num,&thisnode,true)==0) {
thisnode.aux=gurunum;
putnodedat(cfg.node_num,&thisnode);
}
attr(cfg.color[clr_chatlocal]);
guruchat(str,gurubuf,gurunum,lastanswer);
str[0]=0;
while(online && (sys_status&SS_GURUCHAT)) {
checkline();
action=NODE_GCHT;
SYNC;
if(str[0]) {
attr(cfg.color[clr_chatlocal]);
guruchat(str,gurubuf,gurunum,lastanswer);
str[0]=0;
}
continue;
}
}
attr(cfg.color[clr_chatremote]);
getstr(str,78,K_WRAP|K_CHAT);
}