umonitor.c 38.3 KB
Newer Older
1
2
/* Synchronet for *nix node activity monitor */

Rob Swindell's avatar
Rob Swindell committed
3
/* $Id: umonitor.c,v 1.99 2020/08/17 00:48:52 rswindell Exp $ */
rswindell's avatar
rswindell committed
4
// vi: tabstop=4
5
6
7
8
9

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
rswindell's avatar
rswindell committed
10
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
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
 *																			*
 * 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.	*
 ****************************************************************************/

37
#include <signal.h>
deuce's avatar
deuce committed
38
#include <sys/types.h>
39
#include <time.h>
deuce's avatar
deuce committed
40
41
42
#ifdef __QNX__
#include <string.h>
#endif
43
#include <stdio.h>
44
45
46
47

#include "ciolib.h"
#define __COLORS		/* Disable the colour macros in sbbsdefs.h ToDo */
#include "sbbs.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

/********************/
/* Global Variables */
/********************/
uifcapi_t uifc; /* User Interface (UIFC) Library API */
67
68
const char *YesStr="Yes";
const char *NoStr="No";
69
70
71
72
73
74
75
76
77
78
79
80
81
82

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);
}
83

84
85
void bail(int code)
{
deuce's avatar
deuce committed
86
87
88
	if(code) {
		puts("\nHit a key...");
		getch();
89
	}
deuce's avatar
deuce committed
90
	uifc.bail();
91

deuce's avatar
deuce committed
92
	exit(code);
93
94
95
96
}

void allocfail(uint size)
{
deuce's avatar
deuce committed
97
98
	printf("\7Error allocating %u bytes of memory.\n",size);
	bail(1);
99
100
}

101
void node_toggles(scfg_t *cfg,int nodenum)  {
102
	int nodefile = -1;
103
104
105
106
107
	char**	opt;
	int		i,j;
	node_t	node;
	int		save=0;

deuce's avatar
deuce committed
108
109
110
	if((opt=(char **)alloca(sizeof(char *)*(4+1)))==NULL)
		allocfail(sizeof(char *)*(4+1));
	for(i=0;i<(4+1);i++)
111
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
112
113
114
			allocfail(MAX_OPLN);

	i=0;
115
116
	uifc.helpbuf=	"`Node Toggles\n"
	                "`------------`\n\n"
deuce's avatar
deuce committed
117
118
119
120
121
122
123
124
125
126
127
	                "`The following are `Yes/No `options.  Hitting Enter toggles between.\n\n"
	                "`Locked for SysOps only : `Locks the node so that only SysOps may \n"
	                "                         logon to them.\n"
	                "`Interrupt (Hangup)     : `The current user will be kicked as soon as it \n"
	                "                         is safe to do so.  A brief message is given\n"
	                "                         to user.\n"
	                "`Re-run on logoff       : `Toggles the system to reload the configuration\n"
	                "                         files when the current user logs off.\n"
	                "`Down node after logoff : `Takes the node offline after current user logs\n"
	                "                         off.\n\n"
	                "`[Note] `These toggles take effect immediately.";
128
	while(save==0) {
129
		if(getnodedat(cfg,nodenum,&node,FALSE,&nodefile)) {
130
131
132
			uifc.msg("Error reading node data!");
			break;
		}
133
134
135
		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);
rswindell's avatar
rswindell committed
136
137
138
		sprintf(opt[j++],"%-30s%3s","Re-run on logoff",node.misc&NODE_RRUN ? YesStr : NoStr);
		sprintf(opt[j++],"%-30s%3s","Down node after logoff"
			,(node.misc&NODE_DOWN || (node.status==NODE_OFFLINE)) ? YesStr : NoStr);
139
140
		opt[j][0]=0;

141
		switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Node Toggles",opt)) {
142
143
144
145
146
147
148
149
			case 0:	/* Locked */
				node.misc ^= NODE_LOCK;
				break;

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

rswindell's avatar
rswindell committed
150
			case 2:	/* Re-run */
151
152
153
				node.misc ^= NODE_RRUN;
				break;

rswindell's avatar
rswindell committed
154
			case 3:	/* Down */
155
				if(node.status != NODE_WFC && node.status != NODE_OFFLINE)
156
					node.misc ^= NODE_DOWN;
157
				else {
158
159
160
161
162
					if(node.status!=NODE_OFFLINE)
						node.status=NODE_OFFLINE;
					else
						node.status=NODE_WFC;
				}
163
164
165
166
167
				break;

			case -1:
				save=1;
				break;
168

169
170
171
172
			default:
				uifc.msg("Option not implemented");
				continue;
		}
173
		putnodedat(cfg,nodenum,&node,FALSE,nodefile);
deuce's avatar
deuce committed
174
	}
deuce's avatar
deuce committed
175
176
177
178
179
180
181
}

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

	if(bbs_startup->temp_dir[0])
deuce's avatar
deuce committed
182
		snprintf(str,sizeof(str),"%slocalspy%d.sock", bbs_startup->temp_dir, nodenum);
