]> gitweb.fperrin.net Git - iftop.git/blob - tui.c
Import iftop-1.0pre4
[iftop.git] / tui.c
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