|
|
1.1 root 1: /* getnode.cpp */
2:
3: /* Synchronet node information retrieval functions */
4:
1.1.1.2 ! root 5: /* $Id: getnode.cpp,v 1.43 2011/09/21 03:10:53 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
1.1.1.2 ! root 11: * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39: #include "cmdshell.h"
40:
41: /****************************************************************************/
42: /* Reads the data for node number 'number' into the structure 'node' */
43: /* from NODE.DAB */
44: /* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
45: /****************************************************************************/
46: int sbbs_t::getnodedat(uint number, node_t *node, bool lockit)
47: {
48: char str[MAX_PATH+1];
49: int rd=sizeof(node_t);
50: int count;
51:
52: if(node==NULL || number<1)
53: return(-1);
54:
55: if(number>cfg.sys_nodes) {
56: errormsg(WHERE,ERR_CHK,"node number",number);
57: return(-1);
58: }
59:
60: if(node!=&thisnode)
61: memset(node,0,sizeof(node_t));
62: sprintf(str,"%snode.dab",cfg.ctrl_dir);
63: if(nodefile==-1) {
64: if((nodefile=nopen(str,O_RDWR|O_DENYNONE))==-1) {
65: errormsg(WHERE,ERR_OPEN,str,O_RDWR|O_DENYNONE);
66: return(errno);
67: }
68: }
69: else
70: utime(str,NULL); /* NFS fix... utime() forces a cache refresh */
71:
72: number--; /* make zero based */
73: for(count=0;count<LOOP_NODEDAB;count++) {
74: if(count)
75: mswait(100);
76: if(lockit && lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))!=0) {
77: unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
78: continue;
79: }
80: lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
81: rd=read(nodefile,node,sizeof(node_t));
82: if(!lockit || rd!=sizeof(node_t))
83: unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
84: if(rd==sizeof(node_t))
85: break;
86: }
87: if(!lockit && cfg.node_misc&NM_CLOSENODEDAB) {
88: close(nodefile);
89: nodefile=-1;
90: }
91:
92: if(count==LOOP_NODEDAB) {
93: errormsg(WHERE,rd==sizeof(node_t) ? ERR_LOCK : ERR_READ,"node.dab",number+1);
1.1.1.2 ! root 94: if(nodefile!=-1)
! 95: close(nodefile);
! 96: nodefile=-1;
1.1 root 97: return(-2);
98: }
99: if(count>(LOOP_NODEDAB/2)) {
100: sprintf(str,"NODE.DAB (node %d) COLLISION - Count: %d"
101: ,number+1, count);
1.1.1.2 ! root 102: logline(LOG_WARNING,"!!",str);
1.1 root 103: }
104:
105: return(0);
106: }
107:
108: /****************************************************************************/
109: /* Synchronizes all the nodes knowledge of the other nodes' actions, mode, */
110: /* status and other flags. */
111: /* Assumes that getnodedat(node_num,&thisnode,0) was called right before it */
112: /* is called. */
113: /****************************************************************************/
114: void sbbs_t::nodesync()
115: {
116: char str[256],today[32];
117: int atr=curatr;
118:
119: if(nodesync_inside || !online)
120: return;
121: nodesync_inside=1;
122:
123: if(thisnode.action!=action) {
124: if(getnodedat(cfg.node_num,&thisnode,true)==0) {
125: thisnode.action=action;
126: putnodedat(cfg.node_num,&thisnode);
127: }
128: }
129:
130: criterrs=thisnode.errors;
131:
132: if(sys_status&SS_USERON) {
133:
134: if(thisnode.status==NODE_WFC) {
1.1.1.2 ! root 135: lprintf(LOG_ERR, "Node %d NODE STATUS FIXUP", cfg.node_num);
1.1 root 136: if(getnodedat(cfg.node_num,&thisnode,true)==0) {
137: thisnode.status=NODE_INUSE;
138: putnodedat(cfg.node_num,&thisnode);
139: }
140: }
141:
142: if(!(sys_status&SS_NEWDAY)) {
143: now=time(NULL);
144: unixtodstr(&cfg,logontime,str);
145: unixtodstr(&cfg,now,today);
146: if(strcmp(str,today)) { /* New day, clear "today" user vars */
147: sys_status|=SS_NEWDAY; // So we don't keep doing this over&over
1.1.1.2 ! root 148: resetdailyuserdat(&cfg, &useron,/* write: */true);
1.1 root 149: }
150: }
151: if(thisnode.misc&NODE_UDAT && !(useron.rest&FLAG('G'))) { /* not guest */
152: getuserdat(&cfg, &useron);
153: if(getnodedat(cfg.node_num,&thisnode,true)==0) {
154: thisnode.misc&=~NODE_UDAT;
155: putnodedat(cfg.node_num,&thisnode);
156: }
157: }
1.1.1.2 ! root 158: if(!(sys_status&SS_MOFF)) {
! 159: if(thisnode.misc&NODE_MSGW)
! 160: getsmsg(useron.number); /* getsmsg clears MSGW flag */
! 161: if(thisnode.misc&NODE_NMSG)
! 162: getnmsg(); /* getnmsg clears NMSG flag */
! 163: }
1.1 root 164: }
165:
166: if(cfg.sync_mod[0])
167: exec_bin(cfg.sync_mod,&main_csi);
168:
169: if(thisnode.misc&NODE_INTR) {
170: bputs(text[NodeLocked]);
1.1.1.2 ! root 171: logline(LOG_NOTICE,nulstr,"Interrupted");
1.1 root 172: hangup();
173: nodesync_inside=0;
174: return;
175: }
176:
177: if(thisnode.misc&NODE_LCHAT) { // pulled into local chat with sysop
178: SAVELINE;
179: privchat(true);
180: RESTORELINE;
181: }
182:
183: if(sys_status&SS_USERON && memcmp(&nodesync_user,&useron,sizeof(user_t))) {
184: getusrdirs();
185: getusrsubs();
186: memcpy(&nodesync_user,&useron,sizeof(nodesync_user));
187: }
188:
189: if(sys_status&SS_USERON && online && (timeleft/60)<(5-timeleft_warn)
190: && !SYSOP) {
191: timeleft_warn=5-(timeleft/60);
1.1.1.2 ! root 192: if(!(sys_status&SS_MOFF)) {
! 193: attr(LIGHTGRAY);
! 194: bprintf(text[OnlyXminutesLeft]
! 195: ,((ushort)timeleft/60)+1,(timeleft/60) ? "s" : nulstr);
! 196: }
1.1 root 197: }
198:
199: attr(atr); /* replace original attributes */
200: nodesync_inside=0;
201: }
202:
203: /****************************************************************************/
204: /* Prints short messages waiting for this node, if any... */
205: /****************************************************************************/
206: int sbbs_t::getnmsg()
207: {
208: char str[MAX_PATH+1], *buf;
209: int file;
210: long length;
211:
212: if(getnodedat(cfg.node_num,&thisnode,true)==0) {
213: thisnode.misc&=~NODE_NMSG; /* clear the NMSG flag */
214: putnodedat(cfg.node_num,&thisnode);
215: }
216:
217: sprintf(str,"%smsgs/n%3.3u.msg",cfg.data_dir,cfg.node_num);
218: if(flength(str)<1L)
219: return(0);
220: if((file=nopen(str,O_RDWR))==-1) {
221: /**
222: errormsg(WHERE,ERR_OPEN,str,O_RDWR);
223: **/
224: return(errno);
225: }
1.1.1.2 ! root 226: length=(long)filelength(file);
1.1 root 227: if(!length) {
228: close(file);
229: return(0);
230: }
231: if((buf=(char *)malloc(length+1))==NULL) {
232: close(file);
233: errormsg(WHERE,ERR_ALLOC,str,length+1);
234: return(-1);
235: }
236: if(lread(file,buf,length)!=length) {
237: close(file);
238: free(buf);
239: errormsg(WHERE,ERR_READ,str,length);
240: return(errno);
241: }
242: chsize(file,0L);
243: close(file);
244: buf[length]=0;
245:
246: if(thisnode.action==NODE_MAIN || thisnode.action==NODE_XFER
247: || sys_status&SS_IN_CTRLP) {
248: CRLF;
249: }
250: putmsg(buf,P_NOATCODES);
251: free(buf);
252:
253: return(0);
254: }
255:
256: /****************************************************************************/
257: /* 'ext' must be at least 128 bytes! */
258: /****************************************************************************/
259: int sbbs_t::getnodeext(uint number, char *ext)
260: {
261: char str[MAX_PATH+1];
262: int rd,count;
263:
264: if(!number || number>cfg.sys_nodes) {
265: errormsg(WHERE,ERR_CHK,"node number",number);
266: return(-1);
267: }
268:
269: sprintf(str,"%snode.exb",cfg.ctrl_dir);
270: if((node_ext=nopen(str,O_RDONLY|O_DENYNONE))==-1) {
271: memset(ext,0,128);
272: errormsg(WHERE,ERR_OPEN,str,O_RDONLY|O_DENYNONE);
273: return(errno);
274: }
275:
276: number--; /* make zero based */
277: for(count=0;count<LOOP_NODEDAB;count++) {
278: if(count)
279: mswait(100);
280: if(lock(node_ext,(long)number*128L,128)!=0)
281: continue;
282: lseek(node_ext,(long)number*128L,SEEK_SET);
283: rd=read(node_ext,ext,128);
284: unlock(node_ext,(long)number*128L,128);
285: if(rd==128)
286: break;
287: }
288: close(node_ext);
289: node_ext=-1;
290:
291:
292: if(count==LOOP_NODEDAB) {
293: errormsg(WHERE,ERR_READ,"node.exb",number+1);
294: return(-2);
295: }
296: if(count>(LOOP_NODEDAB/2)) {
297: sprintf(str,"NODE.EXB (node %d) COLLISION - Count: %d"
298: ,number+1, count);
299: logline("!!",str);
300: }
301:
302: return(0);
303: }
304:
305:
306: /****************************************************************************/
307: /* Prints short messages waiting for 'usernumber', if any... */
308: /* then deletes them. */
309: /****************************************************************************/
310: int sbbs_t::getsmsg(int usernumber)
311: {
312: char str[MAX_PATH+1], *buf;
313: int file;
314: long length;
1.1.1.2 ! root 315: node_t node;
! 316: int i;
! 317:
! 318: for(i=1;i<=cfg.sys_nodes;i++) { /* clear msg waiting flag */
! 319: if(getnodedat(i,&node,true)==0) {
! 320: if(node.useron==usernumber
! 321: && (node.status==NODE_INUSE || node.status==NODE_QUIET)
! 322: && node.misc&NODE_MSGW)
! 323: node.misc&=~NODE_MSGW;
! 324: putnodedat(i,&node);
! 325: }
! 326: }
1.1 root 327:
328: sprintf(str,"%smsgs/%4.4u.msg",cfg.data_dir,usernumber);
329: if(flength(str)<1L)
330: return(0);
331: if((file=nopen(str,O_RDWR))==-1) {
332: errormsg(WHERE,ERR_OPEN,str,O_RDWR);
333: return(errno);
334: }
1.1.1.2 ! root 335: length=(long)filelength(file);
1.1 root 336: if((buf=(char *)malloc(length+1))==NULL) {
337: close(file);
338: errormsg(WHERE,ERR_ALLOC,str,length+1);
339: return(-1);
340: }
341: if(lread(file,buf,length)!=length) {
342: close(file);
343: free(buf);
344: errormsg(WHERE,ERR_READ,str,length);
345: return(errno);
346: }
347: chsize(file,0L);
348: close(file);
349: buf[length]=0;
350: getnodedat(cfg.node_num,&thisnode,0);
351: if(thisnode.action==NODE_MAIN || thisnode.action==NODE_XFER
352: || sys_status&SS_IN_CTRLP) {
353: CRLF;
354: }
355: putmsg(buf,P_NOATCODES);
356: free(buf);
357:
358: return(0);
359: }
360:
361: /****************************************************************************/
362: /* This function lists users that are online. */
363: /* If listself is true, it will list the current node. */
364: /* Returns number of active nodes (not including current node). */
365: /****************************************************************************/
366: int sbbs_t::whos_online(bool listself)
367: {
368: int i,j;
369: node_t node;
370:
371: CRLF;
372: bputs(text[NodeLstHdr]);
373: for(j=0,i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
374: getnodedat(i,&node,0);
375: if(i==cfg.node_num) {
376: if(listself)
377: printnodedat(i,&node);
378: continue;
379: }
380: if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) {
381: printnodedat(i,&node);
382: if(!lastnodemsg)
383: lastnodemsg=i;
384: j++;
385: }
386: }
387: if(!j)
388: bputs(text[NoOtherActiveNodes]);
389: return(j);
390: }
391:
392: void sbbs_t::nodelist(void)
393: {
394: node_t node;
395:
396: CRLF;
397: bputs(text[NodeLstHdr]);
398: for(int i=1;i<=cfg.sys_nodes && i<=cfg.sys_lastnode;i++) {
399: getnodedat(i,&node,0);
400: printnodedat(i,&node);
401: }
402: }
403:
1.1.1.2 ! root 404: static char* node_connection_desc(sbbs_t* sbbs, ushort conn, char* str)
! 405: {
! 406: switch(conn) {
! 407: case NODE_CONNECTION_LOCAL:
! 408: return (char*)" Locally"; /* obsolete */
! 409: case NODE_CONNECTION_TELNET:
! 410: return sbbs->text[NodeConnectionTelnet];
! 411: case NODE_CONNECTION_RLOGIN:
! 412: return sbbs->text[NodeConnectionRLogin];
! 413: case NODE_CONNECTION_SSH:
! 414: return sbbs->text[NodeConnectionSSH];
! 415: default:
! 416: sprintf(str,sbbs->text[NodeConnectionModem],conn);
! 417: break;
! 418: }
! 419:
! 420: return str;
! 421: }
! 422:
1.1 root 423: /****************************************************************************/
424: /* Displays the information for node number 'number' contained in 'node' */
425: /****************************************************************************/
426: void sbbs_t::printnodedat(uint number, node_t* node)
427: {
428: uint i;
429: char hour,mer[3];
430: char tmp[512];
431:
432: attr(cfg.color[clr_nodenum]);
433: bprintf("%3d ",number);
434: attr(cfg.color[clr_nodestatus]);
435: switch(node->status) {
436: case NODE_WFC:
1.1.1.2 ! root 437: bputs(text[NodeStatusWaitingForCall]);
1.1 root 438: break;
439: case NODE_OFFLINE:
1.1.1.2 ! root 440: bputs(text[NodeStatusOffline]);
1.1 root 441: break;
442: case NODE_NETTING:
1.1.1.2 ! root 443: bputs("Networking"); /* obsolete */
1.1 root 444: break;
445: case NODE_LOGON:
1.1.1.2 ! root 446: bputs(text[NodeStatusLogon]);
! 447: bputs(node_connection_desc(this, node->connection, tmp));
1.1 root 448: break;
449: case NODE_EVENT_WAITING:
1.1.1.2 ! root 450: bputs(text[NodeStatusEventWaiting]);
1.1 root 451: break;
452: case NODE_EVENT_LIMBO:
1.1.1.2 ! root 453: bprintf(text[NodeStatusEventLimbo],node->aux);
1.1 root 454: break;
455: case NODE_EVENT_RUNNING:
1.1.1.2 ! root 456: bputs(text[NodeStatusEventRunning]);
1.1 root 457: break;
458: case NODE_NEWUSER:
1.1.1.2 ! root 459: bputs(text[NodeStatusNewUser]);
! 460: bputs(node_connection_desc(this, node->connection, tmp));
1.1 root 461: break;
462: case NODE_QUIET:
463: if(!SYSOP) {
1.1.1.2 ! root 464: bputs(text[NodeStatusWaitingForCall]);
1.1 root 465: break;
466: }
467: case NODE_INUSE:
468: if(node->misc&NODE_EXT) {
469: getnodeext(number,tmp);
470: bputs(tmp);
471: break;
472: }
473: attr(cfg.color[clr_nodeuser]);
474: if(node->misc&NODE_ANON && !SYSOP)
1.1.1.2 ! root 475: bputs(text[UNKNOWN_USER]);
1.1 root 476: else
477: bputs(username(&cfg,node->useron,tmp));
478: attr(cfg.color[clr_nodestatus]);
479: bputs(" ");
480: switch(node->action) {
481: case NODE_MAIN:
482: bputs("at main menu");
483: break;
484: case NODE_RMSG:
485: bputs("reading messages");
486: break;
487: case NODE_RMAL:
488: bputs("reading mail");
489: break;
490: case NODE_RSML:
491: bputs("reading sent mail");
492: break;
493: case NODE_RTXT:
494: bputs("reading text files");
495: break;
496: case NODE_PMSG:
497: bputs("posting message");
498: break;
499: case NODE_SMAL:
500: bputs("sending mail");
501: break;
502: case NODE_AMSG:
503: bputs("posting auto-message");
504: break;
505: case NODE_XTRN:
506: if(node->aux<1 || node->aux>cfg.total_xtrns)
507: bputs("at external program menu");
508: else {
509: bputs("running ");
510: i=node->aux-1;
1.1.1.2 ! root 511: if(SYSOP || chk_ar(cfg.xtrn[i]->ar,&useron,&client))
1.1 root 512: bputs(cfg.xtrn[node->aux-1]->name);
513: else
514: bputs("external program");
515: }
516: break;
517: case NODE_DFLT:
518: bputs("changing defaults");
519: break;
520: case NODE_XFER:
521: bputs("at transfer menu");
522: break;
523: case NODE_RFSD:
524: bprintf("retrieving from device #%d",node->aux);
525: break;
526: case NODE_DLNG:
527: bprintf("downloading");
528: break;
529: case NODE_ULNG:
530: bputs("uploading");
531: break;
532: case NODE_BXFR:
533: bputs("transferring bidirectional");
534: break;
535: case NODE_LFIL:
536: bputs("listing files");
537: break;
538: case NODE_LOGN:
539: bputs("logging on");
540: break;
541: case NODE_LCHT:
542: bprintf("in local chat with %s",cfg.sys_op);
543: break;
544: case NODE_MCHT:
545: if(node->aux) {
546: bprintf("in multinode chat channel %d",node->aux&0xff);
547: if(node->aux&0x1f00) { /* password */
548: outchar('*');
549: if(SYSOP)
550: bprintf(" %s",unpackchatpass(tmp,node));
551: }
552: }
553: else
554: bputs("in multinode global chat channel");
555: break;
556: case NODE_PAGE:
557: bprintf("paging node %u for private chat",node->aux);
558: break;
559: case NODE_PCHT:
560: if(node->aux)
561: bprintf("in private chat with node %u",node->aux);
562: else
563: bprintf("in local chat with %s",cfg.sys_op);
564: break;
565: case NODE_GCHT:
566: i=node->aux;
567: if(i>=cfg.total_gurus)
568: i=0;
569: bprintf("chatting with %s",cfg.guru[i]->name);
570: break;
571: case NODE_CHAT:
572: bputs("in chat section");
573: break;
574: case NODE_TQWK:
575: bputs("transferring QWK packet");
576: break;
577: case NODE_SYSP:
578: bputs("performing sysop activities");
579: break;
580: default:
581: bputs(ultoa(node->action,tmp,10));
582: break; }
1.1.1.2 ! root 583: bputs(node_connection_desc(this, node->connection, tmp));
1.1 root 584: if(node->action==NODE_DLNG) {
585: if(cfg.sys_misc&SM_MILITARY) {
586: hour=node->aux/60;
587: mer[0]=0;
588: }
589: else if((node->aux/60)>=12) {
590: if(node->aux/60==12)
591: hour=12;
592: else
593: hour=(node->aux/60)-12;
594: strcpy(mer,"pm");
595: }
596: else {
597: if((node->aux/60)==0) /* 12 midnite */
598: hour=12;
599: else hour=node->aux/60;
600: strcpy(mer,"am");
601: }
602: bprintf(" ETA %02d:%02d %s"
603: ,hour,node->aux%60,mer);
604: }
605: break;
606: }
607: i=NODE_LOCK;
608: if(node->status==NODE_INUSE || SYSOP)
609: i|=NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG;
610: if(node->misc&i) {
611: bputs(" (");
612: if(node->misc&(i&NODE_AOFF))
613: outchar('A');
614: if(node->misc&NODE_LOCK)
615: outchar('L');
616: if(node->misc&(i&(NODE_MSGW|NODE_NMSG)))
617: outchar('M');
618: if(node->misc&(i&NODE_POFF))
619: outchar('P');
620: outchar(')');
621: }
622: if(SYSOP && ((node->misc
623: &(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN|NODE_LCHAT))
624: || node->status==NODE_QUIET)) {
625: bputs(" [");
626: if(node->misc&NODE_ANON)
627: outchar('A');
628: if(node->misc&NODE_INTR)
629: outchar('I');
630: if(node->misc&NODE_RRUN)
631: outchar('R');
632: if(node->misc&NODE_UDAT)
633: outchar('U');
634: if(node->status==NODE_QUIET)
635: outchar('Q');
636: if(node->misc&NODE_EVENT)
637: outchar('E');
638: if(node->misc&NODE_DOWN)
639: outchar('D');
640: if(node->misc&NODE_LCHAT)
641: outchar('C');
642: outchar(']');
643: }
644: if(node->errors && SYSOP) {
645: attr(cfg.color[clr_err]);
646: bprintf(" %d error%c",node->errors, node->errors>1 ? 's' : '\0' );
647: }
648: attr(LIGHTGRAY);
649: CRLF;
650: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.