Skip to content
Snippets Groups Projects
chat.cpp 49.8 KiB
Newer Older
				ansi_getxy(&x,&y);
				ANSI_RESTORE();
			}
			attr(cfg.color[clr_chatremote]);
			if(sys_status&SS_SPLITP && !remote_activity)
				bputs("\b \b");             /* Delete fake cursor */
			remote_activity=1;
			if(ch==BS || ch==DEL) {
				if(remotechar) {
					bputs("\b \b");
					remotechar--;
					remotebuf[remoteline][remotechar]=0; } }
			else if(ch==TAB) {
				outchar(SP);
				remotebuf[remoteline][remotechar]=SP;
				remotechar++;
				while(remotechar<78 && remotechar%8) {
					outchar(SP);
					remotebuf[remoteline][remotechar++]=SP; } }
			else if(ch>=SP || ch==CR) {
				if(ch!=CR) {
					outchar(ch);
					remotebuf[remoteline][remotechar]=ch; }

				if(ch==CR || (remotechar>68 && ch==SP) || ++remotechar>78) {

					remotebuf[remoteline][remotechar]=0;
					remotechar=0;

					if(sys_status&SS_SPLITP && remote_y==12) {
						CRLF;
						bprintf(local ? local_sep : sep
							,thisnode.misc&NODE_MSGW ? 'T':SP
							,sectostr(timeleft,tmp)
							,thisnode.misc&NODE_NMSG ? 'M':SP);
						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]); }
						remoteline=0;
						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)
								bputs("\x1b[K"); } } } }
			ch=0;
			write(in,&ch,1);

			if(!(sys_status&SS_SPLITP))
				localchar=remotechar;
			}

		if(sys_status&SS_SPLITP && remote_activity) {
			bputs("\1i_\1n");  /* Fake cursor */
			ANSI_SAVE();
			GOTOXY(x,y); }

		if(!activity) { 						/* no activity so chk node.dab */
			if(!local) {
				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);
				getnodedat(cfg.node_num,&thisnode,1);
				thisnode.misc&=~NODE_RPCHT;
				putnodedat(cfg.node_num,&thisnode); 
			}
			mswait(1); }
		checkline();
		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];
	uint 	i,j;
	ulong	l;
	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_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);

	strcpy(str,lastnodemsguser);
	getstr(str,LEN_ALIAS,K_UPRLWR|K_LINE|K_EDIT|K_AUTODEL);
	if(sys_status&SS_ABORT)
		return(0);
	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); }
		strcpy(lastnodemsguser,str);
		if(telegram)
			return(node.useron);
		return(j); }
	if(all && !stricmp(str,"ALL"))
		return(-1);

	if(str[0]=='\'') {
		j=userdatdupe(0,U_HANDLE,LEN_HANDLE,str+1,0);
		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);
	getuserrec(&cfg,j,U_MISC,8,tmp);
	l=ahtoul(tmp);
	if(l&(DELETED|INACTIVE)) {              /* Deleted or Inactive User */
		bputs(text[UnknownUser]);
		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); }
			if(telegram)
				return(j);
			strcpy(lastnodemsguser,str);
			return(i); } }
	if(telegram) {
		strcpy(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;
	sys_status|=SS_IN_CTRLP;
	getnodedat(cfg.node_num,&savenode,0);
	nodemsg_inside++;
	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 */
			ch=toupper(inkey(0));
			if(ch && strchr("TMCQ\r",ch))
				break;
			if(sys_status&SS_ABORT)
				break;
			getnodedat(cfg.node_num,&thisnode,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();
			gettimeleft();
			checkline(); }

		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);
					break; }
				if(usernumber!=1 && useron.rest&FLAG('E')) {
					bputs(text[R_Email]);
					break; }
				now=time(NULL);
				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;
					sprintf(str,"%4s%s\r\n",nulstr,line);
					strcat(buf,str);
					if(line[0]) {
						if(i)
							strcat(logbuf,"   ");
						strcat(logbuf,line);
					}
					i++; }
				if(!i)
					break;
				if(sys_status&SS_ABORT) {
					CRLF;
					break; }
				putsmsg(&cfg,usernumber,buf);
				sprintf(str,"%s sent telegram to %s #%u"
					,useron.alias,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(i,buf);
						if(!(node.misc&NODE_ANON))
							bprintf(text[MsgSentToUser],"Message"
								,username(&cfg,usernumber,tmp),usernumber);
						sprintf(str,"%s sent message to %s on node %d:"
							,useron.alias,username(&cfg,usernumber,tmp),i);
						logline("C",str);
						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(i,buf); }
					sprintf(str,"%s sent message to all nodes",useron.alias);
					logline("C",str);
					logline(nulstr,line); 
				}
				break;
			case 'C':   /* Chat */
				bputs("Chat\r\n");
				if(action==NODE_PCHT) { /* already in pchat */
					done=1;
					break; }
				privchat();
				action=savenode.action;
				break;
			default:
				bputs("Quit\r\n");
				done=1;
				break; } }
	nodemsg_inside--;
	if(!nodemsg_inside)
		sys_status&=~SS_IN_CTRLP;
	getnodedat(cfg.node_num,&thisnode,1);
	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	str[512],cstr[512],*ptr,*answer[100],answers,theanswer[1024]
			,mistakes=1,hu=0;
	int		file;
	uint 	c,i,j,k;
	long 	len;
	struct	tm *tm_p;
	struct	tm tm;

	now=time(NULL);
	if(tm_p)
		tm=*tm_p;
	else
		memset(&tm,0,sizeof(tm));

	for(i=0;i<100;i++) {
		if((answer[i]=(char *)MALLOC(513))==NULL) {
			errormsg(WHERE,ERR_ALLOC,nulstr,513);
			while(i) {
				i--;
				FREE(answer[i]); }
			sys_status&=~SS_GURUCHAT;
			return; } }
	ptr=gurubuf;
	len=strlen(gurubuf);
	strupr(line);
	j=strlen(line);
	k=0;
	for(i=0;i<j;i++) {
		if(!isalnum(line[i]) && !k)	/* beginning non-alphanumeric */
			continue;
		if(!isalnum(line[i]) && line[i]==line[i+1])	/* redundant non-alnum */
			continue;
		if(!isalnum(line[i]) && line[i+1]=='?')	/* fix "WHAT ?" */
			continue;
		cstr[k++]=line[i]; }
	cstr[k]=0;
	while(k) {
		k--;
		if(!isalnum(cstr[k]))
			continue;
		break; }
	if(k<1) {
		for(i=0;i<100;i++)
			FREE(answer[i]);
		return; }
	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<512 && 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<SP) ptr++;	/* skip [CR]LF */
						answer[answers][i++]=CR;
						answer[answers][i++]=LF; } }
				answer[answers][i]=0;
				if(!strlen(answer[answers]) || answer[answers][0]=='(') {
					ptr-=strlen(answer[answers]);
					break; }
				while(*ptr && *ptr<SP) ptr++;	/* skip [CR]LF */
				answers++; }
			if(answers==100)
				while(*ptr && *ptr!='(' && ptr<gurubuf+len)
					ptr++;
			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)
								strcat(theanswer,useron.alias);
							else
								strcat(theanswer,text[UNKNOWN_USER]);
							break;
						case 'B':
							if(sys_status&SS_USERON)
								strcat(theanswer,useron.birth);
							else
								strcat(theanswer,"00/00/00");
							break;
						case 'C':
                    		if(sys_status&SS_USERON)
								strcat(theanswer,useron.comp);
							else
								strcat(theanswer,"PC Jr.");
							break;
						case 'D':
                    		if(sys_status&SS_USERON)
								strcat(theanswer,ultoac(useron.dlb,tmp));
							else
								strcat(theanswer,"0");
							break;
						case 'G':
							strcat(theanswer,cfg.guru[gurunum]->name);
							break;
						case 'H':
							hu=1;
							break;
						case 'I':
							strcat(theanswer,cfg.sys_id);
							break;
						case 'J':
							sprintf(tmp,"%u",tm.tm_mday);
							break;
						case 'L':
                    		if(sys_status&SS_USERON)
								strcat(theanswer,ultoa(useron.level,tmp,10));
							else
								strcat(theanswer,"0");
							break;
						case 'M':
							strcat(theanswer,month[tm.tm_mon]);
							break;
						case 'N':   /* Note */
                    		if(sys_status&SS_USERON)
								strcat(theanswer,useron.note);
							else
								strcat(theanswer,text[UNKNOWN_USER]);
							break;
						case 'O':
							strcat(theanswer,cfg.sys_op);
							break;
						case 'P':
                    		if(sys_status&SS_USERON)
								strcat(theanswer,useron.phone);
							else
								strcat(theanswer,"000-000-0000");
							break;
						case 'Q':
								sys_status&=~SS_GURUCHAT;
							break;
						case 'R':
                    		if(sys_status&SS_USERON)
								strcat(theanswer,useron.name);
							else
								strcat(theanswer,text[UNKNOWN_USER]);
							break;
						case 'S':
							strcat(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);
							strcat(theanswer,tmp);
							break;
						case 'U':
                    		if(sys_status&SS_USERON)
								strcat(theanswer,ultoac(useron.ulb,tmp));
							else
								strcat(theanswer,"0");
							break;
						case 'W':
							strcat(theanswer,weekday[tm.tm_wday]);
							break;
						case 'Y':   /* Current year */
							sprintf(tmp,"%u",1900+tm.tm_year);
							strcat(theanswer,tmp);
							break;
						case 'Z':
							if(sys_status&SS_USERON)
								strcat(theanswer,useron.zipcode);
							else
								strcat(theanswer,"90210");
							break;
						case '$':   /* Credits */
                    		if(sys_status&SS_USERON)
								strcat(theanswer,ultoac(useron.cdt,tmp));
							else
								strcat(theanswer,"0");
							break;
						case '#':
                    		if(sys_status&SS_USERON)
								strcat(theanswer,ultoa(getage(&cfg,useron.birth)
									,tmp,10));
							else
								strcat(theanswer,"0");
							break;
						case '!':
							mistakes=!mistakes;
							break;
						case '_':
							mswait(500);
							break; }
					k=strlen(theanswer); }
				else
					theanswer[k++]=answer[i][j]; }
			theanswer[k]=0;
			mswait(500+sbbs_random(1000));	 /* thinking time */
			if(action!=NODE_MCHT) {
				for(i=0;i<k;i++) {
					if(mistakes && theanswer[i]!=theanswer[i-1] &&
						((!isalnum(theanswer[i]) && !sbbs_random(100))
						|| (isalnum(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));
							while(c) {
								bputs("\b \b");
								c--; } } }
					outchar(theanswer[i]);
					if(theanswer[i]==theanswer[i+1])
					if(theanswer[i]==SP)
					} }
			else {
				mswait(strlen(theanswer)*100);
				bprintf(text[ChatLineFmt],cfg.guru[gurunum]->name
					,cfg.sys_nodes+1,':',theanswer); }
			CRLF;
			sprintf(str,"%sguru.log",cfg.data_dir);
			if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1)
				errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
			else {
				if(action==NODE_MCHT) {
					sprintf(str,"[Multi] ");
					write(file,str,strlen(str)); }
				sprintf(str,"%s:\r\n",sys_status&SS_USERON
					? useron.alias : "UNKNOWN");
				write(file,str,strlen(str));
				write(file,line,strlen(line));
				if(action!=NODE_MCHT)
					write(file,crlf,2);
				sprintf(str,"%s:\r\n",cfg.guru[gurunum]->name);
				write(file,str,strlen(str));
				write(file,theanswer,strlen(theanswer));
				write(file,crlf,2);
				close(file); }
			if(hu)
				hangup();
			break; } }
	for(i=0;i<100;i++)
		FREE(answer[i]);
}