deuce's avatar
deuce committed
183
184
185
186
187
188
189
	else
		snprintf(str,sizeof(str),"%slocalspy%d.sock", bbs_startup->ctrl_dir, nodenum);
	i=spyon(str);
	switch(i) {
		case SPY_NOSOCKET:
			uifc.msg("Could not create socket");
			return(-1);
190

deuce's avatar
deuce committed
191
		case SPY_NOCONNECT:
192
			SAFEPRINTF(str2,"Failed to connect to %s",str);
deuce's avatar
deuce committed
193
194
195
196
197
198
199
200
201
202
			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);
203

deuce's avatar
deuce committed
204
205
206
		case SPY_STDINLOST:
			uifc.msg("STDIN has gone away... you probably can't close this window.  :-)");
			return(-1);
207

deuce's avatar
deuce committed
208
209
		case SPY_CLOSED:
			break;
210

deuce's avatar
deuce committed
211
212
213
214
215
216
217
218
		default:
			sprintf(str,"Unknown return code %d",i);
			uifc.msg(str);
			return(-1);
	}
	return(0);
}

219
int sendmessage(scfg_t *cfg, int nodenum,node_t *node)  {
220
221
	char str[80],str2[80];

222
	uifc.input(WIN_MID|WIN_SAV,0,0,"Telegram",str2,58,K_WRAP|K_MSG);
223
	SAFEPRINTF(str,"\1n\1y\1hMessage From Sysop:\1w %s\r\n",str2);
224
	if(getnodedat(cfg,nodenum,node,FALSE,NULL))
225
226
227
		return(-1);
	if(node->useron==0)
		return(-1);
228
	putsmsg(cfg, node->useron, str);
229
230
231
	return(0);
}

232
int clearerrors(scfg_t *cfg, int nodenum, node_t *node) {
233
234
	int nodefile = -1;
	if(getnodedat(cfg,nodenum,node,TRUE,&nodefile)) {
235
236
237
238
		uifc.msg("getnodedat() failed! (Nothing done)");
		return(-1);
	}
	node->errors=0;
239
	putnodedat(cfg,nodenum,node,TRUE,nodefile);
240
	uifc.msg("Error count cleared for this node.");
241
242
243
	return(0);
}

244
245
246
247
248
/* Assumes a 12 char outstr */
char *getsizestr(char *outstr, long size, BOOL bytes) {
	if(bytes) {
		if(size < 1000) {	/* Bytes */
			snprintf(outstr,12,"%ld bytes",size);
249
			return(outstr);
250
251
252
		}
		if(size<10000) {	/* Bytes with comma */
			snprintf(outstr,12,"%ld,%03ld bytes",(size/1000),(size%1000));
253
			return(outstr);
254
255
256
257
258
		}
		size = size/1024;
	}
	if(size<1000) {	/* KB */
		snprintf(outstr,12,"%ld KB",size);
259
		return(outstr);
260
261
262
	}
	if(size<999999) { /* KB With comma */
		snprintf(outstr,12,"%ld,%03ld KB",(size/1000),(size%1000));
263
		return(outstr);
264
265
266
267
	}
	size = size/1024;
	if(size<1000) {	/* MB */
		snprintf(outstr,12,"%ld MB",size);
268
		return(outstr);
269
270
271
	}
	if(size<999999) { /* MB With comma */
		snprintf(outstr,12,"%ld,%03ld MB",(size/1000),(size%1000));
272
		return(outstr);
273
274
275
276
	}
	size = size/1024;
	if(size<1000) {	/* GB */
		snprintf(outstr,12,"%ld GB",size);
277
		return(outstr);
278
279
280
	}
	if(size<999999) { /* GB With comma */
		snprintf(outstr,12,"%ld,%03ld GB",(size/1000),(size%1000));
281
		return(outstr);
282
283
284
285
	}
	size = size/1024;
	if(size<1000) {	/* TB (Yeah, right) */
		snprintf(outstr,12,"%ld TB",size);
286
		return(outstr);
287
288
	}
	sprintf(outstr,"Plenty");
289
	return(outstr);
290
291
292
293
294
295
}

/* Assumes a 12 char outstr */
char *getnumstr(char *outstr, ulong size) {
	if(size < 1000) {
		snprintf(outstr,12,"%ld",size);
296
		return(outstr);
297
298
299
	}
	if(size<1000000) {
		snprintf(outstr,12,"%ld,%03ld",(size/1000),(size%1000));
300
		return(outstr);
301
302
303
	}
	if(size<1000000000) {
		snprintf(outstr,12,"%ld,%03ld,%03ld",(size/1000000),((size/1000)%1000),(size%1000));
304
		return(outstr);
305
306
307
308
	}
	size=size/1000000;
	if(size<1000000) {
		snprintf(outstr,12,"%ld,%03ld M",(size/1000),(size%1000));
309
		return(outstr);
310
311
312
	}
	if(size<10000000) {
		snprintf(outstr,12,"%ld,%03ld,%03ld M",(size/1000000),((size/1000)%1000),(size%1000));
313
		return(outstr);
314
315
	}
	sprintf(outstr,"Plenty");
316
	return(outstr);
317
318
}

