ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.2
Committed: Fri Mar 28 18:42:57 2003 UTC (21 years, 5 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.1: +123 -24 lines
Log Message:
The display function has been updated in preperation for being able to
display what the user wishes on request.

What to sort by is now a optional command line argument. Valid arguments are
currently cpu, mem and load. This will also eventually be able to be changed
"on the fly". The infastructure for doing this has been built in in this
change.

File Contents

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