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