ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.5
Committed: Sun Mar 30 10:58:21 2003 UTC (21 years, 9 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.4: +27 -10 lines
Log Message:
Allows the user to hit "q" to quit the program. The program is now interactive,
as it now uses select to work out if it needs to do something from the user, or
from the TCP connection.

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 pajs 1.4 #include <curses.h>
37 pajs 1.1
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 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));}
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 pajs 1.1 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 pajs 1.2 */
214 pajs 1.1
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 pajs 1.2 void display(machine_data_list_t *machine_data_list, display_config_t *display_config, int num_lines, int *title){
580 pajs 1.1 int line_num=4;
581 pajs 1.2 int x=1;
582    
583     if(*title){
584 pajs 1.4 // printf("\033[2J");
585 pajs 1.2 // printf("\033[1;1HHostname CPU Load Page Page Mem Swap Net Net Disk Disk");
586 pajs 1.4 // printw("\033[2;1H used%% (1m) ins outs used used rx tx read write");
587     move(1,1);
588     printw("%-11s", "Hostname");
589 pajs 1.2 x=x+11+1;
590     if(display_config->cpu_used){
591 pajs 1.4 move(1,x);
592     printw("%5s", "CPU");
593     move(2,x);
594     printw("%5s", "used%");
595 pajs 1.2 x+=6;
596     }
597     if(display_config->load_1){
598 pajs 1.4 move(1,x);
599     printw("%5s", "Load");
600     move(2,x);
601     printw("%5s", "(1m)");
602 pajs 1.2 x+=6;
603     }
604     if(display_config->pages_in){
605 pajs 1.4 move(1,x);
606     printw("%5s", "Page");
607     move(2,x);
608     printw("%5s", "ins");
609 pajs 1.2 x+=6;
610     }
611     if(display_config->pages_out){
612 pajs 1.4 move(1,x);
613     printw("%5s", "Page");
614     move(2,x);
615     printw("%5s", "outs");
616 pajs 1.2 x+=6;
617     }
618     if(display_config->memory_used_pecent){
619 pajs 1.4 move(1,x);
620     printw("%5s", "Mem");
621     move(2,x);
622     printw("%5s", "used");
623 pajs 1.2 x+=6;
624     }
625     if(display_config->swap_used_pecent){
626 pajs 1.4 move(1,x);
627     printw("%5s", "Swap");
628     move(2,x);
629     printw("%5s", "used");
630 pajs 1.2 x+=6;
631     }
632     if(display_config->network_io_total_rx){
633 pajs 1.4 move(1,x);
634     printw("%8s", "Net");
635     move(2,x);
636     printw("%8s", "rx");
637 pajs 1.2 x+=9;
638     }
639     if(display_config->network_io_total_tx){
640 pajs 1.4 move(1,x);
641     printw("%8s", "Net");
642     move(2,x);
643     printw("%8s", "tx");
644 pajs 1.2 x+=9;
645     }
646     if(display_config->disk_io_total_read){
647 pajs 1.4 move(1,x);
648     printw("%9s", "Disk");
649     move(2,x);
650     printw("%9s", "read");
651 pajs 1.2 x+=10;
652     }
653     if(display_config->disk_io_total_read){
654 pajs 1.4 move(1,x);
655     printw("%9s", "Disk");
656     move(2,x);
657     printw("%9s", "write");
658 pajs 1.2 x+=10;
659     }
660    
661     *title=0;
662     }
663 pajs 1.1
664     for(;num_lines;num_lines--){
665     if(machine_data_list==NULL) break;
666 pajs 1.4 move(line_num++, 1);
667     printw("%-11s", machine_data_list->sysname);
668 pajs 1.2
669 pajs 1.4 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 pajs 1.2
680 pajs 1.1 machine_data_list=machine_data_list->next;
681     }
682    
683 pajs 1.2
684 pajs 1.4 refresh();
685 pajs 1.1
686     }
687    
688     int main(int argc, char **argv){
689 pajs 1.4 WINDOW *window;
690 pajs 1.5 fd_set infds;
691 pajs 1.4
692 pajs 1.1 FILE *control;
693     FILE *data;
694    
695     char *machine_list=NULL;
696     char *response=NULL;
697    
698     char *servername;
699     int server_control_port;
700     int server_data_port;
701    
702     machine_data_list_t *machine_data_list=NULL;
703    
704     int num_hosts;
705     int max_display=0;
706 pajs 1.2 int title;
707 pajs 1.1
708     int cmdopt;
709     extern int optind;
710     extern char *optarg;
711    
712     display_config_t display_config;
713 pajs 1.4 char ch;
714    
715 pajs 1.5 int data_fileno, stdin_fileno, biggest_fileno;
716    
717 pajs 1.4 sortby_ptr=NULL;
718 pajs 1.1
719     /* What to display defaults */
720     display_config.cpu_user=0;
721     display_config.cpu_idle=0;
722     display_config.cpu_iowait=0;
723     display_config.cpu_kernel=0;
724     display_config.cpu_swap=0;
725     display_config.cpu_used=1;
726    
727     display_config.memory_total=0;
728     display_config.memory_free=0;
729     display_config.memory_used=0;
730     display_config.memory_used_pecent=1;
731    
732     display_config.swap_total=0;
733     display_config.swap_free=0;
734     display_config.swap_used=0;
735     display_config.swap_used_pecent=1;
736    
737     display_config.load_1=1;
738     display_config.load_5=0;
739     display_config.load_15=0;
740    
741     display_config.pages_in=1;
742     display_config.pages_out=1;
743    
744     display_config.processes_total=0;
745     display_config.processes_sleeping=0;
746     display_config.processes_cpu=0;
747     display_config.processes_zombie=0;
748     display_config.processes_stopped=0;
749    
750 pajs 1.2 display_config.network_io_total_tx=1;
751     display_config.network_io_total_rx=1;
752 pajs 1.1 display_config.network_all_stats=1;
753    
754 pajs 1.4 display_config.disk_io_total_write=0;
755     display_config.disk_io_total_read=0;
756 pajs 1.2 display_config.disk_io_all_stats=0;
757 pajs 1.1
758     display_config.disk_total_used=0;
759     display_config.disk_all_stats=0;
760    
761 pajs 1.2 while((cmdopt=getopt(argc, argv, "d:s:")) != -1){
762 pajs 1.1 switch(cmdopt){
763     case 'd':
764     max_display=atoi(optarg);
765     break;
766 pajs 1.2 case 's':
767     if(!strcmp(optarg, "cpu")){
768     sortby_ptr=cmp_cpu_used;
769     }
770     if(!strcmp(optarg, "load")){
771     sortby_ptr=cmp_load_1;
772     }
773     if(!strcmp(optarg, "mem")){
774     sortby_ptr=cmp_memory_used_pecent;
775     }
776     if(sortby_ptr==NULL){
777     errf("Invalid sort type");
778     exit(1);
779     }
780     break;
781 pajs 1.1 }
782     }
783    
784 pajs 1.2 if(sortby_ptr==NULL) sortby_ptr=cmp_cpu_used;
785 pajs 1.1
786     if(argc<(optind+2)){
787     printf("Usage is %s <-d lines> hostname port <machine list>\n", argv[0]);
788     exit(1);
789     }
790    
791     servername=argv[optind];
792     server_control_port=atoi(argv[optind+1]);
793    
794     control=create_tcp_connection(servername, server_control_port);
795     if(control==NULL){
796     errf("Failed to connect (%m)");
797     }
798    
799     if(argc==4){
800     /* We've been passed a machine list */
801     /* list currently needs to be ; seperated */
802     machine_list=strdup(argv[3]);
803     }
804    
805     if((tcp_comm(control, NULL, &response, "PROTOCOL 1.1"))!=0){
806     errf("Incorrect version number (%s)", response);
807     exit(1);
808     }
809    
810     if((tcp_comm(control, "stattop", &response, "OK"))!=0){
811     errf("Unexpected response %s", response);
812     exit(1);
813     }
814    
815     if(machine_list!=NULL){
816     if((tcp_comm(control, "SETHOSTLIST", &response, "OK"))!=0){
817     errf("Unexpected response %s", response);
818     exit(1);
819     }
820     if((tcp_comm(control, machine_list, &response, "OK"))!=0){
821     errf("Unexpected response %s", response);
822     exit(1);
823     }
824     }
825    
826     if((tcp_comm(control, "STARTDATA", &response, NULL))!=0){
827     errf("Unexpected response %s", response);
828     exit(1);
829     }
830    
831     server_data_port=atoi(response);
832     if(server_data_port==0){
833     errf("Unexpected response %s", response);
834     exit(1);
835     }
836    
837     data=create_tcp_connection(servername, server_data_port);
838     if(data==NULL){
839     errf("Failed to connect to host %s on port %d (%m)",servername, server_data_port);
840     }
841    
842 pajs 1.2 /*
843 pajs 1.1 printf("\033[2J");
844     printf("\033[1;1HHostname CPU Load Page Page Mem Swap Net Net Disk Disk");
845     printf("\033[2;1H used%% (1m) ins outs used used rx tx read write");
846 pajs 1.2 */
847 pajs 1.4
848     initscr();
849     nonl();
850     cbreak();
851     echo();
852     window=newwin(0, 0, 0, 0);
853    
854 pajs 1.5 stdin_fileno=fileno(stdin);
855     data_fileno=fileno(data);
856     biggest_fileno=(data_fileno>stdin_fileno) ? (data_fileno+1) : (stdin_fileno+1);
857    
858 pajs 1.1 for(;;){
859 pajs 1.5 FD_ZERO(&infds);
860     FD_SET(stdin_fileno, &infds);
861     FD_SET(data_fileno, &infds);
862     select(biggest_fileno, &infds, NULL, NULL, NULL);
863    
864     if(FD_ISSET(stdin_fileno, &infds)){
865    
866     ch=getc(stdin);
867    
868     if(ch=='q'){
869     endwin();
870     exit(0);
871     }
872     }
873     if(FD_ISSET(data_fileno, &infds)){
874     response=fpgetline(data);
875     if (response==NULL){
876     errf("Failed to read data (%m)");
877     exit(1);
878     }
879 pajs 1.1 }
880    
881 pajs 1.4
882 pajs 1.1 num_hosts=parse_xml(response, &machine_data_list);
883     if(num_hosts==-1) continue;
884 pajs 1.2 machine_data_list=sort_machine_stats(machine_data_list, num_hosts, sortby_ptr);
885 pajs 1.1 if(max_display==0){
886 pajs 1.2 display(machine_data_list, &display_config, num_hosts, &title);
887 pajs 1.1 }else{
888 pajs 1.2 display(machine_data_list, &display_config, max_display, &title);
889 pajs 1.1 }
890    
891     }
892     exit(0);
893     }