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