/* * Copyright (c) 2002 Pedro Bastos * 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. * 3. Neither the name of the author nor the name of his contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY PEDRO BASTOS AND HIS 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. * */ /* * "Que importa a paisagem, a Gloria, a baia, a linha do horizonte ? * - O que eu vejo e' o beco." * -- Manuel Bandeira * "Poema do Beco" */ #include #include #include #include #include #include #include #include #include #include #include #include "machmon.h" #include "global.h" #include "lncurses.h" #include "conf.h" #include "extern.h" static int signal_setup(void); static int timer_setup(int); static void getkey(int); static void rezscr(volatile sig_atomic_t sigval); static void sync_run(volatile sig_atomic_t sigval); #ifdef OPENBSD __dead void internal_loop(void); __dead void usage(void); __dead void quit(volatile sig_atomic_t sigval); #endif #ifdef FREEBSD void internal_loop(void); void usage(void); void quit(volatile sig_atomic_t sigval); #endif /* * Here we set flags to their default values: run time flags filled, internal * flags empty. */ int run_flags = 0xff; int int_flags = 0x0; /* * Some static parameters that will be needed furthermore, including the time * to synchronize data collection. */ static char *file; static uid_t u_uid = 0; int MAIN_WINDOW; int REAL_WINDOW; int synctime = 10; #ifdef OPENBSD __dead void #else void #endif quit(volatile sig_atomic_t sigval) { (void) touchwin(stdscr); (void) move(0, 0); (void) clrtoeol(); (void) printw("Thanks for using Machmon!\n"); (void) refresh(); (void) endwin(); (void) exit(0); } void rezscr(volatile sig_atomic_t sigval) { endwin(); ncurses_start(); } void sync_run(volatile sig_atomic_t sigval) { int i = 0; y = 0; x = 0; (void) wclear(twin); (void) touchwin(window[REAL_WINDOW]); move(y, x); for (i = 0; conf_param[i].refer_name != NULL; i++) if (run_flags & conf_param[i].bitmask) { conf_param[i].FUNCTION(); (void) wnoutrefresh(twin); } output("\n~wPress ~R'i'~w to show network statistics or ~R'q'~w to quit."); (void) move(0, 0); (void) doupdate(); (void) untouchwin(twin); return; } static int signal_setup(void) { struct sigaction sigact; (void) memset(&sigact, 0x0, sizeof sigact); sigact.sa_flags = SA_RESTART; (void) sigemptyset(&sigact.sa_mask); sigact.sa_handler = sync_run; if (sigaction(SIGALRM, &sigact, (struct sigaction *) 0) == -1) return (0); sigact.sa_handler = quit; if (sigaction(SIGHUP, &sigact, (struct sigaction *) 0) == -1) return (0); if (sigaction(SIGQUIT, &sigact, (struct sigaction *) 0) == -1) return (0); if (sigaction(SIGINT, &sigact, (struct sigaction *) 0) == -1) return (0); if (sigaction(SIGABRT, &sigact, (struct sigaction *) 0) == -1) return (0); if (sigaction(SIGTERM, &sigact, (struct sigaction *) 0) == -1) return (0); sigact.sa_handler = rezscr; if (sigaction(SIGWINCH, &sigact, (struct sigaction *) 0) == -1) return (0); return (1); } static int timer_setup(int secs) { struct itimerval ival; (void) memset(&ival, 0x0, sizeof ival); ival.it_value.tv_sec = 0; ival.it_value.tv_usec = 1; ival.it_interval.tv_sec = 10; ival.it_interval.tv_usec = 0; if (setitimer(ITIMER_REAL, &ival, NULL) == 0) return (1); return (0); } int xatoi(const char *buf, int *outnum) { char *ep; long lval; errno = 0; lval = strtol(optarg, &ep, 10); if (buf[0] == '\0' || *ep != '\0') return (-1); if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) || (lval > INT_MAX || lval < INT_MIN)) return (-1); if (outnum) *outnum = lval; return (0); } #ifdef OPENBSD __dead void #else void #endif usage(void) { (void) fprintf(stderr, "Usage:\n%s [-dh] [-c] file [-t] time\n", __progname); exit(1); } int main(int argc, char **argv) { int ch; synctime = 10; while ((ch = getopt(argc, argv, "dht:u:c:")) != -1) { switch (ch) { case 'd': ADD_FLAG(int_flags, FO_F); break; case 'h': usage(); /* NOTREACHED */ case 't': if (xatoi(optarg, &synctime) == -1) errx(1, "-t: %s: not a number", optarg); break; case 'c': POINTER_FILL(file, 2 * MAXPATHLEN); STRING_COPY(file, optarg, 2 * MAXPATHLEN); run_flags = 0x0; if (!get_conf(file)) err(1, "get_conf"); free(file); break; case 'u': /* XXX - should be xatoui() * (see strtoul() manpage) */ if (xatoi(optarg, &u_uid) == -1) { struct passwd *pwd; pwd = getpwnam(optarg); if (pwd == NULL) errx(1, "-u: %s: not a userid or a username", optarg); u_uid = pwd->pw_uid; } } } argc -= optind; argv += optind; /* * Code that should be removed as soon as possible: */ if(!kernel_start()) /* begin meta-conversation with kernel */ err(1, "kernel_start"); (void) setegid(getgid()); (void) setgid(getgid()); /* * End. */ if (!signal_setup()) err(1, "signal_setup"); if (!ncurses_start()) { warnx("could not initialize display"); exit(0); } d_htnm(); if (!timer_setup(synctime)) /* set up alarm clock */ err(1, "setup_timer"); internal_loop(); /* NOTREACHED */ #ifdef FREEBSD return (0); /* eheh */ #endif } #ifdef OPENBSD __dead void #else void #endif internal_loop(void) { fd_set *fdkey; /* stdin file descriptor */ struct timeval *tv; /* time struct */ for (;;) { POINTER_FILL(fdkey, sizeof(fd_mask) * howmany((STDIN_FILENO + 1), NFDBITS)); FD_SET(STDIN_FILENO, fdkey); POINTER_FILL(tv, sizeof(struct timeval)); tv->tv_sec = 0; tv->tv_usec = 25000; if (select(1, fdkey, NULL, NULL, tv) > 0) { int ch; if ((ch = wgetch(twin)) != NULL) getkey(ch); } free(tv); free(fdkey); } } static void getkey(int c) { switch (c) { case 114: get_conf("machmon.conf"); break; case 105: ADD_FLAG(run_flags, IF_F); popup_win(2, "Next run will show network statistics."); break; case 27: case 113: case 156: case 274: quit(0); /* user request */ break; } return; } char * plural(int n) { return (n != 1 ? "s" : ""); } char * plurales(int n) { return (n != 1 ? "es" : ""); } char * and(int l) { return (l > 0 ? ", " : ""); }