ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.7
Committed: Sun Mar 30 22:16:20 2003 UTC (21 years, 9 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.6: +85 -11 lines
Log Message:
Added support for sorting on the fly. I have followed a basic convention of
a capital letter will do sorting, and a lower case letter will change the
display properties.

Currently q or Q will quit.
C will sort by CPU
S will sort by Swap
M will sort by Memory
L will sort by Load
N will sort by Network. Network sorting is toggled thru 3 options. First
time it will sort by rx+tx. 2nd time it will sort by rx, 3rd time tx. Then
it will repeat to the start again.

The display function has been updated slightly. The arguments it takes
(num_lines) now means the number of lines on the screen, rather than
the number of hosts to display. A status of what its sorting by has been
added to the bottom line. This line could be used for other "stuff" in the
future as well.

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