ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.24
Committed: Wed Jun 2 16:13:06 2004 UTC (19 years, 11 months ago) by ats
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.23: +1 -1 lines
Log Message:
Include ukcprog.h after all the system headers, so that it defines
get_host_addr correctly on Linux.

File Contents

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