Annotation of embedaddon/iftop/ui.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * ui.c:
                      3:  *
                      4:  */
                      5: 
1.1.1.2 ! misho       6: #include "config.h"
        !             7: 
1.1       misho       8: #include <sys/types.h>
                      9: 
                     10: #include <ctype.h>
1.1.1.2 ! misho      11: #include <ncurses.h>
1.1       misho      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: 
1.1.1.2 ! misho      31: #include "ui_common.h"
1.1       misho      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"\
1.1.1.2 ! misho      41: "                                        T - toggle cumulative line totals\n"\
1.1       misho      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"\
1.1.1.2 ! misho      54: "iftop, version " PACKAGE_VERSION
1.1       misho      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: 
1.1.1.2 ! misho      86: static int rateidx_init = 0;
        !            87: 
1.1       misho      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;
1.1.1.2 ! misho     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:     }
1.1       misho     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 */
1.1.1.2 ! misho     156:             readable_size(i, s, sizeof s, options.log_scale ? 1000 : 1024, options.bandwidth_in_bytes);
1.1       misho     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];
1.1.1.2 ! misho     182:     float n = 0;
1.1       misho     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: 
1.1.1.2 ! misho     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: 
1.1       misho     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 */
1.1.1.2 ! misho     376:     mvaddstr(y, 16, "cum: ");
1.1       misho     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) {
1.1.1.2 ! misho     416:       ++rateidx;
        !           417:       wantbiggerrate = 0;
1.1       misho     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 */
1.1.1.2 ! misho     437:     (void) curs_set(0);    /* hide blinking cursor in ui */
1.1       misho     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 '!': {
1.1.1.2 ! misho     729: #ifdef ALLOW_SUBSHELL
1.1       misho     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) {
1.1.1.2 ! misho     766:                     showhelp("Show cumulative totals");
1.1       misho     767:                 }
                    768:                 else {
1.1.1.2 ! misho     769:                     showhelp("Hide cumulative totals");
1.1       misho     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>