git-svn: trunk@4386
Török Edvin authored on 2008/11/13 01:53:27... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Wed Nov 12 17:52:12 EET 2008 (edwin) |
|
2 |
+------------------------------------ |
|
3 |
+ * contrib/clamdtop/TODO, contrib/clamdtop/clamdtop.c: refactor, minor fixes |
|
4 |
+ |
|
1 | 5 |
Wed Nov 12 16:31:34 CET 2008 (tk) |
2 | 6 |
--------------------------------- |
3 | 7 |
* libclamav: introduce new API calls for engine management (THIS REVISION IS |
... | ... |
@@ -1,6 +1,9 @@ |
1 | 1 |
select one clamd when monitoring more, and show details for that only |
2 |
-better handling for connection errors (inform user within an ncurses window) |
|
2 |
+parse pool states, and show those that are != VALID |
|
3 |
+highlight problems in version/dbversion/dbtime (old db version, old dbtime, |
|
4 |
+different db versions). |
|
3 | 5 |
write a manpage |
6 |
+check that it works for clamd w/o STATS support (version should still work). |
|
4 | 7 |
consider writing a GUI using Tk 8.5 (version 8.5 has much nicer widgets than 8.4) |
5 | 8 |
integrate into toplevel clamav, and build if ncurses is available (optional) |
6 | 9 |
figure out minimum version of ncurses required, I used 5.5 during development. |
... | ... |
@@ -56,6 +56,7 @@ typedef struct connection { |
56 | 56 |
int tcp; |
57 | 57 |
struct timeval tv_conn; |
58 | 58 |
char *version; |
59 |
+ int line; |
|
59 | 60 |
} conn_t; |
60 | 61 |
|
61 | 62 |
struct global_stats { |
... | ... |
@@ -72,6 +73,7 @@ struct stats { |
72 | 72 |
char *db_version; |
73 | 73 |
struct tm db_time; |
74 | 74 |
const char *version; |
75 |
+ int stats_unsupp; |
|
75 | 76 |
uint8_t conn_hr, conn_min, conn_sec; |
76 | 77 |
/* threads - primary */ |
77 | 78 |
unsigned prim_live, prim_idle, prim_max; |
... | ... |
@@ -89,6 +91,18 @@ static int send_string_noreconn(conn_t *conn, const char *cmd); |
89 | 89 |
static void send_string(conn_t *conn, const char *cmd); |
90 | 90 |
static void read_version(conn_t *conn); |
91 | 91 |
|
92 |
+enum exit_reason { |
|
93 |
+ FAIL_INITIAL_CONN=1, |
|
94 |
+ OUT_OF_MEMORY, |
|
95 |
+ RECONNECT_FAIL, |
|
96 |
+ SIGINT_REASON |
|
97 |
+}; |
|
98 |
+ |
|
99 |
+static void exit_program(enum exit_reason reason, const char *func, unsigned line); |
|
100 |
+#define EXIT_PROGRAM(r) exit_program(r, __PRETTY_FUNCTION__, __LINE__); |
|
101 |
+#define OOM_CHECK(p) do { if (!p) EXIT_PROGRAM(OUT_OF_MEMORY); } while (0) |
|
102 |
+ |
|
103 |
+ |
|
92 | 104 |
static struct global_stats global; |
93 | 105 |
static int curses_inited = 1; |
94 | 106 |
static int maxystats=0; |
... | ... |
@@ -96,6 +110,7 @@ static int maxystats=0; |
96 | 96 |
enum colors { |
97 | 97 |
header_color=1, |
98 | 98 |
version_color, |
99 |
+ error_color, |
|
99 | 100 |
value_color, |
100 | 101 |
descr_color, |
101 | 102 |
queue_header_color, |
... | ... |
@@ -112,6 +127,7 @@ enum colors { |
112 | 112 |
|
113 | 113 |
#define VALUE_ATTR A_BOLD | COLOR_PAIR(value_color) |
114 | 114 |
#define DESCR_ATTR COLOR_PAIR(descr_color) |
115 |
+#define ERROR_ATTR A_BOLD | COLOR_PAIR(error_color) |
|
115 | 116 |
|
116 | 117 |
static WINDOW *header_window = NULL; |
117 | 118 |
static WINDOW *stats_head_window = NULL; |
... | ... |
@@ -125,7 +141,7 @@ static char *queue_header = NULL; |
125 | 125 |
static char *clamd_header = NULL; |
126 | 126 |
|
127 | 127 |
#define CMDHEAD " COMMAND TIME QUEUED FILE" |
128 |
-#define CMDHEAD2 "NO COMMAND TIME QUEUED FILE" |
|
128 |
+#define CMDHEAD2 " # COMMAND TIME QUEUED FILE" |
|
129 | 129 |
|
130 | 130 |
/* |
131 | 131 |
* CLAMD - which local/remote clamd this is |
... | ... |
@@ -149,11 +165,9 @@ static void resize(void) |
149 | 149 |
free(queue_header); |
150 | 150 |
free(clamd_header); |
151 | 151 |
queue_header = malloc(maxx + 1); |
152 |
+ OOM_CHECK(queue_header); |
|
152 | 153 |
clamd_header = malloc(maxx + 1); |
153 |
- if(!queue_header || !clamd_header) { |
|
154 |
- fprintf(stderr,"Out of memory\n"); |
|
155 |
- exit(1); |
|
156 |
- } |
|
154 |
+ OOM_CHECK(clamd_header); |
|
157 | 155 |
strncpy(queue_header, global.num_clamd>1 ? CMDHEAD2 : CMDHEAD, maxx); |
158 | 156 |
strncpy(clamd_header, SUMHEAD, maxx); |
159 | 157 |
queue_header[maxx] = '\0'; |
... | ... |
@@ -203,7 +217,7 @@ static void init_windows(int num_clamd) |
203 | 203 |
stats_window = subwin(stdscr, maxystats, maxx, num_clamd+2, 0); |
204 | 204 |
status_bar_window = subwin(stdscr, 1, maxx, maxy-1, 0); |
205 | 205 |
/* memwindow overlaps, used only in details mode */ |
206 |
- mem_window = derwin(stats_window, 6, 48, 0, maxx-48); |
|
206 |
+ mem_window = derwin(stats_window, 6, 41, 0, maxx-41); |
|
207 | 207 |
touchwin(stdscr); |
208 | 208 |
werase(stdscr); |
209 | 209 |
refresh(); |
... | ... |
@@ -227,6 +241,7 @@ static void init_ncurses(int num_clamd) |
227 | 227 |
|
228 | 228 |
init_pair(header_color, COLOR_BLACK, COLOR_WHITE); |
229 | 229 |
init_pair(version_color, DEFAULT_COLOR, DEFAULT_COLOR); |
230 |
+ init_pair(error_color, COLOR_WHITE, COLOR_RED); |
|
230 | 231 |
init_pair(value_color, COLOR_GREEN, DEFAULT_COLOR); |
231 | 232 |
init_pair(descr_color, COLOR_CYAN, DEFAULT_COLOR); |
232 | 233 |
init_pair(queue_header_color, COLOR_BLACK, COLOR_GREEN); |
... | ... |
@@ -297,7 +312,7 @@ static void show_bar(WINDOW *win, size_t i, unsigned live, unsigned idle, |
297 | 297 |
unsigned max, int blink) |
298 | 298 |
{ |
299 | 299 |
int y,x; |
300 |
- unsigned len = 47; |
|
300 |
+ unsigned len = 39; |
|
301 | 301 |
unsigned start = 1; |
302 | 302 |
unsigned activ = max ? ((live-idle)*(len - start - 2) + (max/2)) / max : 0; |
303 | 303 |
unsigned dim = max ? idle*(len - start - 2) / max : 0; |
... | ... |
@@ -333,8 +348,10 @@ static void cleanup(void) |
333 | 333 |
{ |
334 | 334 |
unsigned i; |
335 | 335 |
if (curses_inited) { |
336 |
- werase(status_bar_window); |
|
337 |
- wrefresh(status_bar_window); |
|
336 |
+ if (status_bar_window) { |
|
337 |
+ werase(status_bar_window); |
|
338 |
+ wrefresh(status_bar_window); |
|
339 |
+ } |
|
338 | 340 |
rm_windows(); |
339 | 341 |
endwin(); |
340 | 342 |
} |
... | ... |
@@ -358,11 +375,6 @@ static void cleanup(void) |
358 | 358 |
} |
359 | 359 |
} |
360 | 360 |
|
361 |
-enum exit_reason { |
|
362 |
- FAIL_INITIAL_CONN=1, |
|
363 |
- OUT_OF_MEMORY, |
|
364 |
- RECONNECT_FAIL |
|
365 |
-}; |
|
366 | 361 |
|
367 | 362 |
static void exit_program(enum exit_reason reason, const char *func, unsigned line) |
368 | 363 |
{ |
... | ... |
@@ -376,6 +388,9 @@ static void exit_program(enum exit_reason reason, const char *func, unsigned lin |
376 | 376 |
case RECONNECT_FAIL: |
377 | 377 |
exit_reason = "Failed to reconnect to clamd after connection was lost"; |
378 | 378 |
break; |
379 |
+ case SIGINT_REASON: |
|
380 |
+ exit_reason = "User interrupt"; |
|
381 |
+ break; |
|
379 | 382 |
default: |
380 | 383 |
exit_reason = "Unknown"; |
381 | 384 |
break; |
... | ... |
@@ -385,9 +400,6 @@ static void exit_program(enum exit_reason reason, const char *func, unsigned lin |
385 | 385 |
exit(reason); |
386 | 386 |
} |
387 | 387 |
|
388 |
-#define EXIT_PROGRAM(r) exit_program(r, __PRETTY_FUNCTION__, __LINE__); |
|
389 |
-#define OOM_CHECK(p) do { if (!p) EXIT_PROGRAM(OUT_OF_MEMORY); } while (0) |
|
390 |
- |
|
391 | 388 |
struct task { |
392 | 389 |
char *line; |
393 | 390 |
double tim; |
... | ... |
@@ -406,17 +418,23 @@ static int tasks_compare(const void *a, const void *b) |
406 | 406 |
} |
407 | 407 |
|
408 | 408 |
/* ----------- Socket routines ----------------------- */ |
409 |
-static void print_con_error(const char *fmt, ...) |
|
409 |
+static void print_con_info(conn_t *conn, const char *fmt, ...) |
|
410 | 410 |
{ |
411 | 411 |
va_list ap; |
412 | 412 |
va_start(ap, fmt); |
413 |
-/* if (version_window) { |
|
414 |
- werase(version_window); |
|
415 |
- wmove(version_window, 0, 0); |
|
416 |
- vwprintw(version_window, fmt, ap); |
|
417 |
- wrefresh(version_window); |
|
418 |
- } else*/ |
|
419 |
- vfprintf(stderr, fmt, ap); |
|
413 |
+ if (stats_head_window) { |
|
414 |
+ char *buf = malloc(maxx+1); |
|
415 |
+ memset(buf, ' ', maxx); |
|
416 |
+ OOM_CHECK(buf); |
|
417 |
+ vsnprintf(buf, maxx, fmt, ap); |
|
418 |
+ buf[strlen(buf)] = ' '; |
|
419 |
+ buf[maxx] = '\0'; |
|
420 |
+ wattron(stats_head_window, ERROR_ATTR); |
|
421 |
+ mvwprintw(stats_head_window, conn->line, 0, "%s", buf); |
|
422 |
+ wattroff(stats_head_window, ERROR_ATTR); |
|
423 |
+ wrefresh(stats_head_window); |
|
424 |
+ } else |
|
425 |
+ vfprintf(stdout, fmt, ap); |
|
420 | 426 |
va_end(ap); |
421 | 427 |
} |
422 | 428 |
|
... | ... |
@@ -424,6 +442,7 @@ static void print_con_error(const char *fmt, ...) |
424 | 424 |
static int make_connection(const char *soname, conn_t *conn) |
425 | 425 |
{ |
426 | 426 |
int s; |
427 |
+ struct timeval tv; |
|
427 | 428 |
conn->tcp = 0; |
428 | 429 |
#ifdef _WIN32 |
429 | 430 |
{ |
... | ... |
@@ -438,7 +457,7 @@ static int make_connection(const char *soname, conn_t *conn) |
438 | 438 |
memset(&addr, 0, sizeof(addr)); |
439 | 439 |
addr.sun_family = AF_UNIX; |
440 | 440 |
strncpy(addr.sun_path, soname, sizeof(addr.sun_path)); |
441 |
- printf("Connecting to: %s\n", soname); |
|
441 |
+ print_con_info(conn, "Connecting to: %s\n", soname); |
|
442 | 442 |
if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) { |
443 | 443 |
perror("connect"); |
444 | 444 |
return -1; |
... | ... |
@@ -458,7 +477,7 @@ static int make_connection(const char *soname, conn_t *conn) |
458 | 458 |
} |
459 | 459 |
if(!port) |
460 | 460 |
port = 3310; |
461 |
- printf("Looking up: %s\n", host); |
|
461 |
+ print_con_info(conn, "Looking up: %s\n", host); |
|
462 | 462 |
if((hp = gethostbyname(host)) == NULL) { |
463 | 463 |
herror("Cannot find host"); |
464 | 464 |
return -1; |
... | ... |
@@ -472,7 +491,7 @@ static int make_connection(const char *soname, conn_t *conn) |
472 | 472 |
server.sin_family = AF_INET; |
473 | 473 |
server.sin_port = htons(port); |
474 | 474 |
server.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr; |
475 |
- printf("Connecting to: %s:%u\n", inet_ntoa(server.sin_addr), port); |
|
475 |
+ print_con_info(conn, "Connecting to: %s:%u\n", inet_ntoa(server.sin_addr), port); |
|
476 | 476 |
if (connect(s, (struct sockaddr *)&server, sizeof(server))) { |
477 | 477 |
perror("connect"); |
478 | 478 |
return -1; |
... | ... |
@@ -481,6 +500,9 @@ static int make_connection(const char *soname, conn_t *conn) |
481 | 481 |
conn->remote = soname; |
482 | 482 |
conn->sd = s; |
483 | 483 |
gettimeofday(&conn->tv_conn, NULL); |
484 |
+ tv.tv_sec = 4; |
|
485 |
+ tv.tv_usec = 0; |
|
486 |
+ setsockopt(conn->sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); |
|
484 | 487 |
send_string(conn, "SESSION\nVERSION\n"); |
485 | 488 |
read_version(conn); |
486 | 489 |
return 0; |
... | ... |
@@ -508,9 +530,8 @@ static void reconnect(conn_t *conn) |
508 | 508 |
if(++tries > 3) { |
509 | 509 |
EXIT_PROGRAM(RECONNECT_FAIL); |
510 | 510 |
} |
511 |
- print_con_error("%s: %s", conn->remote, strerror(errno)); |
|
512 | 511 |
if (make_connection(conn->remote, conn) < 0) { |
513 |
- print_con_error("Unable to reconnect to %s: %s", conn->remote, strerror(errno)); |
|
512 |
+ print_con_info(conn, "Unable to reconnect to %s: %s", conn->remote, strerror(errno)); |
|
514 | 513 |
exit(3); |
515 | 514 |
} |
516 | 515 |
free(conn->version); |
... | ... |
@@ -520,17 +541,23 @@ static void reconnect(conn_t *conn) |
520 | 520 |
static int recv_line(conn_t *conn, char *buf, size_t len) |
521 | 521 |
{ |
522 | 522 |
assert(len > 0); |
523 |
- assert(conn && conn->sd > 0); |
|
523 |
+ assert(conn); |
|
524 | 524 |
assert(buf); |
525 | 525 |
|
526 | 526 |
len--; |
527 |
- if (!len) |
|
527 |
+ if (!len || conn->sd == -1) |
|
528 | 528 |
return 0; |
529 |
+ assert(conn->sd > 0); |
|
529 | 530 |
while (len > 0) { |
530 | 531 |
ssize_t nread = recv(conn->sd, buf, len, MSG_PEEK); |
531 |
- if (nread == -1) |
|
532 |
- reconnect(conn); |
|
533 |
- else { |
|
532 |
+ if (nread <= 0) { |
|
533 |
+ print_con_info(conn, "%s: %s", conn->remote, strerror(errno)); |
|
534 |
+ /* it could be a timeout, be nice and send an END */ |
|
535 |
+ send_string_noreconn(conn, "END\n"); |
|
536 |
+ close(conn->sd); |
|
537 |
+ conn->sd = -1; |
|
538 |
+ return 0; |
|
539 |
+ } else { |
|
534 | 540 |
char *p = memchr(buf, '\n', nread); |
535 | 541 |
if (p) { |
536 | 542 |
len = p - buf + 1; |
... | ... |
@@ -557,7 +584,6 @@ static void output_queue(size_t line, ssize_t max) |
557 | 557 |
{ |
558 | 558 |
ssize_t i; |
559 | 559 |
struct task *tasks = global.tasks; |
560 |
- assert(tasks); |
|
561 | 560 |
wattron(stats_window, COLOR_PAIR(queue_header_color)); |
562 | 561 |
mvwprintw(stats_window, line++, 0, "%s", queue_header); |
563 | 562 |
wattroff(stats_window, COLOR_PAIR(queue_header_color)); |
... | ... |
@@ -567,6 +593,7 @@ static void output_queue(size_t line, ssize_t max) |
567 | 567 |
--max; |
568 | 568 |
if (max < 0) max = 0; |
569 | 569 |
for(i=0;i<max;i++) { |
570 |
+ assert(tasks); |
|
570 | 571 |
char *cmde = strchr(tasks[i].line, ' '); |
571 | 572 |
if(cmde) { |
572 | 573 |
char cmd[16]; |
... | ... |
@@ -608,18 +635,11 @@ static void parse_queue(conn_t *conn, char* buf, size_t len, unsigned idx) |
608 | 608 |
continue; |
609 | 609 |
++global.n; |
610 | 610 |
global.tasks = realloc(global.tasks, sizeof(*global.tasks)*global.n); |
611 |
- if(!global.tasks) { |
|
612 |
- fprintf(stderr, "Out of memory\n"); |
|
613 |
- /* OOM */ |
|
614 |
- exit(1); |
|
615 |
- } |
|
611 |
+ OOM_CHECK(global.tasks); |
|
616 | 612 |
global.tasks[global.n-1].line = strdup(buf); |
617 |
- if(!global.tasks[global.n-1].line) { |
|
618 |
- fprintf(stderr, "Out of memory\n"); |
|
619 |
- exit(1); |
|
620 |
- } |
|
613 |
+ OOM_CHECK(global.tasks[global.n-1].line); |
|
621 | 614 |
global.tasks[global.n-1].tim = tim; |
622 |
- global.tasks[global.n-1].clamd_no = idx; |
|
615 |
+ global.tasks[global.n-1].clamd_no = idx + 1; |
|
623 | 616 |
} while (recv_line(conn, buf, len) && buf[0] == '\t' && strcmp("END\n", buf) != 0); |
624 | 617 |
} |
625 | 618 |
|
... | ... |
@@ -634,18 +654,18 @@ static void output_memstats(struct stats *stats) |
634 | 634 |
werase(mem_window); |
635 | 635 |
box(mem_window, 0, 0); |
636 | 636 |
|
637 |
- snprintf(buf, sizeof(buf),"heap %4luM mmap %4luM releasable %3luM", |
|
637 |
+ snprintf(buf, sizeof(buf),"heap %4luM mmap %4luM unused %3luM", |
|
638 | 638 |
stats->lheapu/1024, stats->lmmapu/1024, stats->lreleasable/1024); |
639 |
- mvwprintw(mem_window, 1, 1, "Memory: "); |
|
639 |
+ mvwprintw(mem_window, 1, 1, "Mem: "); |
|
640 | 640 |
print_colored(mem_window, buf); |
641 | 641 |
|
642 |
- mvwprintw(mem_window, 2, 1, "Malloc: "); |
|
643 |
- snprintf(buf, sizeof(buf),"used %4luM free %4luM total %4luM", |
|
642 |
+ mvwprintw(mem_window, 2, 1, "Libc: "); |
|
643 |
+ snprintf(buf, sizeof(buf),"used %4luM free %4luM total %4luM", |
|
644 | 644 |
stats->ltotalu/1024, stats->ltotalf/1024, (stats->ltotalu+stats->ltotalf)/1024); |
645 | 645 |
print_colored(mem_window, buf); |
646 | 646 |
|
647 |
- mvwprintw(mem_window, 3, 1, "Mempool: "); |
|
648 |
- snprintf(buf, sizeof(buf), "count %u used %4luM total %4luM", |
|
647 |
+ mvwprintw(mem_window, 3, 1, "Pool: "); |
|
648 |
+ snprintf(buf, sizeof(buf), "count %u used %4luM total %4luM", |
|
649 | 649 |
stats->pools_cnt, stats->lpoolu/1024, stats->lpoolt/1024); |
650 | 650 |
print_colored(mem_window, buf); |
651 | 651 |
|
... | ... |
@@ -699,8 +719,8 @@ static int output_stats(struct stats *stats, unsigned idx) |
699 | 699 |
char mem[6]; |
700 | 700 |
WINDOW *win = stats_head_window; |
701 | 701 |
|
702 |
- if (stats->mem == -1) |
|
703 |
- strcpy(mem, "N/A"); |
|
702 |
+ if (stats->mem == -1 || stats->stats_unsupp) |
|
703 |
+ strncpy(mem, "N/A", sizeof(mem)); |
|
704 | 704 |
else { |
705 | 705 |
char c; |
706 | 706 |
double s; |
... | ... |
@@ -720,7 +740,7 @@ static int output_stats(struct stats *stats, unsigned idx) |
720 | 720 |
i = idx+1; |
721 | 721 |
|
722 | 722 |
if (!stats->db_time.tm_year) |
723 |
- strcpy(timbuf,"N/A"); |
|
723 |
+ strncpy(timbuf,"N/A",sizeof(timbuf)); |
|
724 | 724 |
else |
725 | 725 |
snprintf(timbuf, sizeof(timbuf), "%04u-%02u-%02u %02uh", |
726 | 726 |
1900 + stats->db_time.tm_year, |
... | ... |
@@ -728,14 +748,19 @@ static int output_stats(struct stats *stats, unsigned idx) |
728 | 728 |
stats->db_time.tm_mday, |
729 | 729 |
stats->db_time.tm_hour); |
730 | 730 |
|
731 |
- 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, |
|
731 |
+ if (!stats->stats_unsupp) { |
|
732 |
+ 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, |
|
732 | 733 |
stats->live, stats->idle, |
733 | 734 |
stats->current_q, stats->biggest_queue, |
734 | 735 |
mem, |
735 | 736 |
stats->remote, stats->engine_version, stats->db_version, timbuf); |
737 |
+ } else { |
|
738 |
+ 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, |
|
739 |
+ stats->remote, stats->engine_version, stats->db_version, timbuf); |
|
740 |
+ } |
|
736 | 741 |
win = stats_window; |
737 | 742 |
i = 0; |
738 |
- if (show_detail(idx)) { |
|
743 |
+ if (show_detail(idx) && !stats->stats_unsupp) { |
|
739 | 744 |
mvwprintw(win, i++, 0, "Primary threads: "); |
740 | 745 |
snprintf(buf, sizeof(buf), "live %3u idle %3u max %3u", stats->prim_live, stats->prim_idle, stats->prim_max); |
741 | 746 |
print_colored(win, buf); |
... | ... |
@@ -757,7 +782,7 @@ static int output_stats(struct stats *stats, unsigned idx) |
757 | 757 |
stats->biggest_queue = stats->current_q; |
758 | 758 |
blink = 1; |
759 | 759 |
} |
760 |
- if (show_detail(idx)) { |
|
760 |
+ if (show_detail(idx) && !stats->stats_unsupp) { |
|
761 | 761 |
show_bar(win, i++, stats->current_q, 0, biggest_queue, blink); |
762 | 762 |
} |
763 | 763 |
return i; |
... | ... |
@@ -810,10 +835,7 @@ static void parse_stats(conn_t *conn, struct stats *stats, unsigned idx) |
810 | 810 |
p++; |
811 | 811 |
|
812 | 812 |
stats->engine_version = malloc(p - pstart+1); |
813 |
- if (!stats->engine_version) { |
|
814 |
- fprintf(stderr,"Out of memory!\n"); |
|
815 |
- exit(1); |
|
816 |
- } |
|
813 |
+ OOM_CHECK(stats->engine_version); |
|
817 | 814 |
|
818 | 815 |
memcpy(stats->engine_version, pstart, p-pstart); |
819 | 816 |
stats->engine_version[p-pstart] = '\0'; |
... | ... |
@@ -827,10 +849,7 @@ static void parse_stats(conn_t *conn, struct stats *stats, unsigned idx) |
827 | 827 |
if (!p) |
828 | 828 |
p = pstart + strlen(pstart); |
829 | 829 |
stats->db_version = malloc(p - pstart + 1); |
830 |
- if (!stats->db_version) { |
|
831 |
- fprintf(stderr, "Out of memory!\n"); |
|
832 |
- exit(1); |
|
833 |
- } |
|
830 |
+ OOM_CHECK(stats->db_version); |
|
834 | 831 |
memcpy(stats->db_version, pstart, p-pstart); |
835 | 832 |
stats->db_version[p-pstart] = '\0'; |
836 | 833 |
if(*p) p++; |
... | ... |
@@ -865,6 +884,10 @@ static void parse_stats(conn_t *conn, struct stats *stats, unsigned idx) |
865 | 865 |
parse_memstats(val, stats); |
866 | 866 |
continue; |
867 | 867 |
} |
868 |
+ if(!strncmp("UNKNOWN COMMAND", buf, 15)) { |
|
869 |
+ stats->stats_unsupp = 1; |
|
870 |
+ break; |
|
871 |
+ } |
|
868 | 872 |
for(j=1;j<strlen(buf);j++) |
869 | 873 |
buf[j] = tolower(buf[j]); |
870 | 874 |
/* mvwprintw(win, i, 0, "%s", buf); |
... | ... |
@@ -914,6 +937,11 @@ static void read_version(conn_t *conn) |
914 | 914 |
} |
915 | 915 |
} |
916 | 916 |
|
917 |
+static void sigint(int a) |
|
918 |
+{ |
|
919 |
+ EXIT_PROGRAM(SIGINT_REASON); |
|
920 |
+} |
|
921 |
+ |
|
917 | 922 |
/* -------------------------- Initialization ---------------- */ |
918 | 923 |
static void setup_connections(int argc, char *argv[]) |
919 | 924 |
{ |
... | ... |
@@ -941,6 +969,7 @@ static void setup_connections(int argc, char *argv[]) |
941 | 941 |
global.conn = calloc(global.num_clamd, sizeof(*global.conn)); |
942 | 942 |
OOM_CHECK(global.conn); |
943 | 943 |
for (i=0;i<global.num_clamd;i++) { |
944 |
+ global.conn[i].line = i+1; |
|
944 | 945 |
if (make_connection(argv[i+1], &global.conn[i]) < 0) { |
945 | 946 |
EXIT_PROGRAM(FAIL_INITIAL_CONN); |
946 | 947 |
} |
... | ... |
@@ -948,13 +977,14 @@ static void setup_connections(int argc, char *argv[]) |
948 | 948 |
} |
949 | 949 |
#ifndef _WIN32 |
950 | 950 |
signal(SIGPIPE, SIG_IGN); |
951 |
+ signal(SIGINT, sigint); |
|
951 | 952 |
#endif |
952 | 953 |
} |
953 | 954 |
|
954 | 955 |
static void free_global_stats(void) |
955 | 956 |
{ |
956 | 957 |
unsigned i; |
957 |
- for (i=0;i<global.n;i++) { |
|
958 |
+ for (i=0;i<(unsigned)global.n;i++) { |
|
958 | 959 |
free(global.tasks[i].line); |
959 | 960 |
} |
960 | 961 |
for (i=0;i<global.num_clamd;i++) { |
... | ... |
@@ -999,12 +1029,16 @@ int main(int argc, char *argv[]) |
999 | 999 |
memset(stats, 0, sizeof(*stats)); |
1000 | 1000 |
parse_stats(&global.conn[i], stats, i); |
1001 | 1001 |
} |
1002 |
- assert(global.tasks); |
|
1003 |
- qsort(global.tasks, global.n, sizeof(*global.tasks), tasks_compare); |
|
1002 |
+ if (global.tasks) |
|
1003 |
+ qsort(global.tasks, global.n, sizeof(*global.tasks), tasks_compare); |
|
1004 | 1004 |
tv_last = tv; |
1005 | 1005 |
} |
1006 | 1006 |
/* always show, so that screen resizes take effect instantly*/ |
1007 | 1007 |
output_all(); |
1008 |
+ for(i=0;i<global.num_clamd;i++) { |
|
1009 |
+ if (global.conn[i].sd == -1) |
|
1010 |
+ reconnect(&global.conn[i]); |
|
1011 |
+ } |
|
1008 | 1012 |
} while(toupper(ch = getch()) != 'Q'); |
1009 | 1013 |
free_global_stats(); |
1010 | 1014 |
normal_exit = 1; |