ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.14
Committed: Wed Apr 9 21:55:10 2003 UTC (21 years, 1 month ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.13: +214 -54 lines
Log Message:
Now copes with resizing with regard to x-coord. This also copes with
units changing. (u or U)

It still doesn't do resizing properly tho :)

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