ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.6
Committed: Sun Mar 30 17:11:26 2003 UTC (21 years, 8 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.5: +5 -0 lines
Log Message:
Now tests for either curses or ncurses. By default prefers to use curses,
but will use ncurses if curses is not available or if forced by a configure
flag. Also minor other tweaks.

File Contents

# Content
1 /*
2 * i-scream central monitoring system
3 * http://www.i-scream.org.uk
4 * Copyright (C) 2000-2002 i-scream
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <ukcprog.h>
32
33 #include <libxml/xmlmemory.h>
34 #include <libxml/parser.h>
35 #include "genmergesort.h"
36
37 #ifdef HAVE_NCURSES_H
38 #include <ncurses.h>
39 #else
40 #include <curses.h>
41 #endif
42
43 struct host_line_t{
44 char *hostname;
45 int line;
46
47 struct host_line_t *next;
48 };
49 typedef struct host_line_t host_line_list_t;
50
51 struct diskio_data_t{
52 char *name;
53
54 long long read;
55 long long write;
56
57 struct diskio_data_t *next;
58 };
59 typedef struct diskio_data_t diskio_data_list_t;
60
61 struct network_data_t{
62 char *name;
63
64 long long rx;
65 long long tx;
66
67 struct network_data_t *next;
68 };
69 typedef struct network_data_t network_data_list_t;
70
71 /*
72 struct disk_data_t{
73 char *name;
74 char *mount_pnt;
75
76 long long total_space;
77 long long total_used;
78 long long total_avail;
79 // Other data we are less intrested in are not stored
80
81 struct disk_data_t *next;
82 };
83 typedef struct disk_data_t disk_data_list_t;
84 */
85 #define MAXHOSTNAMESIZE 10
86 struct machine_data_t{
87
88 char *name;
89
90 char sysname[MAXHOSTNAMESIZE+1];
91
92 double cpu_user;
93 double cpu_idle;
94 double cpu_iowait;
95 double cpu_kernel;
96 double cpu_swap;
97 double cpu_used; /* 100 - idle */
98
99 long long memory_total;
100 long long memory_free;
101 long long memory_used;
102 double memory_used_pecent;
103
104 long long swap_total;
105 long long swap_free;
106 long long swap_used;
107 double swap_used_pecent;
108
109 int pages_in;
110 int pages_out;
111
112 double load_1;
113 double load_5;
114 double load_15;
115
116 int processes_total;
117 int processes_sleeping;
118 int processes_cpu;
119 int processes_zombie;
120 int processes_stopped;
121
122 network_data_list_t *network_data_list;
123 long long network_io_total_tx;
124 long long network_io_total_rx;
125
126 diskio_data_list_t *diskio_data_list;
127 long long disk_io_total_write;
128 long long disk_io_total_read;
129
130 /* Maybe in the future */
131 /*
132 disk_data_list_t disk_data_list;
133 double disk_total_used;
134 */
135
136 struct machine_data_t *next;
137 };
138
139 typedef struct machine_data_t machine_data_list_t;
140
141 typedef struct{
142 int cpu_user;
143 int cpu_idle;
144 int cpu_iowait;
145 int cpu_kernel;
146 int cpu_swap;
147 int cpu_used;
148
149 int memory_total;
150 int memory_free;
151 int memory_used;
152 int memory_used_pecent;
153
154 int swap_total;
155 int swap_free;
156 int swap_used;
157 int swap_used_pecent;
158
159 int load_1;
160 int load_5;
161 int load_15;
162
163 int pages_in;
164 int pages_out;
165
166 int processes_total;
167 int processes_sleeping;
168 int processes_cpu;
169 int processes_zombie;
170 int processes_stopped;
171
172 int network_io_total_tx;
173 int network_io_total_rx;
174 int network_all_stats;
175
176 int disk_io_total_write;
177 int disk_io_total_read;
178 int disk_io_all_stats;
179
180 int disk_total_used;
181 int disk_all_stats;
182 }display_config_t;
183
184 GENERIC_MERGE_SORT(static, sort_machine_stats, machine_data_list_t, next)
185
186 #define MKCMP(x) int cmp_##x(machine_data_list_t *a, machine_data_list_t *b){return ((a->x) == (b->x)? 0 : (((a->x) > (b->x))? -1 : 1));}
187
188
189 int (*sortby_ptr)(machine_data_list_t *a, machine_data_list_t *b);
190
191 MKCMP(cpu_used)
192 MKCMP(load_1)
193 MKCMP(network_io_total_tx)
194 MKCMP(network_io_total_rx)
195 MKCMP(disk_io_total_write)
196 MKCMP(disk_io_total_read)
197 MKCMP(memory_used_pecent)
198 MKCMP(swap_used_pecent)
199
200 /*
201 int cmp_cpu(machine_data_list_t *a, machine_data_list_t *b){
202
203 if(a->cpu_used == b->cpu_used){
204 if(a->load_1 == b->load_1) return 0;
205 if(a->load_1 > b->load_1){
206 return -1;
207 }else{
208 return 1;
209 }
210 }
211
212 if((a->cpu_used) > (b->cpu_used)){
213 return -1;
214 }else{
215 return 1;
216 }
217 }
218 */
219
220 FILE *create_tcp_connection(char *hostname, int port){
221 int sock;
222 struct sockaddr_in addr;
223 struct in_addr haddr;
224 FILE *f;
225
226 if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0){
227 return NULL;
228 }
229
230 if((get_host_addr(hostname, &haddr))!=0){
231 close(sock);
232 return NULL;
233 }
234
235 memset(&addr, 0, sizeof(addr));
236 addr.sin_family = AF_INET;
237 memcpy(&addr.sin_addr, &haddr, sizeof(haddr));
238 addr.sin_port = htons(port);
239
240 if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) !=0){
241 close(sock);
242 return NULL;
243 }
244
245 if((f=fdopen(sock, "r+"))==NULL){
246 close(sock);
247 return NULL;
248 }
249
250 return f;
251 }
252
253 int tcp_comm(FILE *f, char *send, char **response, char *expected){
254
255 if(send!=NULL){
256 fprintf(f, "%s\n", send);
257 }
258 fflush(f);
259 *response=fpgetline(f);
260 fseek(f, 0, SEEK_CUR);
261
262 if( (*response==NULL) || (strcmp(*response, "ERROR")==0) ) return -1;
263
264 if(expected==NULL) return 0;
265
266 if((strcmp(expected, *response))==0) return 0;
267
268 return -1;
269 }
270
271 /* Takes a xml char * and a machine_data_list_t. This will parse
272 * the xml and put it into the correct entry of the machine_data
273 * linked list. This will return the number of entries in the linked
274 * list, or -1 on a error.
275 */
276 int parse_xml(char *xml, machine_data_list_t **md){
277 xmlDocPtr doc;
278 xmlNodePtr cur;
279 xmlNodePtr ele;
280 xmlAttr *list;
281
282 static int num_hosts=0;
283
284 machine_data_list_t *machine_data_list=*md;
285
286 int found_host=0;
287
288 char *hostname=NULL;
289 network_data_list_t *network_data_list=NULL;
290 network_data_list_t *ndl_ptr=NULL;
291 diskio_data_list_t *diskio_data_list=NULL;
292 diskio_data_list_t *didl_ptr=NULL;
293 char *tmp;
294
295 doc=xmlParseDoc(xml);
296 if(doc==NULL) return -1;
297
298 cur = xmlDocGetRootElement(doc);
299 if(cur==NULL){
300 xmlFreeDoc(doc);
301 return -1;
302 }
303
304
305 /* Get the hostname */
306 list=cur->properties;
307 while(list!=NULL){
308 if((xmlStrcmp(list->name, (const xmlChar *) "machine_name"))==0){
309 hostname = xmlNodeGetContent(list->children);
310 if(hostname==NULL){
311 return -1;
312 }
313 }
314 list=list->next;
315 }
316 if(hostname==NULL){
317 return -1;
318 }
319
320 /* Get machine_data for host.. Or create if it doesn't have one */
321 while(machine_data_list!=NULL){
322 if((strncmp(machine_data_list->name, hostname, strlen(hostname)))==0){
323 found_host=1;
324 break;
325 }
326 machine_data_list=machine_data_list->next;
327 }
328
329 if(!found_host){
330 /* We didn't find this host, but we should be at the end of the list */
331 machine_data_list=malloc(sizeof(machine_data_list_t));
332 if(machine_data_list==NULL) return -1;
333 machine_data_list->next=(*md);
334 machine_data_list->name=hostname;
335 machine_data_list->network_data_list=NULL;
336 machine_data_list->diskio_data_list=NULL;
337 *md=machine_data_list;
338 num_hosts++;
339 }
340
341 /* Now we want to pull out the data */
342
343 cur = cur->xmlChildrenNode;
344 while(cur != NULL) {
345 ele=cur->xmlChildrenNode;
346 while(ele != NULL){
347
348 /* CPU Stats */
349 if(!xmlStrcmp(cur->name, (const xmlChar *) "cpu")){
350 tmp=xmlNodeGetContent(ele);
351 if(!xmlStrcmp(ele->name, (const xmlChar *) "user")){
352 machine_data_list->cpu_user=atof(tmp);
353 }
354 if(!xmlStrcmp(ele->name, (const xmlChar *) "kernel")){
355 machine_data_list->cpu_kernel=atof(tmp);
356 }
357 if(!xmlStrcmp(ele->name, (const xmlChar *) "idle")){
358 machine_data_list->cpu_idle=atof(tmp);
359 }
360 if(!xmlStrcmp(ele->name, (const xmlChar *) "iowait")){
361 machine_data_list->cpu_iowait=atof(tmp);
362 }
363 if(!xmlStrcmp(ele->name, (const xmlChar *) "swap")){
364 machine_data_list->cpu_iowait=atof(tmp);
365 }
366
367 if(tmp!=NULL) xmlFree(tmp);
368 }
369
370 /* Memory Stats */
371 if(!xmlStrcmp(cur->name, (const xmlChar *) "memory")){
372 tmp=xmlNodeGetContent(ele);
373 if(!xmlStrcmp(ele->name, (const xmlChar *) "total")){
374 machine_data_list->memory_total=atoll(tmp);
375 }
376 if(!xmlStrcmp(ele->name, (const xmlChar *) "free")){
377 machine_data_list->memory_free=atoll(tmp);
378 }
379 if(!xmlStrcmp(ele->name, (const xmlChar *) "used")){
380 machine_data_list->memory_used=atoll(tmp);
381 }
382
383 if(tmp!=NULL) xmlFree(tmp);
384 }
385
386 /* Load Stats */
387 if(!xmlStrcmp(cur->name, (const xmlChar *) "load")){
388 tmp=xmlNodeGetContent(ele);
389 if(!xmlStrcmp(ele->name, (const xmlChar *) "load1")){
390 machine_data_list->load_1=atof(tmp);
391 }
392 if(!xmlStrcmp(ele->name, (const xmlChar *) "load5")){
393 machine_data_list->load_5=atof(tmp);
394 }
395 if(!xmlStrcmp(ele->name, (const xmlChar *) "load15")){
396 machine_data_list->load_15=atof(tmp);
397 }
398
399 if(tmp!=NULL) xmlFree(tmp);
400 }
401
402 /* swap stats */
403 if(!xmlStrcmp(cur->name, (const xmlChar *) "swap")){
404 tmp=xmlNodeGetContent(ele);
405 if(!xmlStrcmp(ele->name, (const xmlChar *) "total")){
406 machine_data_list->swap_total=atoll(tmp);
407 }
408 if(!xmlStrcmp(ele->name, (const xmlChar *) "free")){
409 machine_data_list->swap_free=atoll(tmp);
410 }
411 if(!xmlStrcmp(ele->name, (const xmlChar *) "used")){
412 machine_data_list->swap_used=atoll(tmp);
413 }
414
415 if(tmp!=NULL) xmlFree(tmp);
416 }
417
418 /* Process stat */
419 if(!xmlStrcmp(cur->name, (const xmlChar *) "processes")){
420 tmp=xmlNodeGetContent(ele);
421 if(!xmlStrcmp(ele->name, (const xmlChar *) "sleeping")){
422 machine_data_list->processes_sleeping=atoi(tmp);
423 }
424 if(!xmlStrcmp(ele->name, (const xmlChar *) "cpu")){
425 machine_data_list->processes_cpu=atoi(tmp);
426 }
427 if(!xmlStrcmp(ele->name, (const xmlChar *) "zombie")){
428 machine_data_list->processes_zombie=atoi(tmp);
429 }
430 if(!xmlStrcmp(ele->name, (const xmlChar *) "total")){
431 machine_data_list->processes_total=atoi(tmp);
432 }
433
434 if(tmp!=NULL) xmlFree(tmp);
435 }
436
437 /* paging stats */
438 if(!xmlStrcmp(cur->name, (const xmlChar *) "pages")){
439 tmp=xmlNodeGetContent(ele);
440 if(!xmlStrcmp(ele->name, (const xmlChar *) "pageins")){
441 machine_data_list->pages_in=atoi(tmp);
442 }
443 if(!xmlStrcmp(ele->name, (const xmlChar *) "pageouts")){
444 machine_data_list->pages_out=atoi(tmp);
445 }
446
447 if(tmp!=NULL) xmlFree(tmp);
448 }
449
450 /* OS stats */
451 if(!xmlStrcmp(cur->name, (const xmlChar *) "os")){
452 tmp=xmlNodeGetContent(ele);
453 if(!xmlStrcmp(ele->name, (const xmlChar *) "sysname")){
454 strlcpy(machine_data_list->sysname, tmp, MAXHOSTNAMESIZE+1);
455 }
456 if(tmp!=NULL) xmlFree(tmp);
457 }
458
459 /* Network stats */
460 /* Needs to connect current stat to a previous one. Or create it if new */
461 /* Get name.. Walk list. If match, copy rx/tx values. Else malloc, add to list */
462 if(!xmlStrcmp(cur->name, (const xmlChar *) "net")){
463
464 list=ele->properties;
465 if(list==NULL) continue;
466 network_data_list=malloc(sizeof(network_data_list_t));
467 if(network_data_list==NULL) return -1;
468 while(list!=NULL){
469 tmp=xmlNodeGetContent(list->children);
470 if(!xmlStrcmp(list->name, (const xmlChar *) "name")){
471 network_data_list->name=strdup(tmp);
472 }
473 if(!xmlStrcmp(list->name, (const xmlChar *) "rx")){
474 network_data_list->rx=atoll(tmp);
475 }
476 if(!xmlStrcmp(list->name, (const xmlChar *) "tx")){
477 network_data_list->tx=atoll(tmp);
478 }
479
480 xmlFree(tmp);
481 list=list->next;
482 }
483 if(network_data_list->name==NULL) continue;
484 found_host=0;
485 ndl_ptr=machine_data_list->network_data_list;
486 while(ndl_ptr!=NULL){
487 if(!strcmp(ndl_ptr->name, network_data_list->name)){
488 found_host=1;
489 break;
490 }
491 ndl_ptr=ndl_ptr->next;
492 }
493 if(found_host){
494 ndl_ptr->rx=network_data_list->rx;
495 ndl_ptr->tx=network_data_list->tx;
496 free(network_data_list->name);
497 free(network_data_list);
498 }else{
499 network_data_list->next=machine_data_list->network_data_list;
500 machine_data_list->network_data_list=network_data_list;
501 }
502 }
503
504 /* Disk IO stats */
505 if(!xmlStrcmp(cur->name, (const xmlChar *) "diskio")){
506
507 list=ele->properties;
508 if(list==NULL) continue;
509 diskio_data_list=malloc(sizeof(diskio_data_list_t));
510 if(diskio_data_list==NULL) return -1;
511 while(list!=NULL){
512 tmp=xmlNodeGetContent(list->children);
513 if(!xmlStrcmp(list->name, (const xmlChar *) "name")){
514 diskio_data_list->name=strdup(tmp);
515 }
516 if(!xmlStrcmp(list->name, (const xmlChar *) "rbytes")){
517 diskio_data_list->read=atoll(tmp);
518 }
519 if(!xmlStrcmp(list->name, (const xmlChar *) "wbytes")){
520 diskio_data_list->write=atoll(tmp);
521 }
522
523 xmlFree(tmp);
524 list=list->next;
525 }
526 if(diskio_data_list->name==NULL) continue;
527 found_host=0;
528 didl_ptr=machine_data_list->diskio_data_list;
529 while(didl_ptr!=NULL){
530 if(!strcmp(didl_ptr->name, diskio_data_list->name)){
531 found_host=1;
532 break;
533 }
534 didl_ptr=didl_ptr->next;
535 }
536 if(found_host){
537 didl_ptr->read=diskio_data_list->read;
538 didl_ptr->write=diskio_data_list->write;
539 free(diskio_data_list->name);
540 free(diskio_data_list);
541 }else{
542 diskio_data_list->next=machine_data_list->diskio_data_list;
543 machine_data_list->diskio_data_list=diskio_data_list;
544 }
545 }
546
547
548
549 ele=ele->next;
550 }
551 cur=cur->next;
552 }
553
554 /* Append data we want thats not stored in the server */
555 machine_data_list->cpu_used=100.00-machine_data_list->cpu_idle;
556 machine_data_list->memory_used_pecent=((double)machine_data_list->memory_used / (double)machine_data_list->memory_total) * 100.00;
557 machine_data_list->swap_used_pecent=((double)machine_data_list->swap_used / (double)machine_data_list->swap_total) * 100.00;
558
559 ndl_ptr=machine_data_list->network_data_list;
560 machine_data_list->network_io_total_tx=0;
561 machine_data_list->network_io_total_rx=0;
562 while(ndl_ptr!=NULL){
563 machine_data_list->network_io_total_tx+=ndl_ptr->tx;
564 machine_data_list->network_io_total_rx+=ndl_ptr->rx;
565 ndl_ptr=ndl_ptr->next;
566 }
567
568 didl_ptr=machine_data_list->diskio_data_list;
569 machine_data_list->disk_io_total_read=0;
570 machine_data_list->disk_io_total_write=0;
571 while(didl_ptr!=NULL){
572 machine_data_list->disk_io_total_read+=didl_ptr->read;
573 machine_data_list->disk_io_total_write+=didl_ptr->write;
574 didl_ptr=didl_ptr->next;
575 }
576
577 xmlFreeDoc(doc);
578
579 return num_hosts;
580
581
582 }
583
584 void display(machine_data_list_t *machine_data_list, display_config_t *display_config, int num_lines, int *title){
585 int line_num=4;
586 int x=1;
587
588 if(*title){
589 // printf("\033[2J");
590 // printf("\033[1;1HHostname CPU Load Page Page Mem Swap Net Net Disk Disk");
591 // printw("\033[2;1H used%% (1m) ins outs used used rx tx read write");
592 move(1,1);
593 printw("%-11s", "Hostname");
594 x=x+11+1;
595 if(display_config->cpu_used){
596 move(1,x);
597 printw("%5s", "CPU");
598 move(2,x);
599 printw("%5s", "used%");
600 x+=6;
601 }
602 if(display_config->load_1){
603 move(1,x);
604 printw("%5s", "Load");
605 move(2,x);
606 printw("%5s", "(1m)");
607 x+=6;
608 }
609 if(display_config->pages_in){
610 move(1,x);
611 printw("%5s", "Page");
612 move(2,x);
613 printw("%5s", "ins");
614 x+=6;
615 }
616 if(display_config->pages_out){
617 move(1,x);
618 printw("%5s", "Page");
619 move(2,x);
620 printw("%5s", "outs");
621 x+=6;
622 }
623 if(display_config->memory_used_pecent){
624 move(1,x);
625 printw("%5s", "Mem");
626 move(2,x);
627 printw("%5s", "used");
628 x+=6;
629 }
630 if(display_config->swap_used_pecent){
631 move(1,x);
632 printw("%5s", "Swap");
633 move(2,x);
634 printw("%5s", "used");
635 x+=6;
636 }
637 if(display_config->network_io_total_rx){
638 move(1,x);
639 printw("%8s", "Net");
640 move(2,x);
641 printw("%8s", "rx");
642 x+=9;
643 }
644 if(display_config->network_io_total_tx){
645 move(1,x);
646 printw("%8s", "Net");
647 move(2,x);
648 printw("%8s", "tx");
649 x+=9;
650 }
651 if(display_config->disk_io_total_read){
652 move(1,x);
653 printw("%9s", "Disk");
654 move(2,x);
655 printw("%9s", "read");
656 x+=10;
657 }
658 if(display_config->disk_io_total_read){
659 move(1,x);
660 printw("%9s", "Disk");
661 move(2,x);
662 printw("%9s", "write");
663 x+=10;
664 }
665
666 *title=0;
667 }
668
669 for(;num_lines;num_lines--){
670 if(machine_data_list==NULL) break;
671 move(line_num++, 1);
672 printw("%-11s", machine_data_list->sysname);
673
674 if(display_config->cpu_used) printw(" %5.1f", machine_data_list->cpu_used);
675 if(display_config->load_1) printw(" %5.1f", machine_data_list->load_1);
676 if(display_config->pages_in) printw(" %5d", machine_data_list->pages_in);
677 if(display_config->pages_out) printw(" %5d", machine_data_list->pages_out);
678 if(display_config->memory_used_pecent) printw(" %5.1f", machine_data_list->memory_used_pecent);
679 if(display_config->swap_used_pecent) printw(" %5.1f", machine_data_list->swap_used_pecent);
680 if(display_config->network_io_total_rx) printw(" %8lld", machine_data_list->network_io_total_rx);
681 if(display_config->network_io_total_tx) printw(" %8lld", machine_data_list->network_io_total_tx);
682 if(display_config->disk_io_total_read) printw(" %9lld", machine_data_list->disk_io_total_read);
683 if(display_config->disk_io_total_write) printw(" %9lld", machine_data_list->disk_io_total_write);
684
685 machine_data_list=machine_data_list->next;
686 }
687
688
689 refresh();
690
691 }
692
693 int main(int argc, char **argv){
694 WINDOW *window;
695 fd_set infds;
696
697 FILE *control;
698 FILE *data;
699
700 char *machine_list=NULL;
701 char *response=NULL;
702
703 char *servername;
704 int server_control_port;
705 int server_data_port;
706
707 machine_data_list_t *machine_data_list=NULL;
708
709 int num_hosts;
710 int max_display=0;
711 int title;
712
713 int cmdopt;
714 extern int optind;
715 extern char *optarg;
716
717 display_config_t display_config;
718 char ch;
719
720 int data_fileno, stdin_fileno, biggest_fileno;
721
722 sortby_ptr=NULL;
723
724 /* What to display defaults */
725 display_config.cpu_user=0;
726 display_config.cpu_idle=0;
727 display_config.cpu_iowait=0;
728 display_config.cpu_kernel=0;
729 display_config.cpu_swap=0;
730 display_config.cpu_used=1;
731
732 display_config.memory_total=0;
733 display_config.memory_free=0;
734 display_config.memory_used=0;
735 display_config.memory_used_pecent=1;
736
737 display_config.swap_total=0;
738 display_config.swap_free=0;
739 display_config.swap_used=0;
740 display_config.swap_used_pecent=1;
741
742 display_config.load_1=1;
743 display_config.load_5=0;
744 display_config.load_15=0;
745
746 display_config.pages_in=1;
747 display_config.pages_out=1;
748
749 display_config.processes_total=0;
750 display_config.processes_sleeping=0;
751 display_config.processes_cpu=0;
752 display_config.processes_zombie=0;
753 display_config.processes_stopped=0;
754
755 display_config.network_io_total_tx=1;
756 display_config.network_io_total_rx=1;
757 display_config.network_all_stats=1;
758
759 display_config.disk_io_total_write=0;
760 display_config.disk_io_total_read=0;
761 display_config.disk_io_all_stats=0;
762
763 display_config.disk_total_used=0;
764 display_config.disk_all_stats=0;
765
766 while((cmdopt=getopt(argc, argv, "d:s:")) != -1){
767 switch(cmdopt){
768 case 'd':
769 max_display=atoi(optarg);
770 break;
771 case 's':
772 if(!strcmp(optarg, "cpu")){
773 sortby_ptr=cmp_cpu_used;
774 }
775 if(!strcmp(optarg, "load")){
776 sortby_ptr=cmp_load_1;
777 }
778 if(!strcmp(optarg, "mem")){
779 sortby_ptr=cmp_memory_used_pecent;
780 }
781 if(sortby_ptr==NULL){
782 errf("Invalid sort type");
783 exit(1);
784 }
785 break;
786 }
787 }
788
789 if(sortby_ptr==NULL) sortby_ptr=cmp_cpu_used;
790
791 if(argc<(optind+2)){
792 printf("Usage is %s <-d lines> hostname port <machine list>\n", argv[0]);
793 exit(1);
794 }
795
796 servername=argv[optind];
797 server_control_port=atoi(argv[optind+1]);
798
799 control=create_tcp_connection(servername, server_control_port);
800 if(control==NULL){
801 errf("Failed to connect (%m)");
802 }
803
804 if(argc==4){
805 /* We've been passed a machine list */
806 /* list currently needs to be ; seperated */
807 machine_list=strdup(argv[3]);
808 }
809
810 if((tcp_comm(control, NULL, &response, "PROTOCOL 1.1"))!=0){
811 errf("Incorrect version number (%s)", response);
812 exit(1);
813 }
814
815 if((tcp_comm(control, "stattop", &response, "OK"))!=0){
816 errf("Unexpected response %s", response);
817 exit(1);
818 }
819
820 if(machine_list!=NULL){
821 if((tcp_comm(control, "SETHOSTLIST", &response, "OK"))!=0){
822 errf("Unexpected response %s", response);
823 exit(1);
824 }
825 if((tcp_comm(control, machine_list, &response, "OK"))!=0){
826 errf("Unexpected response %s", response);
827 exit(1);
828 }
829 }
830
831 if((tcp_comm(control, "STARTDATA", &response, NULL))!=0){
832 errf("Unexpected response %s", response);
833 exit(1);
834 }
835
836 server_data_port=atoi(response);
837 if(server_data_port==0){
838 errf("Unexpected response %s", response);
839 exit(1);
840 }
841
842 data=create_tcp_connection(servername, server_data_port);
843 if(data==NULL){
844 errf("Failed to connect to host %s on port %d (%m)",servername, server_data_port);
845 }
846
847 /*
848 printf("\033[2J");
849 printf("\033[1;1HHostname CPU Load Page Page Mem Swap Net Net Disk Disk");
850 printf("\033[2;1H used%% (1m) ins outs used used rx tx read write");
851 */
852
853 initscr();
854 nonl();
855 cbreak();
856 echo();
857 window=newwin(0, 0, 0, 0);
858
859 stdin_fileno=fileno(stdin);
860 data_fileno=fileno(data);
861 biggest_fileno=(data_fileno>stdin_fileno) ? (data_fileno+1) : (stdin_fileno+1);
862
863 for(;;){
864 FD_ZERO(&infds);
865 FD_SET(stdin_fileno, &infds);
866 FD_SET(data_fileno, &infds);
867 select(biggest_fileno, &infds, NULL, NULL, NULL);
868
869 if(FD_ISSET(stdin_fileno, &infds)){
870
871 ch=getc(stdin);
872
873 if(ch=='q'){
874 endwin();
875 exit(0);
876 }
877 }
878 if(FD_ISSET(data_fileno, &infds)){
879 response=fpgetline(data);
880 if (response==NULL){
881 errf("Failed to read data (%m)");
882 exit(1);
883 }
884 }
885
886
887 num_hosts=parse_xml(response, &machine_data_list);
888 if(num_hosts==-1) continue;
889 machine_data_list=sort_machine_stats(machine_data_list, num_hosts, sortby_ptr);
890 if(max_display==0){
891 display(machine_data_list, &display_config, num_hosts, &title);
892 }else{
893 display(machine_data_list, &display_config, max_display, &title);
894 }
895
896 }
897 exit(0);
898 }