/*
 * Copyright (c) 2001 Hellmuth Michaelis. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *---------------------------------------------------------------------------
 *
 *	nifmon - curses fullscreen output
 *	---------------------------------
 *
 *      last edit-date: [Sun Sep  9 11:53:51 2001]
 *
 *---------------------------------------------------------------------------*/

#include "nifmon.h"

/*---------------------------------------------------------------------------*
 *	init curses fullscreen display
 *---------------------------------------------------------------------------*/
void
init_screen(char *interface)
{
	char buffer[512];
	int uheight, lheight;

	initscr();		/* curses init */

	if ((COLS < 80) || (LINES < 24))
	{
		endwin();
		fprintf(stderr,
			"ERROR, minimal screensize must be 80x24, is %dx%d, terminating!",
			COLS, LINES);
		do_exit(1);
	}

	noecho();
	raw();

	uheight = 10;

	if ((upper_w = newwin(uheight, COLS, 0, 0)) == NULL)
	{
		endwin();
		fprintf(stderr,
			"ERROR, curses init upper window, terminating!");
		do_exit(1);
	}

	lheight = LINES - uheight;	/* rest of display */

	if ((lower_w = newwin(lheight, COLS, 0 + uheight, 0)) == NULL)
	{
		endwin();
		fprintf(stderr,
			"ERROR, curses init lower window, LINES = %d, lheight = %d, uheight = %d, terminating!",
			LINES, lheight, uheight);
		do_exit(1);
	}

	scrollok(lower_w, 1);

	sprintf(buffer,	"----- network interface monitor (%d.%d) ---------------- %s -", VERSION, RELEASE, interface);

	while (strlen(buffer) < COLS)
		strcat(buffer, "-");

	wmove(upper_w, 0, 0);
	wstandout(upper_w);
	waddstr(upper_w, buffer);
	wstandend(upper_w);

	wmove(upper_w, 1, 0);
	/*                01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
	if (if_flags & IFF_POINTOPOINT)
		waddstr(upper_w, "addr:                                                      dst:                ");
	else
		waddstr(upper_w, "addr:                                                      brc:                ");

	wmove(upper_w, 2, 0);
	/*                01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
	waddstr(upper_w, "chg:                                                                           ");
	wmove(upper_w, 3, 0);
	/*                01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
	waddstr(upper_w, "  bytes in:                               bytes out:                           ");
	wmove(upper_w, 4, 0);
	waddstr(upper_w, "packets in:                             packets out:                           ");
	wmove(upper_w, 5, 0);
	waddstr(upper_w, " inbytes/h: -                  inbytes/m: -                inbytes/s: -        ");
	wmove(upper_w, 6, 0);
	waddstr(upper_w, "outbytes/h: -                 outbytes/m: -               outbytes/s: -        ");
	wmove(upper_w, 7, 0);
	waddstr(upper_w, "  inpkts/h: -                   inpkts/m: -                 inpkts/s: -        ");
	wmove(upper_w, 8, 0);
	waddstr(upper_w, " outpkts/h: -                  outpkts/m: -                outpkts/s: -        ");

	wmove(upper_w, 9, 0);
	sprintf(buffer, "----- tcpdump output --------------------------------------------------");
	while (strlen(buffer) < COLS)
		strcat(buffer, "-");

	wstandout(upper_w);
	waddstr(upper_w, buffer);
	wstandend(upper_w);

	leaveok(upper_w, 1);
	leaveok(lower_w, 1);

	refresh();

	wrefresh(upper_w);

	wmove(lower_w, 0, 0);
	wrefresh(lower_w);

	curses_ready = 1;
}

/*---------------------------------------------------------------------------*
 *	curses menu for fullscreen command mode
 *---------------------------------------------------------------------------*/
void
do_menu(void)
{
	static char *menu[WMITEMS] = {
		"1 - (D)isplay refresh",
		"2 - (Q)uit the program",
	};

	WINDOW *menu_w;
	int c;
	int mpos;
	fd_set set;
	struct timeval timeout;

	/* create a new window in the lower screen area */

	if ((menu_w = newwin(WMENU_HGT, WMENU_LEN, WMENU_POSLN, WMENU_POSCO)) == NULL)
		return;

	/* create a border around the window */

	box(menu_w, '|', '-');

	/* add a title */

	wstandout(menu_w);
	mvwaddstr(menu_w, 0, (WMENU_LEN / 2) - (strlen(WMENU_TITLE) / 2), WMENU_TITLE);
	wstandend(menu_w);

	/* fill the window with the menu options */

	for (mpos = 0; mpos <= (WMITEMS - 1); mpos++)
		mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);

	/* highlight the first menu option */

	mpos = 0;
	wstandout(menu_w);
	mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
	wstandend(menu_w);

	/* input loop */

	for (;;)
	{
		wrefresh(menu_w);

		FD_ZERO(&set);
		FD_SET(STDIN_FILENO, &set);
		timeout.tv_sec = WMTIMEOUT;
		timeout.tv_usec = 0;

		/* if no char is available within timeout, exit menu */

		if ((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0)
			goto mexit;

		c = wgetch(menu_w);

		switch (c)
		{
			case ' ':
			case '\t':	/* hilite next option */
				mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
				mpos++;
				if (mpos >= WMITEMS)
					mpos = 0;
				wstandout(menu_w);
				mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]);
				wstandend(menu_w);
				break;

			case ('0' + WREFRESH + 1):	/* display refresh */
			case 'D':
			case 'd':
				wrefresh(curscr);
				goto mexit;

			case ('0' + WQUIT + 1):	/* quit program */
			case 'Q':
			case 'q':
				do_exit(0);
				goto mexit;


			case '\n':
			case '\r':	/* exec highlighted option */
				switch (mpos)
				{
					case WREFRESH:
						wrefresh(curscr);
						break;

					case WQUIT:
						do_exit(0);
						break;
				}
				goto mexit;
				break;

			default:
				goto mexit;
				break;
		}
	}

