ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.9
Committed: Wed Apr 2 15:23:26 2003 UTC (21 years, 8 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.8: +71 -0 lines
Log Message:
(unchecked) This update should mean it will compile on linux and freebsd.
I think we've got to the point where it should be called 1.1 :)
(If this actually works that is :) )

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