/*****************************************************************************
 *
 * File ..................: mbmon/mbmon.c
 * Purpose ...............: Monitor Program 
 * Last modification date : 13-Nov-1999
 * Todo ..................: Trace logfiles
 *                          Chat with user via server
 *
 *****************************************************************************
 * Copyright (C) 1997-1999
 *   
 * Michiel Broek		FIDO:		2:2801/16
 * Beekmansbos 10		Internet:	mbroek@ux123.pttnwb.nl
 * 1971 BV IJmuiden
 * the Netherlands
 *
 * This file is part of MBSE BBS.
 *
 * This BBS 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, or (at your option) any
 * later version.
 *
 * MB BBS is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with MB BBS; see the file COPYING.  If not, write to the Free
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *****************************************************************************/

#define	DB_LASTCALL
#define	DB_SYSINFO

#include "../include/libs.h"
#include "../include/structs.h"
#include "../include/records.h"
#include "../common/common.h"
#include "screen.h"
#include "mutil.h"
#include "ledit.h"
#include "../dbase/dbcfg.h"




static void die(int onsig)
{
	signal(onsig, SIG_IGN);
	screen_stop(); 
	if (onsig && (onsig <= NSIG))
		WriteError("$Finished on signal %s", SigName[onsig]);
	else
		Syslog(' ', "Normally finished");
	ExitClient(0);
}



void ShowSysinfo(void)
{
	int	ch;
	FILE	*fil;
	char	temp[81];

	clr_index();
	working(1, 1, 1);
	IsDoing("Show System Info");
	LoadConfig();

	sprintf(temp, "%s/etc/sysinfo.data", getenv("MBSE_ROOT"));
	if ((fil = fopen(temp, "r")) == NULL) {
		working(2, 0, 0);
		return;
	}
	fclose(fil);
	working(0, 0, 0);

	clr_index();
	set_color(WHITE, BLACK);
	mvprintw( 5, 6, "4.   SHOW BBS SYSTEM INFO");
	set_color(CYAN, BLACK);
	mvprintw( 7, 6, "1.   Total calls");
	mvprintw( 8, 6, "2.   Pots calls");
	mvprintw( 9, 6, "3.   ISDN calls");
	mvprintw(10, 6, "4.   Network calls");
	mvprintw(11, 6, "5.   Local calls");
	mvprintw(12, 6, "6.   Date started");
	mvprintw(13, 6, "7.   Last caller");
	center_addstr(LINES - 4, (char *)"Press any key");
	IsDoing("View System Info");

	do {
		show_date(LIGHTGRAY, BLACK, 0, 0);
		set_color(LIGHTGRAY, BLACK);
		fil = fopen(temp, "r");
		fread(&SYSINFO, sizeof(SYSINFO), 1, fil);
		fclose(fil);
		show_int( 7,26, SYSINFO.SystemCalls);
		show_int( 8,26, SYSINFO.Pots);
		show_int( 9,26, SYSINFO.ISDN);
		show_int(10,26, SYSINFO.Network);
		show_int(11,26, SYSINFO.Local);
		mvprintw(12,26, (char *)"%s", ctime(&SYSINFO.StartDate));
		show_str(13,26,35, SYSINFO.LastCaller);
		fflush(stdout);
		ch = testkey(LINES - 4, COLS / 2 + 8);
	} while (ch == '\0');
}



