Annotation of embedaddon/mtr/curses.c, revision 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>