319
int drawstats(scfg_t *cfg, int nodenum, node_t *node, int *curp, int *barp) {
320
321
322
323
324
325
326
327
	stats_t	sstats;
	stats_t	nstats;
	char	statbuf[6*78];		/* Buffer to hold the stats for passing to uifc.showbuf() */
	char	str[4][4][12];
	char	usrname[128];
	ulong	free;
	uint	i,l,m;
	time_t	t;
328
	int		shownode=1;
329

330
	if(getnodedat(cfg,nodenum,node,FALSE,NULL)) {
331
332
333
334
		shownode=0;
	}
	else {
		getstats(cfg, nodenum, &nstats);
335
336
337
338
339
340
341
342
343
344
	}
	username(cfg,node->useron,usrname);

	getstats(cfg, 0, &sstats);
	t=time(NULL);
	strftime(str[0][0],12,"%b %e",localtime(&t));
	free=getfreediskspace(cfg->temp_dir,1024);
	if(free<1000) {
		free=getfreediskspace(cfg->temp_dir,0);
		getsizestr(str[0][1],free,TRUE);
345
	}
346
347
	else
		getsizestr(str[0][1],free,FALSE);
348
349
350
351
352
	if(shownode) {
		snprintf(str[1][0],12,"%s/%s",getnumstr(str[3][2],nstats.ltoday),getnumstr(str[3][3],sstats.ltoday));
		getnumstr(str[1][1],sstats.logons);
		snprintf(str[1][2],12,"%s/%s",getnumstr(str[3][2],nstats.ttoday),getnumstr(str[3][3],sstats.ttoday));
		getnumstr(str[1][3],sstats.timeon);
rswindell's avatar
rswindell committed
353
		snprintf(str[2][0],12,"%s/%s",getnumstr(str[3][2],sstats.etoday),getnumstr(str[3][3],getmail(cfg,0,0,0)));
354
355
356
357
358
359
		l=m=0;
		for(i=0;i<cfg->total_subs;i++)
			l+=getposts(cfg,i); 			/* l=total posts */
		for(i=0;i<cfg->total_dirs;i++)
			m+=getfiles(cfg,i); 			/* m=total files */
		snprintf(str[2][1],12,"%s/%s",getnumstr(str[3][2],sstats.ptoday),getnumstr(str[3][3],l));
rswindell's avatar
rswindell committed
360
		snprintf(str[2][2],12,"%s/%s",getnumstr(str[3][2],sstats.ftoday),getnumstr(str[3][3],getmail(cfg,1,0,0)));
361
362
363
364
365
366
367
368
369
370
371
		snprintf(str[2][3],12,"%s/%s",getnumstr(str[3][2],sstats.nusers),getnumstr(str[3][3],total_users(cfg)));
		getsizestr(str[3][0],sstats.ulb,TRUE);
		snprintf(str[3][1],12,"%s/%s",getnumstr(str[3][2],sstats.uls),getnumstr(str[3][3],m));
		getsizestr(str[3][2],sstats.dlb,TRUE);
		getnumstr(str[3][3],sstats.dls);
	}
	else {
		snprintf(str[1][0],12,"%s",getnumstr(str[3][3],sstats.ltoday));
		getnumstr(str[1][1],sstats.logons);
		snprintf(str[1][2],12,"%s",getnumstr(str[3][3],sstats.ttoday));
		getnumstr(str[1][3],sstats.timeon);
rswindell's avatar
rswindell committed
372
		snprintf(str[2][0],12,"%s/%s",getnumstr(str[3][2],sstats.etoday),getnumstr(str[3][3],getmail(cfg,0,0,0)));
373
374
375
376
377
378
		l=m=0;
		for(i=0;i<cfg->total_subs;i++)
			l+=getposts(cfg,i); 			/* l=total posts */
		for(i=0;i<cfg->total_dirs;i++)
			m+=getfiles(cfg,i); 			/* m=total files */
		snprintf(str[2][1],12,"%s/%s",getnumstr(str[3][2],sstats.ptoday),getnumstr(str[3][3],l));
rswindell's avatar
rswindell committed
379
		snprintf(str[2][2],12,"%s/%s",getnumstr(str[3][2],sstats.ftoday),getnumstr(str[3][3],getmail(cfg,1,0,0)));
380
381
382
383
384
385
		snprintf(str[2][3],12,"%s/%s",getnumstr(str[3][2],sstats.nusers),getnumstr(str[3][3],total_users(cfg)));
		getsizestr(str[3][0],sstats.ulb,TRUE);
		snprintf(str[3][1],12,"%s/%s",getnumstr(str[3][2],sstats.uls),getnumstr(str[3][3],m));
		getsizestr(str[3][2],sstats.dlb,TRUE);
		getnumstr(str[3][3],sstats.dls);
	}
deuce's avatar
deuce committed
386
387
388
389
	snprintf(statbuf,sizeof(statbuf),"`Node #`: %-3d %6s  `Space`: %s"
			"\n`Logons`: %-11s `Total`: %-11s `Timeon`: %-11s `Total`: %-11s"
			"\n`Emails`: %-11s `Posts`: %-11s `Fbacks`: %-11s `Users`: %-11s"
			"\n`Uloads`: %-11s `Files`: %-11s `Dloads`: %-11s `Files`: %-11s",
390
391
392
393
394
			nodenum,str[0][0],str[0][1],
			str[1][0],str[1][1],str[1][2],str[1][3],
			str[2][0],str[2][1],str[2][2],str[2][3],
			str[3][0],str[3][1],str[3][2],str[3][3]);

deuce's avatar
deuce committed
395
	uifc.showbuf(WIN_HLP|WIN_L2R|WIN_DYN|WIN_PACK,1,1,80,6,"Statistics",statbuf,curp,barp);
396
/* Node 5 :	Mar 11  Space: 162,024k
397
   Logons: 23/103      Total: 62,610      Timeon: 322/2430    Total: 5,321,900
398
399
400
401
402
   Emails: 4/265       Posts: 4/12811     Fbacks: 2/17	       Users: 1/592
   Uloads: 324k        Files: 1/2195      Dloads: 9,308k      Files: 52 */
	return(0);
}

