ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.11
Committed: Wed Apr 2 15:47:25 2003 UTC (21 years, 8 months ago) by pajs
Content type: text/plain
Branch: MAIN
CVS Tags: IDAR_1_0
Changes since 1.10: +1 -0 lines
Log Message:
Now works on freebsd too :)

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