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

    1: /*
    2:  * tui.c:
    3:  *
    4:  * Based on ui.c from the original iftop sources.
    5:  *
    6:  * This user interface does not make use of curses. Instead, it prints its
    7:  * output to STDOUT. This output is activated by providing the '-t' flag.
    8:  *
    9:  */
   10: 
   11: #include "config.h"
   12: 
   13: #include <string.h>
   14: #include <stdio.h>
   15: #include <signal.h>
   16: #include <stdlib.h>
   17: #include <unistd.h>
   18: 
   19: #if defined(HAVE_TERMIOS_H)
   20: #include <termios.h>
   21: #elif defined(HAVE_SGTTY_H) && defined(TIOCSETP)
   22: #include <sys/ioctl.h>
   23: #include <sgtty.h>
   24: #elif defined(HAVE_TERMIO_H)
   25: #include <sys/ioctl.h>
   26: #include <termio.h>
   27: #else
   28: #include <stdlib.h>
   29: #endif
   30: 
   31: #include "sorted_list.h"
   32: #include "options.h"
   33: #include "ui_common.h"
   34: 
   35: /* Width of the host column in the output */
   36: #define PRINT_WIDTH 40
   37: 
   38: 
   39: /*
   40:  * UI print function
   41:  */
   42: void tui_print() {
   43:   sorted_list_node* nn = NULL;
   44:   char host1[HOSTNAME_LENGTH], host2[HOSTNAME_LENGTH];
   45:   char buf0_10[10], buf1_10[10], buf2_10[10];
   46:   int j;
   47:   static char *label;
   48:   static char *labellong;
   49:   int l = 0;
   50: 
   51:   if (!label) {
   52:     xfree(label);
   53:     label = (char *)calloc(PRINT_WIDTH + 1, 1);
   54:   }
   55: 
   56:   if (!labellong) {
   57:     xfree(labellong);
   58:     labellong = (char *)calloc(PRINT_WIDTH + 1 + 9, 1);
   59:   }
   60: 
   61:   if (options.paused ) {
   62:     return;
   63:   }
   64: 
   65:   /* Headings */
   66:   snprintf(label, PRINT_WIDTH, "%-*s", PRINT_WIDTH, "Host name (port/service if enabled)");
   67:   printf("%s %s     %10s %10s %10s %10s\n", "   #", label, "last 2s", "last 10s", "last 40s", "cumulative");
   68: 
   69:   /* Divider line */
   70:   for (j = 0; j < PRINT_WIDTH + 52; j++) {
   71:     printf("-");
   72:   }
   73:   printf("\n");
   74: 
   75:   /* Traverse the list of all connections */
   76:   while((nn = sorted_list_next_item(&screen_list, nn)) != NULL && l < options.num_lines) {
   77:     /* Increment the line counter */
   78:     l++;
   79: 
   80:     /* Get the connection information */
   81:     host_pair_line* screen_line = (host_pair_line*)nn->data;
   82: 
   83:     /* Assemble host information */
   84:     sprint_host(host1, screen_line->ap.af, &(screen_line->ap.src6), screen_line->ap.src_port, screen_line->ap.protocol, PRINT_WIDTH, options.aggregate_src);
   85:     sprint_host(host2, screen_line->ap.af, &(screen_line->ap.dst6), screen_line->ap.dst_port, screen_line->ap.protocol, PRINT_WIDTH, options.aggregate_dest);
   86: 
   87:     /* Send rate per connection */
   88:     printf("%4d %s%s", l, host1, " =>");
   89:     for(j = 0; j < HISTORY_DIVISIONS; j++) {
   90:       readable_size(screen_line->sent[j], buf0_10, 10, 1024, options.bandwidth_in_bytes);
   91:       printf(" %10s", buf0_10);
   92:     }
   93:     /* Cumulative sent data per connection */
   94:     readable_size(screen_line->total_sent, buf0_10, 10, 1024, 1);
   95:     printf(" %10s\n", buf0_10);
   96: 
   97:     /* Receive rate per connection */
   98:     printf("     %s%s", host2, " <=");
   99:     for(j = 0; j < HISTORY_DIVISIONS; j++) {
  100:       readable_size(screen_line->recv[j], buf0_10, 10, 1024, options.bandwidth_in_bytes);
  101:       printf(" %10s", buf0_10);
  102:     }
  103:     /* Cumulative received data per connection */
  104:     readable_size(screen_line->total_recv, buf0_10, 10, 1024, 1);
  105:     printf(" %10s\n", buf0_10);
  106:   }
  107: 
  108:   /* Divider line */
  109:   for (j = 0; j < PRINT_WIDTH + 52; j++) {
  110:     printf("-");
  111:   }
  112:   printf("\n");
  113: 
  114:   /* Rate totals */
  115:   snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total send rate:");
  116:   printf("%s ", labellong);
  117:   for(j = 0; j < HISTORY_DIVISIONS; j++) {
  118:     readable_size((((host_pair_line *)&totals)->sent[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes);
  119:     printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' ');
  120:   }
  121: 
  122:   snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total receive rate:");
  123:   printf("%s ", labellong);
  124:   for(j = 0; j < HISTORY_DIVISIONS; j++) {
  125:     readable_size((((host_pair_line *)&totals)->recv[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes);
  126:     printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' ');
  127:   }
  128: 
  129:   snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total send and receive rate:");
  130:   printf("%s ", labellong);
  131:   for(j = 0; j < HISTORY_DIVISIONS; j++) {
  132:     readable_size((((host_pair_line *)&totals)->sent[j] + ((host_pair_line *)&totals)->recv[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes);
  133:     printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' ');
  134:   }
  135: 
  136:   /* Divider line */
  137:   for (j = 0; j < PRINT_WIDTH + 52; j++) {
  138:     printf("-");
  139:   }
  140:   printf("\n");
  141: 
  142:   /* Peak traffic */
  143:   snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Peak rate (sent/received/total):");
  144:   readable_size(peaksent / RESOLUTION, buf0_10, 10, 1024, options.bandwidth_in_bytes);
  145:   readable_size(peakrecv / RESOLUTION, buf1_10, 10, 1024, options.bandwidth_in_bytes);
  146:   readable_size(peaktotal / RESOLUTION, buf2_10, 10, 1024, options.bandwidth_in_bytes);
  147:   printf("%s %10s %10s %10s\n", labellong, buf0_10, buf1_10, buf2_10);
  148: 
  149:   /* Cumulative totals */
  150:   snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Cumulative (sent/received/total):");
  151:   readable_size(history_totals.total_sent, buf0_10, 10, 1024, 1);
  152:   readable_size(history_totals.total_recv, buf1_10, 10, 1024, 1);
  153:   readable_size(history_totals.total_recv + history_totals.total_sent, buf2_10, 10, 1024, 1);
  154:   printf("%s %10s %10s %10s\n", labellong, buf0_10, buf1_10, buf2_10);
  155: 
  156:   /* Double divider line */
  157:   for (j = 0; j < PRINT_WIDTH + 52; j++) {
  158:     printf("=");
  159:   }
  160:   printf("\n\n");
  161: }
  162: 
  163: 
  164: /*
  165:  * Text interface data structure initializations.
  166:  */
  167: void tui_init() {
  168:   screen_list_init();
  169:   screen_hash = addr_hash_create();
  170:   service_hash = serv_hash_create();
  171:   serv_hash_initialise(service_hash);
  172: 
  173:   printf("Listening on %s\n", options.interface);
  174: }
  175: 
  176: 
  177: /*
  178:  * Tick function indicating screen refresh
  179:  */
  180: void tui_tick(int print) {
  181:   if (print) {
  182:     tui_print();
  183:   }
  184: }
  185: 
  186: 
  187: /*
  188:  * Main UI loop. Code any interactive character inputs here.
  189:  */
  190: void tui_loop() {
  191:   int i;
  192:   extern sig_atomic_t foad;
  193: 
  194: #if defined(HAVE_TERMIOS_H)
  195:   struct termios new_termios, old_termios;
  196: 
  197:   tcgetattr(STDIN_FILENO, &old_termios);
  198:   new_termios = old_termios;
  199:   new_termios.c_lflag &= ~(ICANON|ECHO);
  200:   new_termios.c_cc[VMIN] = 1;
  201:   new_termios.c_cc[VTIME] = 0;
  202:   tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
  203: #elif defined(HAVE_SGTTY_H) && defined(TIOCSETP)
  204:   struct sgttyb new_tty, old_tty;
  205: 
  206:   ioctl(STDIN_FILENO, TIOCGETP, &old_tty);
  207:   new_tty = old_tty;
  208:   new_tty.sg_flags &= ~(ICANON|ECHO);
  209:   ioctl(STDIN_FILENO, TIOCSETP, &new_tty);
  210: #elif defined(HAVE_TERMIO_H)
  211:   struct termio new_termio, old_termio;
  212: 
  213:   ioctl(0, TCGETA, &old_termio);
  214:   new_termio = old_termio;
  215:   new_termio.c_lflag &= ~(ICANON|ECHO);
  216:   new_termio.c_cc[VMIN] = 1;
  217:   new_termio.c_cc[VTIME] = 0;
  218:   ioctl(0, TCSETA, &new_termio);
  219: #else
  220:   system("/bin/stty cbreak -echo >/dev/null 2>&1");
  221: #endif
  222: 
  223:   while ((i = getchar()) != 'q' && foad == 0) {
  224:     switch (i) {
  225:       case 'u':
  226:         tick(1);
  227:         break;
  228:       case 'n':
  229:         options.dnsresolution ^= 1;
  230:         printf("DNS resolution is %s.\n\n", options.dnsresolution ? "ON" : "OFF");
  231:         tick(1);
  232:         break;
  233:       case 'N':
  234:         options.portresolution ^= 1;
  235:         printf("Port resolution is %s.\n\n", options.portresolution ? "ON" : "OFF");
  236:         tick(1);
  237:         break;
  238:       case 's':
  239:         options.aggregate_src ^= 1;
  240:         printf("%s source host\n\n", options.aggregate_src ? "Hide" : "Show");
  241:         tick(1);
  242:         break;
  243:       case 'd':
  244:         options.aggregate_dest ^= 1;
  245:         printf("%s destination host\n\n", options.aggregate_dest ? "Hide" : "Show");
  246:         tick(1);
  247:         break;
  248:       case 'S':
  249:         if (options.showports == OPTION_PORTS_OFF) {
  250:           options.showports = OPTION_PORTS_SRC;
  251:         }
  252:         else if (options.showports == OPTION_PORTS_DEST) {
  253:           options.showports = OPTION_PORTS_ON;
  254:         }
  255:         else if(options.showports == OPTION_PORTS_ON) {
  256:           options.showports = OPTION_PORTS_DEST;
  257:         }
  258:         else {
  259:           options.showports = OPTION_PORTS_OFF;
  260:         }
  261:         printf("Showing ports:%s%s%s%s.\n\n",
  262:           options.showports == OPTION_PORTS_SRC ? " src" : "",
  263:           options.showports == OPTION_PORTS_DEST ? " dest" : "",
  264:           options.showports == OPTION_PORTS_ON ? " both" : "",
  265:           options.showports == OPTION_PORTS_OFF ? " none" : "");
  266:         tick(1);
  267:         break;
  268:       case 'D':
  269:         if (options.showports == OPTION_PORTS_OFF) {
  270:           options.showports = OPTION_PORTS_DEST;
  271:         }
  272:         else if (options.showports == OPTION_PORTS_SRC) {
  273:           options.showports = OPTION_PORTS_ON;
  274:         }
  275:         else if(options.showports == OPTION_PORTS_ON) {
  276:           options.showports = OPTION_PORTS_SRC;
  277:         }
  278:         else {
  279:           options.showports = OPTION_PORTS_OFF;
  280:         }
  281:         printf("Showing ports:%s%s%s%s.\n\n",
  282:           options.showports == OPTION_PORTS_SRC ? " src" : "",
  283:           options.showports == OPTION_PORTS_DEST ? " dest" : "",
  284:           options.showports == OPTION_PORTS_ON ? " both" : "",
  285:           options.showports == OPTION_PORTS_OFF ? " none" : "");
  286:         tick(1);
  287:         break;
  288:       case 'p':
  289:         options.showports =
  290:          (options.showports == OPTION_PORTS_OFF) ?
  291:           OPTION_PORTS_ON :
  292:           OPTION_PORTS_OFF;
  293:         printf("Showing ports:%s%s%s%s.\n\n",
  294:           options.showports == OPTION_PORTS_SRC ? " src" : "",
  295:           options.showports == OPTION_PORTS_DEST ? " dest" : "",
  296:           options.showports == OPTION_PORTS_ON ? " both" : "",
  297:           options.showports == OPTION_PORTS_OFF ? " none" : "");
  298:         tick(1);
  299:         break;
  300:       case 'P':
  301:         options.paused ^= 1;
  302:         if (options.paused) {
  303:           printf("Pausing... press 'P' again to continue.\n");
  304:         }
  305: 	else {
  306: 	  printf("Continuing.\n\n");
  307: 	  tick(1);
  308: 	}
  309: 	break;
  310:       case 'o':
  311:         options.freezeorder ^= 1;
  312:         printf("Order %s.\n\n", options.freezeorder ? "frozen" : "unfrozen");
  313: 	tick(1);
  314: 	break;
  315:       case '1':
  316:         options.sort = OPTION_SORT_DIV1;
  317:         printf("Sorting by column 1.\n\n");
  318: 	tick(1);
  319:         break;
  320:       case '2':
  321:         options.sort = OPTION_SORT_DIV2;
  322:         printf("Sorting by column 2.\n\n");
  323:         tick(1);
  324:         break;
  325:       case '3':
  326:         options.sort = OPTION_SORT_DIV3;
  327:         printf("Sorting by column 3.\n\n");
  328:         tick(1);
  329:         break;
  330:       case '<':
  331:         options.sort = OPTION_SORT_SRC;
  332:         printf("Sorting by column source.\n\n");
  333:         tick(1);
  334:         break;
  335:       case '>':
  336:         options.sort = OPTION_SORT_DEST;
  337:         printf("Sorting by column destination.\n\n");
  338:         tick(1);
  339:         break;
  340:       default:
  341:         break;
  342:     }
  343:   }
  344: 
  345: #if defined(HAVE_TERMIOS_H)
  346:   tcsetattr(STDIN_FILENO, TCSANOW, &old_termios);
  347: #elif defined(HAVE_SGTTY_H) && defined(TIOCSETP)
  348:   ioctl(0, TIOCSETP, &old_tty);
  349: #elif defined(HAVE_TERMIO_H)
  350:   ioctl(0, TCSETA, &old_termio);
  351: #else
  352:   system("/bin/stty -cbreak echo >/dev/null 2>&1");
  353: #endif
  354: }
  355: 

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