403
404
405
406
407
408
409
410
411
412
int view_log(char *filename, char *title)
{
	char str[1024];
	int buffile;
	int j;
	char *buf;

	if(fexist(filename)) {
		if((buffile=sopen(filename,O_RDONLY,SH_DENYWR))>=0) {
			j=filelength(buffile);
413
			if(j >= 0 && (buf=(char *)malloc(j+1))!=NULL) {
414
415
416
417
				read(buffile,buf,j);
				close(buffile);
				*(buf+j)=0;
				uifc.showbuf(WIN_MID,0,0,76,uifc.scrn_len-2,title,buf,NULL,NULL);
418
				free(buf);
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
				return(0);
			}
			close(buffile);
			uifc.msg("Error allocating memory for the error log");
			return(3);
		}
		sprintf(str,"Error opening %s",title);
		uifc.msg(str);
		return(1);
	}
	sprintf(str,"%s does not exists",title);
	uifc.msg(str);
	return(2);
}

int view_logs(scfg_t *cfg)
{
	char**	opt;
	int		i;
	char	str[1024];
	struct tm tm;
	struct tm tm_yest;
	time_t	now;

	now=time(NULL);
	localtime_r(&now,&tm);
	now -= 60*60*24;
	localtime_r(&now,&tm_yest);
447
	const int num_opts = 12;
448
449
450
	if((opt=(char **)alloca(sizeof(char *)*(num_opts+1)))==NULL)
		allocfail(sizeof(char *)*(num_opts+1));
	for(i=0;i<(num_opts+1);i++)
451
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
452
453
454
			allocfail(MAX_OPLN);

	i=0;
455
456
	strcpy(opt[i++],"Today's callers");
	strcpy(opt[i++],"Yesterday's callers");
457
	strcpy(opt[i++],"Error log");
458
459
	strcpy(opt[i++],"Today's log");
	strcpy(opt[i++],"Yesterday's log");
460
	strcpy(opt[i++],"Spam log");
461
	strcpy(opt[i++],"SBBSecho log");
462
	strcpy(opt[i++],"EchoMail stats");
463
	strcpy(opt[i++],"BinkP stats");
464
	strcpy(opt[i++],"Bad Areas list");
465
466
467
468
	strcpy(opt[i++],"Guru log");
	strcpy(opt[i++],"Hack log");
	opt[i][0]=0;
	i=0;
469
	uifc.helpbuf=	"`View Logs\n"
deuce's avatar
deuce committed
470
471
472
473
474
475
476
	                "`---------\n\n"
	                "`Today's callers     : `View a list of Today's callers.\n"
	                "`Yesterday's callers : `View a list of Yesterday's callers.\n"
	                "`Error log           : `View the Error log.\n"
	                "`Today's log         : `View Today's system activity.\n"
	                "`Yesterday's log     : `View Yesterday's system activity.\n"
	                "`Spam log            : `View the log of Spam E-Mail sent to the system.\n"
477
	                "`SBBSecho log        : `View the FidoNet EchoMail program log.\n"
478
479
	                "`EchoMail stats      : `view the FidoNet EchoMail statistics.\n"
					"`Binkp stats         : `view the BinkP FidoNet mailer statistics.\n"
480
	                "`Bad Areas list      : `view the list of unknown EchoMail areas.\n"
deuce's avatar
deuce committed
481
482
	                "`Guru log            : `View the transcriptions of chats with the Guru.\n"
	                "`Hack log            : `View the Hack attempt log.";
483

484
	while(1) {
485
		switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"View Logs",opt))  {
486
487
488
			case -1:
				return(0);
			case 0:
deuce's avatar
deuce committed
489
				sprintf(str,"%slogs/%2.2d%2.2d%2.2d.lol",cfg->logs_dir,tm.tm_mon+1,tm.tm_mday
490
491
492
493
					,TM_YEAR(tm.tm_year));
				view_log(str,"Todays Callers");
				break;
			case 1:
deuce's avatar
deuce committed
494
				sprintf(str,"%slogs/%2.2d%2.2d%2.2d.lol",cfg->logs_dir,tm_yest.tm_mon+1
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
					,tm_yest.tm_mday,TM_YEAR(tm_yest.tm_year));
				view_log(str,"Yesterdays Callers");
				break;
			case 2:
				sprintf(str,"%s/error.log",cfg->logs_dir);
				view_log(str,"Error Log");
				break;
			case 3:
				sprintf(str,"%slogs/%2.2d%2.2d%2.2d.log",cfg->logs_dir,tm.tm_mon+1,tm.tm_mday
					,TM_YEAR(tm.tm_year));
				view_log(str,"Todays Log");
				break;
			case 4:
				sprintf(str,"%slogs/%2.2d%2.2d%2.2d.log",cfg->logs_dir,tm_yest.tm_mon+1
					,tm_yest.tm_mday,TM_YEAR(tm_yest.tm_year));
				view_log(str,"Yesterdays Log");
				break;
			case 5:
				sprintf(str,"%sspam.log",cfg->logs_dir);
				view_log(str,"SPAM Log");
				break;
			case 6:
				sprintf(str,"%ssbbsecho.log",cfg->logs_dir);
518
				view_log(str,"SBBSecho Log");
519
520
				break;
			case 7:
521
522
523
524
				sprintf(str,"%sechostats.ini",cfg->data_dir);
				view_log(str,"EchoMail Stats");
				break;
			case 8:
525
526
527
528
				sprintf(str,"%sbinkstats.ini",cfg->data_dir);
				view_log(str,"BinkP Stats");
				break;
			case 9:
529
530
531
				sprintf(str,"%sbadareas.lst",cfg->data_dir);
				view_log(str,"Bad Area List");
				break;
532
			case 10:
533
534
535
				sprintf(str,"%sguru.log",cfg->logs_dir);
				view_log(str,"Guru Log");
				break;
536
			case 11:
537
538
539
540
541
542
543
544
545
546
				sprintf(str,"%shack.log",cfg->logs_dir);
				view_log(str,"Hack Log");
				break;
		}
	}
}

