ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.10
Committed: Wed Apr 2 15:41:01 2003 UTC (21 years, 1 month ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.9: +1 -0 lines
Log Message:
Linux now working.

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 pajs 1.10 #include <netdb.h>
33 pajs 1.1
34     #include <libxml/xmlmemory.h>
35     #include <libxml/parser.h>
36     #include "genmergesort.h"
37 tdb 1.6
38     #ifdef HAVE_NCURSES_H
39     #include <ncurses.h>
40     #else
41 pajs 1.4 #include <curses.h>
42 tdb 1.6 #endif
43 pajs 1.1
44     struct host_line_t{
45     char *hostname;
46     int line;
47    
48     struct host_line_t *next;
49     };
50     typedef struct host_line_t host_line_list_t;
51    
52     struct diskio_data_t{
53     char *name;
54    
55     long long read;
56     long long write;
57    
58     struct diskio_data_t *next;
59     };
60     typedef struct diskio_data_t diskio_data_list_t;
61    
62     struct network_data_t{
63     char *name;
64    
65     long long rx;
66     long long tx;
67    
68     struct network_data_t *next;
69     };
70     typedef struct network_data_t network_data_list_t;
71    
72     /*
73     struct disk_data_t{
74     char *name;
75     char *mount_pnt;
76    
77     long long total_space;
78     long long total_used;
79     long long total_avail;
80     // Other data we are less intrested in are not stored
81    
82     struct disk_data_t *next;
83     };
84     typedef struct disk_data_t disk_data_list_t;
85     */
86     #define MAXHOSTNAMESIZE 10
87     struct machine_data_t{
88    
89     char *name;
90    
91     char sysname[MAXHOSTNAMESIZE+1];
92    
93     double cpu_user;
94     double cpu_idle;
95     double cpu_iowait;
96     double cpu_kernel;
97     double cpu_swap;
98     double cpu_used; /* 100 - idle */
99    
100     long long memory_total;
101     long long memory_free;
102     long long memory_used;
103     double memory_used_pecent;
104    
105     long long swap_total;
106     long long swap_free;
107     long long swap_used;
108     double swap_used_pecent;
109    
110     int pages_in;
111     int pages_out;
112    
113     double load_1;
114     double load_5;
115     double load_15;
116    
117     int processes_total;
118     int processes_sleeping;
119     int processes_cpu;
120     int processes_zombie;
121     int processes_stopped;
122    
123     network_data_list_t *network_data_list;
124     long long network_io_total_tx;
125     long long network_io_total_rx;
126 pajs 1.7 long long network_io_total;
127 pajs 1.1
128     diskio_data_list_t *diskio_data_list;
129     long long disk_io_total_write;
130     long long disk_io_total_read;
131 pajs 1.7 long long disk_io_total;
132 pajs 1.1
133     /* Maybe in the future */
134     /*
135     disk_data_list_t disk_data_list;
136     double disk_total_used;
137     */
138    
139     struct machine_data_t *next;
140     };
141    
142     typedef struct machine_data_t machine_data_list_t;
143    
144 pajs 1.7 #define SORTBYMAXNAME 128
145 pajs 1.1 typedef struct{
146     int cpu_user;
147     int cpu_idle;
148     int cpu_iowait;
149     int cpu_kernel;
150     int cpu_swap;
151     int cpu_used;
152    
153     int memory_total;
154     int memory_free;
155     int memory_used;
156     int memory_used_pecent;
157    
158     int swap_total;
159     int swap_free;
160     int swap_used;
161     int swap_used_pecent;
162    
163     int load_1;
164     int load_5;
165     int load_15;
166    
167     int pages_in;
168     int pages_out;
169    
170     int processes_total;
171     int processes_sleeping;
172     int processes_cpu;
173     int processes_zombie;
174     int processes_stopped;
175    
176     int network_io_total_tx;
177     int network_io_total_rx;
178     int network_all_stats;
179    
180     int disk_io_total_write;
181     int disk_io_total_read;
182     int disk_io_all_stats;
183    
184     int disk_total_used;
185     int disk_all_stats;
186 pajs 1.7
187     char sortby[SORTBYMAXNAME];
188 pajs 1.1 }display_config_t;
189    
190     GENERIC_MERGE_SORT(static, sort_machine_stats, machine_data_list_t, next)
191    
192 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));}
193    
194    
195     int (*sortby_ptr)(machine_data_list_t *a, machine_data_list_t *b);
196    
197     MKCMP(cpu_used)
198     MKCMP(load_1)
199 pajs 1.7 MKCMP(network_io_total)
200 pajs 1.2 MKCMP(network_io_total_tx)
201     MKCMP(network_io_total_rx)
202 pajs 1.7 MKCMP(disk_io_total)
203 pajs 1.2 MKCMP(disk_io_total_write)
204     MKCMP(disk_io_total_read)
205     MKCMP(memory_used_pecent)
206     MKCMP(swap_used_pecent)
207    
208 pajs 1.7 #define CPU_USED "CPU used"
209     #define LOAD "Load (1)"
210     #define NETIORX "total Network RX for all interfaces"
211     #define NETIOTX "total Network TX for all interfaces"
212     #define NETIO "total Network IO for all interfaces (rx+tx)"
213     #define MEM "Memory usage"
214     #define SWAP "Swap usage"
215     #define DISKIOR "DiskIO reads"
216     #define DISKIOW "DiskIO writes"
217     #define DISKIO "Total DiskIO (reads+writes)"
218    
219    
220 pajs 1.2 /*
221 pajs 1.1 int cmp_cpu(machine_data_list_t *a, machine_data_list_t *b){
222    
223     if(a->cpu_used == b->cpu_used){
224     if(a->load_1 == b->load_1) return 0;
225     if(a->load_1 > b->load_1){
226     return -1;
227     }else{
228     return 1;
229     }
230     }
231    
232     if((a->cpu_used) > (b->cpu_used)){
233     return -1;
234     }else{
235     return 1;
236     }
237     }
238 pajs 1.2 */
239 pajs 1.9
240     #ifndef HAVE_ATOLL
241     long long int atoll (const char *nptr){
242     return strtoll (nptr, (char **) NULL, 10);
243     }
244     #endif
245    
246     #ifndef HAVE_STRLCPY
247     /*
248     * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
249     * All rights reserved.
250     *
251     * Redistribution and use in source and binary forms, with or without
252     * modification, are permitted provided that the following conditions
253     * are met:
254     * 1. Redistributions of source code must retain the above copyright
255     * notice, this list of conditions and the following disclaimer.
256     * 2. Redistributions in binary form must reproduce the above copyright
257     * notice, this list of conditions and the following disclaimer in the
258     * documentation and/or other materials provided with the distribution.
259     * 3. The name of the author may not be used to endorse or promote products
260     * derived from this software without specific prior written permission.
261     *
262     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
263     * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
264     * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
265     * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
266     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
267     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
268     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
269     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
270     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
271     * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272     */
273    
274     /*
275     * Copy src to string dst of size siz. At most siz-1 characters
276     * will be copied. Always NUL terminates (unless siz == 0).
277     * Returns strlen(src); if retval >= siz, truncation occurred.
278     */
279     size_t
280     strlcpy(dst, src, siz)
281     char *dst;
282     const char *src;
283     size_t siz;
284     {
285     register char *d = dst;
286     register const char *s = src;
287     register size_t n = siz;
288    
289     /* Copy as many bytes as will fit */
290     if (n != 0 && --n != 0) {
291     do {
292     if ((*d++ = *s++) == 0)
293     break;
294     } while (--n != 0);
295     }
296    
297     /* Not enough room in dst, add NUL and traverse rest of src */
298     if (n == 0) {
299     if (siz != 0)
300     *d = '\0'; /* NUL-terminate dst */
301     while (*s++)
302     ;
303     }
304    
305     return(s - src - 1); /* count does not include NUL */
306     }
307    
308     #endif
309    
310 pajs 1.1
311     FILE *create_tcp_connection(char *hostname, int port){
312     int sock;
313     struct sockaddr_in addr;
314     struct in_addr haddr;
315     FILE *f;
316    
317     if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0){
318     return NULL;
319     }
320    
321     if((get_host_addr(hostname, &haddr))!=0){
322     close(sock);
323     return NULL;
324     }
325    
326     memset(&addr, 0, sizeof(addr));
327     addr.sin_family = AF_INET;
328     memcpy(&addr.sin_addr, &haddr, sizeof(haddr));
329     addr.sin_port = htons(port);
330    
331     if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) !=0){
332     close(sock);
333     return NULL;
334     }
335    
336     if((f=fdopen(sock, "r+"))==NULL){
337     close(sock);
338     return NULL;
339     }
340    
341     return f;
342     }
343    
344     int tcp_comm(FILE *f, char *send, char **response, char *expected){
345    
346     if(send!=NULL){
347     fprintf(f, "%s\n", send);
348     }
349     fflush(f);
350     *response=fpgetline(f);
351     fseek(f, 0, SEEK_CUR);
352    
353     if( (*response==NULL) || (strcmp(*response, "ERROR")==0) ) return -1;
354    
355     if(expected==NULL) return 0;
356    
357     if((strcmp(expected, *response))==0) return 0;
358    
359     return -1;
360     }
361    
362     /* Takes a xml char * and a machine_data_list_t. This will parse
363     * the xml and put it into the correct entry of the machine_data
364     * linked list. This will return the number of entries in the linked
365     * list, or -1 on a error.
366     */
367     int parse_xml(char *xml, machine_data_list_t **md){
368     xmlDocPtr doc;
369     xmlNodePtr cur;
370     xmlNodePtr ele;
371     xmlAttr *list;
372    
373     static int num_hosts=0;
374    
375     machine_data_list_t *machine_data_list=*md;
376    
377     int found_host=0;
378    
379     char *hostname=NULL;
380     network_data_list_t *network_data_list=NULL;
381     network_data_list_t *ndl_ptr=NULL;
382     diskio_data_list_t *diskio_data_list=NULL;
383     diskio_data_list_t *didl_ptr=NULL;
384     char *tmp;
385    
386     doc=xmlParseDoc(xml);
387     if(doc==NULL) return -1;
388    
389     cur = xmlDocGetRootElement(doc);
390     if(cur==NULL){
391     xmlFreeDoc(doc);
392     return -1;
393     }
394    
395    
396     /* Get the hostname */
397     list=cur->properties;
398     while(list!=NULL){
399     if((xmlStrcmp(list->name, (const xmlChar *) "machine_name"))==0){
400     hostname = xmlNodeGetContent(list->children);
401     if(hostname==NULL){
402     return -1;
403     }
404     }
405     list=list->next;
406     }
407     if(hostname==NULL){
408     return -1;
409     }
410    
411     /* Get machine_data for host.. Or create if it doesn't have one */
412     while(machine_data_list!=NULL){
413     if((strncmp(machine_data_list->name, hostname, strlen(hostname)))==0){
414     found_host=1;
415     break;
416     }
417     machine_data_list=machine_data_list->next;
418     }
419    
420     if(!found_host){
421     /* We didn't find this host, but we should be at the end of the list */
422     machine_data_list=malloc(sizeof(machine_data_list_t));
423     if(machine_data_list==NULL) return -1;
424     machine_data_list->next=(*md);
425     machine_data_list->name=hostname;
426     machine_data_list->network_data_list=NULL;
427     machine_data_list->diskio_data_list=NULL;
428     *md=machine_data_list;
429     num_hosts++;
430     }
431    
432     /* Now we want to pull out the data */
433    
434     cur = cur->xmlChildrenNode;
435     while(cur != NULL) {
436     ele=cur->xmlChildrenNode;
437     while(ele != NULL){
438    
439     /* CPU Stats */
440     if(!xmlStrcmp(cur->name, (const xmlChar *) "cpu")){
441     tmp=xmlNodeGetContent(ele);
442     if(!xmlStrcmp(ele->name, (const xmlChar *) "user")){
443     machine_data_list->cpu_user=atof(tmp);
444     }
445     if(!xmlStrcmp(ele->name, (const xmlChar *) "kernel")){
446     machine_data_list->cpu_kernel=atof(tmp);
447     }
448     if(!xmlStrcmp(ele->name, (const xmlChar *) "idle")){
449     machine_data_list->cpu_idle=atof(tmp);
450     }
451     if(!xmlStrcmp(ele->name, (const xmlChar *) "iowait")){
452     machine_data_list->cpu_iowait=atof(tmp);
453     }
454     if(!xmlStrcmp(ele->name, (const xmlChar *) "swap")){
455     machine_data_list->cpu_iowait=atof(tmp);
456     }
457    
458     if(tmp!=NULL) xmlFree(tmp);
459     }
460    
461     /* Memory Stats */
462     if(!xmlStrcmp(cur->name, (const xmlChar *) "memory")){
463     tmp=xmlNodeGetContent(ele);
464     if(!xmlStrcmp(ele->name, (const xmlChar *) "total")){
465     machine_data_list->memory_total=atoll(tmp);
466     }
467     if(!xmlStrcmp(ele->name, (const xmlChar *) "free")){
468     machine_data_list->memory_free=atoll(tmp);
469     }
470     if(!xmlStrcmp(ele->name, (const xmlChar *) "used")){
471     machine_data_list->memory_used=atoll(tmp);
472     }
473    
474     if(tmp!=NULL) xmlFree(tmp);
475     }
476    
477     /* Load Stats */
478     if(!xmlStrcmp(cur->name, (const xmlChar *) "load")){
479     tmp=xmlNodeGetContent(ele);
480     if(!xmlStrcmp(ele->name, (const xmlChar *) "load1")){
481     machine_data_list->load_1=atof(tmp);
482     }
483     if(!xmlStrcmp(ele->name, (const xmlChar *) "load5")){
484     machine_data_list->load_5=atof(tmp);
485     }
486     if(!xmlStrcmp(ele->name, (const xmlChar *) "load15")){
487     machine_data_list->load_15=atof(tmp);
488     }
489    
490     if(tmp!=NULL) xmlFree(tmp);
491     }
492    
493     /* swap stats */
494     if(!xmlStrcmp(cur->name, (const xmlChar *) "swap")){
495     tmp=xmlNodeGetContent(ele);
496     if(!xmlStrcmp(ele->name, (const xmlChar *) "total")){
497     machine_data_list->swap_total=atoll(tmp);
498     }
499     if(!xmlStrcmp(ele->name, (const xmlChar *) "free")){
500     machine_data_list->swap_free=atoll(tmp);
501     }
502     if(!xmlStrcmp(ele->name, (const xmlChar *) "used")){
503     machine_data_list->swap_used=atoll(tmp);
504     }
505    
506     if(tmp!=NULL) xmlFree(tmp);
507     }
508    
509     /* Process stat */
510     if(!xmlStrcmp(cur->name, (const xmlChar *) "processes")){
511     tmp=xmlNodeGetContent(ele);
512     if(!xmlStrcmp(ele->name, (const xmlChar *) "sleeping")){
513     machine_data_list->processes_sleeping=atoi(tmp);
514     }
515     if(!xmlStrcmp(ele->name, (const xmlChar *) "cpu")){
516     machine_data_list->processes_cpu=atoi(tmp);
517     }
518     if(!xmlStrcmp(ele->name, (const xmlChar *) "zombie")){
519     machine_data_list->processes_zombie=atoi(tmp);
520     }
521     if(!xmlStrcmp(ele->name, (const xmlChar *) "total")){
522     machine_data_list->processes_total=atoi(tmp);
523     }
524    
525     if(tmp!=NULL) xmlFree(tmp);
526     }
527    
528     /* paging stats */
529     if(!xmlStrcmp(cur->name, (const xmlChar *) "pages")){
530     tmp=xmlNodeGetContent(ele);
531     if(!xmlStrcmp(ele->name, (const xmlChar *) "pageins")){
532     machine_data_list->pages_in=atoi(tmp);
533     }
534     if(!xmlStrcmp(ele->name, (const xmlChar *) "pageouts")){
535     machine_data_list->pages_out=atoi(tmp);
536     }
537    
538     if(tmp!=NULL) xmlFree(tmp);
539     }
540    
541     /* OS stats */
542     if(!xmlStrcmp(cur->name, (const xmlChar *) "os")){
543     tmp=xmlNodeGetContent(ele);
544     if(!xmlStrcmp(ele->name, (const xmlChar *) "sysname")){
545     strlcpy(machine_data_list->sysname, tmp, MAXHOSTNAMESIZE+1);
546     }
547     if(tmp!=NULL) xmlFree(tmp);
548     }
549    
550     /* Network stats */
551     /* Needs to connect current stat to a previous one. Or create it if new */
552     /* Get name.. Walk list. If match, copy rx/tx values. Else malloc, add to list */
553     if(!xmlStrcmp(cur->name, (const xmlChar *) "net")){
554    
555     list=ele->properties;
556     if(list==NULL) continue;
557     network_data_list=malloc(sizeof(network_data_list_t));
558     if(network_data_list==NULL) return -1;
559     while(list!=NULL){
560     tmp=xmlNodeGetContent(list->children);
561     if(!xmlStrcmp(list->name, (const xmlChar *) "name")){
562     network_data_list->name=strdup(tmp);
563     }
564     if(!xmlStrcmp(list->name, (const xmlChar *) "rx")){
565     network_data_list->rx=atoll(tmp);
566     }
567     if(!xmlStrcmp(list->name, (const xmlChar *) "tx")){
568     network_data_list->tx=atoll(tmp);
569     }
570    
571     xmlFree(tmp);
572     list=list->next;
573     }
574     if(network_data_list->name==NULL) continue;
575     found_host=0;
576     ndl_ptr=machine_data_list->network_data_list;
577     while(ndl_ptr!=NULL){
578     if(!strcmp(ndl_ptr->name, network_data_list->name)){
579     found_host=1;
580     break;
581     }
582     ndl_ptr=ndl_ptr->next;
583     }
584     if(found_host){
585     ndl_ptr->rx=network_data_list->rx;
586     ndl_ptr->tx=network_data_list->tx;
587     free(network_data_list->name);
588     free(network_data_list);
589     }else{
590     network_data_list->next=machine_data_list->network_data_list;
591     machine_data_list->network_data_list=network_data_list;
592     }
593     }
594    
595     /* Disk IO stats */
596     if(!xmlStrcmp(cur->name, (const xmlChar *) "diskio")){
597    
598     list=ele->properties;
599     if(list==NULL) continue;
600     diskio_data_list=malloc(sizeof(diskio_data_list_t));
601     if(diskio_data_list==NULL) return -1;
602     while(list!=NULL){
603     tmp=xmlNodeGetContent(list->children);
604     if(!xmlStrcmp(list->name, (const xmlChar *) "name")){
605     diskio_data_list->name=strdup(tmp);
606     }
607     if(!xmlStrcmp(list->name, (const xmlChar *) "rbytes")){
608     diskio_data_list->read=atoll(tmp);
609     }
610     if(!xmlStrcmp(list->name, (const xmlChar *) "wbytes")){
611     diskio_data_list->write=atoll(tmp);
612     }
613    
614     xmlFree(tmp);
615     list=list->next;
616     }
617     if(diskio_data_list->name==NULL) continue;
618     found_host=0;
619     didl_ptr=machine_data_list->diskio_data_list;
620     while(didl_ptr!=NULL){
621     if(!strcmp(didl_ptr->name, diskio_data_list->name)){
622     found_host=1;
623     break;
624     }
625     didl_ptr=didl_ptr->next;
626     }
627     if(found_host){
628     didl_ptr->read=diskio_data_list->read;
629     didl_ptr->write=diskio_data_list->write;
630     free(diskio_data_list->name);
631     free(diskio_data_list);
632     }else{
633     diskio_data_list->next=machine_data_list->diskio_data_list;
634     machine_data_list->diskio_data_list=diskio_data_list;
635     }
636     }
637    
638    
639    
640     ele=ele->next;
641     }
642     cur=cur->next;
643     }
644    
645     /* Append data we want thats not stored in the server */
646     machine_data_list->cpu_used=100.00-machine_data_list->cpu_idle;
647     machine_data_list->memory_used_pecent=((double)machine_data_list->memory_used / (double)machine_data_list->memory_total) * 100.00;
648     machine_data_list->swap_used_pecent=((double)machine_data_list->swap_used / (double)machine_data_list->swap_total) * 100.00;
649    
650     ndl_ptr=machine_data_list->network_data_list;
651     machine_data_list->network_io_total_tx=0;
652     machine_data_list->network_io_total_rx=0;
653     while(ndl_ptr!=NULL){
654     machine_data_list->network_io_total_tx+=ndl_ptr->tx;
655     machine_data_list->network_io_total_rx+=ndl_ptr->rx;
656     ndl_ptr=ndl_ptr->next;
657     }
658 pajs 1.7 machine_data_list->network_io_total=machine_data_list->network_io_total_rx+machine_data_list->network_io_total_tx;
659 pajs 1.1
660     didl_ptr=machine_data_list->diskio_data_list;
661     machine_data_list->disk_io_total_read=0;
662     machine_data_list->disk_io_total_write=0;
663     while(didl_ptr!=NULL){
664     machine_data_list->disk_io_total_read+=didl_ptr->read;
665     machine_data_list->disk_io_total_write+=didl_ptr->write;
666     didl_ptr=didl_ptr->next;
667     }
668 pajs 1.7 machine_data_list->disk_io_total=machine_data_list->disk_io_total_read+machine_data_list->disk_io_total_write;
669 pajs 1.1
670     xmlFreeDoc(doc);
671    
672     return num_hosts;
673    
674    
675     }
676    
677 pajs 1.2 void display(machine_data_list_t *machine_data_list, display_config_t *display_config, int num_lines, int *title){
678 pajs 1.1 int line_num=4;
679 pajs 1.7 int counter;
680 pajs 1.2 int x=1;
681    
682     if(*title){
683 pajs 1.8 clear();
684 pajs 1.7 move (num_lines-3, 1);
685     printw("Sorting by %-64s", display_config->sortby);
686    
687 pajs 1.4 move(1,1);
688     printw("%-11s", "Hostname");
689 pajs 1.2 x=x+11+1;
690     if(display_config->cpu_used){
691 pajs 1.4 move(1,x);
692     printw("%5s", "CPU");
693     move(2,x);
694     printw("%5s", "used%");
695 pajs 1.2 x+=6;
696     }
697     if(display_config->load_1){
698 pajs 1.4 move(1,x);
699     printw("%5s", "Load");
700     move(2,x);
701     printw("%5s", "(1m)");
702 pajs 1.2 x+=6;
703     }
704     if(display_config->pages_in){
705 pajs 1.4 move(1,x);
706     printw("%5s", "Page");
707     move(2,x);
708     printw("%5s", "ins");
709 pajs 1.2 x+=6;
710     }
711     if(display_config->pages_out){
712 pajs 1.4 move(1,x);
713     printw("%5s", "Page");
714     move(2,x);
715     printw("%5s", "outs");
716 pajs 1.2 x+=6;
717     }
718     if(display_config->memory_used_pecent){
719 pajs 1.4 move(1,x);
720     printw("%5s", "Mem");
721     move(2,x);
722     printw("%5s", "used");
723 pajs 1.2 x+=6;
724     }
725     if(display_config->swap_used_pecent){
726 pajs 1.4 move(1,x);
727     printw("%5s", "Swap");
728     move(2,x);
729     printw("%5s", "used");
730 pajs 1.2 x+=6;
731     }
732     if(display_config->network_io_total_rx){
733 pajs 1.4 move(1,x);
734     printw("%8s", "Net");
735     move(2,x);
736     printw("%8s", "rx");
737 pajs 1.2 x+=9;
738     }
739     if(display_config->network_io_total_tx){
740 pajs 1.4 move(1,x);
741     printw("%8s", "Net");
742     move(2,x);
743     printw("%8s", "tx");
744 pajs 1.2 x+=9;
745     }
746     if(display_config->disk_io_total_read){
747 pajs 1.4 move(1,x);
748     printw("%9s", "Disk");
749     move(2,x);
750     printw("%9s", "read");
751 pajs 1.2 x+=10;
752     }
753     if(display_config->disk_io_total_read){
754 pajs 1.4 move(1,x);
755     printw("%9s", "Disk");
756     move(2,x);
757     printw("%9s", "write");
758 pajs 1.2 x+=10;
759     }
760    
761     *title=0;
762     }
763 pajs 1.1
764 pajs 1.7 /* Counter starts at 8, for padding (eg, headers, borders etc) */
765     for(counter=8;counter<num_lines;counter++){
766 pajs 1.1 if(machine_data_list==NULL) break;
767 pajs 1.4 move(line_num++, 1);
768     printw("%-11s", machine_data_list->sysname);
769 pajs 1.2
770 pajs 1.4 if(display_config->cpu_used) printw(" %5.1f", machine_data_list->cpu_used);
771     if(display_config->load_1) printw(" %5.1f", machine_data_list->load_1);
772     if(display_config->pages_in) printw(" %5d", machine_data_list->pages_in);
773     if(display_config->pages_out) printw(" %5d", machine_data_list->pages_out);
774     if(display_config->memory_used_pecent) printw(" %5.1f", machine_data_list->memory_used_pecent);
775     if(display_config->swap_used_pecent) printw(" %5.1f", machine_data_list->swap_used_pecent);
776     if(display_config->network_io_total_rx) printw(" %8lld", machine_data_list->network_io_total_rx);
777     if(display_config->network_io_total_tx) printw(" %8lld", machine_data_list->network_io_total_tx);
778     if(display_config->disk_io_total_read) printw(" %9lld", machine_data_list->disk_io_total_read);
779     if(display_config->disk_io_total_write) printw(" %9lld", machine_data_list->disk_io_total_write);
780 pajs 1.2
781 pajs 1.1 machine_data_list=machine_data_list->next;
782     }
783    
784 pajs 1.2
785 pajs 1.4 refresh();
786 pajs 1.1
787     }
788    
789     int main(int argc, char **argv){
790 pajs 1.4 WINDOW *window;
791 pajs 1.5 fd_set infds;
792 pajs 1.7 int maxx, maxy;
793 pajs 1.4
794 pajs 1.1 FILE *control;
795     FILE *data;
796    
797     char *machine_list=NULL;
798     char *response=NULL;
799    
800     char *servername;
801     int server_control_port;
802     int server_data_port;
803    
804     machine_data_list_t *machine_data_list=NULL;
805    
806     int num_hosts;
807     int max_display=0;
808 pajs 1.7 int title=1;
809 pajs 1.1
810     int cmdopt;
811     extern int optind;
812     extern char *optarg;
813    
814     display_config_t display_config;
815 pajs 1.4 char ch;
816    
817 pajs 1.5 int data_fileno, stdin_fileno, biggest_fileno;
818    
819 pajs 1.4 sortby_ptr=NULL;
820 pajs 1.1
821     /* What to display defaults */
822     display_config.cpu_user=0;
823     display_config.cpu_idle=0;
824     display_config.cpu_iowait=0;
825     display_config.cpu_kernel=0;
826     display_config.cpu_swap=0;
827     display_config.cpu_used=1;
828    
829     display_config.memory_total=0;
830     display_config.memory_free=0;
831     display_config.memory_used=0;
832     display_config.memory_used_pecent=1;
833    
834     display_config.swap_total=0;
835     display_config.swap_free=0;
836     display_config.swap_used=0;
837     display_config.swap_used_pecent=1;
838    
839     display_config.load_1=1;
840     display_config.load_5=0;
841     display_config.load_15=0;
842    
843     display_config.pages_in=1;
844     display_config.pages_out=1;
845    
846     display_config.processes_total=0;
847     display_config.processes_sleeping=0;
848     display_config.processes_cpu=0;
849     display_config.processes_zombie=0;
850     display_config.processes_stopped=0;
851    
852 pajs 1.2 display_config.network_io_total_tx=1;
853     display_config.network_io_total_rx=1;
854 pajs 1.8 display_config.network_all_stats=0;
855 pajs 1.1
856 pajs 1.8 display_config.disk_io_total_write=1;
857     display_config.disk_io_total_read=1;
858 pajs 1.2 display_config.disk_io_all_stats=0;
859 pajs 1.1
860     display_config.disk_total_used=0;
861     display_config.disk_all_stats=0;
862    
863 pajs 1.2 while((cmdopt=getopt(argc, argv, "d:s:")) != -1){
864 pajs 1.1 switch(cmdopt){
865     case 'd':
866     max_display=atoi(optarg);
867     break;
868 pajs 1.2 case 's':
869     if(!strcmp(optarg, "cpu")){
870     sortby_ptr=cmp_cpu_used;
871 pajs 1.7 strlcpy(display_config.sortby, CPU_USED, SORTBYMAXNAME);
872 pajs 1.2 }
873     if(!strcmp(optarg, "load")){
874     sortby_ptr=cmp_load_1;
875 pajs 1.7 strlcpy(display_config.sortby, LOAD, SORTBYMAXNAME);
876 pajs 1.2 }
877     if(!strcmp(optarg, "mem")){
878     sortby_ptr=cmp_memory_used_pecent;
879 pajs 1.7 strlcpy(display_config.sortby, MEM, SORTBYMAXNAME);
880 pajs 1.2 }
881 pajs 1.7 if(!strcmp(optarg, "swap")){
882     sortby_ptr=cmp_swap_used_pecent;
883     strlcpy(display_config.sortby, SWAP, SORTBYMAXNAME);
884     }
885 pajs 1.2 if(sortby_ptr==NULL){
886     errf("Invalid sort type");
887     exit(1);
888     }
889     break;
890 pajs 1.1 }
891     }
892    
893 pajs 1.7 if(sortby_ptr==NULL){
894     sortby_ptr=cmp_cpu_used;
895     strlcpy(display_config.sortby, "CPU Used", SORTBYMAXNAME);
896     }
897 pajs 1.1
898     if(argc<(optind+2)){
899     printf("Usage is %s <-d lines> hostname port <machine list>\n", argv[0]);
900     exit(1);
901     }
902    
903     servername=argv[optind];
904     server_control_port=atoi(argv[optind+1]);
905    
906     control=create_tcp_connection(servername, server_control_port);
907     if(control==NULL){
908     errf("Failed to connect (%m)");
909     }
910    
911     if(argc==4){
912     /* We've been passed a machine list */
913     /* list currently needs to be ; seperated */
914     machine_list=strdup(argv[3]);
915     }
916    
917     if((tcp_comm(control, NULL, &response, "PROTOCOL 1.1"))!=0){
918     errf("Incorrect version number (%s)", response);
919     exit(1);
920     }
921    
922     if((tcp_comm(control, "stattop", &response, "OK"))!=0){
923     errf("Unexpected response %s", response);
924     exit(1);
925     }
926    
927     if(machine_list!=NULL){
928     if((tcp_comm(control, "SETHOSTLIST", &response, "OK"))!=0){
929     errf("Unexpected response %s", response);
930     exit(1);
931     }
932     if((tcp_comm(control, machine_list, &response, "OK"))!=0){
933     errf("Unexpected response %s", response);
934     exit(1);
935     }
936     }
937    
938     if((tcp_comm(control, "STARTDATA", &response, NULL))!=0){
939     errf("Unexpected response %s", response);
940     exit(1);
941     }
942    
943     server_data_port=atoi(response);
944     if(server_data_port==0){
945     errf("Unexpected response %s", response);
946     exit(1);
947     }
948    
949     data=create_tcp_connection(servername, server_data_port);
950     if(data==NULL){
951     errf("Failed to connect to host %s on port %d (%m)",servername, server_data_port);
952     }
953    
954 pajs 1.2 /*
955 pajs 1.1 printf("\033[2J");
956     printf("\033[1;1HHostname CPU Load Page Page Mem Swap Net Net Disk Disk");
957     printf("\033[2;1H used%% (1m) ins outs used used rx tx read write");
958 pajs 1.2 */
959 pajs 1.4
960     initscr();
961     nonl();
962     cbreak();
963     echo();
964     window=newwin(0, 0, 0, 0);
965 pajs 1.7 getmaxyx(window, maxy, maxx);
966 pajs 1.4
967 pajs 1.5 stdin_fileno=fileno(stdin);
968     data_fileno=fileno(data);
969     biggest_fileno=(data_fileno>stdin_fileno) ? (data_fileno+1) : (stdin_fileno+1);
970 pajs 1.7
971 pajs 1.1 for(;;){
972 pajs 1.5 FD_ZERO(&infds);
973     FD_SET(stdin_fileno, &infds);
974     FD_SET(data_fileno, &infds);
975     select(biggest_fileno, &infds, NULL, NULL, NULL);
976    
977     if(FD_ISSET(stdin_fileno, &infds)){
978    
979     ch=getc(stdin);
980 pajs 1.7 switch(ch){
981 pajs 1.8
982     /* Quit */
983 pajs 1.7 case 'Q':
984     case 'q':
985     endwin();
986     exit(0);
987     break;
988    
989 pajs 1.8 /* Sort by */
990 pajs 1.7 case 'C':
991     sortby_ptr=cmp_cpu_used;
992     strlcpy(display_config.sortby, CPU_USED, SORTBYMAXNAME);
993     break;
994    
995     case 'M':
996     sortby_ptr=cmp_memory_used_pecent;
997     strlcpy(display_config.sortby, MEM, SORTBYMAXNAME);
998     break;
999    
1000     case 'L':
1001     sortby_ptr=cmp_load_1;
1002     strlcpy(display_config.sortby, LOAD, SORTBYMAXNAME);
1003     break;
1004    
1005     case 'S':
1006     sortby_ptr=cmp_swap_used_pecent;
1007     strlcpy(display_config.sortby, SWAP, SORTBYMAXNAME);
1008     break;
1009    
1010     case 'N':
1011     if(sortby_ptr==cmp_network_io_total){
1012     strlcpy(display_config.sortby, NETIORX, SORTBYMAXNAME);
1013     sortby_ptr=cmp_network_io_total_rx;
1014     }else if(sortby_ptr==cmp_network_io_total_rx){
1015     strlcpy(display_config.sortby, NETIOTX, SORTBYMAXNAME);
1016     sortby_ptr=cmp_network_io_total_tx;
1017     }else{
1018     strlcpy(display_config.sortby, NETIO, SORTBYMAXNAME);
1019     sortby_ptr=cmp_network_io_total;
1020     }
1021     break;
1022 pajs 1.8 case 'D':
1023     if(sortby_ptr==cmp_disk_io_total){
1024     strlcpy(display_config.sortby, DISKIOR, SORTBYMAXNAME);
1025     sortby_ptr=cmp_disk_io_total_read;
1026     }else if(sortby_ptr==cmp_disk_io_total_read){
1027     strlcpy(display_config.sortby, DISKIOW, SORTBYMAXNAME);
1028     sortby_ptr=cmp_disk_io_total_write;
1029     }else{
1030     strlcpy(display_config.sortby, DISKIO, SORTBYMAXNAME);
1031     sortby_ptr=cmp_disk_io_total;
1032     }
1033     break;
1034    
1035     /* Display */
1036    
1037     case 'd':
1038     if(display_config.disk_io_total_read){
1039     display_config.disk_io_total_read=0;
1040     display_config.disk_io_total_write=0;
1041     }else{
1042     display_config.disk_io_total_read=1;
1043     display_config.disk_io_total_write=1;
1044     }
1045     break;
1046     case 'n':
1047     if(display_config.network_io_total_rx){
1048     display_config.network_io_total_rx=0;
1049     display_config.network_io_total_tx=0;
1050     }else{
1051     display_config.network_io_total_rx=1;
1052     display_config.network_io_total_tx=1;
1053     }
1054     break;
1055     case 'm':
1056     if(display_config.memory_used_pecent){
1057     display_config.memory_used_pecent=0;
1058     }else{
1059     display_config.memory_used_pecent=1;
1060     }
1061     break;
1062    
1063     case 's':
1064     if(display_config.swap_used_pecent){
1065     display_config.swap_used_pecent=0;
1066     }else{
1067     display_config.swap_used_pecent=1;
1068     }
1069     break;
1070     case 'l':
1071     if(display_config.load_1){
1072     display_config.load_1=0;
1073     }else{
1074     display_config.load_1=1;
1075     }
1076     break;
1077     case 'p':
1078     if(display_config.pages_in){
1079     display_config.pages_in=0;
1080     display_config.pages_out=0;
1081     }else{
1082     display_config.pages_in=1;
1083     display_config.pages_out=1;
1084     }
1085     break;
1086     case 'c':
1087     if(display_config.cpu_used){
1088     display_config.cpu_used=0;
1089     }else{
1090     display_config.cpu_used=1;
1091     }
1092     break;
1093 pajs 1.5
1094 pajs 1.8 default:
1095     /* Invalid key.. Ignore.. Set Title to -1, as the
1096     * title++ will then make that "0" (false) so a
1097     * screen redraw will not happen */
1098     title=-1;
1099     break;
1100 pajs 1.5 }
1101 pajs 1.8
1102     /* Increment title so it becomes true (and making the screen update */
1103     title++;
1104 pajs 1.7
1105 pajs 1.5 }
1106     if(FD_ISSET(data_fileno, &infds)){
1107     response=fpgetline(data);
1108     if (response==NULL){
1109     errf("Failed to read data (%m)");
1110     exit(1);
1111     }
1112 pajs 1.1 }
1113    
1114 pajs 1.4
1115 pajs 1.1 num_hosts=parse_xml(response, &machine_data_list);
1116     if(num_hosts==-1) continue;
1117 pajs 1.2 machine_data_list=sort_machine_stats(machine_data_list, num_hosts, sortby_ptr);
1118 pajs 1.1 if(max_display==0){
1119 pajs 1.7 display(machine_data_list, &display_config, maxy, &title);
1120 pajs 1.1 }else{
1121 pajs 1.2 display(machine_data_list, &display_config, max_display, &title);
1122 pajs 1.1 }
1123    
1124     }
1125     exit(0);
1126     }