umonitor.c 15.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* umonitor.c */

/* Synchronet for *nix node activity monitor */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

38
#include "sbbs.h"
39
40
#include "conwrap.h"	/* this has to go BEFORE curses.h so getkey() can be macroed around */
#include <curses.h>
deuce's avatar
deuce committed
41
42
43
44
45
#include <sys/types.h>
#include <sys/time.h>
#ifdef __QNX__
#include <string.h>
#endif
46
#include <stdio.h>
47
#include <unistd.h>
48
#include "genwrap.h"
49
50
51
#include "uifc.h"
#include "sbbsdefs.h"
#include "genwrap.h"	/* stricmp */
52
#include "dirwrap.h"	/* lock/unlock/sopen */
53
#include "filewrap.h"	/* lock/unlock/sopen */
54
55
56
#include "sbbs_ini.h"	/* INI parsing */
#include "scfglib.h"	/* SCFG files */
#include "ars_defs.h"	/* needed for SCFG files */
57
#include "userdat.h"	/* getnodedat() */
58
#include "spyon.h"
59
#include "chat.h"
60

61
#define CTRL(x) (x&037)
62
63
64
65
66
67

/********************/
/* Global Variables */
/********************/
uifcapi_t uifc; /* User Interface (UIFC) Library API */
char tmp[256];
68
69
const char *YesStr="Yes";
const char *NoStr="No";
deuce's avatar
deuce committed
70
box_t boxch;
71
72
73
74
75
76
77
78
79
80
81
82
83
84

int lprintf(char *fmt, ...)
{
	va_list argptr;
	char sbuf[1024];
	int	len;

	va_start(argptr,fmt);
	len=vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
	sbuf[sizeof(sbuf)-1]=0;
	va_end(argptr);
	uifc.msg(sbuf);
	return(len);
}
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
void bail(int code)
{
    if(code) {
        puts("\nHit a key...");
        getch(); 
	}
    uifc.bail();

    exit(code);
}

void allocfail(uint size)
{
    printf("\7Error allocating %u bytes of memory.\n",size);
    bail(1);
101
102
}

103
104
void node_toggles(scfg_t *cfg,int nodenum)  {
	int nodefile;
105
106
107
108
109
110
111
112
113
114
115
116
117
	char**	opt;
	int		i,j;
	node_t	node;
	int		save=0;

	if((opt=(char **)MALLOC(sizeof(char *)*(MAX_OPTS+1)))==NULL)
		allocfail(sizeof(char *)*(MAX_OPTS+1));
	for(i=0;i<(MAX_OPTS+1);i++)
		if((opt[i]=(char *)MALLOC(MAX_OPLN))==NULL)
			allocfail(MAX_OPLN);

	i=0;
	uifc.helpbuf=	"`Node Toggles:`\n"
118
					"\nToDo: Add help (Mention that changes take effect immediately)";
119
	while(save==0) {
120
		if(getnodedat(cfg,nodenum,&node,&nodefile)) {
121
122
123
			uifc.msg("Error reading node data!");
			break;
		}
124
125
126
127
128
129
		j=0;
		sprintf(opt[j++],"%-30s%3s","Locked for SysOps only",node.misc&NODE_LOCK ? YesStr : NoStr);
		sprintf(opt[j++],"%-30s%3s","Interrupt (Hangup)",node.misc&NODE_INTR ? YesStr : NoStr);
		sprintf(opt[j++],"%-30s%3s","Page disabled",node.misc&NODE_POFF ? YesStr : NoStr);
		sprintf(opt[j++],"%-30s%3s","Activity alert disabled",node.misc&NODE_AOFF ? YesStr : NoStr);
		sprintf(opt[j++],"%-30s%3s","Re-run on logoff",node.misc&NODE_RRUN ? YesStr : NoStr);
130
		sprintf(opt[j++],"%-30s%3s","Down node after logoff",(node.misc&NODE_DOWN || (node.status==NODE_OFFLINE)) ? YesStr : NoStr);
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
		sprintf(opt[j++],"%-30s%3s","Reset private chat",node.misc&NODE_RPCHT ? YesStr : NoStr);
		opt[j][0]=0;

		switch(uifc.list(WIN_MID,0,0,0,&i,0,"Node Toggles",opt)) {
			case 0:	/* Locked */
				node.misc ^= NODE_LOCK;
				break;

			case 1:	/* Interrupt */
				node.misc ^= NODE_INTR;
				break;

			case 2:	/* Page disabled */
				node.misc ^= NODE_POFF;
				break;

			case 3:	/* Activity alert */
				node.misc ^= NODE_AOFF;
				break;

			case 4:	/* Re-run */
				node.misc ^= NODE_RRUN;
				break;

			case 5:	/* Down */
156
				if(node.status != NODE_WFC && node.status != NODE_OFFLINE)
157
					node.misc ^= NODE_DOWN;
158
				else {
159
160
161
162
163
					if(node.status!=NODE_OFFLINE)
						node.status=NODE_OFFLINE;
					else
						node.status=NODE_WFC;
				}
164
165
166
167
168
169
170
171
172
173
174
175
176
177
				break;

			case 6:	/* Reset chat */
				node.misc ^= NODE_RPCHT;
				break;
				
			case -1:
				save=1;
				break;
				
			default:
				uifc.msg("Option not implemented");
				continue;
		}
178
		putnodedat(cfg,nodenum,&node,nodefile);
deuce's avatar
deuce committed
179
	}
deuce's avatar
deuce committed
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
}