int do_cmd(char *cmd)
{
	int i;
547
548
549
550
	struct text_info ti;
	char *p;

	gettextinfo(&ti);
551
	p=alloca(ti.screenheight*ti.screenwidth*2);
552
	gettext(1,1,ti.screenwidth,ti.screenheight,p);
553
	i=system(cmd);
554
	puttext(1,1,ti.screenwidth,ti.screenheight,p);
555
556
557
	return(i);
}

558
int qwk_callouts(scfg_t *cfg)
559
{
560
561
562
563
564
565
566
567
568
	char**	opt;
	int		i,j;
	char	str[1024];

	if(cfg->total_qhubs<1) {
		uifc.msg("No QWK hubs configured!");
		return(1);
	}

deuce's avatar
deuce committed
569
570
571
	if((opt=(char **)alloca(sizeof(char *)*(cfg->total_qhubs+1)))==NULL)
		allocfail(sizeof(char *)*(cfg->total_qhubs+1));
	for(i=0;i<(cfg->total_qhubs+1);i++)
572
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
573
574
575
			allocfail(MAX_OPLN);


576
577
578
579
	uifc.helpbuf=	"`QWK Callouts\n"
					"`------------\n\n"
					"Select the Hub and press enter to initiate a call out to\n"
					"the highlighted system.";
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

	j=0;
	while(1) {
		for(i=0;i<cfg->total_qhubs;i++) {
			strcpy(opt[i],cfg->qhub[i]->id);
			sprintf(str,"%sqnet/%s.now",cfg->data_dir,cfg->qhub[i]->id);
			if(fexist(str))
				strcat(opt[i]," (pending)");
		}
		opt[i][0]=0;
		switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"QWK Callouts",opt))  {
			case -1:
				return(0);
				break;
			default:
				sprintf(str,"%sqnet/%s.now",cfg->data_dir,cfg->qhub[j]->id);
				ftouch(str);
		}
	}
599
600
601
	return(0);
}

602
int run_events(scfg_t *cfg)
603
{
604
605
606
607
	char**	opt;
	int		i,j;
	char	str[1024];

deuce's avatar
deuce committed
608
609
610
	if((opt=(char **)alloca(sizeof(char *)*(cfg->total_events+1)))==NULL)
		allocfail(sizeof(char *)*(cfg->total_events+1));
	for(i=0;i<(cfg->total_events+1);i++)
611
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
612
613
614
615
616
617
618
619
			allocfail(MAX_OPLN);

	if(cfg->total_events<1) {
		uifc.msg("No events configured!");
		return(1);
	}
	j=0;

620
621
622
	uifc.helpbuf=	"`Run Events\n"
					"`----------\n\n"
					"To run and event, highlight it and press Enter";
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640

	while(1) {
		for(i=0;i<cfg->total_events;i++) {
			strcpy(opt[i],cfg->event[i]->code);
			sprintf(str,"%s%s.now",cfg->data_dir,cfg->event[i]->code);
			if(fexist(str))
				strcat(opt[i]," (pending)");
		}
		opt[i][0]=0;
		switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"Run Events",opt))  {
			case -1:
				return(0);
				break;
			default:
				sprintf(str,"%s%s.now",cfg->data_dir,cfg->event[j]->code);
				ftouch(str);
		}
	}