void ShowLastcaller(void)
{
	int	records, i, y, o;
	char	pick[12];
	FILE	*fil;
	char	temp[121];
	long	offset;
	char	action[8];

	clr_index();
	working(1, 0, 0);
	IsDoing("Show Lastcallers");
	LoadConfig();

	sprintf(temp, "%s/etc/lastcall.data", getenv("MBSE_ROOT"));
	if ((fil = fopen(temp, "r")) == NULL) {
		working(2, 0, 0);
		return;
	}
	records = 0;
	fread(&LCALLhdr, sizeof(LCALLhdr), 1, fil);
	while (fread(&LCALL, LCALLhdr.recsize, 1, fil) == 1)
		records++;

	working(0, 0, 0);
	o = 0;

	for (;;) {
		clr_index();
		set_color(WHITE, BLACK);
		mvprintw( 4, 6, "5.    SHOW BBS LASTCALLERS");
		set_color(YELLOW, RED);
		mvprintw( 6, 1, "Nr Username       Location     Level Device Time   Mins Calls Speed     Actions");
		set_color(CYAN, BLACK);
		if (records != 0) {
			working(1, 0, 0);
			y = 7;
			set_color(CYAN, BLACK);
			for (i = 1; i <= 10; i++) {
				if ((o + i) <= records) {
					offset = sizeof(LCALLhdr) + (((o + i) - 1) * LCALLhdr.recsize);
					fseek(fil, offset, 0);
					fread(&LCALL, LCALLhdr.recsize, 1, fil);
					LCALL.UserName[15] = '\0';
					LCALL.Location[12] = '\0';
					strcpy(action, "-------");
					if (LCALL.Hidden)
						action[0] = 'H';
					if (LCALL.Download)
						action[1] = 'D';
					if (LCALL.Upload)
						action[2] = 'U';
					if (LCALL.Read) 
						action[3] = 'R';
					if (LCALL.Wrote)
						action[4] = 'W';
					if (LCALL.Chat)
						action[5] = 'C';
					if (LCALL.Olr)
						action[6] = 'O';
					sprintf(temp, "%2d %-14s %-12s %5d %-6s %s %4d %5d %-9s %s", 
						o + i, LCALL.UserName, LCALL.Location, LCALL.SecLevel, LCALL.Device, str_time(atoi(LCALL.TimeOn)), LCALL.CallTime, LCALL.Calls, LCALL.Speed, action);
					temp[81] = '\0';
					mvprintw(y, 1, temp);
					y++;
				}
			}
		}
		working(0, 0, 0);
		strcpy(pick, select_show(records));
		
		if (strncmp(pick, "-", 1) == 0) {
			fclose(fil);
			return;
		}

		if (strncmp(pick, "N", 1) == 0)
			if ((o + 10) < records)
				o = o + 10;

		if (strncmp(pick, "P", 1) == 0)
			if ((o - 10) >= 0)
				o = o - 10;
	}
}



void system_moni(void)
{
	int ch, y, eof;
	char *cnt;
	char buf[128];
	time_t start, now;

	clr_index();
	set_color(WHITE, BLACK);
	mvprintw( 5, 6, "1.    SERVER CLIENTS");
	set_color(YELLOW, RED);
	mvprintw( 7, 1, "Pid   tty    user             program  city            doing              time ");
	set_color(CYAN, BLACK);
	center_addstr(LINES - 4, (char *)"Press any key");
	IsDoing("System Monitor");

	do {
		show_date(LIGHTGRAY, BLACK, 0, 0);

		eof = 0;
		set_color(LIGHTGRAY, BLACK);

		for (y = 8; y <= LINES - 5; y++) { 
			if (y == 8)
				sprintf(buf, "GMON:0;");
			else
				sprintf(buf, "GMNE:0;");
			if (eof == 0) {
				if (socket_send(buf) == 0) {
					strcpy(buf, socket_receive());
					locate(y, 1);
					clrtoeol();
					if (strncmp(buf, "301", 3) == 0) {
						/* There's no more information 
						 */
						eof = 1;
					} else {
						cnt = strtok(buf, ",");
						mvprintw(y, 1, (char *)"%.5s", strtok(NULL, ","));
						mvprintw(y, 7, (char *)"%.6s", strtok(NULL, ","));
						mvprintw(y,14, (char *)"%.16s", strtok(NULL, ","));
						mvprintw(y,31, (char *)"%.8s", strtok(NULL, ","));
						mvprintw(y,40, (char *)"%.15s", strtok(NULL, ","));
						mvprintw(y,56, (char *)"%.18s", strtok(NULL, ","));
						start = atoi(strtok(NULL, ";"));
						now = time(NULL);
						mvprintw(y,75, (char *)"%s", t_elapsed(start, now));
					}
				}
			} else {
				/*
				 *  If no valid data, clear line
				 */
				locate(y, 1);
				clrtoeol();
			}
		} /* for () */

		ch = testkey(LINES - 4, COLS / 2 + 8);
	} while (ch == '\0');
}



