File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / curses.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:33:48 2016 UTC (7 years, 7 months ago) by misho
Branches: mtr, elwix, MAIN
CVS tags: v0_86, HEAD
mtr 0.86

    1: /*
    2:     mtr  --  a network diagnostic tool
    3:     Copyright (C) 1997,1998  Matt Kimball
    4: 
    5:     This program is free software; you can redistribute it and/or modify
    6:     it under the terms of the GNU General Public License version 2 as 
    7:     published by the Free Software Foundation.
    8: 
    9:     This program is distributed in the hope that it will be useful,
   10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12:     GNU General Public License for more details.
   13: 
   14:     You should have received a copy of the GNU General Public License
   15:     along with this program; if not, write to the Free Software
   16:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   17: */
   18: 
   19: #include "config.h"
   20: 
   21: #include <strings.h>
   22: #include <unistd.h>
   23: 
   24: #ifndef NO_CURSES
   25: #include <ctype.h>
   26: #include <stdlib.h>
   27: #include <string.h>
   28: 
   29: /* MacOSX may need this before scoket.h...*/
   30: #if defined(HAVE_SYS_TYPES_H)
   31: #include <sys/types.h>
   32: #else
   33: /* If a system doesn't have sys/types.h, lets hope that time_t is an int */
   34: #define time_t int
   35: #endif
   36: 
   37: #include <sys/socket.h>
   38: #include <netinet/in.h>
   39: #include <arpa/inet.h>
   40: 
   41: #if defined(HAVE_NCURSES_H)
   42: #  include <ncurses.h>
   43: #elif defined(HAVE_NCURSES_CURSES_H)
   44: #  include <ncurses/curses.h>
   45: #elif defined(HAVE_CURSES_H)
   46: #  include <curses.h>
   47: #elif defined(HAVE_CURSESX_H)
   48: #  include <cursesX.h>
   49: #else
   50: #  error No curses header file available
   51: #endif
   52: 
   53: #ifndef HAVE_ATTRON
   54: #define attron(x) 
   55: #define attroff(x) 
   56: #endif
   57: 
   58: #ifndef getmaxyx
   59: #  define getmaxyx(win,y,x)	((y) = (win)->_maxy + 1, (x) = (win)->_maxx + 1)
   60: #endif
   61: 
   62: #include "mtr.h"
   63: #include "mtr-curses.h"
   64: #include "net.h"
   65: #include "dns.h"
   66: #include "asn.h"
   67: #include "display.h"
   68: 
   69: #include "version.h"
   70: #endif
   71: 
   72: #include <time.h>
   73: 
   74: extern char LocalHostname[];
   75: extern int fstTTL;
   76: extern int maxTTL;
   77: extern int cpacketsize;
   78: extern int bitpattern;
   79: extern int tos;
   80: extern float WaitTime;
   81: extern int af;
   82: extern int mtrtype;
   83: 
   84: static int __unused_int;
   85: 
   86: void pwcenter(char *str) 
   87: {
   88:   int maxx;
   89:   int cx;
   90: 
   91:   getmaxyx(stdscr, __unused_int, maxx);
   92:   cx = (signed)(maxx - strlen(str)) / 2;
   93:   while(cx-- > 0)
   94:     printw(" ");
   95:   printw(str);
   96: }
   97: 
   98: 
   99: int mtr_curses_keyaction(void)
  100: {
  101:   int c = getch();
  102:   int i=0;
  103:   float f = 0.0;
  104:   char buf[MAXFLD+1];
  105: 
  106:   if(c == 'q')
  107:     return ActionQuit;
  108:   if(c==3)
  109:      return ActionQuit;
  110:   if (c==12)
  111:      return ActionClear;
  112:   if ((c==19) || (tolower (c) == 'p'))
  113:      return ActionPause;
  114:   if ((c==17) || (c == ' '))
  115:      return ActionResume;
  116:   if(tolower(c) == 'r')
  117:     return ActionReset;
  118:   if (tolower(c) == 'd')
  119:     return ActionDisplay;
  120:   if (tolower(c) == 'e')
  121:     return ActionMPLS;
  122:   if (tolower(c) == 'n')
  123:     return ActionDNS;
  124: #ifdef IPINFO
  125:   if (tolower(c) == 'y')
  126:     return ActionII;
  127:   if (tolower(c) == 'z')
  128:     return ActionAS;
  129: #endif
  130:   if (c == '+')
  131:     return ActionScrollDown;
  132:   if (c == '-')
  133:     return ActionScrollUp;
  134: 
  135:   if (tolower(c) == 's') {
  136:     mvprintw(2, 0, "Change Packet Size: %d\n", cpacketsize );
  137:     mvprintw(3, 0, "Size Range: %d-%d, < 0:random.\n", MINPACKET, MAXPACKET);
  138:     move(2,20);
  139:     refresh();
  140:     while ( (c=getch ()) != '\n' && i < MAXFLD ) {
  141:       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh ();
  142:       buf[i++] = c;   /* need more checking on 'c' */
  143:     }
  144:     buf[i] = '\0';
  145:     cpacketsize = atoi ( buf );
  146:     return ActionNone;
  147:   }
  148:   if (tolower(c) == 'b') {
  149:     mvprintw(2, 0, "Ping Bit Pattern: %d\n", bitpattern );
  150:     mvprintw(3, 0, "Pattern Range: 0(0x00)-255(0xff), <0 random.\n");
  151:     move(2,18);
  152:     refresh();
  153:     while ( (c=getch ()) != '\n' && i < MAXFLD ) {
  154:       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh ();
  155:       buf[i++] = c;   /* need more checking on 'c' */
  156:     }
  157:     buf[i] = '\0';
  158:     bitpattern = atoi ( buf );
  159:     if( bitpattern > 255 ) { bitpattern = -1; }
  160:     return ActionNone;
  161:   }
  162:   if ( c == 'Q') {    /* can not be tolower(c) */
  163:     mvprintw(2, 0, "Type of Service(tos): %d\n", tos );
  164:     mvprintw(3, 0, "default 0x00, min cost 0x02, rel 0x04,, thr 0x08, low del 0x10...\n");
  165:     move(2,22);
  166:     refresh();
  167:     while ( (c=getch ()) != '\n' && i < MAXFLD ) {
  168:       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
  169:       buf[i++] = c;   /* need more checking on 'c' */
  170:     }
  171:     buf[i] = '\0';
  172:     tos = atoi ( buf );
  173:     if( tos > 255 || tos <0 ) {
  174:       tos = 0;
  175:     }
  176:     return ActionNone;
  177:   }
  178:   if (tolower(c) == 'i') {
  179:     mvprintw(2, 0, "Interval : %0.0f\n\n", WaitTime );
  180:     move(2,11);
  181:     refresh();
  182:     while ( (c=getch ()) != '\n' && i < MAXFLD ) {
  183:       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
  184:       buf[i++] = c;   /* need more checking on 'c' */
  185:     }
  186:     buf[i] = '\0';
  187: 
  188:     f = atof( buf );
  189: 
  190:     if (f <= 0.0) return ActionNone;
  191:     if (getuid() != 0 && f < 1.0)
  192:       return ActionNone;
  193:     WaitTime = f;
  194: 
  195:     return ActionNone;
  196:   }
  197:   if (tolower(c) == 'f') {
  198:     mvprintw(2, 0, "First TTL: %d\n\n", fstTTL );
  199:     move(2,11);
  200:     refresh();
  201:     while ( (c=getch ()) != '\n' && i < MAXFLD ) {
  202:       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
  203:       buf[i++] = c;   /* need more checking on 'c' */
  204:     }
  205:     buf[i] = '\0';
  206:     i = atoi( buf );
  207: 
  208:     if ( i < 1 || i> maxTTL ) return ActionNone;
  209:     fstTTL = i;
  210: 
  211:     return ActionNone;
  212:   }
  213:   if (tolower(c) == 'm') {
  214:     mvprintw(2, 0, "Max TTL: %d\n\n", maxTTL );
  215:     move(2,9);
  216:     refresh();
  217:     while ( (c=getch ()) != '\n' && i < MAXFLD ) {
  218:       attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
  219:       buf[i++] = c;   /* need more checking on 'c' */
  220:     }
  221:     buf[i] = '\0';
  222:     i = atoi( buf );
  223: 
  224:     if ( i < fstTTL || i>(MaxHost-1) ) return ActionNone;
  225:     maxTTL = i;
  226: 
  227:     return ActionNone;
  228:   }
  229:   /* fields to display & their ordering */
  230:   if (tolower(c) == 'o') {
  231:     mvprintw(2, 0, "Fields: %s\n\n", fld_active );
  232: 
  233:     for( i=0; i<MAXFLD; i++ ){
  234:       if( data_fields[i].descr != NULL )
  235:           printw( "  %s\n", data_fields[i].descr);
  236:     }
  237:     printw("\n");
  238:     move(2,8);                /* length of "Fields: " */
  239:     refresh();
  240: 
  241:     i = 0;
  242:     while ( (c=getch ()) != '\n' && i < MAXFLD ) {
  243:       if( strchr(available_options, c) ) {
  244:         attron(A_BOLD); printw("%c", c); attroff(A_BOLD); refresh();
  245:         buf[i++] = c; /* Only permit values in "available_options" be entered */
  246:       } else {
  247:         printf("\a"); /* Illegal character. Beep, ring the bell. */
  248:       }
  249:     }
  250:     buf[i] = '\0';
  251:     if ( strlen( buf ) > 0 ) strcpy( fld_active, buf );
  252: 
  253:     return ActionNone;
  254:   }
  255:   if (tolower(c) == 'j') {
  256:     if( index(fld_active, 'N') ) {
  257:       strcpy(fld_active, "DR AGJMXI");        /* GeoMean and jitter */
  258:     } else {
  259:       strcpy(fld_active, "LS NABWV");         /* default */
  260:     }
  261:     return ActionNone;
  262:   }
  263:   if (tolower(c) == 'u') {
  264:     switch ( mtrtype ) {
  265:     case IPPROTO_ICMP:
  266:     case IPPROTO_TCP:
  267:       mtrtype = IPPROTO_UDP;
  268:       break;
  269:     case IPPROTO_UDP:
  270:       mtrtype = IPPROTO_ICMP;
  271:       break;
  272:     }
  273:     return ActionNone;
  274:   }
  275:   if (tolower(c) == 't') {
  276:     switch ( mtrtype ) {
  277:     case IPPROTO_ICMP:
  278:     case IPPROTO_UDP:
  279:       mtrtype = IPPROTO_TCP;
  280:       break;
  281:     case IPPROTO_TCP:
  282:       mtrtype = IPPROTO_ICMP;
  283:       break;
  284:     }
  285:     return ActionNone;
  286:   }
  287:   /* reserve to display help message -Min */
  288:   if (tolower(c) == '?'|| tolower(c) == 'h') {
  289:     int pressanykey_row = 20;
  290:     mvprintw(2, 0, "Command:\n" );
  291:     printw("  ?|h     help\n" );
  292:     printw("  p       pause (SPACE to resume)\n" );
  293:     printw("  d       switching display mode\n" );
  294:     printw("  e       toggle MPLS information on/off\n" );
  295:     printw("  n       toggle DNS on/off\n" );
  296:     printw("  r       reset all counters\n" );
  297:     printw("  o str   set the columns to display, default str='LRS N BAWV'\n" );
  298:     printw("  j       toggle latency(LS NABWV)/jitter(DR AGJMXI) stats\n" );
  299:     printw("  c <n>   report cycle n, default n=infinite\n" );
  300:     printw("  i <n>   set the ping interval to n seconds, default n=1\n" );
  301:     printw("  f <n>   set the initial time-to-live(ttl), default n=1\n" );
  302:     printw("  m <n>   set the max time-to-live, default n= # of hops\n" );
  303:     printw("  s <n>   set the packet size to n or random(n<0)\n" );
  304:     printw("  b <c>   set ping bit pattern to c(0..255) or random(c<0)\n" );
  305:     printw("  Q <t>   set ping packet's TOS to t\n" );
  306:     printw("  u       switch between ICMP ECHO and UDP datagrams\n" );
  307: #ifdef IPINFO
  308:     printw("  y       switching IP info\n");
  309:     printw("  z       toggle ASN info on/off\n");
  310:     pressanykey_row += 2;
  311: #endif
  312:     printw("\n");
  313:     mvprintw(pressanykey_row, 0, " press any key to go back..." );
  314: 
  315:     getch();                  /* get any key */
  316:     return ActionNone;
  317:   }
  318: 
  319:   return ActionNone;          /* ignore unknown input */
  320: }
  321: 
  322: 
  323: void mtr_curses_hosts(int startstat) 
  324: {
  325:   int max;
  326:   int at;
  327:   struct mplslen *mpls, *mplss;
  328:   ip_t *addr, *addrs;
  329:   int y;
  330:   char *name;
  331: 
  332:   int i, j, k;
  333:   int hd_len;
  334:   char buf[1024];
  335: 
  336:   max = net_max();
  337: 
  338:   for(at = net_min () + display_offset; at < max; at++) {
  339:     printw("%2d. ", at + 1);
  340:     addr = net_addr(at);
  341:     mpls = net_mpls(at);
  342: 
  343:     if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) {
  344:       name = dns_lookup(addr);
  345:       if (! net_up(at))
  346: 	attron(A_BOLD);
  347: #ifdef IPINFO
  348:       if (is_printii())
  349:         printw(fmt_ipinfo(addr));
  350: #endif
  351:       if(name != NULL) {
  352:         if (show_ips) printw("%s (%s)", name, strlongip(addr));
  353:         else printw("%s", name);
  354:       } else {
  355: 	printw("%s", strlongip( addr ) );
  356:       }
  357:       attroff(A_BOLD);
  358: 
  359:       getyx(stdscr, y, __unused_int);
  360:       move(y, startstat);
  361: 
  362:       /* net_xxx returns times in usecs. Just display millisecs */
  363:       hd_len = 0;
  364:       for( i=0; i<MAXFLD; i++ ) {
  365: 	/* Ignore options that don't exist */
  366: 	/* On the other hand, we now check the input side. Shouldn't happen, 
  367: 	   can't be careful enough. */
  368: 	j = fld_index[fld_active[i]];
  369: 	if (j == -1) continue; 
  370: 
  371: 	/* temporay hack for stats usec to ms... */
  372: 	if( index( data_fields[j].format, 'f' ) ) {
  373: 	  sprintf(buf + hd_len, data_fields[j].format,
  374: 		data_fields[j].net_xxx(at) /1000.0 );
  375: 	} else {
  376: 	  sprintf(buf + hd_len, data_fields[j].format,
  377: 		data_fields[j].net_xxx(at) );
  378: 	}
  379: 	hd_len +=  data_fields[j].length;
  380:       }
  381:       buf[hd_len] = 0;
  382:       printw("%s", buf);
  383: 
  384:       for (k=0; k < mpls->labels && enablempls; k++) {
  385:         if((k+1 < mpls->labels) || (mpls->labels == 1)) {
  386:            /* if we have more labels */
  387:            printw("\n    [MPLS: Lbl %lu Exp %u S %u TTL %u]", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]);
  388:         } else {
  389:            /* bottom label */
  390:            printw("\n    [MPLS: Lbl %lu Exp %u S %u TTL %u]", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]);
  391:         }
  392:       }
  393: 
  394:       /* Multi path */
  395:       for (i=0; i < MAXPATH; i++ ) {
  396:         addrs = net_addrs(at, i);
  397:         mplss = net_mplss(at, i);
  398: 	if ( addrcmp( (void *) addrs, (void *) addr, af ) == 0 ) continue;
  399: 	if ( addrcmp( (void *) addrs, (void *) &unspec_addr, af ) == 0 ) break;
  400: 
  401:         name = dns_lookup(addrs);
  402:         if (! net_up(at)) attron(A_BOLD);
  403:         printw("\n    ");
  404: #ifdef IPINFO
  405:         if (is_printii())
  406:           printw(fmt_ipinfo(addrs));
  407: #endif
  408:         if (name != NULL) {
  409: 	  if (show_ips) printw("%s (%s)", name, strlongip(addrs));
  410: 	  else printw("%s", name);
  411:         } else {
  412: 	  printw("%s", strlongip( addrs ) );
  413:         }
  414:         for (k=0; k < mplss->labels && enablempls; k++) {
  415:           printw("\n    [MPLS: Lbl %lu Exp %u S %u TTL %u]", mplss->label[k], mplss->exp[k], mplss->s[k], mplss->ttl[k]);
  416:         }
  417:         attroff(A_BOLD);
  418:       }
  419: 
  420:     } else {
  421:       printw("???");
  422:     }
  423: 
  424:     printw("\n");
  425:   }
  426:   move(2, 0);
  427: }
  428: 
  429: #define NUM_FACTORS 8
  430: static double factors[NUM_FACTORS];
  431: static int scale[NUM_FACTORS];
  432: static int low_ms, high_ms;
  433: 
  434: void mtr_gen_scale(void) 
  435: {
  436: 	int *saved, i, max, at;
  437: 	int range;
  438: 
  439: 	low_ms = 1000000;
  440: 	high_ms = -1;
  441: 
  442: 	for (i = 0; i < NUM_FACTORS; i++) {
  443: 		scale[i] = 0;
  444: 	}
  445: 	max = net_max();
  446: 	for (at = display_offset; at < max; at++) {
  447: 		saved = net_saved_pings(at);
  448: 		for (i = 0; i < SAVED_PINGS; i++) {
  449: 			if (saved[i] < 0) continue;
  450: 			if (saved[i] < low_ms) {
  451: 				low_ms = saved[i];
  452: 			}
  453: 			if (saved[i] > high_ms) {
  454: 				high_ms = saved[i];
  455: 			}
  456: 		}
  457: 	}
  458: 	range = high_ms - low_ms;
  459: 	for (i = 0; i < NUM_FACTORS; i++) {
  460: 		scale[i] = low_ms + ((double)range * factors[i]);
  461: 	}
  462: }
  463: 
  464: 
  465: static char block_map[NUM_FACTORS];
  466: 
  467: void mtr_curses_init() {
  468: 	int i;
  469: 	int block_split;
  470: 
  471: 	/* Initialize factors to a log scale. */
  472: 	for (i = 0; i < NUM_FACTORS; i++) {
  473: 		factors[i] = ((double)1 / NUM_FACTORS) * (i + 1);
  474: 		factors[i] *= factors[i]; /* Squared. */
  475: 	}
  476: 
  477: 	/* Initialize block_map. */
  478: 	block_split = (NUM_FACTORS - 2) / 2;
  479: 	if (block_split > 9) {
  480: 		block_split = 9;
  481: 	}
  482: 	for (i = 1; i <= block_split; i++) {
  483: 		block_map[i] = '0' + i;
  484: 	}
  485: 	for (i = block_split+1; i < NUM_FACTORS-1; i++) {
  486: 		block_map[i] = 'a' + i - block_split - 1;
  487: 	}
  488: 	block_map[0] = '.';
  489: 	block_map[NUM_FACTORS-1] = '>';
  490: }
  491: 
  492: 
  493: static int block_col[NUM_FACTORS+1] =
  494: {	// 1:black 2:red 3:green 4:brown/yellow 5:blue 6:magenta 7:cyan 8:white
  495:         COLOR_PAIR(2)|A_BOLD,
  496: 	A_NORMAL,
  497: 	COLOR_PAIR(3),
  498: 	COLOR_PAIR(3)|A_BOLD,
  499: 	COLOR_PAIR(4)|A_BOLD,
  500: 	COLOR_PAIR(6)|A_BOLD,
  501: 	COLOR_PAIR(6),
  502: 	COLOR_PAIR(2),
  503: 	COLOR_PAIR(2)|A_BOLD
  504: };
  505: 
  506: void mtr_print_scaled(int ms) 
  507: {
  508: 	int i;
  509: 
  510: 	for (i = 0; i < NUM_FACTORS; i++) {
  511: 		if (ms <= scale[i]) {
  512: 			attrset(block_col[i+1]);
  513: 			printw("%c", block_map[i]);
  514: 			attrset(A_NORMAL);
  515: 			return;
  516: 		}
  517: 	}
  518: 	printw(">");
  519: }
  520: 
  521: 
  522: void mtr_fill_graph(int at, int cols) 
  523: {
  524: 	int* saved;
  525: 	int i;
  526: 
  527: 	saved = net_saved_pings(at);
  528: 	for (i = SAVED_PINGS-cols; i < SAVED_PINGS; i++) {
  529: 		if (saved[i] == -2) {
  530: 			printw(" ");
  531: 		} else if (saved[i] == -1) {
  532: 		        attrset(block_col[0]);
  533: 			printw("%c", '?');
  534: 			attrset(A_NORMAL);
  535: 		} else {
  536: 			if (display_mode == 1) {
  537: 				if (saved[i] > scale[6]) {
  538: 					printw("%c", block_map[NUM_FACTORS-1]);
  539: 				} else {
  540: 					printw(".");
  541: 				}
  542: 			} else {
  543: 				mtr_print_scaled(saved[i]);
  544: 			}
  545: 		}
  546: 	}
  547: }
  548: 
  549: 
  550: void mtr_curses_graph(int startstat, int cols) 
  551: {
  552: 	int max, at, y;
  553: 	ip_t * addr;
  554: 	char* name;
  555: 
  556: 	max = net_max();
  557: 
  558: 	for (at = display_offset; at < max; at++) {
  559: 		printw("%2d. ", at+1);
  560: 
  561: 		addr = net_addr(at);
  562: 		if (!addr) {
  563: 			printw("???\n");
  564: 			continue;
  565: 		}
  566: 
  567: 		if (! net_up(at))
  568: 			attron(A_BOLD);
  569: 		if (addrcmp((void *) addr, (void *) &unspec_addr, af)) {
  570: #ifdef IPINFO
  571: 			if (is_printii())
  572: 				printw(fmt_ipinfo(addr));
  573: #endif
  574: 			name = dns_lookup(addr);
  575: 			printw("%s", name?name:strlongip(addr));
  576: 		} else
  577: 			printw("???");
  578: 		attroff(A_BOLD);
  579: 
  580: 		getyx(stdscr, y, __unused_int);
  581: 		move(y, startstat);
  582: 
  583: 		printw(" ");
  584: 		mtr_fill_graph(at, cols);
  585: 		printw("\n");
  586: 	}
  587: }
  588: 
  589: 
  590: void mtr_curses_redraw(void)
  591: {
  592:   int maxx;
  593:   int startstat;
  594:   int rowstat;
  595:   time_t t;
  596: 
  597:   int i, j;
  598:   int  hd_len = 0;
  599:   char buf[1024];
  600:   char fmt[16];
  601:   
  602: 
  603:   erase();
  604:   getmaxyx(stdscr, __unused_int, maxx);
  605: 
  606:   rowstat = 5;
  607: 
  608:   move(0, 0);
  609:   attron(A_BOLD);
  610:   pwcenter("My traceroute  [v" MTR_VERSION "]");
  611:   attroff(A_BOLD);
  612: 
  613:   mvprintw(1, 0, "%s (%s)", LocalHostname, net_localaddr());
  614:   /*
  615:   printw("(tos=0x%X ", tos);
  616:   printw("psize=%d ", packetsize );
  617:   printw("bitpattern=0x%02X)", (unsigned char)(abs(bitpattern)));
  618:   if( cpacketsize > 0 ){
  619:     printw("psize=%d ", cpacketsize);
  620:   } else {
  621:     printw("psize=rand(%d,%d) ",MINPACKET, -cpacketsize);
  622:   }
  623:   if( bitpattern>=0 ){
  624:     printw("bitpattern=0x%02X)", (unsigned char)(bitpattern));
  625:   } else {
  626:     printw("bitpattern=rand(0x00-FF))");
  627:   }
  628:   */
  629:   time(&t);
  630:   mvprintw(1, maxx-25, ctime(&t));
  631: 
  632:   printw("Keys:  ");
  633:   attron(A_BOLD); printw("H"); attroff(A_BOLD); printw("elp   ");
  634:   attron(A_BOLD); printw("D"); attroff(A_BOLD); printw("isplay mode   ");
  635:   attron(A_BOLD); printw("R"); attroff(A_BOLD); printw("estart statistics   ");
  636:   attron(A_BOLD); printw("O"); attroff(A_BOLD); printw("rder of fields   ");
  637:   attron(A_BOLD); printw("q"); attroff(A_BOLD); printw("uit\n");
  638:   
  639:   if (display_mode == 0) {
  640:     for (i=0; i < MAXFLD; i++ ) {
  641: 	j = fld_index[fld_active[i]];
  642: 	if (j < 0) continue;
  643: 
  644: 	sprintf( fmt, "%%%ds", data_fields[j].length );
  645:         sprintf( buf + hd_len, fmt, data_fields[j].title );
  646: 	hd_len +=  data_fields[j].length;
  647:     }
  648:     attron(A_BOLD);
  649:     mvprintw(rowstat - 1, 0, " Host");
  650:     mvprintw(rowstat - 1, maxx-hd_len-1, "%s", buf);
  651:     mvprintw(rowstat - 2, maxx-hd_len-1, "   Packets               Pings");
  652:     attroff(A_BOLD);
  653: 
  654:     move(rowstat, 0);
  655:     mtr_curses_hosts(maxx-hd_len-1);
  656: 
  657:   } else {
  658:     char msg[80];
  659:     int padding = 30;
  660: #ifdef IPINFO
  661:     if (is_printii())
  662:       padding += get_iiwidth();
  663: #endif
  664:     int max_cols = maxx<=SAVED_PINGS+padding ? maxx-padding : SAVED_PINGS;
  665:     startstat = padding - 2;
  666: 
  667:     sprintf(msg, " Last %3d pings", max_cols);
  668:     mvprintw(rowstat - 1, startstat, msg);
  669:     
  670:     attroff(A_BOLD);
  671:     move(rowstat, 0);
  672: 
  673:     mtr_gen_scale();
  674:     mtr_curses_graph(startstat, max_cols);
  675: 
  676:     printw("\n");
  677:     attron(A_BOLD);
  678:     printw("Scale:");
  679:     attroff(A_BOLD);
  680:     
  681:     for (i = 0; i < NUM_FACTORS-1; i++) {
  682:       printw("  ");
  683:       attrset(block_col[i+1]);
  684:       printw("%c", block_map[i]);
  685:       attrset(A_NORMAL);
  686:       printw(":%d ms", scale[i]/1000);
  687:     }
  688:     printw("  ");
  689:     attrset(block_col[NUM_FACTORS]);
  690:     printw("%c", block_map[NUM_FACTORS-1]);
  691:     attrset(A_NORMAL);
  692:   }
  693: 
  694:   refresh();
  695: }
  696: 
  697: 
  698: void mtr_curses_open(void)
  699: {
  700:   initscr();
  701:   raw();
  702:   noecho(); 
  703:   start_color();
  704:   int i;
  705:   for (i = 0; i < 8; i++)
  706:       init_pair(i+1, i, 0);
  707: 
  708:   mtr_curses_init();
  709:   mtr_curses_redraw();
  710: }
  711: 
  712: 
  713: void mtr_curses_close(void)
  714: {  
  715:   printw("\n");
  716:   endwin();
  717: }
  718: 
  719: 
  720: void mtr_curses_clear(void)
  721: {
  722:   mtr_curses_close();
  723:   mtr_curses_open();
  724: }

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