641
642
643
	return(0);
}

644
int recycle_servers(scfg_t *cfg)
645
{
646
647
648
649
	char str[1024];
	char **opt;
	int i=0;

deuce's avatar
deuce committed
650
651
652
	if((opt=(char **)alloca(sizeof(char *)*(5+1)))==NULL)
		allocfail(sizeof(char *)*(5+1));
	for(i=0;i<(5+1);i++)
653
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
654
655
656
657
658
659
660
661
662
663
			allocfail(MAX_OPLN);

	i=0;
	strcpy(opt[i++],"FTP server");
	strcpy(opt[i++],"Mail server");
	strcpy(opt[i++],"Services");
	strcpy(opt[i++],"Telnet server");
	strcpy(opt[i++],"Web server");
	opt[i][0]=0;

664
665
666
667
668
	uifc.helpbuf=	"`Recycle Servers\n"
					"`---------------\n\n"
					"To rerun a server, highlight it and press Enter.\n"
					"This will reload the configuration files for selected\n"
					"server.";
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697

	i=0;
	while(1) {
		switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Recycle Servers",opt))  {
			case -1:
				return(0);
				break;
			case 0:
				sprintf(str,"%sftpsrvr.rec",cfg->ctrl_dir);
				ftouch(str);
				break;
			case 1:
				sprintf(str,"%smailsrvr.rec",cfg->ctrl_dir);
				ftouch(str);
				break;
			case 2:
				sprintf(str,"%sservices.rec",cfg->ctrl_dir);
				ftouch(str);
				break;
			case 3:
				sprintf(str,"%stelnet.rec",cfg->ctrl_dir);
				ftouch(str);
				break;
			case 4:
				sprintf(str,"%swebsrvr.rec",cfg->ctrl_dir);
				ftouch(str);
				break;
		}
	}
698
699
700
	return(0);
}

701
702
703
704
705
706
707
708
709
710
711
712
713
714
char *geteditor(char *edit)
{
	if(getenv("EDITOR")==NULL && (getenv("VISUAL")==NULL || getenv("DISPLAY")==NULL))
		strcpy(edit,"vi");
	else {
		if(getenv("DISPLAY")!=NULL && getenv("VISUAL")!=NULL)
			strcpy(edit,getenv("VISUAL"));
		else
			strcpy(edit,getenv("EDITOR"));
	}
	return(edit);
}


715
716
717
718
719
int edit_cfg(scfg_t *cfg)
{
	char**	opt;
	int		i;
	char	cmd[1024];
720
	char	editcmd[1024];
721

722
723
724
725
	const int num_opts = 16;
	if((opt=(char **)alloca(sizeof(char *)*(num_opts+1)))==NULL)
		allocfail(sizeof(char *)*(num_opts+1));
	for(i=0;i<(num_opts+1);i++)
726
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
727
728
729
			allocfail(MAX_OPLN);

	i=0;
730
	strcpy(opt[i++],"sbbs.ini");
731
	strcpy(opt[i++],"modopts.ini");
732
733
734
735
736
	strcpy(opt[i++],"alias.cfg");
	strcpy(opt[i++],"attr.cfg");
	strcpy(opt[i++],"dns_blacklist.cfg");
	strcpy(opt[i++],"dnsbl_exempt.cfg");
	strcpy(opt[i++],"domains.cfg");
737
738
	strcpy(opt[i++],"mailproc.ini");
	strcpy(opt[i++],"mime_types.ini");
739
	strcpy(opt[i++],"relay.cfg");
740
	strcpy(opt[i++],"sbbsecho.ini");
741
	strcpy(opt[i++],"../data/areas.bbs");
742
	strcpy(opt[i++],"services.ini");
743
	strcpy(opt[i++],"ftpalias.cfg");
744
	strcpy(opt[i++],"sockopts.ini");
745
746
	strcpy(opt[i++],"spambait.cfg");
	opt[i][0]=0;
747
	uifc.helpbuf= "Highlight desired file and hit Enter to edit it.";
748
749
	i=0;
	while(1) {
750
		switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Edit Config File",opt))  {
751
752
			case -1:
				return(0);
753
				break;
754
			default:
755
				sprintf(cmd,"%s %s%s",geteditor(editcmd),cfg->ctrl_dir,opt[i]);
756
757
758
759
760
761
				do_cmd(cmd);
				break;
		}
	}
	return(0);
}
762

