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, 7 months 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

# Content
1 /*
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 #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 #include <netinet/in.h>
33 #include <netdb.h>
34 #include <sys/termios.h>
35
36 #include <libxml/xmlmemory.h>
37 #include <libxml/parser.h>
38 #include "genmergesort.h"
39
40 #ifdef HAVE_NCURSES_H
41 #include <ncurses.h>
42 #else
43 #include <curses.h>
44 #endif
45
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 long long network_io_total;
129
130 diskio_data_list_t *diskio_data_list;
131 long long disk_io_total_write;
132 long long disk_io_total_read;
133 long long disk_io_total;
134
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 #define SORTBYMAXNAME 128
147 typedef struct{
148 int maxx;
149 int maxy;
150
151 char units;
152
153 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
194 char sortby[SORTBYMAXNAME];
195 }display_config_t;
196
197 GENERIC_MERGE_SORT(static, sort_machine_stats, machine_data_list_t, next)
198
199 #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 MKCMP(network_io_total)
207 MKCMP(network_io_total_tx)
208 MKCMP(network_io_total_rx)
209 MKCMP(disk_io_total)
210 MKCMP(disk_io_total_write)
211 MKCMP(disk_io_total_read)
212 MKCMP(memory_used_pecent)
213 MKCMP(swap_used_pecent)
214
215 #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 /*
228 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 */
246
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
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 machine_data_list->network_io_total=machine_data_list->network_io_total_rx+machine_data_list->network_io_total_tx;
666
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 machine_data_list->disk_io_total=machine_data_list->disk_io_total_read+machine_data_list->disk_io_total_write;
676
677 xmlFreeDoc(doc);
678
679 return num_hosts;
680
681
682 }
683
684 void display(machine_data_list_t *machine_data_list, display_config_t *display_config, int *title){
685 int line_num=4;
686 int counter;
687 int x=1;
688
689 if(*title){
690 clear();
691 move (display_config->maxy-3, 1);
692 printw("Sorting by %-64s", display_config->sortby);
693 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
704 move(1,1);
705 printw("%-11s", "Hostname");
706 x=x+11+1;
707 if(display_config->cpu_used && (display_config->maxx > x+6)){
708 move(1,x);
709 printw("%5s", "CPU");
710 move(2,x);
711 printw("%5s", "used%");
712 x+=6;
713 }
714 if(display_config->load_1 && (display_config->maxx > x+6)){
715 move(1,x);
716 printw("%5s", "Load");
717 move(2,x);
718 printw("%5s", "(1m)");
719 x+=6;
720 }
721 if(display_config->pages_in && (display_config->maxx > x+6)){
722 move(1,x);
723 printw("%5s", "Page");
724 move(2,x);
725 printw("%5s", "ins");
726 x+=6;
727 }
728 if(display_config->pages_out && (display_config->maxx > x+6)){
729 move(1,x);
730 printw("%5s", "Page");
731 move(2,x);
732 printw("%5s", "outs");
733 x+=6;
734 }
735 if(display_config->memory_used_pecent && (display_config->maxx > x+6)){
736 move(1,x);
737 printw("%5s", "Mem");
738 move(2,x);
739 printw("%5s", "used");
740 x+=6;
741 }
742 if(display_config->swap_used_pecent && (display_config->maxx > x+6)){
743 move(1,x);
744 printw("%5s", "Swap");
745 move(2,x);
746 printw("%5s", "used");
747 x+=6;
748 }
749 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 }
772 if(display_config->network_io_total_tx){
773 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 }
795
796 if(display_config->disk_io_total_read){
797 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 }
819
820 if(display_config->disk_io_total_read){
821 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 }
843
844 *title=0;
845 }
846
847 /* Counter starts at 8, for padding (eg, headers, borders etc) */
848 for(counter=8;counter<display_config->maxy;counter++){
849 if(machine_data_list==NULL) break;
850 move(line_num++, 1);
851 printw("%-11s", machine_data_list->sysname);
852 x=13;
853
854 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
939 machine_data_list=machine_data_list->next;
940 }
941
942
943 refresh();
944
945 }
946
947 int main(int argc, char **argv){
948 WINDOW *window;
949 fd_set infds;
950 struct winsize size;
951
952 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 int title=1;
966
967 int cmdopt;
968 extern int optind;
969 extern char *optarg;
970
971 display_config_t display_config;
972 char ch;
973
974 int data_fileno, stdin_fileno, biggest_fileno;
975
976 sortby_ptr=NULL;
977
978 /* What to display defaults */
979 display_config.units='b';
980
981 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 display_config.network_io_total_tx=1;
1012 display_config.network_io_total_rx=1;
1013 display_config.network_all_stats=0;
1014
1015 display_config.disk_io_total_write=1;
1016 display_config.disk_io_total_read=1;
1017 display_config.disk_io_all_stats=0;
1018
1019 display_config.disk_total_used=0;
1020 display_config.disk_all_stats=0;
1021
1022 while((cmdopt=getopt(argc, argv, "s:")) != -1){
1023 switch(cmdopt){
1024 case 's':
1025 if(!strcmp(optarg, "cpu")){
1026 sortby_ptr=cmp_cpu_used;
1027 strlcpy(display_config.sortby, CPU_USED, SORTBYMAXNAME);
1028 }
1029 if(!strcmp(optarg, "load")){
1030 sortby_ptr=cmp_load_1;
1031 strlcpy(display_config.sortby, LOAD, SORTBYMAXNAME);
1032 }
1033 if(!strcmp(optarg, "mem")){
1034 sortby_ptr=cmp_memory_used_pecent;
1035 strlcpy(display_config.sortby, MEM, SORTBYMAXNAME);
1036 }
1037 if(!strcmp(optarg, "swap")){
1038 sortby_ptr=cmp_swap_used_pecent;
1039 strlcpy(display_config.sortby, SWAP, SORTBYMAXNAME);
1040 }
1041 if(sortby_ptr==NULL){
1042 errf("Invalid sort type");
1043 exit(1);
1044 }
1045 break;
1046 }
1047 }
1048
1049 if(sortby_ptr==NULL){
1050 sortby_ptr=cmp_cpu_used;
1051 strlcpy(display_config.sortby, "CPU Used", SORTBYMAXNAME);
1052 }
1053
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 exit(1);
1066 }
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 exit(1);
1110 }
1111
1112 /*
1113 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 */
1117
1118 initscr();
1119 nonl();
1120 cbreak();
1121 echo();
1122 window=newwin(0, 0, 0, 0);
1123 getmaxyx(window, display_config.maxy, display_config.maxx);
1124
1125 stdin_fileno=fileno(stdin);
1126 data_fileno=fileno(data);
1127 biggest_fileno=(data_fileno>stdin_fileno) ? (data_fileno+1) : (stdin_fileno+1);
1128
1129 for(;;){
1130 FD_ZERO(&infds);
1131 FD_SET(stdin_fileno, &infds);
1132 FD_SET(data_fileno, &infds);
1133 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 getmaxyx(window, display_config.maxy, display_config.maxx);
1139 title=1;
1140 display(machine_data_list, &display_config, &title);
1141 refresh();
1142 continue;
1143 }
1144
1145 if(FD_ISSET(stdin_fileno, &infds)){
1146
1147 ch=getc(stdin);
1148 switch(ch){
1149
1150 /* Quit */
1151 case 'Q':
1152 case 'q':
1153 endwin();
1154 exit(0);
1155 break;
1156 /* 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
1168 /* Sort by */
1169 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 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
1273 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 }
1280
1281 /* Increment title so it becomes true (and making the screen update */
1282 title++;
1283
1284 }
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 }
1292
1293
1294 num_hosts=parse_xml(response, &machine_data_list);
1295 if(num_hosts==-1) continue;
1296 machine_data_list=sort_machine_stats(machine_data_list, num_hosts, sortby_ptr);
1297 display(machine_data_list, &display_config, &title);
1298
1299 }
1300 exit(0);
1301 }