ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.4
Committed: Sun Mar 30 01:14:49 2003 UTC (21 years, 8 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.3: +79 -41 lines
Log Message:
Now uses ncurses. Not complete, but more infustructure layed down.

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
691 FILE *control;
692 FILE *data;
693
694 char *machine_list=NULL;
695 char *response=NULL;
696
697 char *servername;
698 int server_control_port;
699 int server_data_port;
700
701 machine_data_list_t *machine_data_list=NULL;
702
703 int num_hosts;
704 int max_display=0;
705 int title;
706
707 int cmdopt;
708 extern int optind;
709 extern char *optarg;
710
711 display_config_t display_config;
712 char ch;
713
714 sortby_ptr=NULL;
715
716 /* What to display defaults */
717 display_config.cpu_user=0;
718 display_config.cpu_idle=0;
719 display_config.cpu_iowait=0;
720 display_config.cpu_kernel=0;
721 display_config.cpu_swap=0;
722 display_config.cpu_used=1;
723
724 display_config.memory_total=0;
725 display_config.memory_free=0;
726 display_config.memory_used=0;
727 display_config.memory_used_pecent=1;
728
729 display_config.swap_total=0;
730 display_config.swap_free=0;
731 display_config.swap_used=0;
732 display_config.swap_used_pecent=1;
733
734 display_config.load_1=1;
735 display_config.load_5=0;
736 display_config.load_15=0;
737
738 display_config.pages_in=1;
739 display_config.pages_out=1;
740
741 display_config.processes_total=0;
742 display_config.processes_sleeping=0;
743 display_config.processes_cpu=0;
744 display_config.processes_zombie=0;
745 display_config.processes_stopped=0;
746
747 display_config.network_io_total_tx=1;
748 display_config.network_io_total_rx=1;
749 display_config.network_all_stats=1;
750
751 display_config.disk_io_total_write=0;
752 display_config.disk_io_total_read=0;
753 display_config.disk_io_all_stats=0;
754
755 display_config.disk_total_used=0;
756 display_config.disk_all_stats=0;
757
758 while((cmdopt=getopt(argc, argv, "d:s:")) != -1){
759 switch(cmdopt){
760 case 'd':
761 max_display=atoi(optarg);
762 break;
763 case 's':
764 if(!strcmp(optarg, "cpu")){
765 sortby_ptr=cmp_cpu_used;
766 }
767 if(!strcmp(optarg, "load")){
768 sortby_ptr=cmp_load_1;
769 }
770 if(!strcmp(optarg, "mem")){
771 sortby_ptr=cmp_memory_used_pecent;
772 }
773 if(sortby_ptr==NULL){
774 errf("Invalid sort type");
775 exit(1);
776 }
777 break;
778 }
779 }
780
781 if(sortby_ptr==NULL) sortby_ptr=cmp_cpu_used;
782
783 if(argc<(optind+2)){
784 printf("Usage is %s <-d lines> hostname port <machine list>\n", argv[0]);
785 exit(1);
786 }
787
788 servername=argv[optind];
789 server_control_port=atoi(argv[optind+1]);
790
791 control=create_tcp_connection(servername, server_control_port);
792 if(control==NULL){
793 errf("Failed to connect (%m)");
794 }
795
796 if(argc==4){
797 /* We've been passed a machine list */
798 /* list currently needs to be ; seperated */
799 machine_list=strdup(argv[3]);
800 }
801
802 if((tcp_comm(control, NULL, &response, "PROTOCOL 1.1"))!=0){
803 errf("Incorrect version number (%s)", response);
804 exit(1);
805 }
806
807 if((tcp_comm(control, "stattop", &response, "OK"))!=0){
808 errf("Unexpected response %s", response);
809 exit(1);
810 }
811
812 if(machine_list!=NULL){
813 if((tcp_comm(control, "SETHOSTLIST", &response, "OK"))!=0){
814 errf("Unexpected response %s", response);
815 exit(1);
816 }
817 if((tcp_comm(control, machine_list, &response, "OK"))!=0){
818 errf("Unexpected response %s", response);
819 exit(1);
820 }
821 }
822
823 if((tcp_comm(control, "STARTDATA", &response, NULL))!=0){
824 errf("Unexpected response %s", response);
825 exit(1);
826 }
827
828 server_data_port=atoi(response);
829 if(server_data_port==0){
830 errf("Unexpected response %s", response);
831 exit(1);
832 }
833
834 data=create_tcp_connection(servername, server_data_port);
835 if(data==NULL){
836 errf("Failed to connect to host %s on port %d (%m)",servername, server_data_port);
837 }
838
839 /*
840 printf("\033[2J");
841 printf("\033[1;1HHostname CPU Load Page Page Mem Swap Net Net Disk Disk");
842 printf("\033[2;1H used%% (1m) ins outs used used rx tx read write");
843 */
844
845 initscr();
846 nonl();
847 cbreak();
848 echo();
849 window=newwin(0, 0, 0, 0);
850
851 for(;;){
852 response=fpgetline(data);
853 if (response==NULL){
854 errf("Failed to read data (%m)");
855 exit(1);
856 }
857
858 /* ch=getc(stdin);
859
860 if(ch=='q'){
861 endwin();
862 exit(0);
863 }
864 */
865 num_hosts=parse_xml(response, &machine_data_list);
866 if(num_hosts==-1) continue;
867 machine_data_list=sort_machine_stats(machine_data_list, num_hosts, sortby_ptr);
868 if(max_display==0){
869 display(machine_data_list, &display_config, num_hosts, &title);
870 }else{
871 display(machine_data_list, &display_config, max_display, &title);
872 }
873
874 }
875 exit(0);
876 }