ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.19
Committed: Thu Aug 21 20:36:41 2003 UTC (20 years, 9 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.18: +1 -0 lines
Log Message:
Add a default option to the command line parsing. This does the same as
the -h flag and shows the usage. The intention is to catch unknown flags
and tell the user, rather than printing a warning and loading anyway.

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