ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.5
Committed: Sun Mar 30 10:58:21 2003 UTC (21 years, 2 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.4: +27 -10 lines
Log Message:
Allows the user to hit "q" to quit the program. The program is now interactive,
as it now uses select to work out if it needs to do something from the user, or
from the TCP connection.

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