|
Packit |
b802ec |
/*
|
|
Packit |
b802ec |
mtr -- a network diagnostic tool
|
|
Packit |
b802ec |
Copyright (C) 1997,1998 Matt Kimball
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
b802ec |
it under the terms of the GNU General Public License version 2 as
|
|
Packit |
b802ec |
published by the Free Software Foundation.
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
This program is distributed in the hope that it will be useful,
|
|
Packit |
b802ec |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b802ec |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
b802ec |
GNU General Public License for more details.
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
You should have received a copy of the GNU General Public License
|
|
Packit |
b802ec |
along with this program; if not, write to the Free Software
|
|
Packit |
b802ec |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
Packit |
b802ec |
*/
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "config.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "mtr.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include <strings.h>
|
|
Packit |
b802ec |
#include <unistd.h>
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include <ctype.h>
|
|
Packit |
b802ec |
#include <stdlib.h>
|
|
Packit |
b802ec |
#include <string.h>
|
|
Packit |
b802ec |
#include <time.h>
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* MacOSX may need this before socket.h...*/
|
|
Packit |
b802ec |
#if defined(HAVE_SYS_TYPES_H)
|
|
Packit |
b802ec |
#include <sys/types.h>
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include <sys/socket.h>
|
|
Packit |
b802ec |
#include <netinet/in.h>
|
|
Packit |
b802ec |
#include <arpa/inet.h>
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#if defined(HAVE_NCURSES_H)
|
|
Packit |
b802ec |
#include <ncurses.h>
|
|
Packit |
b802ec |
#elif defined(HAVE_NCURSES_CURSES_H)
|
|
Packit |
b802ec |
#include <ncurses/curses.h>
|
|
Packit |
b802ec |
#elif defined(HAVE_CURSES_H)
|
|
Packit |
b802ec |
#include <curses.h>
|
|
Packit |
b802ec |
#elif defined(HAVE_CURSESX_H)
|
|
Packit |
b802ec |
#include <cursesX.h>
|
|
Packit |
b802ec |
#else
|
|
Packit |
b802ec |
#error No curses header file available
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* This go-around is needed only when compiling with antique version of curses.
|
|
Packit |
b802ec |
getmaxyx is part of Technical Standard X/Open Curses Issue 4, Version 2 (1996).
|
|
Packit |
b802ec |
http://pubs.opengroup.org/onlinepubs/9693989999/toc.pdf see page 106 */
|
|
Packit |
b802ec |
#ifndef getmaxyx
|
|
Packit |
b802ec |
#define getmaxyx(win,y,x) ((y) = (win)->_maxy + 1, (x) = (win)->_maxx + 1)
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#include "mtr.h"
|
|
Packit |
b802ec |
#include "mtr-curses.h"
|
|
Packit |
b802ec |
#include "net.h"
|
|
Packit |
b802ec |
#include "dns.h"
|
|
Packit |
b802ec |
#include "asn.h"
|
|
Packit |
b802ec |
#include "display.h"
|
|
Packit |
b802ec |
#include "utils.h"
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
enum { NUM_FACTORS = 8 };
|
|
Packit |
b802ec |
static double factors[NUM_FACTORS];
|
|
Packit |
b802ec |
static int scale[NUM_FACTORS];
|
|
Packit |
b802ec |
static char block_map[NUM_FACTORS];
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
enum { black = 1, red, green, yellow, blue, magenta, cyan, white };
|
|
Packit |
b802ec |
static const int block_col[NUM_FACTORS + 1] = {
|
|
Packit |
b802ec |
COLOR_PAIR(red) | A_BOLD,
|
|
Packit |
b802ec |
A_NORMAL,
|
|
Packit |
b802ec |
COLOR_PAIR(green),
|
|
Packit |
b802ec |
COLOR_PAIR(green) | A_BOLD,
|
|
Packit |
b802ec |
COLOR_PAIR(yellow) | A_BOLD,
|
|
Packit |
b802ec |
COLOR_PAIR(magenta) | A_BOLD,
|
|
Packit |
b802ec |
COLOR_PAIR(magenta),
|
|
Packit |
b802ec |
COLOR_PAIR(red),
|
|
Packit |
b802ec |
COLOR_PAIR(red) | A_BOLD
|
|
Packit |
b802ec |
};
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void pwcenter(
|
|
Packit |
b802ec |
char *str)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int maxx;
|
|
Packit |
b802ec |
size_t cx;
|
|
Packit |
b802ec |
int __unused_int ATTRIBUTE_UNUSED;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
getmaxyx(stdscr, __unused_int, maxx);
|
|
Packit |
b802ec |
cx = (size_t) (maxx - strlen(str)) / 2;
|
|
Packit |
b802ec |
printw("%*s%s", (int) cx, "", str);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static char *format_number(
|
|
Packit |
b802ec |
int n,
|
|
Packit |
b802ec |
int w,
|
|
Packit |
b802ec |
char *buf)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
if (w != 5)
|
|
Packit |
b802ec |
/* XXX todo: implement w != 5.. */
|
|
Packit |
b802ec |
snprintf(buf, w + 1, "%s", "unimpl");
|
|
Packit |
b802ec |
else if (n < 100000)
|
|
Packit |
b802ec |
/* buf is good as-is */ ;
|
|
Packit |
b802ec |
else if (n < 1000000)
|
|
Packit |
b802ec |
snprintf(buf, w + 1, "%3dk%1d", n / 1000, (n % 1000) / 100);
|
|
Packit |
b802ec |
else if (n < 10000000)
|
|
Packit |
b802ec |
snprintf(buf, w + 1, "%1dM%03d", n / 1000000,
|
|
Packit |
b802ec |
(n % 1000000) / 1000);
|
|
Packit |
b802ec |
else if (n < 100000000)
|
|
Packit |
b802ec |
snprintf(buf, w + 1, "%2dM%02d", n / 1000000,
|
|
Packit |
b802ec |
(n % 1000000) / 10000);
|
|
Packit |
b802ec |
else if (n < 1000000000)
|
|
Packit |
b802ec |
snprintf(buf, w + 1, "%3dM%01d", n / 1000000,
|
|
Packit |
b802ec |
(n % 1000000) / 100000);
|
|
Packit |
b802ec |
else /* if (n < 10000000000) */
|
|
Packit |
b802ec |
snprintf(buf, w + 1, "%1dG%03d", n / 1000000000,
|
|
Packit |
b802ec |
(n % 1000000000) / 1000000);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return buf;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int mtr_curses_keyaction(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int c = getch();
|
|
Packit |
b802ec |
int i = 0;
|
|
Packit |
b802ec |
float f = 0.0;
|
|
Packit |
b802ec |
char buf[MAXFLD + 1];
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (c == 'Q') { /* must be checked before c = tolower(c) */
|
|
Packit |
b802ec |
mvprintw(2, 0, "Type of Service(tos): %d\n", ctl->tos);
|
|
Packit |
b802ec |
mvprintw(3, 0,
|
|
Packit |
b802ec |
"default 0x00, min cost 0x02, rel 0x04,, thr 0x08, low del 0x10...\n");
|
|
Packit |
b802ec |
move(2, 22);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
while ((c = getch()) != '\n' && i < MAXFLD) {
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("%c", c);
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
buf[i++] = c; /* need more checking on 'c' */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
buf[i] = '\0';
|
|
Packit |
b802ec |
ctl->tos = atoi(buf);
|
|
Packit |
b802ec |
if (ctl->tos > 255 || ctl->tos < 0)
|
|
Packit |
b802ec |
ctl->tos = 0;
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
c = tolower(c);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
switch (c) {
|
|
Packit |
b802ec |
case 'q':
|
|
Packit |
b802ec |
case 3:
|
|
Packit |
b802ec |
return ActionQuit;
|
|
Packit |
b802ec |
case 12:
|
|
Packit |
b802ec |
return ActionClear;
|
|
Packit |
b802ec |
case 19:
|
|
Packit |
b802ec |
case 'p':
|
|
Packit |
b802ec |
return ActionPause;
|
|
Packit |
b802ec |
case 17:
|
|
Packit |
b802ec |
case ' ':
|
|
Packit |
b802ec |
return ActionResume;
|
|
Packit |
b802ec |
case 'r':
|
|
Packit |
b802ec |
return ActionReset;
|
|
Packit |
b802ec |
case 'd':
|
|
Packit |
b802ec |
return ActionDisplay;
|
|
Packit |
b802ec |
case 'e':
|
|
Packit |
b802ec |
return ActionMPLS;
|
|
Packit |
b802ec |
case 'n':
|
|
Packit |
b802ec |
return ActionDNS;
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
case 'y':
|
|
Packit |
b802ec |
return ActionII;
|
|
Packit |
b802ec |
case 'z':
|
|
Packit |
b802ec |
return ActionAS;
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
case '+':
|
|
Packit |
b802ec |
return ActionScrollDown;
|
|
Packit |
b802ec |
case '-':
|
|
Packit |
b802ec |
return ActionScrollUp;
|
|
Packit |
b802ec |
case 's':
|
|
Packit |
b802ec |
mvprintw(2, 0, "Change Packet Size: %d\n", ctl->cpacketsize);
|
|
Packit |
b802ec |
mvprintw(3, 0, "Size Range: %d-%d, < 0:random.\n", MINPACKET,
|
|
Packit |
b802ec |
MAXPACKET);
|
|
Packit |
b802ec |
move(2, 20);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
while ((c = getch()) != '\n' && i < MAXFLD) {
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("%c", c);
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
buf[i++] = c; /* need more checking on 'c' */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
buf[i] = '\0';
|
|
Packit |
b802ec |
ctl->cpacketsize = atoi(buf);
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
case 'b':
|
|
Packit |
b802ec |
mvprintw(2, 0, "Ping Bit Pattern: %d\n", ctl->bitpattern);
|
|
Packit |
b802ec |
mvprintw(3, 0, "Pattern Range: 0(0x00)-255(0xff), <0 random.\n");
|
|
Packit |
b802ec |
move(2, 18);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
while ((c = getch()) != '\n' && i < MAXFLD) {
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("%c", c);
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
buf[i++] = c; /* need more checking on 'c' */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
buf[i] = '\0';
|
|
Packit |
b802ec |
ctl->bitpattern = atoi(buf);
|
|
Packit |
b802ec |
if (ctl->bitpattern > 255)
|
|
Packit |
b802ec |
ctl->bitpattern = -1;
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
case 'i':
|
|
Packit |
b802ec |
mvprintw(2, 0, "Interval : %0.0f\n\n", ctl->WaitTime);
|
|
Packit |
b802ec |
move(2, 11);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
while ((c = getch()) != '\n' && i < MAXFLD) {
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("%c", c);
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
buf[i++] = c; /* need more checking on 'c' */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
buf[i] = '\0';
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
f = atof(buf);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (f <= 0.0)
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
if (getuid() != 0 && f < 1.0)
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
ctl->WaitTime = f;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
case 'f':
|
|
Packit |
b802ec |
mvprintw(2, 0, "First TTL: %d\n\n", ctl->fstTTL);
|
|
Packit |
b802ec |
move(2, 11);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
while ((c = getch()) != '\n' && i < MAXFLD) {
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("%c", c);
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
buf[i++] = c; /* need more checking on 'c' */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
buf[i] = '\0';
|
|
Packit |
b802ec |
i = atoi(buf);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (i < 1 || i > ctl->maxTTL)
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
ctl->fstTTL = i;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
case 'm':
|
|
Packit |
b802ec |
mvprintw(2, 0, "Max TTL: %d\n\n", ctl->maxTTL);
|
|
Packit |
b802ec |
move(2, 9);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
while ((c = getch()) != '\n' && i < MAXFLD) {
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("%c", c);
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
buf[i++] = c; /* need more checking on 'c' */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
buf[i] = '\0';
|
|
Packit |
b802ec |
i = atoi(buf);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (i < ctl->fstTTL || i > (MaxHost - 1))
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
ctl->maxTTL = i;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
/* fields to display & their ordering */
|
|
Packit |
b802ec |
case 'o':
|
|
Packit |
b802ec |
mvprintw(2, 0, "Fields: %s\n\n", ctl->fld_active);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (i = 0; i < MAXFLD; i++) {
|
|
Packit |
b802ec |
if (data_fields[i].descr != NULL)
|
|
Packit |
b802ec |
printw(" %s\n", data_fields[i].descr);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
printw("\n");
|
|
Packit |
b802ec |
move(2, 8); /* length of "Fields: " */
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
i = 0;
|
|
Packit |
b802ec |
while ((c = getch()) != '\n' && i < MAXFLD) {
|
|
Packit |
b802ec |
if (strchr(ctl->available_options, c)) {
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("%c", c);
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
buf[i++] = c; /* Only permit values in "available_options" be entered */
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
printf("\a"); /* Illegal character. Beep, ring the bell. */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
buf[i] = '\0';
|
|
Packit |
b802ec |
if (strlen(buf) > 0)
|
|
Packit |
b802ec |
xstrncpy(ctl->fld_active, buf, 2 * MAXFLD);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
case 'j':
|
|
Packit |
b802ec |
if (strchr(ctl->fld_active, 'N'))
|
|
Packit |
b802ec |
/* GeoMean and jitter */
|
|
Packit |
b802ec |
xstrncpy(ctl->fld_active, "DR AGJMXI", 2 * MAXFLD);
|
|
Packit |
b802ec |
else
|
|
Packit |
b802ec |
/* default */
|
|
Packit |
b802ec |
xstrncpy(ctl->fld_active, "LS NABWV", 2 * MAXFLD);
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
case 'u':
|
|
Packit |
b802ec |
switch (ctl->mtrtype) {
|
|
Packit |
b802ec |
case IPPROTO_ICMP:
|
|
Packit |
b802ec |
case IPPROTO_TCP:
|
|
Packit |
b802ec |
ctl->mtrtype = IPPROTO_UDP;
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
case IPPROTO_UDP:
|
|
Packit |
b802ec |
ctl->mtrtype = IPPROTO_ICMP;
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
case 't':
|
|
Packit |
b802ec |
switch (ctl->mtrtype) {
|
|
Packit |
b802ec |
case IPPROTO_ICMP:
|
|
Packit |
b802ec |
case IPPROTO_UDP:
|
|
Packit |
b802ec |
ctl->mtrtype = IPPROTO_TCP;
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
case IPPROTO_TCP:
|
|
Packit |
b802ec |
ctl->mtrtype = IPPROTO_ICMP;
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
/* reserve to display help message -Min */
|
|
Packit |
b802ec |
case '?':
|
|
Packit |
b802ec |
case 'h':
|
|
Packit |
b802ec |
mvprintw(2, 0, "Command:\n");
|
|
Packit |
b802ec |
printw(" ?|h help\n");
|
|
Packit |
b802ec |
printw(" p pause (SPACE to resume)\n");
|
|
Packit |
b802ec |
printw(" d switching display mode\n");
|
|
Packit |
b802ec |
printw(" e toggle MPLS information on/off\n");
|
|
Packit |
b802ec |
printw(" n toggle DNS on/off\n");
|
|
Packit |
b802ec |
printw(" r reset all counters\n");
|
|
Packit |
b802ec |
printw
|
|
Packit |
b802ec |
(" o str set the columns to display, default str='LRS N BAWV'\n");
|
|
Packit |
b802ec |
printw
|
|
Packit |
b802ec |
(" j toggle latency(LS NABWV)/jitter(DR AGJMXI) stats\n");
|
|
Packit |
b802ec |
printw(" c <n> report cycle n, default n=infinite\n");
|
|
Packit |
b802ec |
printw
|
|
Packit |
b802ec |
(" i <n> set the ping interval to n seconds, default n=1\n");
|
|
Packit |
b802ec |
printw
|
|
Packit |
b802ec |
(" f <n> set the initial time-to-live(ttl), default n=1\n");
|
|
Packit |
b802ec |
printw
|
|
Packit |
b802ec |
(" m <n> set the max time-to-live, default n= # of hops\n");
|
|
Packit |
b802ec |
printw(" s <n> set the packet size to n or random(n<0)\n");
|
|
Packit |
b802ec |
printw
|
|
Packit |
b802ec |
(" b <c> set ping bit pattern to c(0..255) or random(c<0)\n");
|
|
Packit |
b802ec |
printw(" Q <t> set ping packet's TOS to t\n");
|
|
Packit |
b802ec |
printw(" u switch between ICMP ECHO and UDP datagrams\n");
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
printw(" y switching IP info\n");
|
|
Packit |
b802ec |
printw(" z toggle ASN info on/off\n");
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
printw("\n");
|
|
Packit |
b802ec |
printw(" press any key to go back...");
|
|
Packit |
b802ec |
getch(); /* read and ignore 'any key' */
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
default: /* ignore unknown input */
|
|
Packit |
b802ec |
return ActionNone;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void format_field(
|
|
Packit |
b802ec |
char *dst,
|
|
Packit |
b802ec |
int dst_length,
|
|
Packit |
b802ec |
const char *format,
|
|
Packit |
b802ec |
int n)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
if (index(format, 'N')) {
|
|
Packit |
b802ec |
*dst++ = ' ';
|
|
Packit |
b802ec |
format_number(n, 5, dst);
|
|
Packit |
b802ec |
} else if (strchr(format, 'f')) {
|
|
Packit |
b802ec |
/* this is for fields where we measure integer microseconds but
|
|
Packit |
b802ec |
display floating point miliseconds. Convert to float here. */
|
|
Packit |
b802ec |
snprintf(dst, dst_length, format, n / 1000.0);
|
|
Packit |
b802ec |
/* this was marked as a temporary hack over 10 years ago. -- REW */
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
snprintf(dst, dst_length, format, n);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void mtr_curses_hosts(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
int startstat)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int max;
|
|
Packit |
b802ec |
int at;
|
|
Packit |
b802ec |
struct mplslen *mpls, *mplss;
|
|
Packit |
b802ec |
ip_t *addr, *addrs;
|
|
Packit |
b802ec |
int y;
|
|
Packit |
b802ec |
char *name;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int i, j, k;
|
|
Packit |
b802ec |
int hd_len;
|
|
Packit |
b802ec |
char buf[1024];
|
|
Packit |
b802ec |
int __unused_int ATTRIBUTE_UNUSED;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
max = net_max(ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (at = net_min(ctl) + ctl->display_offset; at < max; at++) {
|
|
Packit |
b802ec |
printw("%2d. ", at + 1);
|
|
Packit |
b802ec |
addr = net_addr(at);
|
|
Packit |
b802ec |
mpls = net_mpls(at);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af) !=
|
|
Packit |
b802ec |
0) {
|
|
Packit |
b802ec |
name = dns_lookup(ctl, addr);
|
|
Packit |
b802ec |
if (!net_up(at))
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
if (is_printii(ctl))
|
|
Packit |
b802ec |
printw(fmt_ipinfo(ctl, addr));
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
if (name != NULL) {
|
|
Packit |
b802ec |
if (ctl->show_ips)
|
|
Packit |
b802ec |
printw("%s (%s)", name, strlongip(ctl, addr));
|
|
Packit |
b802ec |
else
|
|
Packit |
b802ec |
printw("%s", name);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
printw("%s", strlongip(ctl, addr));
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
getyx(stdscr, y, __unused_int);
|
|
Packit |
b802ec |
move(y, startstat);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* net_xxx returns times in usecs. Just display millisecs */
|
|
Packit |
b802ec |
hd_len = 0;
|
|
Packit |
b802ec |
for (i = 0; i < MAXFLD; i++) {
|
|
Packit |
b802ec |
/* Ignore options that don't exist */
|
|
Packit |
b802ec |
/* On the other hand, we now check the input side. Shouldn't happen,
|
|
Packit |
b802ec |
can't be careful enough. */
|
|
Packit |
b802ec |
j = ctl->fld_index[ctl->fld_active[i]];
|
|
Packit |
b802ec |
if (j == -1)
|
|
Packit |
b802ec |
continue;
|
|
Packit |
b802ec |
format_field(buf + hd_len, sizeof(buf) - hd_len,
|
|
Packit |
b802ec |
data_fields[j].format,
|
|
Packit |
b802ec |
data_fields[j].net_xxx(at));
|
|
Packit |
b802ec |
hd_len += data_fields[j].length;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
buf[hd_len] = 0;
|
|
Packit |
b802ec |
printw("%s", buf);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (k = 0; k < mpls->labels && ctl->enablempls; k++) {
|
|
Packit |
b802ec |
printw("\n [MPLS: Lbl %lu Exp %u S %u TTL %u]",
|
|
Packit |
b802ec |
mpls->label[k], mpls->exp[k], mpls->s[k],
|
|
Packit |
b802ec |
mpls->ttl[k]);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Multi path */
|
|
Packit |
b802ec |
for (i = 0; i < MAXPATH; i++) {
|
|
Packit |
b802ec |
addrs = net_addrs(at, i);
|
|
Packit |
b802ec |
mplss = net_mplss(at, i);
|
|
Packit |
b802ec |
if (addrcmp((void *) addrs, (void *) addr, ctl->af) == 0)
|
|
Packit |
b802ec |
continue;
|
|
Packit |
b802ec |
if (addrcmp
|
|
Packit |
b802ec |
((void *) addrs, (void *) &ctl->unspec_addr,
|
|
Packit |
b802ec |
ctl->af) == 0)
|
|
Packit |
b802ec |
break;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
name = dns_lookup(ctl, addrs);
|
|
Packit |
b802ec |
if (!net_up(at))
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("\n ");
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
if (is_printii(ctl))
|
|
Packit |
b802ec |
printw(fmt_ipinfo(ctl, addrs));
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
if (name != NULL) {
|
|
Packit |
b802ec |
if (ctl->show_ips)
|
|
Packit |
b802ec |
printw("%s (%s)", name, strlongip(ctl, addrs));
|
|
Packit |
b802ec |
else
|
|
Packit |
b802ec |
printw("%s", name);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
printw("%s", strlongip(ctl, addrs));
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
for (k = 0; k < mplss->labels && ctl->enablempls; k++) {
|
|
Packit |
b802ec |
printw("\n [MPLS: Lbl %lu Exp %u S %u TTL %u]",
|
|
Packit |
b802ec |
mplss->label[k], mplss->exp[k], mplss->s[k],
|
|
Packit |
b802ec |
mplss->ttl[k]);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
printw("???");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
printw("\n");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
move(2, 0);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void mtr_gen_scale(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int *saved, i, max, at;
|
|
Packit |
b802ec |
int range;
|
|
Packit |
b802ec |
static int low_ms, high_ms;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
low_ms = 1000000;
|
|
Packit |
b802ec |
high_ms = -1;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (i = 0; i < NUM_FACTORS; i++) {
|
|
Packit |
b802ec |
scale[i] = 0;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
max = net_max(ctl);
|
|
Packit |
b802ec |
for (at = ctl->display_offset; at < max; at++) {
|
|
Packit |
b802ec |
saved = net_saved_pings(at);
|
|
Packit |
b802ec |
for (i = 0; i < SAVED_PINGS; i++) {
|
|
Packit |
b802ec |
if (saved[i] < 0)
|
|
Packit |
b802ec |
continue;
|
|
Packit |
b802ec |
if (saved[i] < low_ms) {
|
|
Packit |
b802ec |
low_ms = saved[i];
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
if (saved[i] > high_ms) {
|
|
Packit |
b802ec |
high_ms = saved[i];
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
range = high_ms - low_ms;
|
|
Packit |
b802ec |
for (i = 0; i < NUM_FACTORS; i++) {
|
|
Packit |
b802ec |
scale[i] = low_ms + ((double) range * factors[i]);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void mtr_curses_init(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int i;
|
|
Packit |
b802ec |
int block_split;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Initialize factors to a log scale. */
|
|
Packit |
b802ec |
for (i = 0; i < NUM_FACTORS; i++) {
|
|
Packit |
b802ec |
factors[i] = ((double) 1 / NUM_FACTORS) * (i + 1);
|
|
Packit |
b802ec |
factors[i] *= factors[i]; /* Squared. */
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
/* Initialize block_map. The block_split is always smaller than 9 */
|
|
Packit |
b802ec |
block_split = (NUM_FACTORS - 2) / 2;
|
|
Packit |
b802ec |
for (i = 1; i <= block_split; i++) {
|
|
Packit |
b802ec |
block_map[i] = '0' + i;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
for (i = block_split + 1; i < NUM_FACTORS - 1; i++) {
|
|
Packit |
b802ec |
block_map[i] = 'a' + i - block_split - 1;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
block_map[0] = '.';
|
|
Packit |
b802ec |
block_map[NUM_FACTORS - 1] = '>';
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void mtr_print_scaled(
|
|
Packit |
b802ec |
int ms)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int i;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (i = 0; i < NUM_FACTORS; i++) {
|
|
Packit |
b802ec |
if (ms <= scale[i]) {
|
|
Packit |
b802ec |
attrset(block_col[i + 1]);
|
|
Packit |
b802ec |
printw("%c", block_map[i]);
|
|
Packit |
b802ec |
attrset(A_NORMAL);
|
|
Packit |
b802ec |
return;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
printw(">");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void mtr_fill_graph(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
int at,
|
|
Packit |
b802ec |
int cols)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int *saved;
|
|
Packit |
b802ec |
int i;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
saved = net_saved_pings(at);
|
|
Packit |
b802ec |
for (i = SAVED_PINGS - cols; i < SAVED_PINGS; i++) {
|
|
Packit |
b802ec |
if (saved[i] == -2) {
|
|
Packit |
b802ec |
printw(" ");
|
|
Packit |
b802ec |
} else if (saved[i] == -1) {
|
|
Packit |
b802ec |
attrset(block_col[0]);
|
|
Packit |
b802ec |
printw("%c", '?');
|
|
Packit |
b802ec |
attrset(A_NORMAL);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
if (ctl->display_mode == DisplayModeBlockmap) {
|
|
Packit |
b802ec |
if (saved[i] > scale[6]) {
|
|
Packit |
b802ec |
printw("%c", block_map[NUM_FACTORS - 1]);
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
printw(".");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
mtr_print_scaled(saved[i]);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
static void mtr_curses_graph(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl,
|
|
Packit |
b802ec |
int startstat,
|
|
Packit |
b802ec |
int cols)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int max, at, y;
|
|
Packit |
b802ec |
ip_t *addr;
|
|
Packit |
b802ec |
char *name;
|
|
Packit |
b802ec |
int __unused_int ATTRIBUTE_UNUSED;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
max = net_max(ctl);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (at = ctl->display_offset; at < max; at++) {
|
|
Packit |
b802ec |
printw("%2d. ", at + 1);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
addr = net_addr(at);
|
|
Packit |
b802ec |
if (!addr) {
|
|
Packit |
b802ec |
printw("???\n");
|
|
Packit |
b802ec |
continue;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (!net_up(at))
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
if (is_printii(ctl))
|
|
Packit |
b802ec |
printw(fmt_ipinfo(ctl, addr));
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
name = dns_lookup(ctl, addr);
|
|
Packit |
b802ec |
printw("%s", name ? name : strlongip(ctl, addr));
|
|
Packit |
b802ec |
} else
|
|
Packit |
b802ec |
printw("???");
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
getyx(stdscr, y, __unused_int);
|
|
Packit |
b802ec |
move(y, startstat);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
printw(" ");
|
|
Packit |
b802ec |
mtr_fill_graph(ctl, at, cols);
|
|
Packit |
b802ec |
printw("\n");
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void mtr_curses_redraw(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int maxx;
|
|
Packit |
b802ec |
int startstat;
|
|
Packit |
b802ec |
int rowstat;
|
|
Packit |
b802ec |
time_t t;
|
|
Packit |
b802ec |
int __unused_int ATTRIBUTE_UNUSED;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
int i, j;
|
|
Packit |
b802ec |
int hd_len = 0;
|
|
Packit |
b802ec |
char buf[1024];
|
|
Packit |
b802ec |
char fmt[16];
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
erase();
|
|
Packit |
b802ec |
getmaxyx(stdscr, __unused_int, maxx);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
rowstat = 5;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
move(0, 0);
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
snprintf(buf, sizeof(buf), "%s%s%s", "My traceroute [v",
|
|
Packit |
b802ec |
PACKAGE_VERSION, "]");
|
|
Packit |
b802ec |
pwcenter(buf);
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
mvprintw(1, 0, "%s (%s)", ctl->LocalHostname, net_localaddr());
|
|
Packit |
b802ec |
t = time(NULL);
|
|
Packit |
b802ec |
mvprintw(1, maxx - 25, iso_time(&t);;
|
|
Packit |
b802ec |
printw("\n");
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
printw("Keys: ");
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("H");
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
printw("elp ");
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("D");
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
printw("isplay mode ");
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("R");
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
printw("estart statistics ");
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("O");
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
printw("rder of fields ");
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("q");
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
printw("uit\n");
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
if (ctl->display_mode == DisplayModeDefault) {
|
|
Packit |
b802ec |
for (i = 0; i < MAXFLD; i++) {
|
|
Packit |
b802ec |
j = ctl->fld_index[ctl->fld_active[i]];
|
|
Packit |
b802ec |
if (j < 0)
|
|
Packit |
b802ec |
continue;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
snprintf(fmt, sizeof(fmt), "%%%ds", data_fields[j].length);
|
|
Packit |
b802ec |
snprintf(buf + hd_len, sizeof(buf) - hd_len, fmt,
|
|
Packit |
b802ec |
data_fields[j].title);
|
|
Packit |
b802ec |
hd_len += data_fields[j].length;
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
mvprintw(rowstat - 1, 0, " Host");
|
|
Packit |
b802ec |
mvprintw(rowstat - 1, maxx - hd_len - 1, "%s", buf);
|
|
Packit |
b802ec |
mvprintw(rowstat - 2, maxx - hd_len - 1,
|
|
Packit |
b802ec |
" Packets Pings");
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
move(rowstat, 0);
|
|
Packit |
b802ec |
mtr_curses_hosts(ctl, maxx - hd_len - 1);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
} else {
|
|
Packit |
b802ec |
char msg[80];
|
|
Packit |
b802ec |
int padding = 30;
|
|
Packit |
b802ec |
int max_cols;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
#ifdef HAVE_IPINFO
|
|
Packit |
b802ec |
if (is_printii(ctl))
|
|
Packit |
b802ec |
padding += get_iiwidth(ctl->ipinfo_no);
|
|
Packit |
b802ec |
#endif
|
|
Packit |
b802ec |
max_cols =
|
|
Packit |
b802ec |
maxx <= SAVED_PINGS + padding ? maxx - padding : SAVED_PINGS;
|
|
Packit |
b802ec |
startstat = padding - 2;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
snprintf(msg, sizeof(msg), " Last %3d pings", max_cols);
|
|
Packit |
b802ec |
mvprintw(rowstat - 1, startstat, msg);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
move(rowstat, 0);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
mtr_gen_scale(ctl);
|
|
Packit |
b802ec |
mtr_curses_graph(ctl, startstat, max_cols);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
printw("\n");
|
|
Packit |
b802ec |
attron(A_BOLD);
|
|
Packit |
b802ec |
printw("Scale:");
|
|
Packit |
b802ec |
attroff(A_BOLD);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
for (i = 0; i < NUM_FACTORS - 1; i++) {
|
|
Packit |
b802ec |
printw(" ");
|
|
Packit |
b802ec |
attrset(block_col[i + 1]);
|
|
Packit |
b802ec |
printw("%c", block_map[i]);
|
|
Packit |
b802ec |
attrset(A_NORMAL);
|
|
Packit |
b802ec |
printw(":%d ms", scale[i] / 1000);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
printw(" ");
|
|
Packit |
b802ec |
attrset(block_col[NUM_FACTORS]);
|
|
Packit |
b802ec |
printw("%c", block_map[NUM_FACTORS - 1]);
|
|
Packit |
b802ec |
attrset(A_NORMAL);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
refresh();
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void mtr_curses_open(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
int bg_col = 0;
|
|
Packit |
b802ec |
int i;
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
initscr();
|
|
Packit |
b802ec |
raw();
|
|
Packit |
b802ec |
noecho();
|
|
Packit |
b802ec |
start_color();
|
|
Packit |
b802ec |
if (use_default_colors() == OK)
|
|
Packit |
b802ec |
bg_col = -1;
|
|
Packit |
b802ec |
for (i = 0; i < NUM_FACTORS; i++)
|
|
Packit |
b802ec |
init_pair(i + 1, i, bg_col);
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
mtr_curses_init();
|
|
Packit |
b802ec |
mtr_curses_redraw(ctl);
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void mtr_curses_close(
|
|
Packit |
b802ec |
void)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
printw("\n");
|
|
Packit |
b802ec |
endwin();
|
|
Packit |
b802ec |
}
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
|
|
Packit |
b802ec |
void mtr_curses_clear(
|
|
Packit |
b802ec |
struct mtr_ctl *ctl)
|
|
Packit |
b802ec |
{
|
|
Packit |
b802ec |
mtr_curses_close();
|
|
Packit |
b802ec |
mtr_curses_open(ctl);
|
|
Packit |
b802ec |
}
|