Annotation of embedaddon/mtr/curses.c, revision 1.1.1.1

1.1       misho       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: #include <strings.h>
                     21: #include <unistd.h>
                     22: 
                     23: #ifndef NO_CURSES
                     24: #include <ctype.h>
                     25: #include <stdlib.h>
                     26: #include <string.h>
                     27: 
                     28: /* MacOSX may need this before scoket.h...*/
                     29: #if defined(HAVE_SYS_TYPES_H)
                     30: #include <sys/types.h>
                     31: #else
                     32: /* If a system doesn't have sys/types.h, lets hope that time_t is an int */
                     33: #define time_t int
                     34: #endif
                     35: 
                     36: #include <sys/socket.h>
                     37: #include <netinet/in.h>
                     38: #include <arpa/inet.h>
                     39: 
                     40: #if defined(HAVE_NCURSES_H)
                     41: #  include <ncurses.h>
                     42: #elif defined(HAVE_NCURSES_CURSES_H)
                     43: #  include <ncurses/curses.h>
                     44: #elif defined(HAVE_CURSES_H)
                     45: #  include <curses.h>
                     46: #elif defined(HAVE_CURSESX_H)
                     47: #  include <cursesX.h>
                     48: #else
                     49: #  error No curses header file available
                     50: #endif
                     51: 
                     52: #ifndef HAVE_ATTRON
                     53: #define attron(x) 
                     54: #define attroff(x) 
                     55: #endif
                     56: 
                     57: #ifndef getmaxyx
                     58: #  define getmaxyx(win,y,x)    ((y) = (win)->_maxy + 1, (x) = (win)->_maxx + 1)
                     59: #endif
                     60: 
                     61: #include "mtr.h"
                     62: #include "mtr-curses.h"
                     63: #include "display.h"
                     64: #include "net.h"
                     65: #include "dns.h"
                     66: #ifndef NO_IPINFO
                     67: #include "asn.h"
                     68: #endif
                     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: #ifndef NO_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: #ifndef NO_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: #ifndef NO_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: #ifndef NO_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: void mtr_print_scaled(int ms) 
                    494: {
                    495:        int i;
                    496: 
                    497:        for (i = 0; i < NUM_FACTORS; i++) {
                    498:                if (ms <= scale[i]) {
                    499:                        printw("%c", block_map[i]);
                    500:                        return;
                    501:                }
                    502:        }
                    503:        printw(">");
                    504: }
                    505: 
                    506: 
                    507: void mtr_fill_graph(int at, int cols) 
                    508: {
                    509:        int* saved;
                    510:        int i;
                    511: 
                    512:        saved = net_saved_pings(at);
                    513:        for (i = SAVED_PINGS-cols; i < SAVED_PINGS; i++) {
                    514:                if (saved[i] == -2) {
                    515:                        printw(" ");
                    516:                } else if (saved[i] == -1) {
                    517:                        attron(A_BOLD);
                    518:                        printw("?");
                    519:                        attroff(A_BOLD);
                    520:                } else {
                    521:                        if (display_mode == 1) {
                    522:                                if (saved[i] > scale[6]) {
                    523:                                        printw("%c", block_map[NUM_FACTORS-1]);
                    524:                                } else {
                    525:                                        printw(".");
                    526:                                }
                    527:                        } else {
                    528:                                mtr_print_scaled(saved[i]);
                    529:                        }
                    530:                }
                    531:        }
                    532: }
                    533: 
                    534: 
                    535: void mtr_curses_graph(int startstat, int cols) 
                    536: {
                    537:        int max, at, y;
                    538:        ip_t * addr;
                    539:        char* name;
                    540: 
                    541:        max = net_max();
                    542: 
                    543:        for (at = display_offset; at < max; at++) {
                    544:                printw("%2d. ", at+1);
                    545: 
                    546:                addr = net_addr(at);
                    547:                if (!addr) {
                    548:                        printw("???\n");
                    549:                        continue;
                    550:                }
                    551: 
                    552:                if (! net_up(at))
                    553:                        attron(A_BOLD);
                    554:                if (addrcmp((void *) addr, (void *) &unspec_addr, af)) {
                    555: #ifndef NO_IPINFO
                    556:                        if (is_printii())
                    557:                                printw(fmt_ipinfo(addr));
                    558: #endif
                    559:                        name = dns_lookup(addr);
                    560:                        printw("%s", name?name:strlongip(addr));
                    561:                } else
                    562:                        printw("???");
                    563:                attroff(A_BOLD);
                    564: 
                    565:                getyx(stdscr, y, __unused_int);
                    566:                move(y, startstat);
                    567: 
                    568:                printw(" ");
                    569:                mtr_fill_graph(at, cols);
                    570:                printw("\n");
                    571:        }
                    572: }
                    573: 
                    574: 
                    575: void mtr_curses_redraw(void)
                    576: {
                    577:   int maxx;
                    578:   int startstat;
                    579:   int rowstat;
                    580:   time_t t;
                    581: 
                    582:   int i, j;
                    583:   int  hd_len = 0;
                    584:   char buf[1024];
                    585:   char fmt[16];
                    586:   
                    587: 
                    588:   erase();
                    589:   getmaxyx(stdscr, __unused_int, maxx);
                    590: 
                    591:   rowstat = 5;
                    592: 
                    593:   move(0, 0);
                    594:   attron(A_BOLD);
                    595:   pwcenter("My traceroute  [v" MTR_VERSION "]");
                    596:   attroff(A_BOLD);
                    597: 
                    598:   mvprintw(1, 0, "%s (%s)", LocalHostname, net_localaddr());
                    599:   /*
                    600:   printw("(tos=0x%X ", tos);
                    601:   printw("psize=%d ", packetsize );
                    602:   printw("bitpattern=0x%02X)", (unsigned char)(abs(bitpattern)));
                    603:   if( cpacketsize > 0 ){
                    604:     printw("psize=%d ", cpacketsize);
                    605:   } else {
                    606:     printw("psize=rand(%d,%d) ",MINPACKET, -cpacketsize);
                    607:   }
                    608:   if( bitpattern>=0 ){
                    609:     printw("bitpattern=0x%02X)", (unsigned char)(bitpattern));
                    610:   } else {
                    611:     printw("bitpattern=rand(0x00-FF))");
                    612:   }
                    613:   */
                    614:   time(&t);
                    615:   mvprintw(1, maxx-25, ctime(&t));
                    616: 
                    617:   printw("Keys:  ");
                    618:   attron(A_BOLD); printw("H"); attroff(A_BOLD); printw("elp   ");
                    619:   attron(A_BOLD); printw("D"); attroff(A_BOLD); printw("isplay mode   ");
                    620:   attron(A_BOLD); printw("R"); attroff(A_BOLD); printw("estart statistics   ");
                    621:   attron(A_BOLD); printw("O"); attroff(A_BOLD); printw("rder of fields   ");
                    622:   attron(A_BOLD); printw("q"); attroff(A_BOLD); printw("uit\n");
                    623:   
                    624:   if (display_mode == 0) {
                    625:     for (i=0; i < MAXFLD; i++ ) {
                    626:        j = fld_index[fld_active[i]];
                    627:        if (j < 0) continue;
                    628: 
                    629:        sprintf( fmt, "%%%ds", data_fields[j].length );
                    630:         sprintf( buf + hd_len, fmt, data_fields[j].title );
                    631:        hd_len +=  data_fields[j].length;
                    632:     }
                    633:     attron(A_BOLD);
                    634:     mvprintw(rowstat - 1, 0, " Host");
                    635:     mvprintw(rowstat - 1, maxx-hd_len-1, "%s", buf);
                    636:     mvprintw(rowstat - 2, maxx-hd_len-1, "   Packets               Pings");
                    637:     attroff(A_BOLD);
                    638: 
                    639:     move(rowstat, 0);
                    640:     mtr_curses_hosts(maxx-hd_len-1);
                    641: 
                    642:   } else {
                    643:     char msg[80];
                    644:     int padding = 30;
                    645: #ifndef NO_IPINFO
                    646:     if (is_printii())
                    647:       padding += get_iiwidth();
                    648: #endif
                    649:     int max_cols = maxx<=SAVED_PINGS+padding ? maxx-padding : SAVED_PINGS;
                    650:     startstat = padding - 2;
                    651: 
                    652:     sprintf(msg, " Last %3d pings", max_cols);
                    653:     mvprintw(rowstat - 1, startstat, msg);
                    654:     
                    655:     attroff(A_BOLD);
                    656:     move(rowstat, 0);
                    657: 
                    658:     mtr_gen_scale();
                    659:     mtr_curses_graph(startstat, max_cols);
                    660: 
                    661:     printw("\n");
                    662:     attron(A_BOLD);
                    663:     printw("Scale:");
                    664:     attroff(A_BOLD);
                    665:     
                    666:     for (i = 0; i < NUM_FACTORS-1; i++) {
                    667:       printw("  %c:%d ms", block_map[i], scale[i]/1000);
                    668:     }
                    669:   }
                    670: 
                    671:   refresh();
                    672: }
                    673: 
                    674: 
                    675: void mtr_curses_open(void)
                    676: {
                    677:   initscr();
                    678:   raw();
                    679:   noecho(); 
                    680: 
                    681:   mtr_curses_init();
                    682:   mtr_curses_redraw();
                    683: }
                    684: 
                    685: 
                    686: void mtr_curses_close(void)
                    687: {  
                    688:   printw("\n");
                    689:   endwin();
                    690: }
                    691: 
                    692: 
                    693: void mtr_curses_clear(void)
                    694: {
                    695:   mtr_curses_close();
                    696:   mtr_curses_open();
                    697: }

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