763
764
765
766
767
int edit_can(scfg_t *cfg)
{
	char**	opt;
	int		i;
	char	cmd[1024];
768
	char	editcmd[1024];
769

770
771
772
773
	const int num_opts = 11;
	if((opt=(char **)alloca(sizeof(char *)*(num_opts+1)))==NULL)
		allocfail(sizeof(char *)*(num_opts+1));
	for(i=0;i<(num_opts+1);i++)
774
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
775
776
777
778
779
780
781
782
783
784
785
786
			allocfail(MAX_OPLN);

	i=0;
	strcpy(opt[i++],"email.can");
	strcpy(opt[i++],"file.can");
	strcpy(opt[i++],"host.can");
	strcpy(opt[i++],"ip.can");
	strcpy(opt[i++],"ip-silent.can");
	strcpy(opt[i++],"name.can");
	strcpy(opt[i++],"phone.can");
	strcpy(opt[i++],"rlogin.can");
	strcpy(opt[i++],"subject.can");
787
788
	strcpy(opt[i++],"../ctrl/twitlist.cfg");
	strcpy(opt[i++],"../ctrl/spamblock.cfg");
789
	opt[i][0]=0;
790
	uifc.helpbuf="Highlight desired file and hit Enter to edit it.";
791
792
	i=0;
	while(1) {
793
		switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,0,"Edit Filter File",opt))  {
794
795
			case -1:
				return(0);
796
				break;
797
			default:
798
				sprintf(cmd,"%s %s%s",geteditor(editcmd),cfg->text_dir,opt[i]);
799
800
801
802
803
804
				do_cmd(cmd);
				break;
		}
	}
	return(0);
}
805

806
int main(int argc, char** argv)  {
807

808
809
810
811
	char**	opt;
	char**	mopt;
	int		main_dflt=0;
	int		main_bar=0;
deuce's avatar
deuce committed
812
	char	revision[16];
813
	char	str[256],ctrl_dir[MAX_PATH + 1];
deuce's avatar
deuce committed
814
815
816
	char	title[256];
	int		i,j;
	node_t	node;
817
	int		nodefile = -1;
818
819
	box_t	boxch;
	scfg_t	cfg;
820
	int		done;
deuce's avatar
deuce committed
821
	int		ciolib_mode=CIOLIB_MODE_AUTO;
822
	time_t	last_semfile_check = time(NULL);
823
	int		idle_sleep=100;
824

deuce's avatar
deuce committed
825
826
827
	/******************/
	/* Ini file stuff */
	/******************/
828
	char	ini_file[MAX_PATH+1];
829
	FILE*				fp=NULL;
830
	bbs_startup_t		bbs_startup;
831

Rob Swindell's avatar
Rob Swindell committed
832
	sscanf("$Revision: 1.99 $", "%*s %s", revision);
833

deuce's avatar
deuce committed
834
	printf("\nSynchronet UNIX Monitor %s-%s  Copyright %s "
deuce's avatar
deuce committed
835
		"Rob Swindell\n",revision,PLATFORM_DESC,&__DATE__[7]);
836

837
	SAFECOPY(ctrl_dir, get_ctrl_dir(/* warn: */TRUE));
838
	backslash(ctrl_dir);
839

deuce's avatar
deuce committed
840
	gethostname(str,sizeof(str)-1);
841
842

	sbbs_get_ini_fname(ini_file, ctrl_dir, str);
843
844

	/* Initialize BBS startup structure */
deuce's avatar
deuce committed
845
846
	memset(&bbs_startup,0,sizeof(bbs_startup));
	bbs_startup.size=sizeof(bbs_startup);
847
	SAFECOPY(bbs_startup.ctrl_dir,ctrl_dir);
848
849
850
851
852
853

	/* 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 */
rswindell's avatar
rswindell committed
854
	sbbs_read_ini(fp, ini_file,
855
		NULL,		/* global_startup */
856
		NULL, &bbs_startup,
857
		NULL, NULL, /* ftp_startup */
858
		NULL, NULL, /* web_startup */
859
860
861
		NULL, NULL, /* mail_startup */
		NULL, NULL  /* services_startup */
		);
862
863
864
865
866
867

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

	chdir(bbs_startup.ctrl_dir);
868

869
	/* Read .cfg files here */
deuce's avatar
deuce committed
870
	memset(&cfg,0,sizeof(cfg));
871
	cfg.size=sizeof(cfg);
872
873
	SAFECOPY(cfg.ctrl_dir,bbs_startup.ctrl_dir);
	if(!load_cfg(&cfg, NULL, TRUE, str)) {
874
875
876
		printf("ERROR! %s\n",str);
		exit(1);
	}
877
	prep_dir(cfg.data_dir, cfg.temp_dir, sizeof(cfg.temp_dir));
878

deuce's avatar
deuce committed
879
	memset(&uifc,0,sizeof(uifc));
880
	uifc.mode|=UIFC_NOCTRL;
881
882
883

	uifc.esc_delay=500;

deuce's avatar
deuce committed
884
885
886
887
888
889
890
891
	boxch.ls=(char)186;
	boxch.rs=(char)186;
	boxch.ts=(char)205;
	boxch.bs=(char)205;
	boxch.tl=(char)201;
	boxch.tr=(char)187;
	boxch.bl=(char)200;
	boxch.br=(char)188;
892
	for(i=1;i<argc;i++) {
deuce's avatar
deuce committed
893
894
895
896
897
898
899
900
901
902
903
		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;
904
905
906
				case 'S':
					idle_sleep=atoi(argv[i]+2);
					break;
907
				case 'I':
deuce's avatar
deuce committed
908
909
910
911
912
913
914
915
					switch(toupper(argv[i][2])) {
						case 'A':
							ciolib_mode=CIOLIB_MODE_ANSI;
							break;
						case 'C':
							ciolib_mode=CIOLIB_MODE_CURSES;
							break;
						case 0:
916
							printf("NOTICE: The -i option is deprecated, use -if instead\n");
deuce's avatar
deuce committed
917
918
919
920
							SLEEP(2000);
						case 'F':
							ciolib_mode=CIOLIB_MODE_CURSES_IBM;
							break;
921
922
923
						case 'I':
							ciolib_mode=CIOLIB_MODE_CURSES_ASCII;
							break;
deuce's avatar
deuce committed
924
925
926
927
928
929
930
931
932
						case 'X':
							ciolib_mode=CIOLIB_MODE_X;
							break;
						case 'W':
							ciolib_mode=CIOLIB_MODE_CONIO;
							break;
						default:
							goto USAGE;
					}
933
					break;
deuce's avatar
deuce committed
934
935
				default:
USAGE:
936
					printf("\nusage: %s [ctrl_dir] [options]\n"
deuce's avatar
deuce committed
937
938
939
					         "options:\n\n"
					         "-c  =  force color mode\n"
					         "-e# =  set escape delay to #msec\n"
940
					         "-iX =  set interface mode to X (default=auto) where X is one of:\n"
deuce's avatar
deuce committed
941
#ifdef __unix__
942
943
944
945
					         "       X = X11 mode\n"
					         "       C = Curses mode\n"
					         "       F = Curses mode with forced IBM charset\n"
							 "       I = Curses mode with forced ASCII charset\n"
deuce's avatar
deuce committed
946
#else
947
					         "       W = Win32 native mode\n"
deuce's avatar
deuce committed
948
#endif
949
					         "       A = ANSI mode\n"
deuce's avatar
deuce committed
950
					         "-l# =  set screen lines to #\n"
Rob Swindell's avatar
Rob Swindell committed
951
					         "-s# =  set idle slsep to # milliseconds (default: %d)\n"
deuce's avatar
deuce committed
952
953
954
955
956
957
					    ,argv[0]
					    ,idle_sleep
					);
					exit(0);
			}
	}