mexit:
	/* delete the menu window */

	delwin(menu_w);

	/* re-display the original lower window contents */

	touchwin(lower_w);
	wrefresh(lower_w);
}

/*---------------------------------------------------------------------------*
 *	data from keyboard available, read and process it 
 *---------------------------------------------------------------------------*/
void
kbdrdhdl(void)
{
	int ch = getch();

	switch (ch)
	{
		case 0x0c:	/* control L */
			wrefresh(curscr);
			break;

		case 0x03:	/* control C */
			do_exit(0);
			break;

		case '\n':
		case '\r':
			do_menu();
			break;
	}
}

/*---------------------------------------------------------------------------*
 *	remove string from buffer
 *---------------------------------------------------------------------------*/
static void sremove(char *buffer, char *string)
{
	char *p;

	p = strstr(buffer, string);

	if(p)
	{
		bcopy(p+strlen(string), p, 1+strlen(p+strlen(string)) );
	}
}

/*---------------------------------------------------------------------------*
 *	remove bytes from buffer start at from with length l
 *---------------------------------------------------------------------------*/
static void sremovefl(char *buffer, int f, int l)
{
	bcopy(buffer+f+l, buffer+f, 1+strlen(buffer+f+l));
}

#ifdef nowineedthis
/*---------------------------------------------------------------------------*
 *	replace in buffer string from with string to
 *---------------------------------------------------------------------------*/
static void sreplace(char *buffer, char *from, char *to)
{
	char *p;

	p = strstr(buffer, from);

	if(p)
	{
		bcopy(to, p, strlen(to));
		bcopy(p+strlen(from), p+strlen(to), 1+strlen(p+strlen(from)));
	}
}
#endif

/*---------------------------------------------------------------------------*
 *	data from tcpdump available, read (as much as possible) and print
 *---------------------------------------------------------------------------*/

#define PBS 1024

void
loghdl(FILE *fp)
{
	char *p;
	fd_set set;
	struct timeval timeout;
	char buffer[PBS];

	if ((fgets(buffer, PBS, fp)) == NULL)
		return;

	timeout.tv_sec = 0;
	timeout.tv_usec = 0;
	
	for(;;)
	{
		/* check if the line has a time stamp, if yes, we display it */

		if(buffer[2] == ':' && buffer[5] == ':')
		{
			/* remove date */
			sremovefl(buffer, 8, 7);

			/* remove our own hostname */		
			sremove(buffer, hostname);

			/* remove more useless stuff */
			sremove(buffer, " [tcp sum ok]");
			sremove(buffer, " [udp sum ok]");

			/* remove newline */
			p = index(buffer, '\n');
			if(p != NULL)
				*p = '\0';

			/* check for and enforce max length */
			*(buffer+COLS-1) = '\0';

			/* print line */
			wprintw(lower_w, "\n%s", buffer);
		}

		/* check for more data from tcpdump */

		FD_ZERO(&set);
		FD_SET(fileno(fp), &set);

		if((select((fileno(fp))+1, &set, NULL, NULL, &timeout)) <= 0)
			break;		/* no data, exit loop */
		fgets(buffer, PBS, fp); /* more data, continue looping */
	}
	wrefresh(lower_w);
}

/* EOF */


syntax highlighted by Code2HTML, v. 0.9.1