ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.3
Committed: Sat Mar 29 19:27:36 2003 UTC (21 years, 2 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.2: +24 -0 lines
Log Message:
Initial stab at the autoconf/automake stuff for idar. Not sure it's
perfect, I've done a lot of this sort of stuff today ;)

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