/****************************************************************************/
/* 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	c,*cp,str[256];
	int		nest;
	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)++;
			SAFECOPY(str,*ptrptr);
			while(**ptrptr && (**ptrptr)!=']')
				(*ptrptr)++;
			(*ptrptr)++;
			cp=strchr(str,']');
			if(cp) *cp=0;
			ar=arstr(NULL,str,&cfg);
			c=chk_ar(ar,&useron);
			if(ar[0]!=AR_NULL)
				FREE(ar);
				result=false;
				break; }
				result=true;
				break; }
			if(c)
				result=true;
			continue; }
		if((**ptrptr)=='(') {
			(*ptrptr)++;
			c=guruexp(&(*ptrptr),line);
				result=false;
				break; }
				result=true;
				break; }
			if(c)
				result=true; }
		if((**ptrptr)==')')
			break;
		c=0;
		while((**ptrptr) && isspace(**ptrptr))
			(*ptrptr)++;
		while((**ptrptr)!='|' && (**ptrptr)!='&' && (**ptrptr)!=')' &&(**ptrptr)) {
			str[c++]=(**ptrptr);
			(*ptrptr)++; }
		str[c]=0;
		if((**ptrptr)=='|') {
			if(!c && result)
				break;
		else if((**ptrptr)=='&') {
			if(!c && !result)
				break;
		if(!c) {				/* support ((exp)op(exp)) */
			(*ptrptr)++;
			continue; }
		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;
			c=true; }
		if(str[strlen(str)-1]=='~') {	/* ~signifies non-isolated word */
			str[strlen(str)-1]=0;
			cp=strstr(line,str);
			if(c && cp!=line)
				cp=0; }
		else {
			cp=strstr(line,str);
			if(cp && c) {
				if(cp!=line || isalnum(*(cp+strlen(str))))
					cp=0; }
			else {	/* must be isolated word */
				while(cp)
					if((cp!=line && isalnum(*(cp-1)))
						|| isalnum(*(cp+strlen(str))))
						cp=strstr(cp+strlen(str),str);
					else
						break; } }
			result=false;
			break; }
			result=true;
			break; }
		if(cp)
			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);
		while(ch--) {
			mswait(200);
			outchar('.'); } }
	bprintf(text[SysopIsHere],cfg.guru[gurunum]->name);
	getnodedat(cfg.node_num,&thisnode,1);
	thisnode.aux=gurunum;
	putnodedat(cfg.node_num,&thisnode);
	attr(cfg.color[clr_chatlocal]);
	strcpy(str,"HELLO");
	guruchat(str,gurubuf,gurunum);
	while(online && (sys_status&SS_GURUCHAT)) {
		checkline();
		action=NODE_GCHT;
		SYNC;
		if((ch=inkey(0))!=0) {
			ungetkey(ch);
			attr(cfg.color[clr_chatremote]);
			if(getstr(str,78,K_WRAP|K_CHAT)) {
				attr(cfg.color[clr_chatlocal]);
				guruchat(str,gurubuf,gurunum); } }
		else
			mswait(1); }
	bputs(text[EndOfChat]);
	sys_status&=~SS_GURUCHAT;
	console=con;				/* restore console state */
}

