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, 9 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

# User Rev Content
1 tdb 1.3 /*
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 pajs 1.1 #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 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));}
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 pajs 1.1 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 pajs 1.2 */
213 pajs 1.1
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 pajs 1.2 void display(machine_data_list_t *machine_data_list, display_config_t *display_config, int num_lines, int *title){
579 pajs 1.1 int line_num=4;
580 pajs 1.2 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 pajs 1.1
642     for(;num_lines;num_lines--){
643     if(machine_data_list==NULL) break;
644 pajs 1.2
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 pajs 1.1 machine_data_list=machine_data_list->next;
659     }
660    
661 pajs 1.2
662 pajs 1.1 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 pajs 1.2 int title;
682 pajs 1.1
683     int cmdopt;
684     extern int optind;
685     extern char *optarg;
686 pajs 1.2 sortby_ptr=NULL;
687 pajs 1.1
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 pajs 1.2 display_config.network_io_total_tx=1;
722     display_config.network_io_total_rx=1;
723 pajs 1.1 display_config.network_all_stats=1;
724    
725 pajs 1.2 display_config.disk_io_total_write=1;
726     display_config.disk_io_total_read=1;
727     display_config.disk_io_all_stats=0;
728 pajs 1.1
729     display_config.disk_total_used=0;
730     display_config.disk_all_stats=0;
731    
732 pajs 1.2
733     while((cmdopt=getopt(argc, argv, "d:s:")) != -1){
734 pajs 1.1 switch(cmdopt){
735     case 'd':
736     max_display=atoi(optarg);
737     break;
738 pajs 1.2 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 pajs 1.1 }
754     }
755    
756 pajs 1.2 if(sortby_ptr==NULL) sortby_ptr=cmp_cpu_used;
757 pajs 1.1
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 pajs 1.2 /*
815 pajs 1.1 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 pajs 1.2 */
819 pajs 1.1 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 pajs 1.2 machine_data_list=sort_machine_stats(machine_data_list, num_hosts, sortby_ptr);
830 pajs 1.1 if(max_display==0){
831 pajs 1.2 display(machine_data_list, &display_config, num_hosts, &title);
832 pajs 1.1 }else{
833 pajs 1.2 display(machine_data_list, &display_config, max_display, &title);
834 pajs 1.1 }
835    
836     }
837     exit(0);
838     }