ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.13
Committed: Wed Apr 9 20:13:53 2003 UTC (21 years, 1 month ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.12: +14 -1 lines
Log Message:
Ok, im sure this prob isn't the "right" way to do resizing.. but it seems
to work.

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