void system_stat(void)
{
	int ch;
	char buf[256];
	char *cnt;
	time_t now;

	clr_index();
	set_color(WHITE, BLACK);
	mvprintw( 5, 6, "2.    SERVER STATISTICS");
	set_color(CYAN, BLACK);
	mvprintw( 7, 6, "First date started");
	mvprintw( 7,62, "BBS Open");
	mvprintw( 8, 6, "Last date started");
	mvprintw( 8,62, "ZMH");
	mvprintw( 9, 6, "Total server starts");
	mvprintw(10, 6, "Connected clients");
	mvprintw(12,30, "Total          Today");
	hor_lin(13,30,8);
	hor_lin(13,45,8);
	mvprintw(14, 6, "Client connects");
	mvprintw(15, 6, "Peak connections");
	mvprintw(16, 6, "Protocol syntax errors");
	mvprintw(17, 6, "Communication errors");
	mvprintw(19, 6, "Next sequence number");
	mvprintw(LINES - 4, 61, "Press any key");
	IsDoing("System Statistics");

	do {
		show_date(LIGHTGRAY, BLACK, 0, 0);

		sprintf(buf, "GSTA:0;");
		if (socket_send(buf) == 0) {
			strcpy(buf, socket_receive());
			set_color(LIGHTGRAY, BLACK);
			cnt = strtok(buf, ",");
			now = atoi(strtok(NULL, ","));
			show_str(7,30,24, ctime(&now));
			now = atoi(strtok(NULL, ","));
			show_str(8,30,24, ctime(&now));
			cnt = strtok(NULL, ",");
			mvprintw(9, 30, (char *)"%s ", strtok(NULL, ","));
			mvprintw(10,30, (char *)"%s ", strtok(NULL, ","));
			mvprintw(14,30, (char *)"%s ", strtok(NULL, ","));
			mvprintw(15,30, (char *)"%s ", strtok(NULL, ","));
			mvprintw(16,30, (char *)"%s ", strtok(NULL, ","));
			mvprintw(17,30, (char *)"%s ", strtok(NULL, ","));
			mvprintw(14,45, (char *)"%s ", strtok(NULL, ","));
			mvprintw(15,45, (char *)"%s ", strtok(NULL, ","));
			mvprintw(16,45, (char *)"%s ", strtok(NULL, ","));
			mvprintw(17,45, (char *)"%s ", strtok(NULL, ","));
			if (atoi(strtok(NULL, ",")) == 1)
				mvprintw(7,72, "Yes");
			else
				mvprintw(7,72, "No ");
			if (atoi(strtok(NULL, ",")) == 1)
				mvprintw(8,72, "Yes");
			else
				mvprintw(8,72, "No ");
			mvprintw(19,30, (char *)"%s", strtok(NULL, ";"));
		}

		ch = testkey(LINES - 4, 75);
	} while (ch == '\0');
}



