Annotation of embedaddon/iftop/tui.c, revision 1.1.1.1
1.1 misho 1: /*
2: * tui.c:
3: *
4: * Based on ui.c from the original iftop sources.
5: *
6: * This user interface does not make use of curses. Instead, it prints its
7: * output to STDOUT. This output is activated by providing the '-t' flag.
8: *
9: */
10:
11: #include "config.h"
12:
13: #include <string.h>
14: #include <stdio.h>
15: #include <signal.h>
16: #include <stdlib.h>
17: #include <unistd.h>
18:
19: #if defined(HAVE_TERMIOS_H)
20: #include <termios.h>
21: #elif defined(HAVE_SGTTY_H) && defined(TIOCSETP)
22: #include <sys/ioctl.h>
23: #include <sgtty.h>
24: #elif defined(HAVE_TERMIO_H)
25: #include <sys/ioctl.h>
26: #include <termio.h>
27: #else
28: #include <stdlib.h>
29: #endif
30:
31: #include "sorted_list.h"
32: #include "options.h"
33: #include "ui_common.h"
34:
35: /* Width of the host column in the output */
36: #define PRINT_WIDTH 40
37:
38:
39: /*
40: * UI print function
41: */
42: void tui_print() {
43: sorted_list_node* nn = NULL;
44: char host1[HOSTNAME_LENGTH], host2[HOSTNAME_LENGTH];
45: char buf0_10[10], buf1_10[10], buf2_10[10];
46: int j;
47: static char *label;
48: static char *labellong;
49: int l = 0;
50:
51: if (!label) {
52: xfree(label);
53: label = (char *)calloc(PRINT_WIDTH + 1, 1);
54: }
55:
56: if (!labellong) {
57: xfree(labellong);
58: labellong = (char *)calloc(PRINT_WIDTH + 1 + 9, 1);
59: }
60:
61: if (options.paused ) {
62: return;
63: }
64:
65: /* Headings */
66: snprintf(label, PRINT_WIDTH, "%-*s", PRINT_WIDTH, "Host name (port/service if enabled)");
67: printf("%s %s %10s %10s %10s %10s\n", " #", label, "last 2s", "last 10s", "last 40s", "cumulative");
68:
69: /* Divider line */
70: for (j = 0; j < PRINT_WIDTH + 52; j++) {
71: printf("-");
72: }
73: printf("\n");
74:
75: /* Traverse the list of all connections */
76: while((nn = sorted_list_next_item(&screen_list, nn)) != NULL && l < options.num_lines) {
77: /* Increment the line counter */
78: l++;
79:
80: /* Get the connection information */
81: host_pair_line* screen_line = (host_pair_line*)nn->data;
82:
83: /* Assemble host information */
84: sprint_host(host1, screen_line->ap.af, &(screen_line->ap.src6), screen_line->ap.src_port, screen_line->ap.protocol, PRINT_WIDTH, options.aggregate_src);
85: sprint_host(host2, screen_line->ap.af, &(screen_line->ap.dst6), screen_line->ap.dst_port, screen_line->ap.protocol, PRINT_WIDTH, options.aggregate_dest);
86:
87: /* Send rate per connection */
88: printf("%4d %s%s", l, host1, " =>");
89: for(j = 0; j < HISTORY_DIVISIONS; j++) {
90: readable_size(screen_line->sent[j], buf0_10, 10, 1024, options.bandwidth_in_bytes);
91: printf(" %10s", buf0_10);
92: }
93: /* Cumulative sent data per connection */
94: readable_size(screen_line->total_sent, buf0_10, 10, 1024, 1);
95: printf(" %10s\n", buf0_10);
96:
97: /* Receive rate per connection */
98: printf(" %s%s", host2, " <=");
99: for(j = 0; j < HISTORY_DIVISIONS; j++) {
100: readable_size(screen_line->recv[j], buf0_10, 10, 1024, options.bandwidth_in_bytes);
101: printf(" %10s", buf0_10);
102: }
103: /* Cumulative received data per connection */
104: readable_size(screen_line->total_recv, buf0_10, 10, 1024, 1);
105: printf(" %10s\n", buf0_10);
106: }
107:
108: /* Divider line */
109: for (j = 0; j < PRINT_WIDTH + 52; j++) {
110: printf("-");
111: }
112: printf("\n");
113:
114: /* Rate totals */
115: snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total send rate:");
116: printf("%s ", labellong);
117: for(j = 0; j < HISTORY_DIVISIONS; j++) {
118: readable_size((((host_pair_line *)&totals)->sent[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes);
119: printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' ');
120: }
121:
122: snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total receive rate:");
123: printf("%s ", labellong);
124: for(j = 0; j < HISTORY_DIVISIONS; j++) {
125: readable_size((((host_pair_line *)&totals)->recv[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes);
126: printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' ');
127: }
128:
129: snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Total send and receive rate:");
130: printf("%s ", labellong);
131: for(j = 0; j < HISTORY_DIVISIONS; j++) {
132: readable_size((((host_pair_line *)&totals)->sent[j] + ((host_pair_line *)&totals)->recv[j]) , buf0_10, 10, 1024, options.bandwidth_in_bytes);
133: printf("%10s%c", buf0_10, j == HISTORY_DIVISIONS - 1 ? '\n' : ' ');
134: }
135:
136: /* Divider line */
137: for (j = 0; j < PRINT_WIDTH + 52; j++) {
138: printf("-");
139: }
140: printf("\n");
141:
142: /* Peak traffic */
143: snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Peak rate (sent/received/total):");
144: readable_size(peaksent / RESOLUTION, buf0_10, 10, 1024, options.bandwidth_in_bytes);
145: readable_size(peakrecv / RESOLUTION, buf1_10, 10, 1024, options.bandwidth_in_bytes);
146: readable_size(peaktotal / RESOLUTION, buf2_10, 10, 1024, options.bandwidth_in_bytes);
147: printf("%s %10s %10s %10s\n", labellong, buf0_10, buf1_10, buf2_10);
148:
149: /* Cumulative totals */
150: snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Cumulative (sent/received/total):");
151: readable_size(history_totals.total_sent, buf0_10, 10, 1024, 1);
152: readable_size(history_totals.total_recv, buf1_10, 10, 1024, 1);
153: readable_size(history_totals.total_recv + history_totals.total_sent, buf2_10, 10, 1024, 1);
154: printf("%s %10s %10s %10s\n", labellong, buf0_10, buf1_10, buf2_10);
155:
156: /* Double divider line */
157: for (j = 0; j < PRINT_WIDTH + 52; j++) {
158: printf("=");
159: }
160: printf("\n\n");
161: }
162:
163:
164: /*
165: * Text interface data structure initializations.
166: */
167: void tui_init() {
168: screen_list_init();
169: screen_hash = addr_hash_create();
170: service_hash = serv_hash_create();
171: serv_hash_initialise(service_hash);
172:
173: printf("Listening on %s\n", options.interface);
174: }
175:
176:
177: /*
178: * Tick function indicating screen refresh
179: */
180: void tui_tick(int print) {
181: if (print) {
182: tui_print();
183: }
184: }
185:
186:
187: /*
188: * Main UI loop. Code any interactive character inputs here.
189: */
190: void tui_loop() {
191: int i;
192: extern sig_atomic_t foad;
193:
194: #if defined(HAVE_TERMIOS_H)
195: struct termios new_termios, old_termios;
196:
197: tcgetattr(STDIN_FILENO, &old_termios);
198: new_termios = old_termios;
199: new_termios.c_lflag &= ~(ICANON|ECHO);
200: new_termios.c_cc[VMIN] = 1;
201: new_termios.c_cc[VTIME] = 0;
202: tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
203: #elif defined(HAVE_SGTTY_H) && defined(TIOCSETP)
204: struct sgttyb new_tty, old_tty;
205:
206: ioctl(STDIN_FILENO, TIOCGETP, &old_tty);
207: new_tty = old_tty;
208: new_tty.sg_flags &= ~(ICANON|ECHO);
209: ioctl(STDIN_FILENO, TIOCSETP, &new_tty);
210: #elif defined(HAVE_TERMIO_H)
211: struct termio new_termio, old_termio;
212:
213: ioctl(0, TCGETA, &old_termio);
214: new_termio = old_termio;
215: new_termio.c_lflag &= ~(ICANON|ECHO);
216: new_termio.c_cc[VMIN] = 1;
217: new_termio.c_cc[VTIME] = 0;
218: ioctl(0, TCSETA, &new_termio);
219: #else
220: system("/bin/stty cbreak -echo >/dev/null 2>&1");
221: #endif
222:
223: while ((i = getchar()) != 'q' && foad == 0) {
224: switch (i) {
225: case 'u':
226: tick(1);
227: break;
228: case 'n':
229: options.dnsresolution ^= 1;
230: printf("DNS resolution is %s.\n\n", options.dnsresolution ? "ON" : "OFF");
231: tick(1);
232: break;
233: case 'N':
234: options.portresolution ^= 1;
235: printf("Port resolution is %s.\n\n", options.portresolution ? "ON" : "OFF");
236: tick(1);
237: break;
238: case 's':
239: options.aggregate_src ^= 1;
240: printf("%s source host\n\n", options.aggregate_src ? "Hide" : "Show");
241: tick(1);
242: break;
243: case 'd':
244: options.aggregate_dest ^= 1;
245: printf("%s destination host\n\n", options.aggregate_dest ? "Hide" : "Show");
246: tick(1);
247: break;
248: case 'S':
249: if (options.showports == OPTION_PORTS_OFF) {
250: options.showports = OPTION_PORTS_SRC;
251: }
252: else if (options.showports == OPTION_PORTS_DEST) {
253: options.showports = OPTION_PORTS_ON;
254: }
255: else if(options.showports == OPTION_PORTS_ON) {
256: options.showports = OPTION_PORTS_DEST;
257: }
258: else {
259: options.showports = OPTION_PORTS_OFF;
260: }
261: printf("Showing ports:%s%s%s%s.\n\n",
262: options.showports == OPTION_PORTS_SRC ? " src" : "",
263: options.showports == OPTION_PORTS_DEST ? " dest" : "",
264: options.showports == OPTION_PORTS_ON ? " both" : "",
265: options.showports == OPTION_PORTS_OFF ? " none" : "");
266: tick(1);
267: break;
268: case 'D':
269: if (options.showports == OPTION_PORTS_OFF) {
270: options.showports = OPTION_PORTS_DEST;
271: }
272: else if (options.showports == OPTION_PORTS_SRC) {
273: options.showports = OPTION_PORTS_ON;
274: }
275: else if(options.showports == OPTION_PORTS_ON) {
276: options.showports = OPTION_PORTS_SRC;
277: }
278: else {
279: options.showports = OPTION_PORTS_OFF;
280: }
281: printf("Showing ports:%s%s%s%s.\n\n",
282: options.showports == OPTION_PORTS_SRC ? " src" : "",
283: options.showports == OPTION_PORTS_DEST ? " dest" : "",
284: options.showports == OPTION_PORTS_ON ? " both" : "",
285: options.showports == OPTION_PORTS_OFF ? " none" : "");
286: tick(1);
287: break;
288: case 'p':
289: options.showports =
290: (options.showports == OPTION_PORTS_OFF) ?
291: OPTION_PORTS_ON :
292: OPTION_PORTS_OFF;
293: printf("Showing ports:%s%s%s%s.\n\n",
294: options.showports == OPTION_PORTS_SRC ? " src" : "",
295: options.showports == OPTION_PORTS_DEST ? " dest" : "",
296: options.showports == OPTION_PORTS_ON ? " both" : "",
297: options.showports == OPTION_PORTS_OFF ? " none" : "");
298: tick(1);
299: break;
300: case 'P':
301: options.paused ^= 1;
302: if (options.paused) {
303: printf("Pausing... press 'P' again to continue.\n");
304: }
305: else {
306: printf("Continuing.\n\n");
307: tick(1);
308: }
309: break;
310: case 'o':
311: options.freezeorder ^= 1;
312: printf("Order %s.\n\n", options.freezeorder ? "frozen" : "unfrozen");
313: tick(1);
314: break;
315: case '1':
316: options.sort = OPTION_SORT_DIV1;
317: printf("Sorting by column 1.\n\n");
318: tick(1);
319: break;
320: case '2':
321: options.sort = OPTION_SORT_DIV2;
322: printf("Sorting by column 2.\n\n");
323: tick(1);
324: break;
325: case '3':
326: options.sort = OPTION_SORT_DIV3;
327: printf("Sorting by column 3.\n\n");
328: tick(1);
329: break;
330: case '<':
331: options.sort = OPTION_SORT_SRC;
332: printf("Sorting by column source.\n\n");
333: tick(1);
334: break;
335: case '>':
336: options.sort = OPTION_SORT_DEST;
337: printf("Sorting by column destination.\n\n");
338: tick(1);
339: break;
340: default:
341: break;
342: }
343: }
344:
345: #if defined(HAVE_TERMIOS_H)
346: tcsetattr(STDIN_FILENO, TCSANOW, &old_termios);
347: #elif defined(HAVE_SGTTY_H) && defined(TIOCSETP)
348: ioctl(0, TIOCSETP, &old_tty);
349: #elif defined(HAVE_TERMIO_H)
350: ioctl(0, TCSETA, &old_termio);
351: #else
352: system("/bin/stty -cbreak echo >/dev/null 2>&1");
353: #endif
354: }
355:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>