File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / iftop / ui.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 18 14:04:50 2016 UTC (7 years, 7 months ago) by misho
Branches: iftop, MAIN
CVS tags: v1_0rc4, HEAD
iftop 1.0pre4

    1: /*
    2:  * ui.c:
    3:  *
    4:  */
    5: 
    6: #include "config.h"
    7: 
    8: #include <sys/types.h>
    9: 
   10: #include <ctype.h>
   11: #include <ncurses.h>
   12: #include <errno.h>
   13: #include <string.h>
   14: #include <math.h>
   15: #include <pthread.h>
   16: #include <signal.h>
   17: #include <stdlib.h>
   18: #include <unistd.h>
   19: #include <netdb.h>
   20: 
   21: #include <sys/wait.h>
   22: 
   23: #include "addr_hash.h"
   24: #include "serv_hash.h"
   25: #include "iftop.h"
   26: #include "resolver.h"
   27: #include "sorted_list.h"
   28: #include "options.h"
   29: #include "screenfilter.h"
   30: 
   31: #include "ui_common.h"
   32: 
   33: #define HELP_TIME 2
   34: 
   35: #define HELP_MESSAGE \
   36: "Host display:                          General:\n"\
   37: " n - toggle DNS host resolution         P - pause display\n"\
   38: " s - toggle show source host            h - toggle this help display\n"\
   39: " d - toggle show destination host       b - toggle bar graph display\n"\
   40: " t - cycle line display mode            B - cycle bar graph average\n"\
   41: "                                        T - toggle cumulative line totals\n"\
   42: "Port display:                           j/k - scroll display\n"\
   43: " N - toggle service resolution          f - edit filter code\n"\
   44: " S - toggle show source port            l - set screen filter\n"\
   45: " D - toggle show destination port       L - lin/log scales\n"\
   46: " p - toggle port display                ! - shell command\n"\
   47: "                                        q - quit\n"\
   48: "Sorting:\n"\
   49: " 1/2/3 - sort by 1st/2nd/3rd column\n"\
   50: " < - sort by source name\n"\
   51: " > - sort by dest name\n"\
   52: " o - freeze current order\n"\
   53: "\n"\
   54: "iftop, version " PACKAGE_VERSION
   55: 
   56: 
   57: extern hash_type* history;
   58: extern int history_pos;
   59: extern int history_len;
   60: 
   61: extern options_t options ;
   62: 
   63: void ui_finish();
   64: 
   65: #define HELP_MSG_SIZE 80
   66: int showhelphint = 0;
   67: int persistenthelp = 0;
   68: time_t helptimer = 0;
   69: char helpmsg[HELP_MSG_SIZE];
   70: int dontshowdisplay = 0;
   71: 
   72: /* Barchart scales. */
   73: static struct {
   74:     int max, interval;
   75: } scale[] = {
   76:         {      64000,     10 },     /* 64 kbit/s */
   77:         {     128000,     10 },
   78:         {     256000,     10 },
   79:         {    1000000,     10 },     /* 1 Mbit/s */
   80:         {   10000000,     10 },     
   81:         {  100000000,    100 },
   82:         { 1000000000,    100 }      /* 1 Gbit/s */
   83:     };
   84: static int rateidx = 0, wantbiggerrate;
   85: 
   86: static int rateidx_init = 0;
   87: 
   88: static int get_bar_interval(float bandwidth) {
   89:     int i = 10;
   90:     if(bandwidth > 100000000) {
   91:         i = 100;
   92:     }
   93:     return i;
   94: }
   95: 
   96: static float get_max_bandwidth() {
   97:     float max;
   98:     if(options.max_bandwidth > 0) {
   99:         max = options.max_bandwidth;
  100:     }
  101:     else {
  102:         max = scale[rateidx].max;
  103:     }
  104:     return max;
  105: }
  106: 
  107: /* rate in bits */
  108: static int get_bar_length(const int rate) {
  109:     float l;
  110:     if (rate <= 0)
  111:         return 0;
  112:     if (rate > scale[rateidx].max) {
  113:       wantbiggerrate = 1;
  114:       if(! rateidx_init) {
  115: 	while(rate > scale[rateidx_init++].max) {
  116: 	}
  117: 	rateidx = rateidx_init;
  118:       }
  119:     }
  120:     if(options.log_scale) {
  121:         l = log(rate) / log(get_max_bandwidth());
  122:     }
  123:     else {
  124:         l = rate / get_max_bandwidth();
  125:     }
  126:     return (l * COLS);
  127: }
  128: 
  129: static void draw_bar_scale(int* y) {
  130:     float i;
  131:     float max,interval;
  132:     max = get_max_bandwidth();
  133:     interval = get_bar_interval(max);
  134:     if(options.showbars) {
  135:         float stop;
  136:         /* Draw bar graph scale on top of the window. */
  137:         move(*y, 0);
  138:         clrtoeol();
  139:         mvhline(*y + 1, 0, 0, COLS);
  140:         /* i in bytes */
  141: 
  142:         if(options.log_scale) {
  143:             i = 1.25;
  144:             stop = max / 8;
  145:         }
  146:         else {
  147:             i = max / (5 * 8);
  148:             stop = max / 8;
  149:         }
  150: 
  151:         /* for (i = 1.25; i * 8 <= max; i *= interval) { */
  152:         while(i <= stop) {
  153:             char s[40], *p;
  154:             int x;
  155:             /* This 1024 vs 1000 stuff is just plain evil */
  156:             readable_size(i, s, sizeof s, options.log_scale ? 1000 : 1024, options.bandwidth_in_bytes);
  157:             p = s + strspn(s, " ");
  158:             x = get_bar_length(i * 8);
  159:             mvaddch(*y + 1, x, ACS_BTEE);
  160:             if (x + strlen(p) >= COLS)
  161:                 x = COLS - strlen(p);
  162:             mvaddstr(*y, x, p);
  163: 
  164:             if(options.log_scale) {
  165:                 i *= interval;
  166:             }
  167:             else {
  168:                 i += max / (5 * 8);
  169:             }
  170:         }
  171:         mvaddch(*y + 1, 0, ACS_LLCORNER);
  172:         *y += 2;
  173:     }
  174:     else {
  175:         mvhline(*y, 0, 0, COLS);
  176:         *y += 1;
  177:     }
  178: }
  179: 
  180: void draw_line_total(float sent, float recv, int y, int x, option_linedisplay_t linedisplay, int bytes) {
  181:     char buf[10];
  182:     float n = 0;
  183:     switch(linedisplay) {
  184:         case OPTION_LINEDISPLAY_TWO_LINE:
  185:           draw_line_total(sent, recv, y, x, OPTION_LINEDISPLAY_ONE_LINE_SENT, bytes);
  186:           draw_line_total(sent, recv, y+1, x, OPTION_LINEDISPLAY_ONE_LINE_RECV, bytes);
  187:           break;
  188:         case OPTION_LINEDISPLAY_ONE_LINE_SENT:
  189:           n = sent;
  190:           break;
  191:         case OPTION_LINEDISPLAY_ONE_LINE_RECV:
  192:           n = recv;
  193:           break;
  194:         case OPTION_LINEDISPLAY_ONE_LINE_BOTH:
  195:           n = recv + sent;
  196:           break;
  197:     }
  198:     if(linedisplay != OPTION_LINEDISPLAY_TWO_LINE) {
  199:         readable_size(n, buf, 10, 1024, bytes);
  200:         mvaddstr(y, x, buf);
  201:     }
  202: }
  203: 
  204: void draw_bar(float n, int y) {
  205:     int L;
  206:     mvchgat(y, 0, -1, A_NORMAL, 0, NULL);
  207:     L = get_bar_length(8 * n);
  208:     if (L > 0)
  209:         mvchgat(y, 0, L + 1, A_REVERSE, 0, NULL);
  210: }
  211: 
  212: void draw_line_totals(int y, host_pair_line* line, option_linedisplay_t linedisplay) {
  213:     int j;
  214:     int x = (COLS - 8 * HISTORY_DIVISIONS);
  215: 
  216:     for(j = 0; j < HISTORY_DIVISIONS; j++) {
  217:         draw_line_total(line->sent[j], line->recv[j], y, x, linedisplay, options.bandwidth_in_bytes);
  218:         x += 8;
  219:     }
  220:     
  221:     if(options.showbars) {
  222:       switch(linedisplay) {
  223:         case OPTION_LINEDISPLAY_TWO_LINE:
  224:           draw_bar(line->sent[options.bar_interval],y);
  225:           draw_bar(line->recv[options.bar_interval],y+1);
  226:           break;
  227:         case OPTION_LINEDISPLAY_ONE_LINE_SENT:
  228:           draw_bar(line->sent[options.bar_interval],y);
  229:           break;
  230:         case OPTION_LINEDISPLAY_ONE_LINE_RECV:
  231:           draw_bar(line->recv[options.bar_interval],y);
  232:           break;
  233:         case OPTION_LINEDISPLAY_ONE_LINE_BOTH:
  234:           draw_bar(line->recv[options.bar_interval] + line->sent[options.bar_interval],y);
  235:           break;
  236:       }
  237:     }
  238: }
  239: 
  240: void draw_totals(host_pair_line* totals) {
  241:     /* Draw rule */
  242:     int y = LINES - 4;
  243:     int j;
  244:     char buf[10];
  245:     int x = (COLS - 8 * HISTORY_DIVISIONS);
  246:     y++;
  247:     draw_line_totals(y, totals, OPTION_LINEDISPLAY_TWO_LINE);
  248:     y += 2;
  249:     for(j = 0; j < HISTORY_DIVISIONS; j++) {
  250:         readable_size((totals->sent[j] + totals->recv[j]) , buf, 10, 1024, options.bandwidth_in_bytes);
  251:         mvaddstr(y, x, buf);
  252:         x += 8;
  253:     }
  254: }
  255: 
  256: extern history_type history_totals;
  257: 
  258: 
  259: void ui_print() {
  260:     sorted_list_node* nn = NULL;
  261:     char host1[HOSTNAME_LENGTH], host2[HOSTNAME_LENGTH];
  262:     static char *line;
  263:     static int lcols;
  264:     int y = 0;
  265: 
  266:     if (dontshowdisplay)
  267:         return;
  268: 
  269:     if (!line || lcols != COLS) {
  270:         xfree(line);
  271:         line = calloc(COLS + 1, 1);
  272:     }
  273: 
  274:     /* 
  275:      * erase() is faster than clear().  Dunno why we switched to 
  276:      * clear() -pdw 24/10/02
  277:      */
  278:     erase();
  279: 
  280:     draw_bar_scale(&y);
  281: 
  282:     if(options.showhelp) {
  283:       mvaddstr(y,0,HELP_MESSAGE);
  284:     }
  285:     else {
  286:       int i = 0;
  287: 
  288:       while(i < options.screen_offset && ((nn = sorted_list_next_item(&screen_list, nn)) != NULL)) {
  289:         i++;
  290:       }
  291: 
  292:       /* Screen layout: we have 2 * HISTORY_DIVISIONS 6-character wide history
  293:        * items, and so can use COLS - 12 * HISTORY_DIVISIONS to print the two
  294:        * host names. */
  295: 
  296:       if(i == 0 || nn != NULL) {
  297:         while((y < LINES - 5) && ((nn = sorted_list_next_item(&screen_list, nn)) != NULL)) {
  298:             int x = 0, L;
  299: 
  300: 
  301:             host_pair_line* screen_line = (host_pair_line*)nn->data;
  302: 
  303:             if(y < LINES - 5) {
  304:                 L = (COLS - 8 * HISTORY_DIVISIONS - 4) / 2;
  305:                 if(options.show_totals) {
  306:                     L -= 4;    
  307:                 }
  308:                 if(L > HOSTNAME_LENGTH) {
  309:                     L = HOSTNAME_LENGTH;
  310:                 }
  311: 
  312:                 sprint_host(host1, screen_line->ap.af,
  313:                             &(screen_line->ap.src6),
  314:                             screen_line->ap.src_port,
  315:                             screen_line->ap.protocol, L, options.aggregate_src);
  316:                 sprint_host(host2, screen_line->ap.af,
  317:                             &(screen_line->ap.dst6),
  318:                             screen_line->ap.dst_port,
  319:                             screen_line->ap.protocol, L, options.aggregate_dest);
  320: 
  321:                 if(!screen_filter_match(host1) && !screen_filter_match(host2)) {
  322:                   continue;
  323:                 }
  324: 
  325:                 mvaddstr(y, x, host1);
  326:                 x += L;
  327: 
  328:                 switch(options.linedisplay) {
  329:                   case OPTION_LINEDISPLAY_TWO_LINE:
  330:                     mvaddstr(y, x, " => ");
  331:                     mvaddstr(y+1, x, " <= ");
  332:                     break;
  333:                   case OPTION_LINEDISPLAY_ONE_LINE_BOTH:
  334:                     mvaddstr(y, x, "<=> ");
  335:                     break;
  336:                   case OPTION_LINEDISPLAY_ONE_LINE_SENT:
  337:                     mvaddstr(y, x, " => ");
  338:                     break;
  339:                   case OPTION_LINEDISPLAY_ONE_LINE_RECV:
  340:                     mvaddstr(y, x, " <= ");
  341:                     break;
  342:                 }
  343: 
  344:                 x += 4;
  345: 
  346: 
  347:                 mvaddstr(y, x, host2);
  348:                 
  349:                 if(options.show_totals) {
  350:                     draw_line_total(screen_line->total_sent, screen_line->total_recv, y, COLS - 8 * (HISTORY_DIVISIONS + 1), options.linedisplay, 1);
  351:                 }
  352: 
  353:                 draw_line_totals(y, screen_line, options.linedisplay);
  354: 
  355:             }
  356:             if(options.linedisplay == OPTION_LINEDISPLAY_TWO_LINE) {
  357:               y += 2;
  358:             }
  359:             else {
  360:               y += 1;
  361:             }
  362:         }
  363:       }
  364:     }
  365: 
  366: 
  367:     y = LINES - 3;
  368:     
  369:     mvhline(y-1, 0, 0, COLS);
  370: 
  371:     mvaddstr(y, 0, "TX: ");
  372:     mvaddstr(y+1, 0, "RX: ");
  373:     mvaddstr(y+2, 0, "TOTAL: ");
  374: 
  375:     /* Cummulative totals */
  376:     mvaddstr(y, 16, "cum: ");
  377: 
  378:     readable_size(history_totals.total_sent, line, 10, 1024, 1);
  379:     mvaddstr(y, 22, line);
  380: 
  381:     readable_size(history_totals.total_recv, line, 10, 1024, 1);
  382:     mvaddstr(y+1, 22, line);
  383: 
  384:     readable_size(history_totals.total_recv + history_totals.total_sent, line, 10, 1024, 1);
  385:     mvaddstr(y+2, 22, line);
  386: 
  387:     /* peak traffic */
  388:     mvaddstr(y, 32, "peak: ");
  389: 
  390:     readable_size(peaksent / RESOLUTION, line, 10, 1024, options.bandwidth_in_bytes);
  391:     mvaddstr(y, 39, line);
  392: 
  393:     readable_size(peakrecv / RESOLUTION, line, 10, 1024, options.bandwidth_in_bytes);
  394:     mvaddstr(y+1, 39, line);
  395: 
  396:     readable_size(peaktotal / RESOLUTION, line, 10, 1024, options.bandwidth_in_bytes);
  397:     mvaddstr(y+2, 39, line);
  398: 
  399:     mvaddstr(y, COLS - 8 * HISTORY_DIVISIONS - 8, "rates:");
  400: 
  401:     draw_totals(&totals);
  402: 
  403: 
  404:     if(showhelphint) {
  405:       mvaddstr(0, 0, " ");
  406:       mvaddstr(0, 1, helpmsg);
  407:       mvaddstr(0, 1 + strlen(helpmsg), " ");
  408:       mvchgat(0, 0, strlen(helpmsg) + 2, A_REVERSE, 0, NULL);
  409:     }
  410:     move(LINES - 1, COLS - 1);
  411:     
  412:     refresh();
  413: 
  414:     /* Bar chart auto scale */
  415:     if (wantbiggerrate && options.max_bandwidth == 0) {
  416:       ++rateidx;
  417:       wantbiggerrate = 0;
  418:     }
  419: }
  420: 
  421: void ui_tick(int print) {
  422:   if(print) {
  423:     ui_print();
  424:   }
  425:   else if(showhelphint && (time(NULL) - helptimer > HELP_TIME) && !persistenthelp) {
  426:     showhelphint = 0;
  427:     ui_print();
  428:   }
  429: }
  430: 
  431: void ui_curses_init() {
  432:     (void) initscr();      /* initialize the curses library */
  433:     keypad(stdscr, TRUE);  /* enable keyboard mapping */
  434:     (void) nonl();         /* tell curses not to do NL->CR/NL on output */
  435:     (void) cbreak();       /* take input chars one at a time, no wait for \n */
  436:     (void) noecho();       /* don't echo input */
  437:     (void) curs_set(0);    /* hide blinking cursor in ui */
  438:     halfdelay(2);
  439: }
  440: 
  441: void showhelp(const char * s) {
  442:   strncpy(helpmsg, s, HELP_MSG_SIZE);
  443:   showhelphint = 1;
  444:   helptimer = time(NULL);
  445:   persistenthelp = 0;
  446:   tick(1);
  447: }
  448: 
  449: void ui_init() {
  450:     char msg[20];
  451:     ui_curses_init();
  452:     
  453:     erase();
  454: 
  455:     screen_list_init();
  456:     screen_hash = addr_hash_create();
  457: 
  458:     service_hash = serv_hash_create();
  459:     serv_hash_initialise(service_hash);
  460: 
  461:     snprintf(msg,20,"Listening on %s",options.interface);
  462:     showhelp(msg);
  463: 
  464: 
  465: }
  466: 
  467: 
  468: void showportstatus() {
  469:   if(options.showports == OPTION_PORTS_ON) {
  470:     showhelp("Port display ON");
  471:   }
  472:   else if(options.showports == OPTION_PORTS_OFF) {
  473:     showhelp("Port display OFF");
  474:   }
  475:   else if(options.showports == OPTION_PORTS_DEST) {
  476:     showhelp("Port display DEST");
  477:   }
  478:   else if(options.showports == OPTION_PORTS_SRC) {
  479:     showhelp("Port display SOURCE");
  480:   }
  481: }
  482: 
  483: 
  484: void ui_loop() {
  485:     /* in edline.c */
  486:     char *edline(int linenum, const char *prompt, const char *initial);
  487:     /* in iftop.c */
  488:     char *set_filter_code(const char *filter);
  489: 
  490:     extern sig_atomic_t foad;
  491: 
  492:     while(foad == 0) {
  493:         int i;
  494:         i = getch();
  495:         switch (i) {
  496:             case 'q':
  497:                 foad = 1;
  498:                 break;
  499: 
  500:             case 'n':
  501:                 if(options.dnsresolution) {
  502:                     options.dnsresolution = 0;
  503:                     showhelp("DNS resolution off");
  504:                 }
  505:                 else {
  506:                     options.dnsresolution = 1;
  507:                     showhelp("DNS resolution on");
  508:                 }
  509:                 tick(1);
  510:                 break;
  511: 
  512:             case 'N':
  513:                 if(options.portresolution) {
  514:                     options.portresolution = 0;
  515:                     showhelp("Port resolution off");
  516:                 }
  517:                 else {
  518:                     options.portresolution = 1;
  519:                     showhelp("Port resolution on");
  520:                 }
  521:                 tick(1);
  522:                 break;
  523: 
  524:             case 'h':
  525:             case '?':
  526:                 options.showhelp = !options.showhelp;
  527:                 tick(1);
  528:                 break;
  529: 
  530:             case 'b':
  531:                 if(options.showbars) {
  532:                     options.showbars = 0;
  533:                     showhelp("Bars off");
  534:                 }
  535:                 else {
  536:                     options.showbars = 1;
  537:                     showhelp("Bars on");
  538:                 }
  539:                 tick(1);
  540:                 break;
  541: 
  542:             case 'B':
  543:                 options.bar_interval = (options.bar_interval + 1) % 3;
  544:                 if(options.bar_interval == 0) {
  545:                     showhelp("Bars show 2s average");
  546:                 }
  547:                 else if(options.bar_interval == 1) { 
  548:                     showhelp("Bars show 10s average");
  549:                 }
  550:                 else {
  551:                     showhelp("Bars show 40s average");
  552:                 }
  553:                 ui_print();
  554:                 break;
  555:             case 's':
  556:                 if(options.aggregate_src) {
  557:                     options.aggregate_src = 0;
  558:                     showhelp("Show source host");
  559:                 }
  560:                 else {
  561:                     options.aggregate_src = 1;
  562:                     showhelp("Hide source host");
  563:                 }
  564:                 break;
  565:             case 'd':
  566:                 if(options.aggregate_dest) {
  567:                     options.aggregate_dest = 0;
  568:                     showhelp("Show dest host");
  569:                 }
  570:                 else {
  571:                     options.aggregate_dest = 1;
  572:                     showhelp("Hide dest host");
  573:                 }
  574:                 break;
  575:             case 'S':
  576:                 /* Show source ports */
  577:                 if(options.showports == OPTION_PORTS_OFF) {
  578:                   options.showports = OPTION_PORTS_SRC;
  579:                 }
  580:                 else if(options.showports == OPTION_PORTS_DEST) {
  581:                   options.showports = OPTION_PORTS_ON;
  582:                 }
  583:                 else if(options.showports == OPTION_PORTS_ON) {
  584:                   options.showports = OPTION_PORTS_DEST;
  585:                 }
  586:                 else {
  587:                   options.showports = OPTION_PORTS_OFF;
  588:                 }
  589:                 showportstatus();
  590:                 break;
  591:             case 'D':
  592:                 /* Show dest ports */
  593:                 if(options.showports == OPTION_PORTS_OFF) {
  594:                   options.showports = OPTION_PORTS_DEST;
  595:                 }
  596:                 else if(options.showports == OPTION_PORTS_SRC) {
  597:                   options.showports = OPTION_PORTS_ON;
  598:                 }
  599:                 else if(options.showports == OPTION_PORTS_ON) {
  600:                   options.showports = OPTION_PORTS_SRC;
  601:                 }
  602:                 else {
  603:                   options.showports = OPTION_PORTS_OFF;
  604:                 }
  605:                 showportstatus();
  606:                 break;
  607:             case 'p':
  608:                 options.showports = 
  609:                   (options.showports == OPTION_PORTS_OFF)
  610:                   ? OPTION_PORTS_ON
  611:                   : OPTION_PORTS_OFF;
  612:                 showportstatus();
  613:                 // Don't tick here, otherwise we get a bogus display
  614:                 break;
  615:             case 'P':
  616:                 if(options.paused) {
  617:                     options.paused = 0;
  618:                     showhelp("Display unpaused");
  619:                 }
  620:                 else {
  621:                     options.paused = 1;
  622:                     showhelp("Display paused");
  623:                     persistenthelp = 1;
  624:                 }
  625:                 break;
  626:             case 'o':
  627:                 if(options.freezeorder) {
  628:                     options.freezeorder = 0;
  629:                     showhelp("Order unfrozen");
  630:                 }
  631:                 else {
  632:                     options.freezeorder = 1;
  633:                     showhelp("Order frozen");
  634:                     persistenthelp = 1;
  635:                 }
  636:                 break;
  637:             case '1':
  638:                 options.sort = OPTION_SORT_DIV1;
  639:                 showhelp("Sort by col 1");
  640:                 break;
  641:             case '2':
  642:                 options.sort = OPTION_SORT_DIV2;
  643:                 showhelp("Sort by col 2");
  644:                 break;
  645:             case '3':
  646:                 options.sort = OPTION_SORT_DIV3;
  647:                 showhelp("Sort by col 3");
  648:                 break;
  649:             case '<':
  650:                 options.sort = OPTION_SORT_SRC;
  651:                 showhelp("Sort by source");
  652:                 break;
  653:             case '>':
  654:                 options.sort = OPTION_SORT_DEST;
  655:                 showhelp("Sort by dest");
  656:                 break;
  657:             case 'j':
  658:                 options.screen_offset++;
  659:                 ui_print();
  660:                 break;
  661:             case 'k':
  662:                 if(options.screen_offset > 0) {
  663:                   options.screen_offset--;
  664:                   ui_print();
  665:                 }
  666:                 break;
  667:             case 't':
  668:                 options.linedisplay = (options.linedisplay + 1) % 4;
  669:                 switch(options.linedisplay) {
  670:                   case OPTION_LINEDISPLAY_TWO_LINE:
  671:                     showhelp("Two lines per host");
  672:                     break;
  673:                   case OPTION_LINEDISPLAY_ONE_LINE_SENT:
  674:                     showhelp("Sent traffic only");
  675:                     break;
  676:                   case OPTION_LINEDISPLAY_ONE_LINE_RECV:
  677:                     showhelp("Received traffic only");
  678:                     break;
  679:                   case OPTION_LINEDISPLAY_ONE_LINE_BOTH:
  680:                     showhelp("One line per host");
  681:                     break;
  682:                 }
  683:                 ui_print();
  684:                 break;
  685:             case 'f': {
  686:                 char *s;
  687:                 dontshowdisplay = 1;
  688:                 if ((s = edline(0, "Net filter", options.filtercode))) {
  689:                     char *m;
  690:                     if (s[strspn(s, " \t")] == 0) {
  691:                         /* Empty filter; set to NULL. */
  692:                         xfree(s);
  693:                         s = NULL;
  694:                     }
  695:                     if (!(m = set_filter_code(s))) {
  696:                         xfree(options.filtercode);
  697:                         options.filtercode = s;
  698:                         /* -lpcap will write junk to stderr; we do our best to
  699:                          * erase it.... */
  700:                         move(COLS - 1, LINES - 1);
  701:                         wrefresh(curscr);
  702:                         showhelp("Installed new filter");
  703:                     } else {
  704:                         showhelp(m);
  705:                         xfree(s);
  706:                     }
  707:                 }
  708:                 dontshowdisplay = 0;
  709:                 ui_print();
  710:                 break;
  711:             }
  712:             case 'l': {
  713: #ifdef HAVE_REGCOMP
  714:                 char *s;
  715:                 dontshowdisplay = 1;
  716:                 if ((s = edline(0, "Screen filter", options.screenfilter))) {
  717:                     if(!screen_filter_set(s)) {
  718:                         showhelp("Invalid regexp");
  719:                     }
  720:                 }
  721:                 dontshowdisplay = 0;
  722:                 ui_print();
  723: #else
  724:                 showhelp("Sorry, screen filters not supported on this platform")
  725: #endif
  726:                 break;
  727:             }
  728:             case '!': {
  729: #ifdef ALLOW_SUBSHELL
  730:                 char *s;
  731:                 dontshowdisplay = 1;
  732:                 if ((s = edline(0, "Command", "")) && s[strspn(s, " \t")]) {
  733:                     int i, dowait = 0;
  734:                     erase();
  735:                     refresh();
  736:                     endwin();
  737:                     errno = 0;
  738:                     i = system(s);
  739:                     if (i == -1 || (i == 127 && errno != 0)) {
  740:                         fprintf(stderr, "system: %s: %s\n", s, strerror(errno));
  741:                         dowait = 1;
  742:                     } else if (i != 0) {
  743:                         if (WIFEXITED(i))
  744:                             fprintf(stderr, "%s: exited with code %d\n", s, WEXITSTATUS(i));
  745:                         else if (WIFSIGNALED(i))
  746:                             fprintf(stderr, "%s: killed by signal %d\n", s, WTERMSIG(i));
  747:                         dowait = 1;
  748:                     }
  749:                     ui_curses_init();
  750:                     if (dowait) {
  751:                         fprintf(stderr, "Press any key....");
  752:                         while (getch() == ERR);
  753:                     }
  754:                     erase();
  755:                     xfree(s);
  756:                 }
  757:                 dontshowdisplay = 0;
  758: #else
  759:                 showhelp("Sorry, subshells have been disabled.");
  760: #endif
  761:                 break;
  762:             }
  763:             case 'T':
  764:                 options.show_totals = !options.show_totals;
  765:                 if(options.show_totals) {
  766:                     showhelp("Show cumulative totals");
  767:                 }
  768:                 else {
  769:                     showhelp("Hide cumulative totals");
  770:                 }
  771:                 ui_print();
  772:                 break;
  773:             case 'L':
  774:                 options.log_scale = !options.log_scale;
  775:                 showhelp(options.log_scale ? "Logarithmic scale" : "Linear scale");
  776:                 ui_print();
  777:                 break;
  778:             case KEY_CLEAR:
  779:             case 12:    /* ^L */
  780:                 wrefresh(curscr);
  781:                 break;
  782:             case ERR:
  783:                 break;
  784:             default:
  785:                 showhelp("Press H or ? for help");
  786:                 break;
  787:         }
  788:         tick(0);
  789:     }
  790: }
  791: 
  792: void ui_finish() {
  793:     endwin();
  794: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>