void disk_stat(void)
{
	int	ch, i;
	char	buf[1024];
	char	*cnt, *type, *fs, *p;
	long	last[10];
	long	size, used, perc;
	char	sign;

	clr_index();
	set_color(WHITE, BLACK);
	mvprintw( 5, 6, "3.    FILESYSTEM USAGE");
	set_color(YELLOW, RED);
	mvprintw( 7, 1, "  Disksize        Used     Perc.  FS-Type   Mountpoint                        ");
	set_color(CYAN, BLACK);
	mvprintw(LINES - 2, 6, "Press any key");
	IsDoing("Filesystem Usage");

	do {
		show_date(LIGHTGRAY, BLACK, 0, 0);

		sprintf(buf, "GDST:0;");
		if (socket_send(buf) == 0) {
			strcpy(buf, socket_receive());
			set_color(LIGHTGRAY, BLACK);
			cnt = strtok(buf, ":");
			cnt = strtok(NULL, ",;");
			if (atoi(cnt)) {
				for (i = 0; i < atoi(cnt); i++) {
					p = strtok(NULL, " ");
					size = atoi(p);
					p = strtok(NULL, " ");
					used = size - atoi(p);
					perc = (used * 100) / size;
					sign = ' ';
					fs = strtok(NULL, " ");
					type = strtok(NULL, ",;");
					if (used > last[i])
						sign = '^';
					if (used < last[i])
						sign = 'v';
					if (last[i] == 0)
						sign = ' ';
					last[i] = used;
					set_color(CYAN, BLACK);
					mvprintw(i+8, 1, "%10lu  %10lu  ", 
							size, used);
					set_color(WHITE, BLACK);
					printf("%c  ", sign);
					set_color(CYAN, BLACK);
					if (strstr(type, "iso") == NULL) {
						if (perc >= 95)
							set_color(LIGHTRED, BLACK);
						else if (perc >= 80)
							set_color(YELLOW, BLACK);
					}
					printf("%3lu", perc);
					putchar('%');
					set_color(CYAN, BLACK);
					printf("   %-8s  %-35s", type, fs);
				}
				locate(i+8, 1);
				clrtoeol();
			}
		}

		ch = testkey(LINES - 2, 20);
	} while (ch == '\0');
}



void soft_info(void)
{
	clr_index();
	set_color(YELLOW, BLACK);
	center_addstr( 7, (char *)"MBSE BBS");
	set_color(WHITE, BLACK);
	center_addstr( 9, (char *)Copyright);
	set_color(YELLOW, BLACK);
	center_addstr(11, (char *)"Made in the Netherlands");
	set_color(LIGHTGREEN, BLACK);
	center_addstr(LINES -8, (char *)"This is free software; released under the terms of the GNU General");
	center_addstr(LINES -7, (char *)"Public License as published by the Free Software Foundation.");
	set_color(CYAN, BLACK);
	center_addstr(LINES -4, (char *)"Press any key");
	readkey(LINES - 4, COLS / 2 + 8, LIGHTGRAY, BLACK);
}



int main(int argc, char *argv[])
{
	struct passwd	*pw;

	/*
	 * Read configuration and connect with the mbsed server.
	 */
	InitConfig();

	/*
	 * Find out who is on the keyboard or automated the keyboard.
	 */
	pw = getpwuid(getuid());
	InitClient(pw->pw_name, (char *)"mbmon", (char *)"nowhere", (char *)"mbmon.log", 0xf);
	Syslog(' ', "Started by %s", pw->pw_name);

	/*
	 * Setup several signals so when the program terminate's it
	 * will properly close the curses screens.
	 */
	signal(SIGINT, (void (*))die);
	signal(SIGBUS, (void (*))die);
	signal(SIGSEGV,(void (*))die);
	signal(SIGTERM,(void (*))die);
	signal(SIGKILL,(void (*))die);

	screen_start((char *)"MBmon");

	for (;;) {

		IsDoing("Browsing Menu");
		clr_index();
		set_color(WHITE, BLACK);
		mvprintw( 5, 6, "0.    MBSE BBS MONITOR");
		set_color(CYAN, BLACK);
		mvprintw( 7, 6, "1.    View Server Clients");
		mvprintw( 8, 6, "2.    View Server Statistics");
		mvprintw( 9, 6, "3.    View Filesystem Usage");
		mvprintw(10, 6, "4.    View System Logfiles");
		mvprintw(11, 6, "5.    View BBS System Information");
		mvprintw(12, 6, "6.    View BBS Lastcallers List");
		mvprintw(13, 6, "7.    View Software Information");

		switch(select_menu(7)) {
		case 0:
			die(0);
			break;
		case 1:
			system_moni();
			break;
		case 2:
			system_stat();
			break;
		case 3:
			disk_stat();
			break;
		case 5:
			ShowSysinfo();
			break;
		case 6:
			ShowLastcaller();
			break;
		case 7:
			soft_info();
			break;
		}
	}
}

