⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sntop.c

📁 sntop是一个基于curses的控制台工具
💻 C
字号:
/* * sntop - simple network top - a top-like console network status tool * sntop.c * 04.30.2000 - 03.21.2001 * * robert m love	<rml@tech9.net> * chris m rivera	<cmrivera@ufl.edu> * * http://sntop.sourceforge.net - homepage * ftp://sntop.sourceforge.net/pub/sntop/ - anon ftp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, v2, as * published by the Free Software Foundation * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Copyright (C) 2001 Robert M. Love and Christopher M. Rivera * * All code by the above authors unless otherwise specified. */#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/time.h>#include <fcntl.h>#include <string.h>#include <errno.h> 		#include <signal.h>		#include <ncurses.h>#if HAVE_SYS_WAIT_H#include <sys/wait.h>#endif /* HAVE_SYS_WAIT_H */#ifndef WEXITSTATUS#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)#endif /* WEXITSTATUS */#ifndef WIFEXITED#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)#endif /* WIFEXITED */#if HAVE_GETOPT_LONG#include <getopt.h>#else#include "getopt_long.h"#endif /* HAVE_GETOPT_LONG */#include "sntop.h"#define SNTOP_VERSION "sntop v1.4.3"int main(int argc, char *argv[]){	char up_status[] = UP;	char down_status[] = DOWN;	char buf[IN_BUF + PING_BUF + PEND_BUF];	char cfile[CONF_BUF];	char hfile[CONF_BUF] = HTML_FILE;	/* Default to FPING_LINE */	char ping[PING_BUF + 1] = FPING_LINE;	char action[ACTION_BUF];	char ch;	FILE *hf = NULL;	fd_set readfds;	struct timeval timeout;	hdc *head = NULL, *current = NULL;	unsigned int up;	unsigned int refresh = REFRESH_TIME;	unsigned int i;	unsigned short int val;	unsigned int bold_attribute = 0; /* no bold if no color */	unsigned short flags = DO_COLOR;	struct option longopts[] = {		{ "once", 0, 0, 'o' },		{ "nocolor", 0, 0, 'c' },		{ "ping", 0, 0, 'p' },		{ "html", 0, 0, 'w' },		{ "secure", 0, 0, 's' },		{ "wfile", 1, 0, 'e' },		{ "refresh", 1, 0, 'r' },		{ "version", 0, 0, 'v' },		{ "help", 0, 0, 'h' },		{ "conf", 1, 0, 'f' },		{ "alarm", 1, 0, 'a' },		{ "log", 1, 0, 'l' },		{ "byte", 1, 0, 'b' },		{ "daemon", 0, 0, 'd' }, 		{ 0, 0, 0, 0 }	};			/* we need to construct the user's home, for the conf file, now,	   so we can change it with -f in the following getopt loop */	snprintf(cfile, CONF_BUF, "%s%s", getenv("HOME"), CONF_UFILE);	while((i = getopt_long(argc, argv, "docpwse:f:r:vhb:a:l:", longopts, (int *) 0)) != -1) {		switch(i) {			case 'd':				flags ^= DAEMON;				break;			case 'o':				flags ^= DO_ONCE;				refresh = 0;				break;			case 'c':				flags ^= DO_COLOR;				break;			case 'p':				strcpy(ping, PING_LINE);				break;			case 'w':				flags ^= DO_HTML;				break;			case 's':				flags ^= SECURE_MODE;				break;			case 'e':				strncpy(hfile, optarg, CONF_BUF);				break;			case 'f':				strncpy(cfile, optarg, CONF_BUF);				break;			case 'r':				refresh = atoi(optarg);				break;			case 'a':				flags ^= DO_ALARM;				strncpy(action, optarg, ACTION_BUF);				break;			case 'l':				flags ^= DO_LOG;				strncpy(action, optarg, ACTION_BUF);				break;			case 'v':				printf("\r" SNTOP_VERSION);			       	printf(" - a top-like console network status monitor\n" SNTOP_AUTHORS "\n");				exit(EXIT_SUCCESS);				break;			case 'b':				snprintf(ping, PING_BUF, "fping -r 1 -b %d -q", atoi(optarg));				break;			case ':': case '?': case 'h':				printf("\r" SNTOP_VERSION ": " SNTOP_AUTHORS "\n\n");				printf("Usage: %s [FLAG(S)...]\n\n", argv[0]);				printf(" -d, --daemon           allow use as a daemon\n");				printf(" -o, --once		poll and display once, then exit\n");				printf(" -c, --nocolor		disable use of ncurses' color\n");				printf(" -p, --ping		use 'ping' in lieu of 'fping'. MUCH SLOWER!\n");				printf(" -w, --html		generate html output of results\n");				printf(" -s, --secure		secure mode: interactive commands are disabled\n");				printf(" -e, --wfile=file	output html to <file> instead of " HTML_FILE "\n");				printf(" -f, --conf=file	read conf data from <file> instead of ~" CONF_UFILE ".\n");				printf("			note, sntop will still try to read from\n");				printf("			%s if <file> fails\n", CONF_SFILE);				printf(" -r, --refresh=time	refresh every <time> seconds instead of every %d\n", REFRESH_TIME);				printf(" -a, --alarm=action	when a site goes down, execute action\n");				printf(" -l, --log=action	when a site changes status, execute action\n");				printf(" -b, --byte=bytes	bytes of ping data to send\n");				printf(" -v, --version		display version information and exit\n");				printf(" -h, --help		display this help and exit\n");				printf("\nSee 'man sntop'\n");				exit(EXIT_SUCCESS);				break;		}	}		signal(SIGINT, aborted);	load_config(cfile, &head);	if (!(flags & DAEMON)) {		printf(SNTOP_VERSION " - loading ... ");		initscr();		/* color code orig. by Ron Cooper <rcooper@crstexas.com> 20001024 */		if ((flags & DO_COLOR) && has_colors()) {			start_color();			bold_attribute = A_BOLD;			/* remap all colors onto a black background */			init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);			init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);			init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);			init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);			init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);			init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);			init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);			init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK); 		}		attrset(COLOR_PAIR(COLOR_YELLOW) | bold_attribute);		printw("(sntop) simple network top\n");		standout();		printw("%-16s  %-12s  %-32s\n", "HOST", "STATUS", "COMMENT");		standend();	}	do {		if (!(flags & DAEMON)) {			move(2, 0);			clrtobot();		}			current = head;		i = up = 0;		if (flags & DO_HTML) start_html(hfile, &hf, refresh);		do {			sprintf(buf, "%s %s %s", ping, current->host, PING_END);			val = sntop_exec(buf);			if (val == 127) {				abortion("error, execution of (f)ping failed", 6);			} else if (val == 0) {				/* site is up */				if ((flags & DO_LOG) && (current->status == down_status))					exec_alarm(action, current->name, current->host, up_status);				current->status = up_status;				if (!(flags & DAEMON)) attrset(COLOR_PAIR(COLOR_GREEN) | bold_attribute);				up++;			} else {				/* site is down */				if (((flags & DO_ALARM) || (flags & DO_LOG))				    && (current->status == up_status))					exec_alarm(action, current->name, current->host, down_status);				current->status = down_status;				if (!(flags & DAEMON)) attrset(COLOR_PAIR(COLOR_RED) | bold_attribute);			}			if (!(flags & DAEMON)) printw("%-16s  %-12s  %-32s\n", current->name, current->status, current->note);			if (flags & DO_HTML) add_html(hf, current->name, current->status, current->note);			i++;			current = current->next;		} while(current->next != NULL);		if (!(flags & DAEMON)) {			attrset(COLOR_PAIR(COLOR_CYAN) | bold_attribute);			printw("\n\n%u hosts polled: %u up, %u down", i, up, i - up);			attrset(COLOR_PAIR(COLOR_YELLOW) | bold_attribute);			refresh();		}		if (flags & DO_HTML) end_html(hf, i, up);				if (!(flags & DAEMON)) {			/* we use select() to sleep for REFRESH seconds or until a key is pressed */			FD_ZERO(&readfds);			FD_SET(0, &readfds);			timeout.tv_sec = refresh; 			timeout.tv_usec = 0;			if (select(1, &readfds, NULL, NULL, &timeout) > 0) {				if (read(0, &ch, 1) != 1)					abortion("error, stdin cannot be read", 4);				if (!(flags & SECURE_MODE)) {					switch (ch) {						case 'q':							flags ^= DO_ONCE;							break;						case 'r':							printw("\nreloading conf data...");							refresh();							load_config(cfile, &head);							printw("done\nrefreshing...");							refresh();							break;						case 'w':							flags ^= DO_HTML;							load_config(cfile, &head);							printw("\nhtml generation toggled %s",								(flags & DO_HTML) ? "ON" : "OFF");							refresh();							break;						default:							printw("\nrefreshing...");							refresh();					}				}			}		}		else sleep(refresh);	} while(!(flags & DO_ONCE));	if (!(flags & DAEMON)) endwin();	exit(EXIT_SUCCESS);}/* * a replacement for my nemesis, fgets() ... reads from f into s, stopping * at n-1 bytes, d, or EOF. clears the remaining line so future reads * start on newline. ignores inline comments, and removes trailing * whitespace. returns upto n bytes in s, with d stripped and \0 appended.; */char * get(char *s, int n, char d, FILE *f){	int c = 0;	char *cs = s;	while(--n > 0 && (c = getc(f)) != EOF && (*cs++ = c) != d && c != '#') ;	if (c == d || c == '#') *--cs = '\0';		else *cs = '\0';	/* remove trailing whitespace */	cs = strchr(s, '\0');	while (*--cs == ' ' || *cs == '\t') /* nop */ ;	*++cs = '\0';	while (c != '\n' && c != EOF) c = getc(f); /* clear the line */	return (c == EOF) ? NULL : s;}void abortion(const char *msg, int type){	endwin();	fprintf(stderr, "sntop: %s\n", msg);	exit(type);}RETSIGTYPE aborted(int ignore)	{ abortion("caught SIGINT -- aborted", 5); }/* * glibc's system() disables interrupt signals which is a pretty evil * thing to do, especially in a loop, as we cant break out. *   * we return 127 on error, as this is what waitpid's status will show * on error since it is unsigned, so we can check against a single value */unsigned short int sntop_exec(char *command){	extern char **environ;        int pid, status;	pid = fork();	if (pid == -1) return 127;	if (pid == 0) {		char * argv[4];		argv[0] = "sh";		argv[1] = "-c";		argv[2] = command;		argv[3] = NULL;		execve("/bin/sh", argv, environ);		exit(127);	}	while(1) {		if (waitpid(pid, &status, 0) == -1)			return 127;		else if (WIFEXITED(status)) return WEXITSTATUS(status);			else return 127;	}}void load_config(char *cfile, hdc **head){	char *field[3];	char buf[IN_BUF];	char up_status[] = UP;	int i;	FILE *cf;	hdc *current = NULL, *last = NULL;	if ((cf = fopen(cfile, "r")) == NULL) {		/* lets try opening the system-wide conf file, then */		strncpy(cfile, CONF_SFILE, CONF_BUF);			if ((cf = fopen(cfile, "r")) == NULL)			abortion("error, cannot open systen or user conf file", 1);	}	if ((*head) != NULL) {		/* if we are called a subsequent time, we free() first */		current = (*head);	        do {			last = current->next;	                free(current);			current = last;		} while (current != NULL);		(*head) = NULL;	}	while (!feof(cf)) {		if ((current = malloc(sizeof(hdc))) == NULL)			abortion("error, malloc() returned NULL", 2);		i = 0;		field[0] = current->name;		field[1] = current->host;		field[2] = current->note;		if ((*head) == NULL) { (*head) = current; last = current; }		last->next = current;		last = current;		current->next = NULL;		current->status = up_status;		while(i < 3) {			if (get(buf, IN_BUF, '\n', cf) == NULL) break;			if (buf[0])				strncpy(field[i++], buf, IN_BUF);		}	}	fclose(cf);}/* written 30,000ft in the air */void exec_alarm(char *command, char *name, char *host, char *status){	extern char **environ;	int pid;	pid = fork();	if (pid == -1) return;	if (pid == 0) {		char *argv[5];		argv[1] = name;		argv[2] = host;		argv[3] = status;		argv[4] = NULL;		if (execve(command, argv, environ) == -1)			abortion("error executing alarm command", 7);	}}void start_html(char *file, FILE **hf, unsigned int refresh){	if (((*hf) = fopen(file, "w")) == NULL)		abortion("error, cannot open html file", 3);	fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", (*hf));	fputs("<HTML>\n<HEAD>\n", (*hf));	if (refresh) fprintf((*hf), "<META http-equiv=\"Refresh\" content=\"%d\">\n", refresh);	fputs("<TITLE>sntop network status</TITLE>\n</HEAD>\n", (*hf));	fputs("<BODY TEXT=\"#000000\" BGCOLOR=\"#FFFFFF\">\n\n", (*hf));	fputs("<P><B>sntop network status - automatically generated html</B></P><BR>\n\n", (*hf));	fputs("<TABLE BORDER CELLPADDING=5>\n<TR VALIGN=top>\n", (*hf));	fputs("<TD BGCOLOR=#EEEEEE><B>Host</B></TD>\n<TD BGCOLOR=#EEEEEE>", (*hf));	fputs("<B>Status</B></TD>\n<TD BGCOLOR=#EEEEEE><B>Comments</B></TD>\n", (*hf));	fputs("</TR>\n", (*hf));}void add_html(FILE *hf, char *name, char *status, char *comments){	fprintf(hf, "<TR>\n<TD BGCOLOR=#EEEEEE>%s</TD>\n", name);	fprintf(hf, "<TD BGCOLOR=#EEEEEE><B><FONT COLOR=%s",			strcmp(status, UP) ? HTML_DOWN : HTML_UP);	fprintf(hf, "</FONT></B></TD>\n<TD BGCOLOR=#EEEEEE>%s</TD>\n", comments);}void end_html(FILE *hf, unsigned int hosts, unsigned int up) {	extern char *tzname[2];	time_t t;	char *s;	fputs("</TABLE>\n\n", hf);	fprintf(hf, "<P><B>%u</B> hosts polled: <B>%u</B> up, <B>%u</B> down</P><BR>\n\n", hosts, up, hosts - up);	/* ok, so these sanity checks are a bit much -- but they arent overkill */	if (time(&t) != (time_t) -1)		if ((s = ctime(&t)) && tzname[0])			fprintf(hf, "<P><SMALL>Last updated: %s %s</SMALL></P>\n\n", s, tzname[0]);	fputs("<P><SMALL>Generated by <A HREF=\"http://sntop.sourceforge.net\">", hf);	fputs(SNTOP_VERSION "</A> - " SNTOP_AUTHORS "</SMALL></P>\n\n", hf);	fputs("</BODY>\n</HTML>", hf);	fclose(hf);}/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -