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, 1 month 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

# User Rev Content
1 pajs 1.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 pajs 1.2 #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 pajs 1.1 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 pajs 1.2 */
189 pajs 1.1
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 pajs 1.2 void display(machine_data_list_t *machine_data_list, display_config_t *display_config, int num_lines, int *title){
555 pajs 1.1 int line_num=4;
556 pajs 1.2 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 pajs 1.1
618     for(;num_lines;num_lines--){
619     if(machine_data_list==NULL) break;
620 pajs 1.2
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 pajs 1.1 machine_data_list=machine_data_list->next;
635     }
636    
637 pajs 1.2
638 pajs 1.1 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 pajs 1.2 int title;
658 pajs 1.1
659     int cmdopt;
660     extern int optind;
661     extern char *optarg;
662 pajs 1.2 sortby_ptr=NULL;
663 pajs 1.1
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 pajs 1.2 display_config.network_io_total_tx=1;
698     display_config.network_io_total_rx=1;
699 pajs 1.1 display_config.network_all_stats=1;
700    
701 pajs 1.2 display_config.disk_io_total_write=1;
702     display_config.disk_io_total_read=1;
703     display_config.disk_io_all_stats=0;
704 pajs 1.1
705     display_config.disk_total_used=0;
706     display_config.disk_all_stats=0;
707    
708 pajs 1.2
709     while((cmdopt=getopt(argc, argv, "d:s:")) != -1){
710 pajs 1.1 switch(cmdopt){
711     case 'd':
712     max_display=atoi(optarg);
713     break;
714 pajs 1.2 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 pajs 1.1 }
730     }
731    
732 pajs 1.2 if(sortby_ptr==NULL) sortby_ptr=cmp_cpu_used;
733 pajs 1.1
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 pajs 1.2 /*
791 pajs 1.1 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 pajs 1.2 */
795 pajs 1.1 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 pajs 1.2 machine_data_list=sort_machine_stats(machine_data_list, num_hosts, sortby_ptr);
806 pajs 1.1 if(max_display==0){
807 pajs 1.2 display(machine_data_list, &display_config, num_hosts, &title);
808 pajs 1.1 }else{
809 pajs 1.2 display(machine_data_list, &display_config, max_display, &title);
810 pajs 1.1 }
811    
812     }
813     exit(0);
814     }