Browse code

select a clamd

git-svn: trunk@4399

Török Edvin authored on 2008/11/14 01:00:10
Showing 2 changed files
... ...
@@ -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();