/****************************************************************************/
/* Packs the password 'pass' into 5bit ASCII inside node_t. 32bits in 		*/
/* node.extaux, and the other 8bits in the upper byte of node.aux			*/
/****************************************************************************/
void packchatpass(char *pass, node_t *node)
{
	char	bits;
	int		i,j;

	node->aux&=~0xff00;		/* clear the password */
	node->extaux=0L;
	if((j=strlen(pass))==0) /* there isn't a password */
		return;
	node->aux|=(int)((pass[0]-64)<<8);  /* 1st char goes in low 5bits of aux */
	if(j==1)	/* password is only one char, we're done */
		return;
	node->aux|=(int)((pass[1]-64)<<13); /* low 3bits of 2nd char go in aux */
	node->extaux|=(long)((pass[1]-64)>>3); /* high 2bits of 2nd char go extaux */
	bits=2;
	for(i=2;i<j;i++) {	/* now process the 3rd char through the last */
		node->extaux|=(long)((long)(pass[i]-64)<<bits);
		bits+=5; }
}

/****************************************************************************/
/* Unpacks the password 'pass' from the 5bit ASCII inside node_t. 32bits in */
/* node.extaux, and the other 8bits in the upper byte of node.aux			*/
/****************************************************************************/
char *unpackchatpass(char *pass, node_t* node)
{
	char 	bits;
	int 	i;

	pass[0]=(node->aux&0x1f00)>>8;
	pass[1]=(char)(((node->aux&0xe000)>>13)|((node->extaux&0x3)<<3));
	bits=2;
	for(i=2;i<8;i++) {
		pass[i]=(char)((node->extaux>>bits)&0x1f);
		bits+=5; }
	pass[8]=0;
	for(i=0;i<8;i++)
		if(pass[i])
			pass[i]+=64;
	return(pass);
}