int dospy(int nodenum, bbs_startup_t *bbs_startup)  {
	char str[80],str2[80];
	int i;

	if(bbs_startup->temp_dir[0])
    	snprintf(str,sizeof(str),"%slocalspy%d.sock", bbs_startup->temp_dir, nodenum);
	else
		snprintf(str,sizeof(str),"%slocalspy%d.sock", bbs_startup->ctrl_dir, nodenum);
	endwin();
	i=spyon(str);
	refresh();
	switch(i) {
		case SPY_NOSOCKET:
			uifc.msg("Could not create socket");
			return(-1);
					
		case SPY_NOCONNECT:
			sprintf(str2,"Failed to connect to %s",str);
			uifc.msg(str2);
			return(-1);

		case SPY_SELECTFAILED:
			uifc.msg("select() failed, connection terminated.");
			return(-1);

		case SPY_SOCKETLOST:
			uifc.msg("Spy socket lost");
			return(-1);
							
		case SPY_STDINLOST:
			uifc.msg("STDIN has gone away... you probably can't close this window.  :-)");
			return(-1);
							
		case SPY_CLOSED:
			break;
			
		default:
			sprintf(str,"Unknown return code %d",i);
			uifc.msg(str);
			return(-1);
	}
	return(0);
}

226
int sendmessage(scfg_t *cfg, int nodenum,node_t *node)  {
227
228
229
230
	char str[80],str2[80];

	uifc.input(WIN_MID,0,0,"Telegram",str2,58,K_WRAP|K_MSG);
	sprintf(str,"\1n\1y\1hMessage From Sysop:\1w %s",str2);
231
	if(getnodedat(cfg,nodenum,node,NULL))
232
233
234
		return(-1);
	if(node->useron==0)
		return(-1);
235
	putsmsg(cfg, node->useron, str);
236
237
238
	return(0);
}

239
240
241
int clearerrors(scfg_t *cfg, int nodenum, node_t *node) {
	int nodefile;
	if(getnodedat(cfg,nodenum,node,&nodefile)) {
242
243
244
245
		uifc.msg("getnodedat() failed! (Nothing done)");
		return(-1);
	}
	node->errors=0;
246
	putnodedat(cfg,nodenum,node,nodefile);
247
248
249
	return(0);
}

