|
|
1.1 root 1: /* node.c */
2:
3: /* Synchronet BBS Node control program */
4:
1.1.1.2 ! root 5: /* $Id: node.c,v 1.20 2004/10/13 04:51:27 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 2004 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: /* Platform-specific headers */
39: #ifdef _WIN32
40: #include <io.h> /* open/close */
41: #include <windows.h>
42: #endif
43:
44: #include <stdio.h>
45: #include <stdlib.h>
46: #include <fcntl.h>
47: #include <string.h>
1.1.1.2 ! root 48: #include <errno.h>
! 49: #include <ctype.h> /* isdigit */
1.1 root 50:
51: /* Synchronet-specific */
52: #include "sbbsdefs.h"
1.1.1.2 ! root 53: #include "genwrap.h" /* stricmp */
! 54: #include "filewrap.h" /* lock/unlock/sopen */
1.1 root 55:
56: enum {
57: MODE_LIST
58: ,MODE_ANON
59: ,MODE_LOCK
60: ,MODE_INTR
61: ,MODE_RRUN
62: ,MODE_DOWN
63: ,MODE_EVENT
64: ,MODE_NOPAGE
65: ,MODE_NOALERTS
66: ,MODE_STATUS
67: ,MODE_USERON
68: ,MODE_ACTION
69: ,MODE_ERRORS
70: ,MODE_MISC
71: ,MODE_CONN
72: ,MODE_AUX
73: ,MODE_EXTAUX
74: };
75:
76: char tmp[256];
77: int nodefile;
78:
1.1.1.2 ! root 79: #if defined(_WIN32) /* Microsoft-supplied cls() routine - ugh! */
! 80:
! 81: /* Standard error macro for reporting API errors */
! 82: #define PERR(bSuccess, api){if(!(bSuccess)) printf("%s:Error %d from %s \
! 83: on line %d\n", __FILE__, GetLastError(), api, __LINE__);}
! 84:
! 85: void cls(void)
! 86: {
! 87: COORD coordScreen = { 0, 0 }; /* here's where we'll home the
! 88: cursor */
! 89: BOOL bSuccess;
! 90: DWORD cCharsWritten;
! 91: CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
! 92: DWORD dwConSize; /* number of character cells in
! 93: the current buffer */
! 94: HANDLE hConsole;
! 95:
! 96: hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
! 97:
! 98: /* get the number of character cells in the current buffer */
! 99:
! 100: bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
! 101: PERR( bSuccess, "GetConsoleScreenBufferInfo" );
! 102: dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
! 103:
! 104: /* fill the entire screen with blanks */
! 105:
! 106: bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',
! 107: dwConSize, coordScreen, &cCharsWritten );
! 108: PERR( bSuccess, "FillConsoleOutputCharacter" );
! 109:
! 110: /* get the current text attribute */
! 111:
! 112: bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
! 113: PERR( bSuccess, "ConsoleScreenBufferInfo" );
! 114:
! 115: /* now set the buffer's attributes accordingly */
! 116:
! 117: bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes,
! 118: dwConSize, coordScreen, &cCharsWritten );
! 119: PERR( bSuccess, "FillConsoleOutputAttribute" );
! 120:
! 121: /* put the cursor at (0, 0) */
! 122:
! 123: bSuccess = SetConsoleCursorPosition( hConsole, coordScreen );
! 124: PERR( bSuccess, "SetConsoleCursorPosition" );
! 125: return;
! 126: }
! 127: #else /* !_WIN32 */
! 128:
! 129: #define cls()
! 130:
! 131: #endif
! 132:
1.1 root 133: #if !defined _MSC_VER && !defined __BORLANDC__
134: char* itoa(int val, char* str, int radix)
135: {
136: switch(radix) {
137: case 8:
138: sprintf(str,"%o",val);
139: break;
140: case 10:
141: sprintf(str,"%u",val);
142: break;
143: case 16:
144: sprintf(str,"%x",val);
145: break;
146: default:
147: sprintf(str,"bad radix: %d",radix);
148: break;
149: }
150: return(str);
151: }
152: #endif
153:
154: /****************************************************************************/
155: /* Reads the data for node number 'number' into the structure 'node' */
156: /* from NODE.DAB */
157: /* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
158: /****************************************************************************/
1.1.1.2 ! root 159: void getnodedat(int number, node_t *node, int lockit)
1.1 root 160: {
1.1.1.2 ! root 161: int count;
1.1 root 162:
163: number--; /* make zero based */
1.1.1.2 ! root 164: for(count=0;count<LOOP_NODEDAB;count++) {
! 165: if(count)
! 166: SLEEP(100);
1.1 root 167: lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
168: if(lockit
1.1.1.2 ! root 169: && lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1)
! 170: continue;
1.1 root 171: if(read(nodefile,node,sizeof(node_t))==sizeof(node_t))
172: break;
1.1.1.2 ! root 173: }
! 174: if(count>=(LOOP_NODEDAB/2))
! 175: printf("NODE.DAB (node %d) COLLISION (READ) - Count: %d\n"
! 176: ,number+1, count);
! 177: else if(count==LOOP_NODEDAB) {
! 178: printf("!Error reading nodefile for node %d\n",number+1);
! 179: }
1.1 root 180: }
181:
182: /****************************************************************************/
183: /* Write the data from the structure 'node' into NODE.DAB */
184: /* getnodedat(num,&node,1); must have been called before calling this func */
185: /* NOTE: ------^ the indicates the node record has been locked */
186: /****************************************************************************/
1.1.1.2 ! root 187: void putnodedat(int number, node_t node)
1.1 root 188: {
189: number--; /* make zero based */
190: lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET);
191: if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) {
192: unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
193: printf("Error writing to nodefile for node %d\n",number+1);
194: return; }
195: unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t));
196: }
197:
198: /****************************************************************************/
199: /* Unpacks the password 'pass' from the 5bit ASCII inside node_t. 32bits in */
200: /* node.extaux, and the other 8bits in the upper byte of node.aux */
201: /****************************************************************************/
202: char *unpackchatpass(char *pass, node_t node)
203: {
204: char bits;
205: int i;
206:
207: pass[0]=(node.aux&0x1f00)>>8;
208: pass[1]=(char)(((node.aux&0xe000)>>13)|((node.extaux&0x3)<<3));
209: bits=2;
210: for(i=2;i<8;i++) {
211: pass[i]=(char)((node.extaux>>bits)&0x1f);
212: bits+=5; }
213: pass[8]=0;
214: for(i=0;i<8;i++)
215: if(pass[i])
216: pass[i]+=64;
217: return(pass);
218: }
219:
220: /****************************************************************************/
221: /* Displays the information for node number 'number' contained in 'node' */
222: /****************************************************************************/
1.1.1.2 ! root 223: void printnodedat(int number, node_t node)
1.1 root 224: {
225: char hour,mer[3];
226:
227: printf("Node %2d: ",number);
228: switch(node.status) {
229: case NODE_WFC:
230: printf("Waiting for call");
231: break;
232: case NODE_OFFLINE:
233: printf("Offline");
234: break;
235: case NODE_NETTING:
236: printf("Networking");
237: break;
238: case NODE_LOGON:
239: printf("At logon prompt");
240: break;
241: case NODE_EVENT_WAITING:
242: printf("Waiting for all nodes to become inactive");
243: break;
244: case NODE_EVENT_LIMBO:
245: printf("Waiting for node %d to finish external event",node.aux);
246: break;
247: case NODE_EVENT_RUNNING:
248: printf("Running external event");
249: break;
250: case NODE_NEWUSER:
251: printf("New user");
252: printf(" applying for access ");
253: if(!node.connection)
254: printf("locally");
255: else if(node.connection==0xffff)
256: printf("via telnet");
257: else
258: printf("at %ubps",node.connection);
259: break;
260: case NODE_QUIET:
261: case NODE_INUSE:
262: printf("User #%d",node.useron);
263: printf(" ");
264: switch(node.action) {
265: case NODE_MAIN:
266: printf("at main menu");
267: break;
268: case NODE_RMSG:
269: printf("reading messages");
270: break;
271: case NODE_RMAL:
272: printf("reading mail");
273: break;
274: case NODE_RSML:
275: printf("reading sent mail");
276: break;
277: case NODE_RTXT:
278: printf("reading text files");
279: break;
280: case NODE_PMSG:
281: printf("posting message");
282: break;
283: case NODE_SMAL:
284: printf("sending mail");
285: break;
286: case NODE_AMSG:
287: printf("posting auto-message");
288: break;
289: case NODE_XTRN:
290: if(!node.aux)
291: printf("at external program menu");
292: else
293: printf("running external program #%d",node.aux);
294: break;
295: case NODE_DFLT:
296: printf("changing defaults");
297: break;
298: case NODE_XFER:
299: printf("at transfer menu");
300: break;
301: case NODE_RFSD:
302: printf("retrieving from device #%d",node.aux);
303: break;
304: case NODE_DLNG:
305: printf("downloading");
306: break;
307: case NODE_ULNG:
308: printf("uploading");
309: break;
310: case NODE_BXFR:
311: printf("transferring bidirectional");
312: break;
313: case NODE_LFIL:
314: printf("listing files");
315: break;
316: case NODE_LOGN:
317: printf("logging on");
318: break;
319: case NODE_LCHT:
320: printf("in local chat with sysop");
321: break;
322: case NODE_MCHT:
323: if(node.aux) {
324: printf("in multinode chat channel %d",node.aux&0xff);
325: if(node.aux&0x1f00) { /* password */
326: putchar('*');
327: printf(" %s",unpackchatpass(tmp,node)); } }
328: else
329: printf("in multinode global chat channel");
330: break;
331: case NODE_PAGE:
332: printf("paging node %u for private chat",node.aux);
333: break;
334: case NODE_PCHT:
335: printf("in private chat with node %u",node.aux);
336: break;
337: case NODE_GCHT:
338: printf("chatting with The Guru");
339: break;
340: case NODE_CHAT:
341: printf("in chat section");
342: break;
343: case NODE_TQWK:
344: printf("transferring QWK packet");
345: break;
346: case NODE_SYSP:
347: printf("performing sysop activities");
348: break;
349: default:
350: printf(itoa(node.action,tmp,10));
351: break; }
352: if(!node.connection)
353: printf(" locally");
354: else if(node.connection==0xffff)
355: printf(" via telnet");
356: else
357: printf(" at %ubps",node.connection);
358: if(node.action==NODE_DLNG) {
359: if((node.aux/60)>=12) {
360: if(node.aux/60==12)
361: hour=12;
362: else
363: hour=(node.aux/60)-12;
364: strcpy(mer,"pm"); }
365: else {
366: if((node.aux/60)==0) /* 12 midnite */
367: hour=12;
368: else hour=node.aux/60;
369: strcpy(mer,"am"); }
370: printf(" ETA %02d:%02d %s"
371: ,hour,node.aux-((node.aux/60)*60),mer); }
372: break; }
373: if(node.misc&(NODE_LOCK|NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG)) {
374: printf(" (");
375: if(node.misc&NODE_AOFF)
376: putchar('A');
377: if(node.misc&NODE_LOCK)
378: putchar('L');
379: if(node.misc&(NODE_MSGW|NODE_NMSG))
380: putchar('M');
381: if(node.misc&NODE_POFF)
382: putchar('P');
383: putchar(')'); }
384: if(((node.misc
385: &(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
386: || node.status==NODE_QUIET)) {
387: printf(" [");
388: if(node.misc&NODE_ANON)
389: putchar('A');
390: if(node.misc&NODE_INTR)
391: putchar('I');
392: if(node.misc&NODE_RRUN)
393: putchar('R');
394: if(node.misc&NODE_UDAT)
395: putchar('U');
396: if(node.status==NODE_QUIET)
397: putchar('Q');
398: if(node.misc&NODE_EVENT)
399: putchar('E');
400: if(node.misc&NODE_DOWN)
401: putchar('D');
402: if(node.misc&NODE_LCHAT)
403: putchar('C');
404: putchar(']'); }
405: if(node.errors)
406: printf(" %d error%c",node.errors, node.errors>1 ? 's' : '\0' );
407: printf("\n");
408: }
409:
410:
411: /****************************/
412: /* Main program entry point */
413: /****************************/
414: int main(int argc, char **argv)
415: {
416: char str[256],ctrl_dir[41],*p,debug=0;
417: int sys_nodes,node_num=0,onoff=0;
418: int i,j,mode=0,misc;
1.1.1.2 ! root 419: int modify=0;
! 420: int loop=0;
! 421: int pause=0;
! 422: long value=0;
1.1 root 423: node_t node;
424:
1.1.1.2 ! root 425: char revision[16];
! 426:
! 427: sscanf("$Revision: 1.20 $", "%*s %s", revision);
! 428:
! 429: printf("\nSynchronet Node Display/Control Utility v%s\n\n", revision);
1.1 root 430:
431: if(sizeof(node_t)!=SIZEOF_NODE_T) {
432: printf("COMPILER ERROR: sizeof(node_t)=%d instead of %d\n"
433: ,sizeof(node_t),SIZEOF_NODE_T);
434: return(-1);
435: }
436:
437: if(argc<2) {
438: printf("usage: node [/debug] [action [on|off]] [node numbers] [...]"
439: "\n\n");
440: printf("actions (default is list):\n\n");
441: printf("list = list status\n");
442: printf("anon = anonymous user\n");
443: printf("lock = locked\n");
444: printf("intr = interrupt\n");
445: printf("down = shut-down\n");
446: printf("rerun = rerun\n");
447: printf("event = run event\n");
448: printf("nopage = page disable\n");
449: printf("noalerts = activity alerts disable\n");
450: printf("status=# = set status value\n");
451: printf("useron=# = set useron number\n");
452: printf("action=# = set action value\n");
453: printf("errors=# = set error counter\n");
454: printf("conn=# = set connection value\n");
455: printf("misc=# = set misc value\n");
456: printf("aux=# = set aux value\n");
457: printf("extaux=# = set extended aux value\n");
458: exit(0); }
459:
460: p=getenv("SBBSCTRL");
461: if(p==NULL) {
462: printf("\7\nSBBSCTRL environment variable is not set.\n");
463: printf("This environment variable must be set to your CTRL directory.");
464: printf("\nExample: SET SBBSCTRL=/sbbs/ctrl\n");
465: exit(1); }
466: sprintf(ctrl_dir,"%.40s",p);
467: if(ctrl_dir[strlen(ctrl_dir)-1]!='\\'
468: && ctrl_dir[strlen(ctrl_dir)-1]!='/')
469: strcat(ctrl_dir,"/");
470:
471: sprintf(str,"%snode.dab",ctrl_dir);
472: if((nodefile=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
1.1.1.2 ! root 473: printf("\7\nError %d opening %s.\n",errno,str);
1.1 root 474: exit(1); }
475:
476: sys_nodes=filelength(nodefile)/sizeof(node_t);
477: if(!sys_nodes) {
478: printf("%s reflects 0 nodes!\n",str);
479: exit(1); }
480:
481: for(i=1;i<argc;i++) {
482: if(isdigit(argv[i][0]))
483: node_num=atoi(argv[i]);
484: else {
485: node_num=onoff=value=0;
1.1.1.2 ! root 486: if(!stricmp(argv[i],"-DEBUG"))
1.1 root 487: debug=1;
1.1.1.2 ! root 488: if(!stricmp(argv[i],"-LOOP"))
! 489: loop=1;
! 490: if(!stricmp(argv[i],"-PAUSE"))
! 491: pause=1;
! 492:
1.1 root 493: else if(!stricmp(argv[i],"LOCK"))
494: mode=MODE_LOCK;
495: else if(!stricmp(argv[i],"ANON"))
496: mode=MODE_ANON;
497: else if(!stricmp(argv[i],"INTR"))
498: mode=MODE_INTR;
499: else if(!stricmp(argv[i],"DOWN"))
500: mode=MODE_DOWN;
501: else if(!stricmp(argv[i],"RERUN"))
502: mode=MODE_RRUN;
503: else if(!stricmp(argv[i],"EVENT"))
504: mode=MODE_EVENT;
505: else if(!stricmp(argv[i],"NOPAGE"))
506: mode=MODE_NOPAGE;
507: else if(!stricmp(argv[i],"NOALERTS"))
508: mode=MODE_NOALERTS;
509: else if(!stricmp(argv[i],"ON"))
510: onoff=1;
511: else if(!stricmp(argv[i],"OFF"))
512: onoff=2;
513: else if(!strnicmp(argv[i],"STATUS=",7)) {
514: mode=MODE_STATUS;
515: value=atoi(argv[i]+7); }
516: else if(!strnicmp(argv[i],"ERRORS=",7)) {
517: mode=MODE_ERRORS;
518: value=atoi(argv[i]+7); }
519: else if(!strnicmp(argv[i],"USERON=",7)) {
520: mode=MODE_USERON;
521: value=atoi(argv[i]+7); }
522: else if(!strnicmp(argv[i],"ACTION=",7)) {
523: mode=MODE_ACTION;
524: value=atoi(argv[i]+7); }
525: else if(!strnicmp(argv[i],"CONN=",5)) {
526: mode=MODE_CONN;
527: value=atoi(argv[i]+5); }
528: else if(!strnicmp(argv[i],"MISC=",5)) {
529: mode=MODE_MISC;
530: value=atoi(argv[i]+5); }
531: else if(!strnicmp(argv[i],"AUX=",4)) {
532: mode=MODE_AUX;
533: value=atoi(argv[i]+4); }
534: else if(!strnicmp(argv[i],"EXTAUX=",7)) {
535: mode=MODE_EXTAUX;
536: value=atoi(argv[i]+7); }
537: }
1.1.1.2 ! root 538: if(mode!=MODE_LIST)
! 539: modify=1;
! 540:
1.1 root 541: if((mode && node_num) || i+1==argc)
1.1.1.2 ! root 542: while(1) {
! 543: for(j=1;j<=sys_nodes;j++)
! 544: if(!node_num || j==node_num) {
! 545: getnodedat(j,&node,modify);
! 546: misc=0;
! 547: switch(mode) {
! 548: case MODE_ANON:
! 549: misc=NODE_ANON;
! 550: break;
! 551: case MODE_LOCK:
! 552: misc=NODE_LOCK;
! 553: break;
! 554: case MODE_INTR:
! 555: misc=NODE_INTR;
! 556: break;
! 557: case MODE_DOWN:
! 558: if(node.status==NODE_WFC)
! 559: node.status=NODE_OFFLINE;
! 560: else
! 561: misc=NODE_DOWN;
! 562: break;
! 563: case MODE_RRUN:
! 564: misc=NODE_RRUN;
! 565: break;
! 566: case MODE_EVENT:
! 567: misc=NODE_EVENT;
! 568: break;
! 569: case MODE_NOPAGE:
! 570: misc=NODE_POFF;
! 571: break;
! 572: case MODE_NOALERTS:
! 573: misc=NODE_AOFF;
! 574: break;
! 575: case MODE_STATUS:
! 576: node.status=(uchar)value;
! 577: break;
! 578: case MODE_ERRORS:
! 579: node.errors=(uchar)value;
! 580: break;
! 581: case MODE_ACTION:
! 582: node.action=(uchar)value;
! 583: break;
! 584: case MODE_USERON:
! 585: node.useron=(uchar)value;
! 586: break;
! 587: case MODE_MISC:
! 588: node.misc=(uchar)value;
! 589: break;
! 590: case MODE_CONN:
! 591: node.connection=(uchar)value;
! 592: break;
! 593: case MODE_AUX:
! 594: node.aux=(uchar)value;
! 595: break;
! 596: case MODE_EXTAUX:
! 597: node.extaux=value;
! 598: break; }
! 599: if(misc) {
! 600: if(onoff==0)
! 601: node.misc^=misc;
! 602: else if(onoff==1)
! 603: node.misc|=misc;
! 604: else if(onoff==2)
! 605: node.misc&=~misc; }
! 606: if(modify)
! 607: putnodedat(j,node);
! 608: printnodedat(j,node);
! 609: if(debug) {
! 610: printf("status=%u\n",node.status);
! 611: printf("errors=%u\n",node.errors);
! 612: printf("action=%d\n",node.action);
! 613: printf("useron=%u\n",node.useron);
! 614: printf("conn=%u\n",node.connection);
! 615: printf("misc=%u\n",node.misc);
! 616: printf("aux=%u\n",node.aux);
! 617: printf("extaux=%lu\n",node.extaux);
! 618: } /* debug */
! 619:
! 620: if(pause) {
! 621: printf("Hit enter...");
! 622: getchar();
! 623: printf("\n");
! 624: }
! 625:
! 626: } /* if(!node_num) */
! 627:
! 628: if(!loop)
! 629: break;
! 630: SLEEP(1000);
! 631: cls();
! 632: } /* while(1) */
! 633:
! 634: } /* for i<argc */
1.1 root 635:
636: close(nodefile);
637: return(0);
638: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.