""
This commit is contained in:
2
Makefile
2
Makefile
@@ -70,7 +70,7 @@ LDLIBS += -lpcap -lcurses -lm
|
|||||||
|
|
||||||
|
|
||||||
SRCS = iftop.c addr_hash.c hash.c ns_hash.c resolver.c ui.c util.c sorted_list.c\
|
SRCS = iftop.c addr_hash.c hash.c ns_hash.c resolver.c ui.c util.c sorted_list.c\
|
||||||
options.c serv_hash.c threadprof.c
|
options.c serv_hash.c threadprof.c edline.c
|
||||||
HDRS = addr_hash.h hash.h iftop.h ns_hash.h resolver.h sorted_list.h ui.h options.h sll.h\
|
HDRS = addr_hash.h hash.h iftop.h ns_hash.h resolver.h sorted_list.h ui.h options.h sll.h\
|
||||||
serv_hash.h threadprof.h ether.h ip.h tcp.h
|
serv_hash.h threadprof.h ether.h ip.h tcp.h
|
||||||
TXTS = README CHANGES INSTALL TODO iftop.8 COPYING
|
TXTS = README CHANGES INSTALL TODO iftop.8 COPYING
|
||||||
|
|||||||
135
edline.c
Normal file
135
edline.c
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* edline.c:
|
||||||
|
* Text input on a line of the screen.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "iftop.h"
|
||||||
|
|
||||||
|
static int min(const int a, const int b) {
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* edline:
|
||||||
|
* Display on line linenum of the screen the prompt and allow the user to input
|
||||||
|
* a line of text, whose initial value is as supplied. */
|
||||||
|
char *edline(int linenum, const char *prompt, const char *initial) {
|
||||||
|
int xstart, slen, off = 0, pos, i, c;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
xstart = strlen(prompt) + 2;
|
||||||
|
|
||||||
|
if (initial) {
|
||||||
|
str = xmalloc(slen = strlen(initial) * 2 + 1);
|
||||||
|
strcpy(str, initial);
|
||||||
|
} else {
|
||||||
|
str = xmalloc(slen = 256);
|
||||||
|
*str = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = strlen(str);
|
||||||
|
|
||||||
|
do {
|
||||||
|
c = getch();
|
||||||
|
switch (c) {
|
||||||
|
case KEY_DL:
|
||||||
|
case 21: /* ^U */
|
||||||
|
*str = 0;
|
||||||
|
pos = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_LEFT:
|
||||||
|
--pos;
|
||||||
|
if (pos < 0) {
|
||||||
|
beep();
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_RIGHT:
|
||||||
|
++pos;
|
||||||
|
if (pos > strlen(str)) {
|
||||||
|
beep();
|
||||||
|
pos = strlen(str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_HOME:
|
||||||
|
case 1: /* ^A */
|
||||||
|
pos = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_END:
|
||||||
|
case 5: /* ^E */
|
||||||
|
pos = strlen(str);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_DC:
|
||||||
|
if (pos == strlen(str))
|
||||||
|
beep();
|
||||||
|
else
|
||||||
|
memmove(str + pos, str + pos + 1, strlen(str + pos + 1) + 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_BACKSPACE:
|
||||||
|
if (pos == 0)
|
||||||
|
beep();
|
||||||
|
else {
|
||||||
|
memmove(str + pos - 1, str + pos, strlen(str + pos) + 1);
|
||||||
|
--pos;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 23: /* ^W */
|
||||||
|
for (i = pos; i > 0; --i)
|
||||||
|
if (!isspace(str[i])) break;
|
||||||
|
for (; i > 0; --i)
|
||||||
|
if (isspace(str[i])) break;
|
||||||
|
if (i != pos) {
|
||||||
|
memmove(str + i, str + pos, strlen(str + pos) + 1);
|
||||||
|
pos = i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ERR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (isprint(c) && c != '\t') {
|
||||||
|
if (strlen(str) == slen - 1)
|
||||||
|
str = xrealloc(str, slen *= 2);
|
||||||
|
memmove(str + pos + 1, str + pos, strlen(str + pos) + 1);
|
||||||
|
str[pos++] = (char)c;
|
||||||
|
} else
|
||||||
|
beep();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* figure out the offset to use for the string */
|
||||||
|
off = 0;
|
||||||
|
if (pos > COLS - xstart - 1)
|
||||||
|
off = pos - (COLS - xstart - 1);
|
||||||
|
|
||||||
|
/* display the string */
|
||||||
|
mvaddstr(linenum, 0, prompt);
|
||||||
|
addstr("> ");
|
||||||
|
addnstr(str + off, min(strlen(str + off), COLS - xstart - 1));
|
||||||
|
clrtoeol();
|
||||||
|
move(linenum, xstart + pos - off);
|
||||||
|
refresh();
|
||||||
|
} while (c != KEY_ENTER && c != '\r' && c != '\x1b' && c != 7 /* ^G */);
|
||||||
|
|
||||||
|
if (c == KEY_ENTER || c == '\r')
|
||||||
|
/* Success */
|
||||||
|
return str;
|
||||||
|
else {
|
||||||
|
xfree(str);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
43
iftop.c
43
iftop.c
@@ -44,6 +44,7 @@ int history_len = 1;
|
|||||||
pthread_mutex_t tick_mutex;
|
pthread_mutex_t tick_mutex;
|
||||||
|
|
||||||
pcap_t* pd; /* pcap descriptor */
|
pcap_t* pd; /* pcap descriptor */
|
||||||
|
struct bpf_program pcap_filter;
|
||||||
pcap_handler packet_handler;
|
pcap_handler packet_handler;
|
||||||
|
|
||||||
sig_atomic_t foad;
|
sig_atomic_t foad;
|
||||||
@@ -307,6 +308,29 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* set_filter_code:
|
||||||
|
* Install some filter code. Returns NULL on success or an error message on
|
||||||
|
* failure. */
|
||||||
|
char *set_filter_code(const char *filter) {
|
||||||
|
char *x;
|
||||||
|
if (filter) {
|
||||||
|
x = xmalloc(strlen(filter) + sizeof "() and ip");
|
||||||
|
sprintf(x, "(%s) and ip", filter);
|
||||||
|
} else
|
||||||
|
x = xstrdup("ip");
|
||||||
|
if (pcap_compile(pd, &pcap_filter, x, 1, 0) == -1) {
|
||||||
|
xfree(x);
|
||||||
|
return pcap_geterr(pd);
|
||||||
|
}
|
||||||
|
xfree(x);
|
||||||
|
if (pcap_setfilter(pd, &pcap_filter) == -1)
|
||||||
|
return pcap_geterr(pd);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* packet_init:
|
* packet_init:
|
||||||
*
|
*
|
||||||
@@ -314,8 +338,7 @@ static void handle_eth_packet(unsigned char* args, const struct pcap_pkthdr* pkt
|
|||||||
*/
|
*/
|
||||||
void packet_init() {
|
void packet_init() {
|
||||||
char errbuf[PCAP_ERRBUF_SIZE];
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
char* str = "ip";
|
char *m;
|
||||||
struct bpf_program F;
|
|
||||||
int s;
|
int s;
|
||||||
struct ifreq ifr = {0};
|
struct ifreq ifr = {0};
|
||||||
int dlt;
|
int dlt;
|
||||||
@@ -369,23 +392,11 @@ void packet_init() {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.filtercode) {
|
if ((m = set_filter_code(options.filtercode))) {
|
||||||
str = xmalloc(strlen(options.filtercode) + sizeof "() and ip");
|
fprintf(stderr, "set_filter_code: %s\n", m);
|
||||||
sprintf(str, "(%s) and ip", options.filtercode);
|
|
||||||
}
|
|
||||||
if (pcap_compile(pd, &F, str, 1, 0) == -1) {
|
|
||||||
fprintf(stderr, "pcap_compile(%s): %s\n", str, pcap_geterr(pd));
|
|
||||||
exit(1);
|
exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pcap_setfilter(pd, &F) == -1) {
|
|
||||||
fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(pd));
|
|
||||||
exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (options.filtercode)
|
|
||||||
xfree(str);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* packet_loop:
|
/* packet_loop:
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ void options_read(int argc, char **argv) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
options.filtercode = optarg;
|
options.filtercode = xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
|
|||||||
66
ui.c
66
ui.c
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@@ -12,6 +13,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include "addr_hash.h"
|
#include "addr_hash.h"
|
||||||
#include "serv_hash.h"
|
#include "serv_hash.h"
|
||||||
#include "iftop.h"
|
#include "iftop.h"
|
||||||
@@ -40,6 +43,8 @@
|
|||||||
" P - pause display\n"\
|
" P - pause display\n"\
|
||||||
" h - toggle this help display\n"\
|
" h - toggle this help display\n"\
|
||||||
" b - toggle bar graph display\n"\
|
" b - toggle bar graph display\n"\
|
||||||
|
" f - edit filter code\n"\
|
||||||
|
" ! - shell command\n"\
|
||||||
" q - quit\n"\
|
" q - quit\n"\
|
||||||
"\niftop, version " IFTOP_VERSION
|
"\niftop, version " IFTOP_VERSION
|
||||||
|
|
||||||
@@ -77,6 +82,7 @@ int peaksent, peakrecv, peaktotal;
|
|||||||
int showhelphint = 0;
|
int showhelphint = 0;
|
||||||
int helptimer = 0;
|
int helptimer = 0;
|
||||||
char helpmsg[HELP_MSG_SIZE];
|
char helpmsg[HELP_MSG_SIZE];
|
||||||
|
int dontshowdisplay = 0;
|
||||||
|
|
||||||
int screen_line_compare(void* a, void* b) {
|
int screen_line_compare(void* a, void* b) {
|
||||||
int i;
|
int i;
|
||||||
@@ -395,6 +401,9 @@ void ui_print() {
|
|||||||
static int lcols;
|
static int lcols;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
||||||
|
if (dontshowdisplay)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!line || lcols != COLS) {
|
if (!line || lcols != COLS) {
|
||||||
xfree(line);
|
xfree(line);
|
||||||
line = calloc(COLS + 1, 1);
|
line = calloc(COLS + 1, 1);
|
||||||
@@ -510,14 +519,18 @@ void ui_tick(int print) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_init() {
|
void ui_curses_init() {
|
||||||
(void) initscr(); /* initialize the curses library */
|
(void) initscr(); /* initialize the curses library */
|
||||||
keypad(stdscr, TRUE); /* enable keyboard mapping */
|
keypad(stdscr, TRUE); /* enable keyboard mapping */
|
||||||
(void) nonl(); /* tell curses not to do NL->CR/NL on output */
|
(void) nonl(); /* tell curses not to do NL->CR/NL on output */
|
||||||
(void) cbreak(); /* take input chars one at a time, no wait for \n */
|
(void) cbreak(); /* take input chars one at a time, no wait for \n */
|
||||||
(void) noecho(); /* don't echo input */
|
(void) noecho(); /* don't echo input */
|
||||||
halfdelay(2);
|
halfdelay(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_init() {
|
||||||
|
ui_curses_init();
|
||||||
|
|
||||||
erase();
|
erase();
|
||||||
|
|
||||||
screen_list_init();
|
screen_list_init();
|
||||||
@@ -551,8 +564,15 @@ void showportstatus() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ui_loop() {
|
void ui_loop() {
|
||||||
|
/* in edline.c */
|
||||||
|
char *edline(int linenum, const char *prompt, const char *initial);
|
||||||
|
/* in iftop.c */
|
||||||
|
int set_filter_code(const char *filter);
|
||||||
|
|
||||||
extern sig_atomic_t foad;
|
extern sig_atomic_t foad;
|
||||||
|
|
||||||
while(foad == 0) {
|
while(foad == 0) {
|
||||||
int i;
|
int i;
|
||||||
i = getch();
|
i = getch();
|
||||||
@@ -586,7 +606,7 @@ void ui_loop() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?'
|
case '?':
|
||||||
options.showhelp = !options.showhelp;
|
options.showhelp = !options.showhelp;
|
||||||
tick(1);
|
tick(1);
|
||||||
break;
|
break;
|
||||||
@@ -666,6 +686,48 @@ void ui_loop() {
|
|||||||
case 'P':
|
case 'P':
|
||||||
options.paused = !options.paused;
|
options.paused = !options.paused;
|
||||||
break;
|
break;
|
||||||
|
case 'f': {
|
||||||
|
char *s;
|
||||||
|
dontshowdisplay = 1;
|
||||||
|
if ((s = edline(0, "Filter", options.filtercode))) {
|
||||||
|
char *m;
|
||||||
|
if (!(m = set_filter_code(s))) {
|
||||||
|
xfree(options.filtercode);
|
||||||
|
options.filtercode = s;
|
||||||
|
} else {
|
||||||
|
showhelp(m);
|
||||||
|
xfree(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dontshowdisplay = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '!': {
|
||||||
|
char *s;
|
||||||
|
dontshowdisplay = 1;
|
||||||
|
if ((s = edline(0, "Command", ""))) {
|
||||||
|
int i;
|
||||||
|
erase();
|
||||||
|
refresh();
|
||||||
|
endwin();
|
||||||
|
errno = 0;
|
||||||
|
i = system(s);
|
||||||
|
if (i == -1 || (i == 127 && errno != 0)) {
|
||||||
|
fprintf(stderr, "system: %s: %s\n", s, strerror(errno));
|
||||||
|
sleep(1);
|
||||||
|
} else if (i != 0) {
|
||||||
|
if (WIFEXITED(i))
|
||||||
|
fprintf(stderr, "%s: exited with code %d\n", s, WEXITSTATUS(i));
|
||||||
|
else if (WIFSIGNALED(i))
|
||||||
|
fprintf(stderr, "%s: killed by signal %d\n", s, WTERMSIG(i));
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
ui_curses_init();
|
||||||
|
erase();
|
||||||
|
xfree(s);
|
||||||
|
}
|
||||||
|
dontshowdisplay = 0;
|
||||||
|
}
|
||||||
case ERR:
|
case ERR:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user