|
|
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.