ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.6
Committed: Sun Mar 30 17:11:26 2003 UTC (21 years, 5 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.5: +5 -0 lines
Log Message:
Now tests for either curses or ncurses. By default prefers to use curses,
but will use ncurses if curses is not available or if forced by a configure
flag. Also minor other tweaks.

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