958

deuce's avatar
deuce committed
959
#ifdef SIGPIPE
960
	signal(SIGPIPE, SIG_IGN);
deuce's avatar
deuce committed
961
#endif
962

963
	uifc.size=sizeof(uifc);
deuce's avatar
deuce committed
964
965
	i=initciolib(ciolib_mode);
	if(i!=0) {
deuce's avatar
deuce committed
966
967
		printf("ciolib library init returned error %d\n",i);
		exit(1);
deuce's avatar
deuce committed
968
	}
deuce's avatar
deuce committed
969
	i=uifcini32(&uifc);  /* curses */
970
971
972
973
974
	if(i!=0) {
		printf("uifc library init returned error %d\n",i);
		exit(1);
	}

975
976
977
978
	const int main_menu_opts = 11;
	if((opt=(char **)alloca(sizeof(char *)*(main_menu_opts+1)))==NULL)
		allocfail(sizeof(char *)*(main_menu_opts+1));
	for(i=0;i<(main_menu_opts+1);i++)
979
		if((opt[i]=(char *)alloca(MAX_OPLN))==NULL)
980
981
			allocfail(MAX_OPLN);

deuce's avatar
deuce committed
982
983
984
	if((mopt=(char **)alloca(sizeof(char *)*cfg.sys_nodes+2))==NULL)
		allocfail(sizeof(char *)*cfg.sys_nodes+2);
	for(i=0;i<cfg.sys_nodes+2;i++)
985
		if((mopt[i]=(char *)alloca(MAX_OPLN))==NULL)
986
987
			allocfail(MAX_OPLN);

988
989
	sprintf(title,"Synchronet UNIX Monitor %s-%s",revision,PLATFORM_DESC);
	if(uifc.scrn(title)) {
990
991
992
993
		printf(" USCRN (len=%d) failed!\n",uifc.scrn_len+1);
		bail(1);
	}

994
	int paging_node = 0;
995
	while(1) {
996
		strcpy(mopt[0],"System Options");
997
		for(i=1;i<=cfg.sys_nodes;i++) {
998
			if((j=getnodedat(&cfg,i,&node,FALSE,NULL)))
999
				sprintf(mopt[i],"Error reading node data (%d)!",j);
1000
			else {
For faster browsing, not all history is shown. View entire blame