From ba7202d03b9acb2c4f92397d142b69c362f1cee9 Mon Sep 17 00:00:00 2001 From: chris <> Date: Fri, 25 Oct 2002 08:24:49 +0000 Subject: [PATCH] "" --- Makefile | 2 +- edline.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ iftop.c | 43 ++++++++++------- options.c | 2 +- ui.c | 66 +++++++++++++++++++++++++- 5 files changed, 228 insertions(+), 20 deletions(-) create mode 100644 edline.c diff --git a/Makefile b/Makefile index 3a7d217..56290cb 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ LDLIBS += -lpcap -lcurses -lm SRCS = iftop.c addr_hash.c hash.c ns_hash.c resolver.c ui.c util.c sorted_list.c\ - options.c serv_hash.c threadprof.c + options.c serv_hash.c threadprof.c edline.c HDRS = addr_hash.h hash.h iftop.h ns_hash.h resolver.h sorted_list.h ui.h options.h sll.h\ serv_hash.h threadprof.h ether.h ip.h tcp.h TXTS = README CHANGES INSTALL TODO iftop.8 COPYING diff --git a/edline.c b/edline.c new file mode 100644 index 0000000..55f0c31 --- /dev/null +++ b/edline.c @@ -0,0 +1,135 @@ +/* + * edline.c: + * Text input on a line of the screen. + * + */ + +static const char rcsid[] = "$Id$"; + +#include +#include +#include + +#include "iftop.h" + +static int min(const int a, const int b) { + return a < b ? a : b; +} + +/* edline: + * Display on line linenum of the screen the prompt and allow the user to input + * a line of text, whose initial value is as supplied. */ +char *edline(int linenum, const char *prompt, const char *initial) { + int xstart, slen, off = 0, pos, i, c; + char *str; + + xstart = strlen(prompt) + 2; + + if (initial) { + str = xmalloc(slen = strlen(initial) * 2 + 1); + strcpy(str, initial); + } else { + str = xmalloc(slen = 256); + *str = 0; + } + + pos = strlen(str); + + do { + c = getch(); + switch (c) { + case KEY_DL: + case 21: /* ^U */ + *str = 0; + pos = 0; + break; + + case KEY_LEFT: + --pos; + if (pos < 0) { + beep(); + pos = 0; + } + break; + + case KEY_RIGHT: + ++pos; + if (pos > strlen(str)) { + beep(); + pos = strlen(str); + } + break; + + case KEY_HOME: + case 1: /* ^A */ + pos = 0; + break; + + case KEY_END: + case 5: /* ^E */ + pos = strlen(str); + break; + + case KEY_DC: + if (pos == strlen(str)) + beep(); + else + memmove(str + pos, str + pos + 1, strlen(str + pos + 1) + 1); + break; + + case KEY_BACKSPACE: + if (pos == 0) + beep(); + else { + memmove(str + pos - 1, str + pos, strlen(str + pos) + 1); + --pos; + } + break; + + case 23: /* ^W */ + for (i = pos; i > 0; --i) + if (!isspace(str[i])) break; + for (; i > 0; --i) + if (isspace(str[i])) break; + if (i != pos) { + memmove(str + i, str + pos, strlen(str + pos) + 1); + pos = i; + } + break; + + case ERR: + break; + + default: + if (isprint(c) && c != '\t') { + if (strlen(str) == slen - 1) + str = xrealloc(str, slen *= 2); + memmove(str + pos + 1, str + pos, strlen(str + pos) + 1); + str[pos++] = (char)c; + } else + beep(); + break; + } + + /* figure out the offset to use for the string */ + off = 0; + if (pos > COLS - xstart - 1) + off = pos - (COLS - xstart - 1); + + /* display the string */ + mvaddstr(linenum, 0, prompt); + addstr("> "); + addnstr(str + off, min(strlen(str + off), COLS - xstart - 1)); + clrtoeol(); + move(linenum, xstart + pos - off); + refresh(); + } while (c != KEY_ENTER && c != '\r' && c != '\x1b' && c != 7 /* ^G */); + + if (c == KEY_ENTER || c == '\r') + /* Success */ + return str; + else { + xfree(str); + return NULL; + } +} diff --git a/iftop.c b/iftop.c index e78cf0e..364e16f 100644 --- a/iftop.c +++ b/iftop.c @@ -44,6 +44,7 @@ int history_len = 1; pthread_mutex_t tick_mutex; pcap_t* pd; /* pcap descriptor */ +struct bpf_program pcap_filter; pcap_handler packet_handler; sig_atomic_t foad; @@ -307,6 +308,29 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt } +/* set_filter_code: + * Install some filter code. Returns NULL on success or an error message on + * failure. */ +char *set_filter_code(const char *filter) { + char *x; + if (filter) { + x = xmalloc(strlen(filter) + sizeof "() and ip"); + sprintf(x, "(%s) and ip", filter); + } else + x = xstrdup("ip"); + if (pcap_compile(pd, &pcap_filter, x, 1, 0) == -1) { + xfree(x); + return pcap_geterr(pd); + } + xfree(x); + if (pcap_setfilter(pd, &pcap_filter) == -1) + return pcap_geterr(pd); + else + return NULL; +} + + + /* * packet_init: * @@ -314,8 +338,7 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt */ void packet_init() { char errbuf[PCAP_ERRBUF_SIZE]; - char* str = "ip"; - struct bpf_program F; + char *m; int s; struct ifreq ifr = {0}; int dlt; @@ -369,23 +392,11 @@ void packet_init() { exit(1); } - if (options.filtercode) { - str = xmalloc(strlen(options.filtercode) + sizeof "() and ip"); - sprintf(str, "(%s) and ip", options.filtercode); - } - if (pcap_compile(pd, &F, str, 1, 0) == -1) { - fprintf(stderr, "pcap_compile(%s): %s\n", str, pcap_geterr(pd)); + if ((m = set_filter_code(options.filtercode))) { + fprintf(stderr, "set_filter_code: %s\n", m); exit(1); return; } - if (pcap_setfilter(pd, &F) == -1) { - fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(pd)); - exit(1); - return; - } - if (options.filtercode) - xfree(str); - } /* packet_loop: diff --git a/options.c b/options.c index defd7a6..98914af 100644 --- a/options.c +++ b/options.c @@ -190,7 +190,7 @@ void options_read(int argc, char **argv) { break; case 'f': - options.filtercode = optarg; + options.filtercode = xstrdup(optarg); break; case 'p': diff --git a/ui.c b/ui.c index e9dacb0..118185b 100644 --- a/ui.c +++ b/ui.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -12,6 +13,8 @@ #include #include +#include + #include "addr_hash.h" #include "serv_hash.h" #include "iftop.h" @@ -40,6 +43,8 @@ " P - pause display\n"\ " h - toggle this help display\n"\ " b - toggle bar graph display\n"\ +" f - edit filter code\n"\ +" ! - shell command\n"\ " q - quit\n"\ "\niftop, version " IFTOP_VERSION @@ -77,6 +82,7 @@ int peaksent, peakrecv, peaktotal; int showhelphint = 0; int helptimer = 0; char helpmsg[HELP_MSG_SIZE]; +int dontshowdisplay = 0; int screen_line_compare(void* a, void* b) { int i; @@ -395,6 +401,9 @@ void ui_print() { static int lcols; int y = 0; + if (dontshowdisplay) + return; + if (!line || lcols != COLS) { xfree(line); line = calloc(COLS + 1, 1); @@ -510,14 +519,18 @@ void ui_tick(int print) { } } -void ui_init() { +void ui_curses_init() { (void) initscr(); /* initialize the curses library */ keypad(stdscr, TRUE); /* enable keyboard mapping */ (void) nonl(); /* tell curses not to do NL->CR/NL on output */ (void) cbreak(); /* take input chars one at a time, no wait for \n */ (void) noecho(); /* don't echo input */ halfdelay(2); +} +void ui_init() { + ui_curses_init(); + erase(); screen_list_init(); @@ -551,8 +564,15 @@ void showportstatus() { } } + void ui_loop() { + /* in edline.c */ + char *edline(int linenum, const char *prompt, const char *initial); + /* in iftop.c */ + int set_filter_code(const char *filter); + extern sig_atomic_t foad; + while(foad == 0) { int i; i = getch(); @@ -586,7 +606,7 @@ void ui_loop() { break; case 'h': - case '?' + case '?': options.showhelp = !options.showhelp; tick(1); break; @@ -666,6 +686,48 @@ void ui_loop() { case 'P': options.paused = !options.paused; break; + case 'f': { + char *s; + dontshowdisplay = 1; + if ((s = edline(0, "Filter", options.filtercode))) { + char *m; + if (!(m = set_filter_code(s))) { + xfree(options.filtercode); + options.filtercode = s; + } else { + showhelp(m); + xfree(s); + } + } + dontshowdisplay = 0; + break; + } + case '!': { + char *s; + dontshowdisplay = 1; + if ((s = edline(0, "Command", ""))) { + int i; + erase(); + refresh(); + endwin(); + errno = 0; + i = system(s); + if (i == -1 || (i == 127 && errno != 0)) { + fprintf(stderr, "system: %s: %s\n", s, strerror(errno)); + sleep(1); + } else if (i != 0) { + if (WIFEXITED(i)) + fprintf(stderr, "%s: exited with code %d\n", s, WEXITSTATUS(i)); + else if (WIFSIGNALED(i)) + fprintf(stderr, "%s: killed by signal %d\n", s, WTERMSIG(i)); + sleep(1); + } + ui_curses_init(); + erase(); + xfree(s); + } + dontshowdisplay = 0; + } case ERR: break; default: