]> gitweb.fperrin.net Git - iftop.git/blob - tui.c
gitignore
[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_unit);
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_unit);
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_unit);
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_unit);
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_unit);
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_unit);
145   readable_size(peakrecv / RESOLUTION, buf1_10, 10, 1024, options.bandwidth_unit);
146   readable_size(peaktotal / RESOLUTION, buf2_10, 10, 1024, options.bandwidth_unit);
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   /* Dropped packets */
157   snprintf(labellong, PRINT_WIDTH + 9, "%-*s", PRINT_WIDTH + 9, "Dropped packets:");
158   readable_size(history_totals.lost_packets, buf0_10, 10, 1024, options.bandwidth_unit);
159   printf("%s %10s\n", labellong, buf0_10, buf1_10, buf2_10);
160
161   /* Double divider line */
162   for (j = 0; j < PRINT_WIDTH + 52; j++) {
163     printf("=");
164   }
165   printf("\n\n");
166 }
167
168
169 /*
170  * Text interface data structure initializations.
171  */
172 void tui_init() {
173   screen_list_init();
174   screen_hash = addr_hash_create();
175   service_hash = serv_hash_create();
176   serv_hash_initialise(service_hash);
177
178   printf("Listening on %s\n", options.interface);
179 }
180
181
182 /*
183  * Tick function indicating screen refresh
184  */
185 void tui_tick(int print) {
186   if (print) {
187     tui_print();
188   }
189 }
190
191
192 /*
193  * Main UI loop. Code any interactive character inputs here.
194  */
195 void tui_loop() {
196   int i;
197   extern sig_atomic_t foad;
198
199 #if defined(HAVE_TERMIOS_H)
200   struct termios new_termios, old_termios;
201
202   tcgetattr(STDIN_FILENO, &old_termios);
203   new_termios = old_termios;
204   new_termios.c_lflag &= ~(ICANON|ECHO);
205   new_termios.c_cc[VMIN] = 1;
206   new_termios.c_cc[VTIME] = 0;
207   tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
208 #elif defined(HAVE_SGTTY_H) && defined(TIOCSETP)
209   struct sgttyb new_tty, old_tty;
210
211   ioctl(STDIN_FILENO, TIOCGETP, &old_tty);
212   new_tty = old_tty;
213   new_tty.sg_flags &= ~(ICANON|ECHO);
214   ioctl(STDIN_FILENO, TIOCSETP, &new_tty);
215 #elif defined(HAVE_TERMIO_H)
216   struct termio new_termio, old_termio;
217
218   ioctl(0, TCGETA, &old_termio);
219   new_termio = old_termio;
220   new_termio.c_lflag &= ~(ICANON|ECHO);
221   new_termio.c_cc[VMIN] = 1;
222   new_termio.c_cc[VTIME] = 0;
223   ioctl(0, TCSETA, &new_termio);
224 #else
225   system("/bin/stty cbreak -echo >/dev/null 2>&1");
226 #endif
227
228   while ((i = getchar()) != 'q' && foad == 0) {
229     switch (i) {
230       case 'u':
231         tick(1);
232         break;
233       case 'n':
234         options.dnsresolution ^= 1;
235         printf("DNS resolution is %s.\n\n", options.dnsresolution ? "ON" : "OFF");
236         tick(1);
237         break;
238       case 'N':
239         options.portresolution ^= 1;
240         printf("Port resolution is %s.\n\n", options.portresolution ? "ON" : "OFF");
241         tick(1);
242         break;
243       case 's':
244         options.aggregate_src ^= 1;
245         printf("%s source host\n\n", options.aggregate_src ? "Hide" : "Show");
246         tick(1);
247         break;
248       case 'd':
249         options.aggregate_dest ^= 1;
250         printf("%s destination host\n\n", options.aggregate_dest ? "Hide" : "Show");
251         tick(1);
252         break;
253       case 'S':
254         if (options.showports == OPTION_PORTS_OFF) {
255           options.showports = OPTION_PORTS_SRC;
256         }
257         else if (options.showports == OPTION_PORTS_DEST) {
258           options.showports = OPTION_PORTS_ON;
259         }
260         else if(options.showports == OPTION_PORTS_ON) {
261           options.showports = OPTION_PORTS_DEST;
262         }
263         else {
264           options.showports = OPTION_PORTS_OFF;
265         }
266         printf("Showing ports:%s%s%s%s.\n\n",
267           options.showports == OPTION_PORTS_SRC ? " src" : "",
268           options.showports == OPTION_PORTS_DEST ? " dest" : "",
269           options.showports == OPTION_PORTS_ON ? " both" : "",
270           options.showports == OPTION_PORTS_OFF ? " none" : "");
271         tick(1);
272         break;
273       case 'D':
274         if (options.showports == OPTION_PORTS_OFF) {
275           options.showports = OPTION_PORTS_DEST;
276         }
277         else if (options.showports == OPTION_PORTS_SRC) {
278           options.showports = OPTION_PORTS_ON;
279         }
280         else if(options.showports == OPTION_PORTS_ON) {
281           options.showports = OPTION_PORTS_SRC;
282         }
283         else {
284           options.showports = OPTION_PORTS_OFF;
285         }
286         printf("Showing ports:%s%s%s%s.\n\n",
287           options.showports == OPTION_PORTS_SRC ? " src" : "",
288           options.showports == OPTION_PORTS_DEST ? " dest" : "",
289           options.showports == OPTION_PORTS_ON ? " both" : "",
290           options.showports == OPTION_PORTS_OFF ? " none" : "");
291         tick(1);
292         break;
293       case 'p':
294         options.showports =
295          (options.showports == OPTION_PORTS_OFF) ?
296           OPTION_PORTS_ON :
297           OPTION_PORTS_OFF;
298         printf("Showing ports:%s%s%s%s.\n\n",
299           options.showports == OPTION_PORTS_SRC ? " src" : "",
300           options.showports == OPTION_PORTS_DEST ? " dest" : "",
301           options.showports == OPTION_PORTS_ON ? " both" : "",
302           options.showports == OPTION_PORTS_OFF ? " none" : "");
303         tick(1);
304         break;
305       case 'P':
306         options.paused ^= 1;
307         if (options.paused) {
308           printf("Pausing... press 'P' again to continue.\n");
309         }
310         else {
311           printf("Continuing.\n\n");
312           tick(1);
313         }
314         break;
315       case 'o':
316         options.freezeorder ^= 1;
317         printf("Order %s.\n\n", options.freezeorder ? "frozen" : "unfrozen");
318         tick(1);
319         break;
320       case '1':
321         options.sort = OPTION_SORT_DIV1;
322         printf("Sorting by column 1.\n\n");
323         tick(1);
324         break;
325       case '2':
326         options.sort = OPTION_SORT_DIV2;
327         printf("Sorting by column 2.\n\n");
328         tick(1);
329         break;
330       case '3':
331         options.sort = OPTION_SORT_DIV3;
332         printf("Sorting by column 3.\n\n");
333         tick(1);
334         break;
335       case '<':
336         options.sort = OPTION_SORT_SRC;
337         printf("Sorting by column source.\n\n");
338         tick(1);
339         break;
340       case '>':
341         options.sort = OPTION_SORT_DEST;
342         printf("Sorting by column destination.\n\n");
343         tick(1);
344         break;
345       default:
346         break;
347     }
348   }
349
350 #if defined(HAVE_TERMIOS_H)
351   tcsetattr(STDIN_FILENO, TCSANOW, &old_termios);
352 #elif defined(HAVE_SGTTY_H) && defined(TIOCSETP)
353   ioctl(0, TIOCSETP, &old_tty);
354 #elif defined(HAVE_TERMIO_H)
355   ioctl(0, TCSETA, &old_termio);
356 #else
357   system("/bin/stty -cbreak echo >/dev/null 2>&1");
358 #endif
359 }
360