ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/idar/idar.c
Revision: 1.8
Committed: Sun Mar 30 23:21:55 2003 UTC (21 years, 8 months ago) by pajs
Content type: text/plain
Branch: MAIN
Changes since 1.7: +87 -5 lines
Log Message:
Now allows the user to choose whats being displayed. Currently only allows
the toggling of what we display by default, but its minor work adding the
others. I think may need to change the display structure, as i dont think
i will end up implementing like my original plan was.

Currently it does
'm' (memory)
's' (swap)
'l' (load)
'd' (disk_io)
'n' (network)
'p' (paging)
'c' (cpu)

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