git-svn: trunk@4399
Török Edvin authored on 2008/11/14 01:00:10... | ... |
@@ -1,3 +1,8 @@ |
1 |
+Thu Nov 13 16:27:57 EET 2008 (edwin) |
|
2 |
+------------------------------------ |
|
3 |
+ * contrib/clamdtop/Makefile, contrib/clamdtop/clamdtop.c: select a |
|
4 |
+ clamd |
|
5 |
+ |
|
1 | 6 |
Thu Nov 13 15:55:20 CET 2008 (tk) |
2 | 7 |
--------------------------------- |
3 | 8 |
* libclamav: drop options parameter in cl_engine_new(); replace cl_engine_dup() |
... | ... |
@@ -106,6 +106,23 @@ static void exit_program(enum exit_reason reason, const char *func, unsigned lin |
106 | 106 |
static struct global_stats global; |
107 | 107 |
static int curses_inited = 1; |
108 | 108 |
static int maxystats=0; |
109 |
+static int detail_selected = -1; |
|
110 |
+ |
|
111 |
+static int detail_exists() |
|
112 |
+{ |
|
113 |
+ return global.num_clamd != 1; |
|
114 |
+} |
|
115 |
+ |
|
116 |
+static int detail_is_selected(int idx) |
|
117 |
+{ |
|
118 |
+ if (!detail_exists()) { |
|
119 |
+ assert(idx == 0); |
|
120 |
+ return 1; |
|
121 |
+ } |
|
122 |
+ return idx == detail_selected; |
|
123 |
+} |
|
124 |
+ |
|
125 |
+ |
|
109 | 126 |
/* ---------------------- NCurses routines -----------------*/ |
110 | 127 |
enum colors { |
111 | 128 |
header_color=1, |
... | ... |
@@ -113,6 +130,7 @@ enum colors { |
113 | 113 |
error_color, |
114 | 114 |
value_color, |
115 | 115 |
descr_color, |
116 |
+ selected_color, |
|
116 | 117 |
queue_header_color, |
117 | 118 |
activ_color, |
118 | 119 |
dim_color, |
... | ... |
@@ -217,14 +235,18 @@ static void init_windows(int num_clamd) |
217 | 217 |
stats_window = subwin(stdscr, maxystats, maxx, num_clamd+2, 0); |
218 | 218 |
status_bar_window = subwin(stdscr, 1, maxx, maxy-1, 0); |
219 | 219 |
/* memwindow overlaps, used only in details mode */ |
220 |
- mem_window = derwin(stats_window, 6, 41, 0, maxx-41); |
|
220 |
+ mem_window = derwin(stats_window, 6, 41, 1, maxx-41); |
|
221 | 221 |
touchwin(stdscr); |
222 | 222 |
werase(stdscr); |
223 | 223 |
refresh(); |
224 | 224 |
memset(status_bar_keys, 0, sizeof(status_bar_keys)); |
225 | 225 |
status_bar_keys[0] = "F1 - help"; |
226 | 226 |
status_bar_keys[1] = "Q - quit"; |
227 |
- status_bar_keys[2] = "R - reset bar maximums"; |
|
227 |
+ status_bar_keys[2] = "R - reset maximums"; |
|
228 |
+ if (num_clamd > 1) { |
|
229 |
+ status_bar_keys[3] = "^ - previous clamd"; |
|
230 |
+ status_bar_keys[4] = "v - next clamd"; |
|
231 |
+ } |
|
228 | 232 |
} |
229 | 233 |
|
230 | 234 |
static void init_ncurses(int num_clamd) |
... | ... |
@@ -245,6 +267,7 @@ static void init_ncurses(int num_clamd) |
245 | 245 |
init_pair(error_color, COLOR_WHITE, COLOR_RED); |
246 | 246 |
init_pair(value_color, COLOR_GREEN, DEFAULT_COLOR); |
247 | 247 |
init_pair(descr_color, COLOR_CYAN, DEFAULT_COLOR); |
248 |
+ init_pair(selected_color, COLOR_BLACK, COLOR_CYAN); |
|
248 | 249 |
init_pair(queue_header_color, COLOR_BLACK, COLOR_GREEN); |
249 | 250 |
init_pair(activ_color, COLOR_MAGENTA, DEFAULT_COLOR); |
250 | 251 |
init_pair(dim_color, COLOR_GREEN, DEFAULT_COLOR); |
... | ... |
@@ -294,10 +317,20 @@ static void header(void) |
294 | 294 |
|
295 | 295 |
werase(status_bar_window); |
296 | 296 |
for(i=0;i<sizeof(status_bar_keys)/sizeof(status_bar_keys[0]);i++) { |
297 |
- if(!status_bar_keys[i]) |
|
297 |
+ const char *s = status_bar_keys[i]; |
|
298 |
+ if(!s) |
|
298 | 299 |
continue; |
299 | 300 |
wattron(status_bar_window, A_REVERSE); |
300 |
- mvwprintw(status_bar_window, 0, x, "%s",status_bar_keys[i]); |
|
301 |
+ if (s[0] == '^') { |
|
302 |
+ mvwaddch(status_bar_window, 0, x, ACS_UARROW); |
|
303 |
+ s++; |
|
304 |
+ x++; |
|
305 |
+ } else if (s[0] == 'v') { |
|
306 |
+ mvwaddch(status_bar_window, 0, x, ACS_DARROW); |
|
307 |
+ s++; |
|
308 |
+ x++; |
|
309 |
+ } |
|
310 |
+ mvwprintw(status_bar_window, 0, x, "%s",s); |
|
301 | 311 |
wattroff(status_bar_window, A_REVERSE); |
302 | 312 |
x += strlen(status_bar_keys[i]) + 1; |
303 | 313 |
} |
... | ... |
@@ -580,43 +613,52 @@ static int recv_line(conn_t *conn, char *buf, size_t len) |
580 | 580 |
|
581 | 581 |
static void output_queue(size_t line, ssize_t max) |
582 | 582 |
{ |
583 |
- ssize_t i; |
|
583 |
+ ssize_t i, j; |
|
584 | 584 |
struct task *tasks = global.tasks; |
585 |
+ struct task *filtered_tasks = calloc(global.n, sizeof(*filtered_tasks)); |
|
586 |
+ OOM_CHECK(filtered_tasks); |
|
587 |
+ for (i=0,j=0;i<global.n;i++) { |
|
588 |
+ if (detail_selected == -1 || detail_is_selected(tasks[i].clamd_no-1)) { |
|
589 |
+ filtered_tasks[j++] = tasks[i]; |
|
590 |
+ } |
|
591 |
+ } |
|
592 |
+ |
|
585 | 593 |
wattron(stats_window, COLOR_PAIR(queue_header_color)); |
586 | 594 |
mvwprintw(stats_window, line++, 0, "%s", queue_header); |
587 | 595 |
wattroff(stats_window, COLOR_PAIR(queue_header_color)); |
588 |
- if (max >= global.n) |
|
589 |
- max = global.n; |
|
596 |
+ if (max >= j) |
|
597 |
+ max = j; |
|
590 | 598 |
else |
591 | 599 |
--max; |
592 | 600 |
if (max < 0) max = 0; |
593 | 601 |
for(i=0;i<max;i++) { |
594 | 602 |
assert(tasks); |
595 |
- char *cmde = strchr(tasks[i].line, ' '); |
|
603 |
+ char *cmde = strchr(filtered_tasks[i].line, ' '); |
|
596 | 604 |
if(cmde) { |
597 | 605 |
char cmd[16]; |
598 | 606 |
const char *filstart = strchr(cmde + 1, ' '); |
599 |
- strncpy(cmd, tasks[i].line, sizeof(cmd)-1); |
|
607 |
+ strncpy(cmd, filtered_tasks[i].line, sizeof(cmd)-1); |
|
600 | 608 |
cmd[15]='\0'; |
601 |
- if (tasks[i].line+15 > cmde) |
|
602 |
- cmd[cmde - tasks[i].line] = '\0'; |
|
609 |
+ if (filtered_tasks[i].line+15 > cmde) |
|
610 |
+ cmd[cmde - filtered_tasks[i].line] = '\0'; |
|
603 | 611 |
if(filstart) { |
604 | 612 |
++filstart; |
605 |
- if (global.num_clamd>1) |
|
606 |
- mvwprintw(stats_window, line + i, 0, "%2u %s", tasks[i].clamd_no, cmd + 1); |
|
613 |
+ if (detail_selected == -1 && global.num_clamd > 1) |
|
614 |
+ mvwprintw(stats_window, line + i, 0, "%2u %s", filtered_tasks[i].clamd_no, cmd + 1); |
|
607 | 615 |
else |
608 | 616 |
mvwprintw(stats_window, line + i, 0, " %s", cmd + 1); |
609 |
- mvwprintw(stats_window, line + i, 15, "%10.03fs", tasks[i].tim); |
|
617 |
+ mvwprintw(stats_window, line + i, 15, "%10.03fs", filtered_tasks[i].tim); |
|
610 | 618 |
mvwprintw(stats_window, line + i, 30, "%s",filstart); |
611 | 619 |
} |
612 | 620 |
} |
613 | 621 |
} |
614 |
- if (max < global.n) { |
|
622 |
+ if (max < j) { |
|
615 | 623 |
/* in summary mode we can only show a max amount of tasks */ |
616 | 624 |
wattron(stats_window, A_DIM | COLOR_PAIR(header_color)); |
617 |
- mvwprintw(stats_window, line+i, 0, "*** %u more task(s) not shown ***", (unsigned)(global.n - max)); |
|
625 |
+ mvwprintw(stats_window, line+i, 0, "*** %u more task(s) not shown ***", (unsigned)(j - max)); |
|
618 | 626 |
wattroff(stats_window, A_DIM | COLOR_PAIR(header_color)); |
619 | 627 |
} |
628 |
+ free(filtered_tasks); |
|
620 | 629 |
} |
621 | 630 |
|
622 | 631 |
/* ---------------------- stats parsing routines ------------------- */ |
... | ... |
@@ -697,20 +739,6 @@ static void parse_memstats(const char *line, struct stats *stats) |
697 | 697 |
if (stats->mem == 0) stats->mem = -1; |
698 | 698 |
} |
699 | 699 |
|
700 |
-static int show_detail(int idx) |
|
701 |
-{ |
|
702 |
- if (global.num_clamd == 1) { |
|
703 |
- assert(idx == 0); |
|
704 |
- return 1; |
|
705 |
- } |
|
706 |
- return 0; |
|
707 |
-} |
|
708 |
- |
|
709 |
-static int has_detail() |
|
710 |
-{ |
|
711 |
- return global.num_clamd == 1; |
|
712 |
-} |
|
713 |
- |
|
714 | 700 |
static int output_stats(struct stats *stats, unsigned idx) |
715 | 701 |
{ |
716 | 702 |
char buf[128]; |
... | ... |
@@ -719,6 +747,10 @@ static int output_stats(struct stats *stats, unsigned idx) |
719 | 719 |
size_t i= 0; |
720 | 720 |
char mem[6]; |
721 | 721 |
WINDOW *win = stats_head_window; |
722 |
+ int sel = detail_is_selected(idx); |
|
723 |
+ char *line = malloc(maxx+1); |
|
724 |
+ |
|
725 |
+ OOM_CHECK(line); |
|
722 | 726 |
|
723 | 727 |
if (stats->mem == -1 || stats->stats_unsupp) |
724 | 728 |
strncpy(mem, "N/A", sizeof(mem)); |
... | ... |
@@ -749,19 +781,36 @@ static int output_stats(struct stats *stats, unsigned idx) |
749 | 749 |
stats->db_time.tm_mday, |
750 | 750 |
stats->db_time.tm_hour); |
751 | 751 |
|
752 |
+ memset(line, ' ', maxx+1); |
|
752 | 753 |
if (!stats->stats_unsupp) { |
753 |
- mvwprintw(win, i++, 0,"%2u %02u:%02u:%02u %3u %3u %5u %5u %5s %-14s %-6s %5s %s", idx+1, stats->conn_hr, stats->conn_min, stats->conn_sec, |
|
754 |
+ snprintf(line, maxx-1, "%2u %02u:%02u:%02u %3u %3u %5u %5u %5s %-14s %-6s %5s %s", idx+1, stats->conn_hr, stats->conn_min, stats->conn_sec, |
|
754 | 755 |
stats->live, stats->idle, |
755 | 756 |
stats->current_q, stats->biggest_queue, |
756 | 757 |
mem, |
757 | 758 |
stats->remote, stats->engine_version, stats->db_version, timbuf); |
758 | 759 |
} else { |
759 |
- mvwprintw(win, i++, 0,"%2u %02u:%02u:%02u N/A N/A N/A N/A N/A %-14s %-6s %5s %s", idx+1, stats->conn_hr, stats->conn_min, stats->conn_sec, |
|
760 |
+ snprintf(line, maxx-1, "%2u %02u:%02u:%02u N/A N/A N/A N/A N/A %-14s %-6s %5s %s", idx+1, stats->conn_hr, stats->conn_min, stats->conn_sec, |
|
760 | 761 |
stats->remote, stats->engine_version, stats->db_version, timbuf); |
761 | 762 |
} |
763 |
+ line[maxx] = '\0'; |
|
764 |
+ line[strlen(line)] = ' '; |
|
765 |
+ if (sel) { |
|
766 |
+ wattron(win, COLOR_PAIR(selected_color)); |
|
767 |
+ } |
|
768 |
+ mvwprintw(win, i++, 0, "%s", line); |
|
769 |
+ if (sel) { |
|
770 |
+ wattroff(win, COLOR_PAIR(selected_color)); |
|
771 |
+ } |
|
762 | 772 |
win = stats_window; |
763 | 773 |
i = 0; |
764 |
- if (show_detail(idx) && !stats->stats_unsupp) { |
|
774 |
+ if (sel && !stats->stats_unsupp) { |
|
775 |
+ memset(line, ' ', maxx+1); |
|
776 |
+ snprintf(line, maxx-1, "Details for Clamd version: %s", stats->version); |
|
777 |
+ line[maxx] = '\0'; |
|
778 |
+ line[strlen(line)]= ' '; |
|
779 |
+ wattron(win, COLOR_PAIR(queue_header_color)); |
|
780 |
+ mvwprintw(win, i++, 0, "%s", line); |
|
781 |
+ wattroff(win, COLOR_PAIR(queue_header_color)); |
|
765 | 782 |
mvwprintw(win, i++, 0, "Primary threads: "); |
766 | 783 |
snprintf(buf, sizeof(buf), "live %3u idle %3u max %3u", stats->prim_live, stats->prim_idle, stats->prim_max); |
767 | 784 |
print_colored(win, buf); |
... | ... |
@@ -783,9 +832,10 @@ static int output_stats(struct stats *stats, unsigned idx) |
783 | 783 |
stats->biggest_queue = stats->current_q; |
784 | 784 |
blink = 1; |
785 | 785 |
} |
786 |
- if (show_detail(idx) && !stats->stats_unsupp) { |
|
786 |
+ if (sel && !stats->stats_unsupp) { |
|
787 | 787 |
show_bar(win, i++, stats->current_q, 0, biggest_queue, blink); |
788 | 788 |
} |
789 |
+ free(line); |
|
789 | 790 |
return i; |
790 | 791 |
} |
791 | 792 |
|
... | ... |
@@ -797,12 +847,15 @@ static void output_all(void) |
797 | 797 |
wattron(stats_head_window, COLOR_PAIR(queue_header_color)); |
798 | 798 |
mvwprintw(stats_head_window, 0, 0, "%s", clamd_header); |
799 | 799 |
wattroff(stats_head_window, COLOR_PAIR(queue_header_color)); |
800 |
- for (i=0;i<global.num_clamd;i++) |
|
801 |
- stats_line = output_stats(&global.all_stats[i], i); |
|
800 |
+ for (i=0;i<global.num_clamd;i++) { |
|
801 |
+ unsigned j = output_stats(&global.all_stats[i], i); |
|
802 |
+ if (j > stats_line) |
|
803 |
+ stats_line = j; |
|
804 |
+ } |
|
802 | 805 |
output_queue(stats_line, maxystats - stats_line-1); |
803 | 806 |
wrefresh(stats_head_window); |
804 | 807 |
wrefresh(stats_window); |
805 |
- if (has_detail()) { |
|
808 |
+ if (detail_exists()) { |
|
806 | 809 |
/* overlaps, must be done at the end */ |
807 | 810 |
wrefresh(mem_window); |
808 | 811 |
} |
... | ... |
@@ -938,7 +991,12 @@ static void read_version(conn_t *conn) |
938 | 938 |
{ |
939 | 939 |
char buf[1024]; |
940 | 940 |
if(recv_line(conn, buf, sizeof(buf))) { |
941 |
+ unsigned i; |
|
941 | 942 |
conn->version = strdup(buf); |
943 |
+ OOM_CHECK(conn->version); |
|
944 |
+ for (i=0;i<strlen(conn->version);i++) |
|
945 |
+ if (conn->version[i] == '\n') |
|
946 |
+ conn->version[i] = ' '; |
|
942 | 947 |
} |
943 | 948 |
} |
944 | 949 |
|
... | ... |
@@ -1075,18 +1133,38 @@ int main(int argc, char *argv[]) |
1075 | 1075 |
|
1076 | 1076 |
memset(&tv_last, 0, sizeof(tv_last)); |
1077 | 1077 |
do { |
1078 |
- if (ch == KEY_F(1)) { |
|
1079 |
- ch = show_help(); |
|
1080 |
- } |
|
1081 |
- if(ch == KEY_RESIZE) { |
|
1082 |
- resize(); |
|
1083 |
- endwin(); |
|
1084 |
- refresh(); |
|
1085 |
- init_windows(global.num_clamd); |
|
1086 |
- } |
|
1087 |
- if(ch == 'R') { |
|
1088 |
- biggest_queue = 1; |
|
1089 |
- biggest_mem = 0; |
|
1078 |
+ switch(ch) { |
|
1079 |
+ case KEY_F(1): |
|
1080 |
+ ch = show_help(); |
|
1081 |
+ break; |
|
1082 |
+ case KEY_RESIZE: |
|
1083 |
+ resize(); |
|
1084 |
+ endwin(); |
|
1085 |
+ refresh(); |
|
1086 |
+ init_windows(global.num_clamd); |
|
1087 |
+ break; |
|
1088 |
+ case 'R': |
|
1089 |
+ biggest_queue = 1; |
|
1090 |
+ biggest_mem = 0; |
|
1091 |
+ break; |
|
1092 |
+ case KEY_UP: |
|
1093 |
+ if (global.num_clamd > 1) { |
|
1094 |
+ if (detail_selected == -1) |
|
1095 |
+ detail_selected = global.num_clamd-1; |
|
1096 |
+ else |
|
1097 |
+ --detail_selected; |
|
1098 |
+ } |
|
1099 |
+ break; |
|
1100 |
+ case KEY_DOWN: |
|
1101 |
+ if (global.num_clamd > 1) { |
|
1102 |
+ if (detail_selected == -1) |
|
1103 |
+ detail_selected = 0; |
|
1104 |
+ else { |
|
1105 |
+ if((unsigned)++detail_selected >= global.num_clamd) |
|
1106 |
+ detail_selected = -1; |
|
1107 |
+ } |
|
1108 |
+ } |
|
1109 |
+ break; |
|
1090 | 1110 |
} |
1091 | 1111 |
gettimeofday(&tv, NULL); |
1092 | 1112 |
header(); |