250
int main(int argc, char** argv)  {
251
252
253
254
255
	char**	opt;
	char**	mopt;
	int		main_dflt=0;
	int		main_bar=0;
	char revision[16];
256
	char str[256],ctrl_dir[41],*p;
257
	char title[256];
258
	int i,j;
259
	node_t node;
260
261
	char	*buf;
	int		buffile;
262
263
264
	int		nodefile;
	box_t	boxch;
	scfg_t	cfg;
265
266
267
268
269
270
271
/******************/
/* Ini file stuff */
/******************/
	char	host_name[128]="";
	char	ini_file[MAX_PATH+1];
	FILE*				fp;
	bbs_startup_t		bbs_startup;
272
273

	sscanf("$Revision$", "%*s %s", revision);
274

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
    printf("\nSynchronet UNIX Monitor %s-%s  Copyright 2003 "
        "Rob Swindell\n",revision,PLATFORM_DESC);

	p=getenv("SBBSCTRL");
	if(p==NULL) {
		printf("\7\nSBBSCTRL environment variable is not set.\n");
		printf("This environment variable must be set to your CTRL directory.");
		printf("\nExample: SET SBBSCTRL=/sbbs/ctrl\n");
		exit(1); }

	sprintf(ctrl_dir,"%.40s",p);
	if(ctrl_dir[strlen(ctrl_dir)-1]!='\\'
		&& ctrl_dir[strlen(ctrl_dir)-1]!='/')
		strcat(ctrl_dir,"/");

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
	gethostname(host_name,sizeof(host_name)-1);
	sprintf(ini_file,"%s%c%s.ini",ctrl_dir,BACKSLASH,host_name);
#if defined(PREFIX)
	if(!fexistcase(ini_file))
		sprintf(ini_file,"%s/etc/sbbs.ini",PREFIX);
#endif
	if(!fexistcase(ini_file))
		sprintf(ini_file,"%s%csbbs.ini",ctrl_dir,BACKSLASH);

	/* Initialize BBS startup structure */
    memset(&bbs_startup,0,sizeof(bbs_startup));
    bbs_startup.size=sizeof(bbs_startup);
    strcpy(bbs_startup.ctrl_dir,ctrl_dir);

	/* Read .ini file here */
	if(ini_file[0]!=0 && (fp=fopen(ini_file,"r"))!=NULL) {
		printf("Reading %s\n",ini_file);
	}
	/* We call this function to set defaults, even if there's no .ini file */
	sbbs_read_ini(fp, 
310
		NULL, &bbs_startup, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
311
312
313
314
315
316
317
318

	/* close .ini file here */
	if(fp!=NULL)
		fclose(fp);

	chdir(bbs_startup.ctrl_dir);
	
	/* Read .cfg files here */
319
	cfg.size=sizeof(cfg);
320
321
322
323
324
	if(!read_main_cfg(&cfg, str)) {
		printf("ERROR! %s\n",str);
		exit(1);
	}

325
326
327
328
329
	if(!read_xtrn_cfg(&cfg, str)) {
		printf("ERROR! %s\n",str);
		exit(1);
	}

deuce's avatar
deuce committed
330
331
332
333
334
/*	if(!read_node_cfg(&cfg, str)) {
		printf("ERROR! %s\n",str);
		exit(1);
	} */

335
336
337
338
    memset(&uifc,0,sizeof(uifc));

	uifc.esc_delay=500;

deuce's avatar
deuce committed
339
340
341
342
343
344
345
346
	boxch.ls=ACS_VLINE; 
	boxch.rs=ACS_VLINE;
	boxch.ts=ACS_HLINE;
	boxch.bs=ACS_HLINE;
	boxch.tl=ACS_ULCORNER;
	boxch.tr=ACS_URCORNER;
	boxch.bl=ACS_LLCORNER;
	boxch.br=ACS_LRCORNER;
347
348
349
350
351
352
353
354
355
356
357
358
359
360
	for(i=1;i<argc;i++) {
        if(argv[i][0]=='-'
            )
            switch(toupper(argv[i][1])) {
                case 'C':
        			uifc.mode|=UIFC_COLOR;
                    break;
                case 'L':
                    uifc.scrn_len=atoi(argv[i]+2);
                    break;
                case 'E':
                    uifc.esc_delay=atoi(argv[i]+2);
                    break;
				case 'I':
361
					/* Set up ex-ascii codes */
deuce's avatar
deuce committed
362
363
364
365
366
367
368
369
					boxch.ls=186; 
					boxch.rs=186;
					boxch.ts=205;
					boxch.bs=205;
					boxch.tl=201;
					boxch.tr=187;
					boxch.bl=200;
					boxch.br=188;
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
					uifc.mode|=UIFC_IBM;
					break;
                default:
                    printf("\nusage: %s [ctrl_dir] [options]"
                        "\n\noptions:\n\n"
                        "-c  =  force color mode\n"
                        "-e# =  set escape delay to #msec\n"
						"-i  =  force IBM charset\n"
                        "-l# =  set screen lines to #\n"
						,argv[0]
                        );
        			exit(0);
           }
    }

	uifc.size=sizeof(uifc);
	i=uifcinic(&uifc);  /* curses */
	if(i!=0) {
		printf("uifc library init returned error %d\n",i);
		exit(1);
	}

	if((opt=(char **)MALLOC(sizeof(char *)*(MAX_OPTS+1)))==NULL)
		allocfail(sizeof(char *)*(MAX_OPTS+1));
	for(i=0;i<(MAX_OPTS+1);i++)
		if((opt[i]=(char *)MALLOC(MAX_OPLN))==NULL)
			allocfail(MAX_OPLN);

	if((mopt=(char **)MALLOC(sizeof(char *)*MAX_OPTS))==NULL)
		allocfail(sizeof(char *)*MAX_OPTS);
	for(i=0;i<MAX_OPTS;i++)
		if((mopt[i]=(char *)MALLOC(MAX_OPLN))==NULL)
			allocfail(MAX_OPLN);

404
405
	sprintf(title,"Synchronet UNIX Monitor %s-%s",revision,PLATFORM_DESC);
	if(uifc.scrn(title)) {
406
407
408
409
410
		printf(" USCRN (len=%d) failed!\n",uifc.scrn_len+1);
		bail(1);
	}

	while(1) {
411
412
413
414
		for(i=1;i<=cfg.sys_nodes;i++) {
			if((j=getnodedat(&cfg,i,&node,NULL)))
				sprintf(mopt[i-1],"Error reading node data (%d)!",j);
			else
415
				sprintf(mopt[i-1],"%3d: %s",i,nodestatus(&cfg,&node,str,71));
416
		}
deuce's avatar
deuce committed
417
		mopt[i-1][0]=0;
418
419

		uifc.helpbuf=	"`Synchronet Monitor:`\n"
deuce's avatar
deuce committed
420
						"\nCTRL-E displays the error log"
421
422
						"\nF12 spys on the currently selected node"
						"\nF11 send message to the currently selected node"
423
						"\nF10 Chats with the user on the currently selected node"
424
425
426
427
428
429
						"\nDEL Clear errors on currently selected node"
						"\nCTRL-L Lock node toggle"
						"\nCTRL-R Rerun node"
						"\nCTRL-D Down node toggle"
						"\nCTRL-I Interrupt node"
						"\nToDo: Add more help. (Explain what you're looking at)";
430
						
431
		j=uifc.list(WIN_ORG|WIN_MID|WIN_ESC|WIN_ACT|WIN_DYN,0,0,70,&main_dflt,&main_bar
432
433
434
			,title,mopt);

		if(j==-7) {	/* CTRL-E */
435
			sprintf(str,"%s/error.log",cfg.data_dir);
436
			if(fexist(str)) {
deuce's avatar
deuce committed
437
				if((buffile=sopen(str,O_RDONLY,SH_DENYWR))>=0) {
438
439
440
441
442
					j=filelength(buffile);
					if((buf=(char *)MALLOC(j+1))!=NULL) {
						read(buffile,buf,j);
						close(buffile);
						*(buf+j)=0;
443
						uifc.showbuf(buf,"Error Log",0);
444
445
446
447
						free(buf);
						continue;
					}
					close(buffile);
deuce's avatar
deuce committed
448
					uifc.msg("Error allocating memory for the error log");
449
450
					continue;
				}
deuce's avatar
deuce committed
451
				uifc.msg("Error opening error log");
452
453
454
455
456
457
			}
			else {
				uifc.msg("Error log does not exist");
			}
			continue;
		}
deuce's avatar
deuce committed
458
		
459
		if(j==-2-KEY_DC) {	/* Clear errors */
460
			clearerrors(&cfg, main_dflt+1,&node);
461
462
463
464
			continue;
		}

		if(j==-2-KEY_F(10)) {	/* Chat */
465
466
467
468
469
			if(getnodedat(&cfg,main_dflt+1,&node,NULL)) {
				uifc.msg("Error reading node data!");
				continue;
			}
			if((node.status&NODE_INUSE) && node.useron)
470
				chat(&cfg,main_dflt+1,&node,&boxch,uifc.timedisplay);
471
472
473
474
			continue;
		}

		if(j==-2-KEY_F(11)) {	/* Send message */
475
			sendmessage(&cfg, main_dflt+1,&node);
476
477
478
479
			continue;
		}
		
		if(j==-2-KEY_F(12)) {	/* Spy */
deuce's avatar
deuce committed
480
			dospy(main_dflt+1,&bbs_startup);
481
482
483
484
485
486
487
488
489
490
491
			continue;
		}
		
		if(j==-2-CTRL('l')) {	/* Lock node */
			if(getnodedat(&cfg,main_dflt+1,&node,&nodefile)) {
				uifc.msg("Error reading node data!");
				continue;
			}
			node.misc^=NODE_LOCK;
			putnodedat(&cfg,main_dflt+1,&node,nodefile);
			continue;
deuce's avatar
deuce committed
492
493
		}
		
494
495
496
497
498
499
500
501
502
		if(j==-2-CTRL('r')) {	/* Rerun node */
			if(getnodedat(&cfg,main_dflt+1,&node,&nodefile)) {
				uifc.msg("Error reading node data!");
				continue;
			}
			node.misc^=NODE_RRUN;
			putnodedat(&cfg,main_dflt+1,&node,nodefile);
			continue;
		}
503

504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
		if(j==-2-CTRL('d')) {	/* Down node */
			if(getnodedat(&cfg,main_dflt+1,&node,&nodefile)) {
				uifc.msg("Error reading node data!");
				continue;
			}
			if(node.status != NODE_WFC && node.status != NODE_OFFLINE)
				node.misc ^= NODE_DOWN;
			else {
				if(node.status!=NODE_OFFLINE)
					node.status=NODE_OFFLINE;
				else
					node.status=NODE_WFC;
			}
			putnodedat(&cfg,main_dflt+1,&node,nodefile);
			continue;
		}

		if(j==-2-CTRL('i')) {	/* Interrupt node */
			if(getnodedat(&cfg,main_dflt+1,&node,&nodefile)) {
				uifc.msg("Error reading node data!");
				continue;
			}
			node.misc^=NODE_INTR;
			putnodedat(&cfg,main_dflt+1,&node,nodefile);
			continue;
		}
		
531
		if(j <= -2)
532
533
			continue;

deuce's avatar
deuce committed
534
		if(j==-1) {
535
			i=0;
536
537
			strcpy(opt[0],YesStr);
			strcpy(opt[1],NoStr);
538
539
540
541
542
			opt[2][0]=0;
			uifc.helpbuf=	"`Exit Synchronet UNIX Monitor:`\n"
							"\n"
							"\nIf you want to exit the Synchronet UNIX monitor utility,"
							"\nselect `Yes`. Otherwise, select `No` or hit ~ ESC ~.";
deuce's avatar
deuce committed
543
			i=uifc.list(WIN_MID,0,0,0,&i,0,"Exit Synchronet Monitor",opt);
544
545
546
547
			if(!i)
				bail(0);
			continue;
		}
548
		if(j<cfg.sys_nodes && j>=0) {
549
550
551
552
			i=0;
			strcpy(opt[i++],"Spy on node");
			strcpy(opt[i++],"Node toggles");
			strcpy(opt[i++],"Clear Errors");
deuce's avatar
deuce committed
553
554
			getnodedat(&cfg,j+1,&node,NULL);
			if((node.status&NODE_INUSE) && node.useron) {
deuce's avatar
deuce committed
555
				strcpy(opt[i++],"Send message to user");
deuce's avatar
deuce committed
556
				strcpy(opt[i++],"Chat with user");
deuce's avatar
deuce committed
557
			}
558
559
560
561
			opt[i][0]=0;
			i=0;
			uifc.helpbuf=	"`Node Options:`\n"
							"\nToDo: Add help";
562
			switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Node Options",opt))  {
563
				case 0:	/* Spy */
deuce's avatar
deuce committed
564
					dospy(j+1,&bbs_startup);
565
566
567
					break;

				case 1: /* Node Toggles */
568
					node_toggles(&cfg, j+1);
569
570
571
					break;

				case 2:
572
					clearerrors(&cfg, j+1,&node);
573
574
					break;

deuce's avatar
deuce committed
575
				case 3:	/* Send message */
576
					sendmessage(&cfg, j+1,&node);
deuce's avatar
deuce committed
577
578
					break;

deuce's avatar
deuce committed
579
				case 4:
580
					chat(&cfg,main_dflt+1,&node,&boxch,uifc.timedisplay);
deuce's avatar
deuce committed
581
582
					break;
				
583
584
585
586
587
588
589
				case -1:
					break;
					
				default:
					uifc.msg("Option not implemented");
					break;
			}
590
591
		}
	}
592
}