Annotation of embedaddon/trafshow/getkey.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1998,2004 Rinet Corp., Novosibirsk, Russia
3: *
4: * Redistribution and use in source forms, with and without modification,
5: * are permitted provided that this entire comment appears intact.
6: *
7: * THIS SOURCE CODE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
8: */
9:
10: #ifdef HAVE_CONFIG_H
11: #include <config.h>
12: #endif
13:
14: #ifdef HAVE_SLCURSES
15: #include <slcurses.h>
16: #elif HAVE_NCURSES
17: #include <ncurses.h>
18: #else
19: #include <curses.h>
20: #endif
21: #include <stdio.h>
22: #include <stdlib.h>
23: #include <string.h>
24: #include <unistd.h>
25:
26: #include "getkey.h"
27: #include "screen.h"
28: #include "session.h"
29: #include "trafshow.h"
30: #include "selector.h"
31: #include "show_if.h"
32: #include "show_stat.h"
33: #include "show_dump.h"
34: #include "events.h"
35: #include "netstat.h"
36: #include "help_page.h"
37:
38:
39: static void read_key(SESSION *sd, const unsigned char *data, int len);
40: static int scan_key(const unsigned char *buf, int len);
41: static void parse_key(int key, PCAP_HANDLER *ph);
42: static void init_edit_string(const char *prompter, const char *charset, int size);
43: static int edit_string(int ch);
44:
45: /* edit string stuff */
46: static const char *numbers = "1234567890";
47: static const char *spaces = " ,.;@/\\";
48: static char prompt_buf[MAX_PARAM_LEN], cut_buf[MAX_PARAM_LEN];
49: static const char *char_set;
50: static int buf_size, cur, nb, win, scr, bartop, barlen, touch, show_win;
51:
52:
53: void
54: getkey_init(ph)
55: PCAP_HANDLER *ph;
56: {
57: SESSION *sd;
58:
59: if ((sd = session_open(0, 0, PlainFile)) == 0) {
60: perror("session_open 0"); /* should not happen */
61: exit(1);
62: }
63: session_setcallback(sd, 0, 0, read_key);
64: session_setcookie(sd, ph);
65: prompt_mode = 0;
66: }
67:
68: static void
69: read_key(sd, data, len)
70: SESSION *sd;
71: const unsigned char *data;
72: int len;
73: {
74: /* sanity check */
75: if (sd && data && len > 0) {
76: int key = scan_key(data, len);
77: if (key != -1)
78: parse_key(key, (PCAP_HANDLER *)session_cookie(sd));
79: }
80: }
81:
82: static SELECTOR *
83: get_selector(ph_list)
84: PCAP_HANDLER *ph_list;
85: {
86: /* return current selector */
87: switch (show_mode) {
88: case Interfaces:
89: return show_if_selector();
90: case NetStat:
91: return show_stat_selector(pcap_get_selected(ph_list));
92: case FlowDump:
93: /* nope */
94: break;
95: case HelpPage:
96: return help_page_selector();
97: }
98: return 0;
99: }
100:
101: static void
102: parse_key(key, ph_list)
103: int key;
104: PCAP_HANDLER *ph_list;
105: {
106: int ch = key;
107: PCAP_HANDLER *ph = 0;
108: SELECTOR *sp = 0;
109: struct timeval now;
110:
111: if (prompt_mode) {
112: const char *txt = 0;
113: int redraw = 1;
114: if ((ch = edit_string(ch)) == 0) /* still edit */
115: return;
116: if (ch > 0) {
117: switch (prompt_mode) {
118: case 'r': /* end of getting refresh time */
119: case 'R':
120: ch = atoi(prompt_buf);
121: if (ch > 0 && ch != refresh_time) {
122: if (ch < purge_time)
123: refresh_time = ch;
124: else txt = "Refresh Time must be less than Purge Time";
125: }
126: break;
127: case 'p': /* end of getting purge time */
128: case 'P':
129: ch = atoi(prompt_buf);
130: if (ch > 0 && ch != purge_time) {
131: if (ch > refresh_time) {
132: purge_time = ch;
133: add_event(0, pcap_purge, ph_list);
134: redraw = 0;
135: } else txt = "Purge Time must be bigger than Refresh Time";
136: }
137: break;
138: case 'f': /* end of getting filter expression */
139: case 'F':
140: if (!expression || strcmp(prompt_buf, expression)) {
141: if (expression) free(expression);
142: expression = strdup(prompt_buf);
143: if ((txt = pcap_setexpr(ph_list, expression)) == 0) {
144: if (prompt_mode == 'F') {
145: add_event(0, pcap_clear, ph_list);
146: redraw = 0;
147: }
148: }
149: }
150: break;
151: case '/': /* end of getting search string */
152: if (prompt_buf[0] == '\0') {
153: if (search) {
154: free(search);
155: search = 0;
156: txt = "Search mode turned Off";
157: }
158: } else if (!search || strcmp(prompt_buf, search)) {
159: if (search) free(search);
160: search = strdup(prompt_buf);
161: }
162: break;
163: case 'a': /* end of getting aggregation masklen */
164: case 'A':
165: if (prompt_buf[0]) {
166: ch = atoi(prompt_buf);
167: if (ch < 0 || ch > ADDRBITLEN) {
168: txt = "Wrong netmask length";
169: break;
170: }
171: } else ch = -1;
172: if (show_mode == NetStat &&
173: (ph = pcap_get_selected(ph_list)) != 0) {
174: if (ph->masklen != ch) {
175: ph->masklen = ch;
176: if (prompt_mode == 'A')
177: netstat_purge(ph, 0);
178: }
179: } else {
180: aggregate = ch;
181: for (ph = ph_list; ph; ph = ph->next) {
182: if (ph->masklen != aggregate) {
183: ph->masklen = aggregate;
184: if (prompt_mode == 'A')
185: netstat_purge(ph, 0);
186: }
187: }
188: }
189: break;
190: }
191: }
192: prompt_mode = 0;
193: if (redraw)
194: add_event(0, pcap_show, ph_list);
195: if (txt)
196: screen_status(txt);
197: else screen_update();
198: return;
199: }
200:
201: /* try global operation keys */
202: switch (ch) {
203: case K_ESC: /* get back show mode */
204: case 'q':
205: case 'Q':
206: switch (show_mode) {
207: case Interfaces:
208: exit(0);
209: case NetStat:
210: if ((ph = pcap_get_selected(ph_list)) != 0 && ph->top)
211: pcaph_close(ph);
212: else show_mode = Interfaces;
213: pcap_show(ph_list);
214: return;
215: case FlowDump:
216: show_dump_close();
217: show_mode = NetStat;
218: pcap_show(ph_list);
219: return;
220: case HelpPage:
221: show_mode = help_page_mode();
222: pcap_show(ph_list);
223: return;
224: }
225: break;
226: case K_CTRL('L'): /* refresh screen */
227: clear();
228: refresh();
229: pcap_show(ph_list);
230: return;
231: case 'h': /* help page if any */
232: case 'H':
233: case '?':
234: case K_F1:
235: if (help_page_list(show_mode)) {
236: show_mode = HelpPage;
237: pcap_show(ph_list);
238: return;
239: }
240: break;
241: case 'r': /* start to get refresh time */
242: case 'R':
243: if (show_mode != FlowDump) {
244: prompt_mode = ch;
245: snprintf(prompt_buf, sizeof(prompt_buf), "%d", refresh_time);
246: init_edit_string("Refresh seconds: ", numbers, 5);
247: selector_withdraw(get_selector(ph_list));
248: screen_update();
249: return;
250: }
251: break;
252: case 'p': /* start to get purge time */
253: case 'P':
254: if (show_mode != FlowDump) {
255: prompt_mode = ch;
256: snprintf(prompt_buf, sizeof(prompt_buf), "%d", purge_time);
257: init_edit_string("Purge seconds: ", numbers, 5);
258: selector_withdraw(get_selector(ph_list));
259: screen_update();
260: return;
261: }
262: break;
263: case 'f': /* start to get filter expression */
264: case 'F':
265: if (show_mode != FlowDump) {
266: prompt_mode = ch;
267: prompt_buf[0] = '\0';
268: if (expression) {
269: (void)strncpy(prompt_buf, expression, sizeof(prompt_buf));
270: prompt_buf[sizeof(prompt_buf)-1] = '\0';
271: }
272: init_edit_string("Filter expression: ", 0, sizeof(prompt_buf));
273: selector_withdraw(get_selector(ph_list));
274: screen_update();
275: return;
276: }
277: break;
278: case '/': /* start to get search string */
279: if (show_mode != FlowDump) {
280: prompt_mode = ch;
281: prompt_buf[0] = '\0';
282: if (search) {
283: (void)strncpy(prompt_buf, search, sizeof(prompt_buf));
284: prompt_buf[sizeof(prompt_buf)-1] = '\0';
285: }
286: init_edit_string("Search string: ", 0, sizeof(prompt_buf));
287: selector_withdraw(get_selector(ph_list));
288: screen_update();
289: return;
290: }
291: break;
292: case K_CTRL('_'): /* turn off search mode */
293: if (show_mode != FlowDump) {
294: if (search) {
295: free(search);
296: search = 0;
297: screen_status("Search mode turned Off");
298: }
299: return;
300: }
301: break;
302: case 'a': /* start to get aggregation masklen */
303: case 'A':
304: if (show_mode != FlowDump) {
305: char buf[100];
306: prompt_mode = ch;
307: prompt_buf[0] = '\0';
308: if (show_mode == NetStat &&
309: (ph = pcap_get_selected(ph_list)) != 0) {
310: if (ph->masklen >= 0)
311: snprintf(prompt_buf, sizeof(prompt_buf), "%d", ph->masklen);
312: snprintf(buf, sizeof(buf), "%s aggregation netmask length: ", ph->name);
313: } else {
314: if (aggregate >= 0)
315: snprintf(prompt_buf, sizeof(prompt_buf), "%d", aggregate);
316: (void)strcpy(buf, "Aggregation netmask length: ");
317: }
318: init_edit_string(buf, numbers, 5);
319: selector_withdraw(get_selector(ph_list));
320: screen_update();
321: return;
322: }
323: break;
324: case K_CTRL('R'): /* reset all netstat hash */
325: if (show_mode == Interfaces) {
326: add_event(0, pcap_clear, ph_list);
327: screen_status("Resetting all flows");
328: return;
329: }
330: break;
331: case 'n': /* toggle numeric values to names conversion */
332: case 'N':
333: if (show_mode != FlowDump) {
334: nflag ^= 1;
335: if (ch == 'N') {
336: add_event(0, pcap_show, ph_list);
337: } else {
338: screen_status("Numeric values turned %s",
339: nflag ? "On" : "Off");
340: }
341: return;
342: }
343: break;
344: }
345:
346: /* prevent screen refresh overhead */
347: gettimeofday(&now, 0);
348: now.tv_sec += refresh_time;
349: add_event(&now, pcap_show, ph_list);
350:
351: /* get current selector */
352: switch (show_mode) {
353: case Interfaces:
354: sp = show_if_selector();
355: break;
356: case NetStat:
357: if ((ph = pcap_get_selected(ph_list)) == 0)
358: return;
359: sp = show_stat_selector(ph);
360:
361: /* try special input for the show mode */
362: if (show_stat_input(ph, ch)) {
363: selector_redraw(sp);
364: return;
365: }
366: break;
367: case FlowDump:
368: /* special input only for the show mode */
369: show_dump_input(ch);
370: return;
371: case HelpPage:
372: sp = help_page_selector();
373: break;
374: }
375:
376: /* try special input for the selecting */
377: ch = selector_move(ch, sp);
378: if (ch < 0) {
379: selector_redraw(sp);
380: return;
381: }
382:
383: /* something selected */
384: switch (show_mode) {
385: case Interfaces:
386: if ((ph = pcap_set_selected(ph_list, ch)) == 0)
387: return; /* should not happen */
388: /*selector_withdraw(sp);*/
389: show_mode = NetStat;
390: pcap_show(ph_list);
391: return;
392: case NetStat:
393: /*selector_withdraw(sp);*/
394: if (ph->masklen == -1) {
395: if (show_dump_open(ph, show_stat_get(ph, ch)) == 0)
396: show_mode = FlowDump;
397: } else if (pcaph_create(ph, (struct netstat_header *)show_stat_get(ph, ch))) {
398: pcap_show(ph_list);
399: }
400: return;
401: case FlowDump:
402: /* not reached; just to avoid compiler warning */
403: return;
404: case HelpPage:
405: key = help_page_key(ch);
406: if (key != -1 && key != 0) {
407: show_mode = help_page_mode(); /* get back show mode */
408: pcap_show(ph_list);
409: parse_key(key, ph_list);
410: }
411: return;
412: }
413: }
414:
415: static int
416: scan_key(buf, len)
417: const unsigned char *buf;
418: int len;
419: {
420: int i;
421:
422: if (buf[0] != ESCAPE) return buf[0];
423: if (len == 1) return K_ESC;
424: i = 1;
425: if (buf[i] == '[' || buf[i] == 'O')
426: if (++i >= len) return -1;
427:
428: switch (buf[i]) {
429: case '\0': /* xterm */
430: return K_HOME;
431: case 'A':
432: case 'i':
433: return K_UP;
434: case 'B':
435: return K_DOWN;
436: case 'D':
437: return K_LEFT;
438: case 'C':
439: return K_RIGHT;
440: case 'I': /* ansi PgUp */
441: case 'V': /* at386 PgUp */
442: case 'S': /* 97801 PgUp */
443: case 'v': /* emacs style */
444: return K_PAGEUP;
445: case 'G': /* ansi PgDn */
446: case 'U': /* at386 PgDn */
447: case 'T': /* 97801 PgDn */
448: return K_PAGEDOWN;
449: case 'H': /* at386 Home */
450: return K_HOME;
451: case 'F': /* ansi End */
452: case 'Y': /* at386 End */
453: return K_END;
454: case '5': /* vt200 PgUp */
455: return K_PAGEUP;
456: case '6': /* vt200 PgUp */
457: return K_PAGEDOWN;
458: case '1': /* vt200 PgUp */
459: if (++i >= len) return -1;
460: switch(buf[i]) { /* xterm */
461: case '1':
462: return K_F1;
463: case '2':
464: return K_F2;
465: case '3':
466: return K_F3;
467: case '4':
468: return K_F4;
469: case '5': /* RS/6000 PgUp is 150g, PgDn is 154g */
470: if (++i >= len) return -1;
471: if (buf[i] == '0')
472: return K_PAGEUP;
473: if (buf[i] == '4')
474: return K_PAGEDOWN;
475: }
476: return K_HOME;
477: case '4': /* vt200 PgUp */
478: return K_END;
479: case '2': /* xterm */
480: case 'L':
481: return K_INS;
482: case 'M':
483: return K_F1;
484: case 'N':
485: return K_F2;
486: case 'O':
487: return K_F3;
488: case 'P':
489: return K_F4;
490: }
491: return -1;
492: }
493:
494: static void
495: init_edit_string(prompter, charset, size)
496: const char *prompter, *charset;
497: int size;
498: {
499: int i;
500:
501: char_set = charset;
502: touch = 0;
503: show_win = 0;
504:
505: *cut_buf = '\0';
506: bartop = strlen(prompter);
507: i = COLS - (bartop + 3);
508: barlen = buf_size = size;
509: if (barlen < 1 || barlen > i) {
510: barlen = i;
511: show_win = 1;
512: }
513:
514: attrset(A_NORMAL);
515: move(LINES-1, 0);
516: clrtoeol();
517: addstr(prompter);
518:
519: nb = strlen(prompt_buf);
520: if (nb >= buf_size) nb = buf_size - 1;
521: prompt_buf[nb] = '\0';
522: cur = nb;
523:
524: win = cur / barlen; /* window number */
525: scr = cur % barlen; /* screen position */
526:
527: if (show_win) mvprintw(LINES-1, COLS-2, "%-2d", win+1);
528:
529: attrset(A_STANDOUT);
530: mvprintw(LINES-1, bartop, "%-*.*s", barlen, barlen, &prompt_buf[win * barlen]);
531:
532: screen_dock_cursor(LINES-1, bartop + scr);
533: }
534:
535: static int
536: edit_string(ch)
537: int ch;
538: {
539: int i;
540:
541: switch (ch) {
542: case K_ESC:
543: case K_CR:
544: case K_NL:
545: prompt_buf[nb] = '\0';
546: attrset(A_NORMAL);
547: move(LINES-1, 0);
548: clrtoeol();
549: screen_dock_cursor(0, 0);
550: return (ch == K_ESC ? -1 : 1);
551:
552: case K_PAGEUP: /* move to begin of window */
553: cur -= cur % barlen;
554: break;
555: case K_PAGEDOWN:/* move to end of window */
556: if (strlen(&prompt_buf[cur]) < barlen)
557: cur = nb;
558: else cur += barlen - cur % barlen - 1;
559: break;
560: case K_UP: /* skip to previous word */
561: case K_CTRL('P'):
562: ch = 0;
563: for (i = cur; i > 0; i--) {
564: if (!ch) {
565: if (strchr(spaces, prompt_buf[i-1]))
566: ch++;
567: } else if (!strchr(spaces, prompt_buf[i-1]))
568: break;
569: }
570: cur = i;
571: break;
572: case K_DOWN: /* skip to next word */
573: case K_CTRL('N'):
574: ch = 0;
575: for (i = cur; i < nb; i++) {
576: if (!ch) {
577: if (strchr(spaces, prompt_buf[i]))
578: ch++;
579: } else if (!strchr(spaces, prompt_buf[i]))
580: break;
581: }
582: cur = i;
583: break;
584: case K_HOME: /* move to begin of line */
585: case K_CTRL('A'):
586: cur = 0;
587: break;
588: case K_END: /* move to end of line */
589: case K_CTRL('E'):
590: cur = nb;
591: break;
592: case K_LEFT: /* move cursor left */
593: case K_CTRL('B'):
594: if (cur > 0) cur--;
595: break;
596: case K_RIGHT: /* move cursor right */
597: case K_CTRL('F'):
598: if (cur < nb) cur++;
599: break;
600: case K_BS: /* backspace */
601: if (nb && cur) {
602: memmove(&prompt_buf[cur-1], &prompt_buf[cur], nb - cur);
603: cur--;
604: nb--;
605: }
606: break;
607: case K_DEL: /* delete */
608: case K_CTRL('D'):
609: if (nb && cur < nb) {
610: memmove(&prompt_buf[cur], &prompt_buf[cur+1], nb - cur);
611: nb--;
612: }
613: break;
614: case K_CTRL('U'): /* erase entire line */
615: (void)strcpy(cut_buf, prompt_buf);
616: nb = 0;
617: cur = 0;
618: break;
619: case K_CTRL('W'): /* erase last word */
620: ch = 0;
621: for (i = cur; i > 0; i--) {
622: if (!ch) {
623: if (strchr(spaces, prompt_buf[i-1]))
624: ch++;
625: } else if (!strchr(spaces, prompt_buf[i-1]))
626: break;
627: }
628: if (cur > i) {
629: memcpy(cut_buf, &prompt_buf[i], cur - i);
630: cut_buf[cur - i] = '\0';
631: memmove(&prompt_buf[i], &prompt_buf[cur], cur - i);
632: nb -= cur - i;
633: cur = i;
634: }
635: break;
636: case K_CTRL('K'): /* erase end of line */
637: if (prompt_buf[cur] != '\0')
638: (void)strcpy(cut_buf, &prompt_buf[cur]);
639: nb = cur;
640: break;
641: case K_TAB: /* insert cut_buf */
642: i = strlen(cut_buf);
643: if (i && (buf_size - 1) - strlen(prompt_buf) >= i) {
644: memmove(&prompt_buf[cur+i], &prompt_buf[cur], nb - cur);
645: memmove(&prompt_buf[cur], cut_buf, i);
646: nb += i;
647: cur += i;
648: }
649: break;
650: default:
651: if (ch < 32 || ch > 126)
652: return 0; /* skip garbage chars */
653:
654: if (char_set && !strchr(char_set, ch)) {
655: beep();
656: return 0;
657: }
658: if (!touch) {
659: nb = 0;
660: cur = 0;
661: }
662: if (nb >= buf_size - 1) { /* no more space available */
663: beep();
664: return 0;
665: }
666: if (nb > cur)
667: memmove(&prompt_buf[cur+1], &prompt_buf[cur], nb - cur);
668: prompt_buf[cur++] = ch;
669: nb++;
670: }
671: touch = 1;
672:
673: prompt_buf[nb] = '\0';
674:
675: win = cur / barlen; /* window number */
676: scr = cur % barlen; /* screen position */
677:
678: attrset(A_STANDOUT);
679: mvprintw(LINES-1, bartop, "%-*.*s", barlen, barlen, &prompt_buf[win * barlen]);
680: if (show_win) {
681: attrset(A_NORMAL);
682: mvprintw(LINES-1, COLS-2, "%-2d", win+1);
683: }
684:
685: screen_dock_cursor(LINES-1, bartop + scr);
686: screen_update();
687: return 0;
688: }
689:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>