ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/saidar/saidar.c
Revision: 1.42
Committed: Sun Oct 3 18:35:58 2010 UTC (13 years, 7 months ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.41: +6 -2 lines
Log Message:
Add support for AIX 5.x - 9.x.

Many thanks to Jens Rehsack <rehsack@googlemail.com> for providing the
patch for this work. Thanks!

File Contents

# Content
1 /*
2 * i-scream libstatgrab
3 * http://www.i-scream.org
4 * Copyright (C) 2000-2004 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 * $Id: saidar.c,v 1.41 2007/01/05 13:30:36 tdb Exp $
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/ioctl.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <signal.h>
33 #include <errno.h>
34 #include <statgrab.h>
35 #include <sys/times.h>
36 #include <limits.h>
37 #include <time.h>
38 #include <math.h>
39 #ifdef AIX
40 #include <termios.h>
41 #else
42 #include <sys/termios.h>
43 #endif
44
45 #ifdef HAVE_NCURSES_H
46 #define COLOR_SUPPORT
47 #endif
48 #include CURSES_HEADER_FILE
49
50 #define THRESHOLD_LOAD 1.0
51
52 #define THRESHOLD_WARN_ZMB 0
53
54 #define THRESHOLD_WARN_CPU 60.0
55 #define THRESHOLD_ALERT_CPU 90.0
56
57 #define THRESHOLD_WARN_SWAP 75.0
58 #define THRESHOLD_ALERT_SWAP 90.0
59
60 #define THRESHOLD_WARN_MEM 75.0
61 #define THRESHOLD_ALERT_MEM 90.0
62
63 #define THRESHOLD_WARN_DISK 75.0
64 #define THRESHOLD_ALERT_DISK 90.0
65
66 int sig_winch_flag = 0;
67
68 typedef struct{
69 sg_cpu_percents *cpu_percents;
70 sg_mem_stats *mem_stats;
71 sg_swap_stats *swap_stats;
72 sg_load_stats *load_stats;
73 sg_process_count *process_count;
74 sg_page_stats *page_stats;
75
76 sg_network_io_stats *network_io_stats;
77 int network_io_entries;
78
79 sg_disk_io_stats *disk_io_stats;
80 int disk_io_entries;
81
82 sg_fs_stats *fs_stats;
83 int fs_entries;
84
85 sg_host_info *host_info;
86 sg_user_stats *user_stats;
87 }stats_t;
88
89 stats_t stats;
90
91 char *size_conv(long long number){
92 char type[] = {'B', 'K', 'M', 'G', 'T'};
93 int x=0;
94 int sign=1;
95 static char string[10];
96
97 if(number < 0){
98 sign=-1;
99 number=-number;
100 }
101
102 for(;x<5;x++){
103 if( (number/1024) < (100)) {
104 break;
105 }
106 number = (number/1024);
107 }
108
109 number = number*sign;
110
111 snprintf(string, 10, "%lld%c", number, type[x]);
112 return string;
113
114 }
115
116 char *hr_uptime(time_t time){
117 int day = 0, hour = 0, min = 0;
118 static char uptime_str[25];
119 int sec = (int) time;
120
121 day = sec / (24*60*60);
122 sec = sec % (24*60*60);
123 hour = sec / (60*60);
124 sec = sec % (60*60);
125 min = sec / 60;
126 sec = sec % 60;
127
128 if(day){
129 snprintf(uptime_str, 25, "%dd %02d:%02d:%02d", day, hour, min, sec);
130 }else{
131 snprintf(uptime_str, 25, "%02d:%02d:%02d", hour, min, sec);
132 }
133 return uptime_str;
134 }
135
136 void display_headings(){
137 int line;
138
139 move(0,0);
140 printw("Hostname :");
141 move(0,27);
142 printw("Uptime : ");
143 move(0,54);
144 printw("Date : ");
145
146 /* Load */
147 move(2,0);
148 printw("Load 1 :");
149 move(3,0);
150 printw("Load 5 :");
151 move(4,0);
152 printw("Load 15 :");
153
154 /* CPU */
155 move(2,21);
156 printw("CPU Idle :");
157 move(3,21);
158 printw("CPU System:");
159 move(4,21);
160 printw("CPU User :");
161
162 /* Process */
163 move(2, 42);
164 printw("Running :");
165 move(3, 42);
166 printw("Sleeping :");
167 move(4, 42);
168 printw("Stopped :");
169 move(2, 62);
170 printw("Zombie :");
171 move(3, 62);
172 printw("Total :");
173 move(4, 62);
174 printw("No. Users :");
175
176 /* Mem */
177 move(6, 0);
178 printw("Mem Total :");
179 move(7, 0);
180 printw("Mem Used :");
181 move(8, 0);
182 printw("Mem Free :");
183
184 /* Swap */
185 move(6, 21);
186 printw("Swap Total:");
187 move(7, 21);
188 printw("Swap Used :");
189 move(8, 21);
190 printw("Swap Free :");
191
192 /* VM */
193 move(6, 42);
194 printw("Mem Used :");
195 move(7, 42);
196 printw("Swap Used :");
197 move(8, 42);
198 printw("Total Used:");
199
200 /* Paging */
201 move(6, 62);
202 printw("Paging in :");
203 move(7, 62);
204 printw("Paging out:");
205
206 /* Disk IO */
207 move(10,0);
208 printw("Disk Name");
209 move(10,15);
210 printw("Read");
211 move(10,28);
212 printw("Write");
213
214 line = 10;
215 if (stats.network_io_stats != NULL) {
216 /* Network IO */
217 move(line, 42);
218 printw("Network Interface");
219 move(line, 67);
220 printw("rx");
221 move(line, 77);
222 printw("tx");
223 line += 2 + stats.network_io_entries;
224 }
225
226 move(line, 42);
227 printw("Mount Point");
228 move(line, 65);
229 printw("Free");
230 move(line, 75);
231 printw("Used");
232
233 refresh();
234 }
235
236 void display_data(int colors){
237 char cur_time[20];
238 struct tm *tm_time;
239 time_t epoc_time;
240 int counter, line;
241 long long r,w;
242 long long rt, wt;
243 sg_disk_io_stats *disk_io_stat_ptr;
244 sg_network_io_stats *network_stat_ptr;
245 sg_fs_stats *disk_stat_ptr;
246 /* Size before it will start overwriting "uptime" */
247 char hostname[15];
248 char *ptr;
249
250 if (stats.host_info != NULL) {
251 move(0,12);
252 strncpy(hostname, stats.host_info->hostname, (sizeof(hostname) - 1));
253 /* strncpy does not NULL terminate.. If only strlcpy was on all platforms :) */
254 hostname[14] = '\0';
255 ptr=strchr(hostname, '.');
256 /* Some hosts give back a FQDN for hostname. To avoid this, we'll
257 * just blank out everything after the first "."
258 */
259 if (ptr != NULL){
260 *ptr = '\0';
261 }
262 if (colors) {
263 attron(COLOR_PAIR(1));
264 }
265 printw("%s", hostname);
266 move(0,36);
267 printw("%s", hr_uptime(stats.host_info->uptime));
268 epoc_time=time(NULL);
269 tm_time = localtime(&epoc_time);
270 strftime(cur_time, 20, "%Y-%m-%d %T", tm_time);
271 move(0,61);
272 printw("%s", cur_time);
273 if (colors) {
274 attroff(COLOR_PAIR(1));
275 }
276 }
277
278 if (stats.load_stats != NULL) {
279 /* Load */
280 if (colors) {
281 attron(COLOR_PAIR(6));
282 }
283 move(2,12);
284 if (colors && fabs(stats.load_stats->min1 - stats.load_stats->min5) > THRESHOLD_LOAD) {
285 attron(A_BOLD);
286 }
287 printw("%6.2f", stats.load_stats->min1);
288 if (colors) {
289 attroff(A_BOLD);
290 }
291 move(3,12);
292 if (colors && fabs(stats.load_stats->min5 - stats.load_stats->min15) > THRESHOLD_LOAD) {
293 attron(A_BOLD);
294 }
295 printw("%6.2f", stats.load_stats->min5);
296 if (colors) {
297 attroff(A_BOLD);
298 }
299 move(4,12);
300 if (colors && fabs(stats.load_stats->min1 - stats.load_stats->min15) > THRESHOLD_LOAD) {
301 attron(A_BOLD);
302 }
303 printw("%6.2f", stats.load_stats->min15);
304 if (colors) {
305 attroff(A_BOLD);
306 }
307 }
308
309 if (stats.cpu_percents != NULL) {
310 /* CPU */
311 move(2,33);
312 printw("%6.2f%%", stats.cpu_percents->idle);
313 move(3,33);
314 printw("%6.2f%%", (stats.cpu_percents->kernel + stats.cpu_percents->iowait + stats.cpu_percents->swap));
315 move(4,33);
316 if (colors && stats.cpu_percents->user + stats.cpu_percents->nice > THRESHOLD_ALERT_CPU) {
317 attron(A_STANDOUT);
318 attron(A_BOLD);
319 }
320 else if (colors && stats.cpu_percents->user + stats.cpu_percents->nice > THRESHOLD_WARN_CPU) {
321 attron(A_BOLD);
322 }
323 printw("%6.2f%%", (stats.cpu_percents->user + stats.cpu_percents->nice));
324 if(colors) {
325 attroff(A_BOLD);
326 attroff(A_STANDOUT);
327 attron(COLOR_PAIR(6));
328 }
329 }
330
331 if (stats.process_count != NULL) {
332 /* Process */
333 move(2, 54);
334 printw("%5d", stats.process_count->running);
335 move(2,74);
336 if (colors && stats.process_count->zombie > THRESHOLD_WARN_ZMB) {
337 attron(A_STANDOUT);
338 attron(A_BOLD);
339 }
340 printw("%5d", stats.process_count->zombie);
341 if(colors) {
342 attroff(A_STANDOUT);
343 attroff(A_BOLD);
344 }
345 move(3, 54);
346 printw("%5d", stats.process_count->sleeping);
347 move(3, 74);
348 printw("%5d", stats.process_count->total);
349 move(4, 54);
350 printw("%5d", stats.process_count->stopped);
351 }
352 if (stats.user_stats != NULL) {
353 move(4,74);
354 printw("%5d", stats.user_stats->num_entries);
355 }
356
357 if(colors) {
358 attroff(COLOR_PAIR(6));
359 attron(COLOR_PAIR(5));
360 }
361 if (stats.mem_stats != NULL) {
362 /* Mem */
363 move(6, 12);
364 printw("%7s", size_conv(stats.mem_stats->total));
365 move(7, 12);
366 printw("%7s", size_conv(stats.mem_stats->used));
367 move(8, 12);
368 printw("%7s", size_conv(stats.mem_stats->free));
369 }
370
371 if (stats.swap_stats != NULL) {
372 /* Swap */
373 move(6, 32);
374 printw("%8s", size_conv(stats.swap_stats->total));
375 move(7, 32);
376 printw("%8s", size_conv(stats.swap_stats->used));
377 move(8, 32);
378 printw("%8s", size_conv(stats.swap_stats->free));
379 }
380
381 /* VM */
382 if (stats.mem_stats != NULL && stats.mem_stats->total != 0) {
383 float f = 100.00 * (float)(stats.mem_stats->used)/stats.mem_stats->total;
384 if (colors && f > THRESHOLD_ALERT_MEM) {
385 attron(A_STANDOUT);
386 attron(A_BOLD);
387 }
388 else if (colors && f > THRESHOLD_WARN_MEM) {
389 attron(A_BOLD);
390 }
391 move(6, 54);
392 printw("%5.2f%%", f);
393 if (colors) {
394 attroff(A_STANDOUT);
395 attroff(A_BOLD);
396 attron(COLOR_PAIR(5));
397 }
398 }
399 if (stats.swap_stats != NULL && stats.swap_stats->total != 0) {
400 float f = 100.00 * (float)(stats.swap_stats->used)/stats.swap_stats->total;
401 if (colors && f > THRESHOLD_ALERT_SWAP) {
402 attron(A_STANDOUT);
403 attron(A_BOLD);
404 }
405 else if (colors && f > THRESHOLD_WARN_SWAP) {
406 attron(A_BOLD);
407 }
408 move(7, 54);
409 printw("%5.2f%%", f);
410 if (colors) {
411 attroff(A_STANDOUT);
412 attroff(A_BOLD);
413 attron(COLOR_PAIR(5));
414 }
415 }
416 if (stats.mem_stats != NULL && stats.swap_stats != NULL &&
417 stats.mem_stats->total != 0 && stats.swap_stats->total != 0) {
418 move(8, 54);
419 printw("%5.2f%%", (100.00 * (float)(stats.mem_stats->used+stats.swap_stats->used)/(stats.mem_stats->total+stats.swap_stats->total)));
420 }
421
422 if (stats.page_stats != NULL) {
423 /* Paging */
424 move(6, 74);
425 printw("%5d", (stats.page_stats->systime)? (stats.page_stats->pages_pagein / stats.page_stats->systime): stats.page_stats->pages_pagein);
426 move(7, 74);
427 printw("%5d", (stats.page_stats->systime)? (stats.page_stats->pages_pageout / stats.page_stats->systime) : stats.page_stats->pages_pageout);
428 }
429 if (colors) {
430 attroff(COLOR_PAIR(5));
431 }
432
433 line = 11;
434 if (stats.disk_io_stats != NULL) {
435 /* Disk IO */
436 disk_io_stat_ptr = stats.disk_io_stats;
437 r=0;
438 w=0;
439 for(counter=0;counter<stats.disk_io_entries;counter++){
440 char name[12];
441 strncpy(name, disk_io_stat_ptr->disk_name, sizeof(name));
442 name[sizeof(name)-1] = '\0'; /* strncpy doesn't terminate longer strings */
443 move(line, 0);
444 printw("%s", name);
445 move(line, 12);
446 rt = (disk_io_stat_ptr->systime)? (disk_io_stat_ptr->read_bytes/disk_io_stat_ptr->systime): disk_io_stat_ptr->read_bytes;
447 if(colors) {
448 attron(COLOR_PAIR(4));
449 }
450 printw("%7s", size_conv(rt));
451 r+=rt;
452 move(line, 26);
453 wt = (disk_io_stat_ptr->systime)? (disk_io_stat_ptr->write_bytes/disk_io_stat_ptr->systime): disk_io_stat_ptr->write_bytes;
454 printw("%7s", size_conv(wt));
455 w+=wt;
456 disk_io_stat_ptr++;
457 line++;
458 if(colors) {
459 attroff(COLOR_PAIR(4));
460 }
461 }
462 line++;
463 move(line, 0);
464 printw("Total");
465 move(line, 12);
466 if(colors) {
467 attron(COLOR_PAIR(4));
468 }
469 printw("%7s", size_conv(r));
470 move(line, 26);
471 printw("%7s", size_conv(w));
472 if(colors) {
473 attroff(COLOR_PAIR(4));
474 }
475 }
476
477 line = 11;
478 if (stats.network_io_stats != NULL) {
479 /* Network */
480 network_stat_ptr = stats.network_io_stats;
481 for(counter=0;counter<stats.network_io_entries;counter++){
482 char name[20];
483 strncpy(name, network_stat_ptr->interface_name, sizeof(name));
484 name[sizeof(name)-1] = '\0'; /* strncpy doesn't terminate longer strings */
485 move(line, 42);
486 printw("%s", name);
487 move(line, 62);
488 rt = (network_stat_ptr->systime)? (network_stat_ptr->rx / network_stat_ptr->systime): network_stat_ptr->rx;
489 if(colors) {
490 attron(COLOR_PAIR(4));
491 }
492 printw("%7s", size_conv(rt));
493 move(line, 72);
494 wt = (network_stat_ptr->systime)? (network_stat_ptr->tx / network_stat_ptr->systime): network_stat_ptr->tx;
495 printw("%7s", size_conv(wt));
496 network_stat_ptr++;
497 line++;
498 if(colors) {
499 attroff(COLOR_PAIR(4));
500 }
501 }
502 line += 2;
503 }
504
505 if (stats.fs_stats != NULL) {
506 /* Disk */
507 disk_stat_ptr = stats.fs_stats;
508 for(counter=0;counter<stats.fs_entries;counter++){
509 char name[20];
510 strncpy(name, disk_stat_ptr->mnt_point, sizeof(name));
511 name[sizeof(name)-1] = '\0'; /* strncpy doesn't terminate longer strings */
512 move(line, 42);
513 printw("%s", name);
514 move(line, 62);
515 if(colors) {
516 attron(COLOR_PAIR(2));
517 }
518 printw("%7s", size_conv(disk_stat_ptr->avail));
519 move(line, 73);
520 if(colors && 100.00 * ((float) disk_stat_ptr->used / (float) (disk_stat_ptr->used + disk_stat_ptr->avail)) > THRESHOLD_ALERT_DISK) {
521 attron(A_STANDOUT);
522 attron(A_BOLD);
523 } else if (colors && 100.00 * ((float) disk_stat_ptr->used / (float) (disk_stat_ptr->used + disk_stat_ptr->avail)) > THRESHOLD_WARN_DISK) {
524 attron(A_BOLD);
525 }
526 printw("%6.2f%%", 100.00 * ((float) disk_stat_ptr->used / (float) (disk_stat_ptr->used + disk_stat_ptr->avail)));
527 disk_stat_ptr++;
528 line++;
529 if(colors) {
530 attroff(COLOR_PAIR(2));
531 attroff(A_STANDOUT);
532 attroff(A_BOLD);
533 }
534 }
535 }
536
537 refresh();
538 }
539
540 void sig_winch_handler(int dummy){
541 sig_winch_flag = 1;
542 signal(SIGWINCH, sig_winch_handler);
543 }
544
545 int get_stats(){
546 stats.cpu_percents = sg_get_cpu_percents();
547 stats.mem_stats = sg_get_mem_stats();
548 stats.swap_stats = sg_get_swap_stats();
549 stats.load_stats = sg_get_load_stats();
550 stats.process_count = sg_get_process_count();
551 stats.page_stats = sg_get_page_stats_diff();
552 stats.network_io_stats = sg_get_network_io_stats_diff(&(stats.network_io_entries));
553 stats.disk_io_stats = sg_get_disk_io_stats_diff(&(stats.disk_io_entries));
554 stats.fs_stats = sg_get_fs_stats(&(stats.fs_entries));
555 stats.host_info = sg_get_host_info();
556 stats.user_stats = sg_get_user_stats();
557
558 return 1;
559 }
560
561 void version_num(char *progname){
562 fprintf(stderr, "%s version %s\n", progname, PACKAGE_VERSION);
563 fprintf(stderr, "\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
564 exit(1);
565 }
566
567 void usage(char *progname){
568 #ifdef COLOR_SUPPORT
569 fprintf(stderr, "Usage: %s [-d delay] [-c] [-v] [-h]\n\n", progname);
570 #else
571 fprintf(stderr, "Usage: %s [-d delay] [-v] [-h]\n\n", progname);
572 #endif
573 fprintf(stderr, " -d Sets the update time in seconds\n");
574 #ifdef COLOR_SUPPORT
575 fprintf(stderr, " -c Enables coloured output\n");
576 #endif
577 fprintf(stderr, " -v Prints version number\n");
578 fprintf(stderr, " -h Displays this help information.\n");
579 fprintf(stderr, "\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
580 exit(1);
581 }
582
583 int main(int argc, char **argv){
584 extern char *optarg;
585 int c;
586 int colouron = 0;
587
588 time_t last_update = 0;
589
590 WINDOW *window;
591
592 extern int errno;
593
594 int delay=2;
595
596 sg_init();
597 if(sg_drop_privileges() != 0){
598 fprintf(stderr, "Failed to drop setuid/setgid privileges\n");
599 return 1;
600 }
601
602 #ifdef COLOR_SUPPORT
603 while ((c = getopt(argc, argv, "d:cvh")) != -1){
604 #else
605 while ((c = getopt(argc, argv, "d:vh")) != -1){
606 #endif
607 switch (c){
608 case 'd':
609 delay = atoi(optarg);
610 if (delay < 1){
611 fprintf(stderr, "Time must be 1 second or greater\n");
612 exit(1);
613 }
614 break;
615 #ifdef COLOR_SUPPORT
616 case 'c':
617 colouron = 1;
618 break;
619 #endif
620 case 'v':
621 version_num(argv[0]);
622 break;
623 case 'h':
624 default:
625 usage(argv[0]);
626 return 1;
627 break;
628 }
629 }
630
631 signal(SIGWINCH, sig_winch_handler);
632 initscr();
633 #ifdef COLOR_SUPPORT
634 /* turn on colour */
635 if (colouron) {
636 if (has_colors()) {
637 start_color();
638 use_default_colors();
639 init_pair(1,COLOR_RED,-1);
640 init_pair(2,COLOR_GREEN,-1);
641 init_pair(3,COLOR_YELLOW,-1);
642 init_pair(4,COLOR_BLUE,-1);
643 init_pair(5,COLOR_MAGENTA,-1);
644 init_pair(6,COLOR_CYAN,-1);
645 } else {
646 fprintf(stderr, "Colour support disabled: your terminal does not support colour.");
647 colouron = 0;
648 }
649 }
650 #endif
651 nonl();
652 curs_set(0);
653 cbreak();
654 noecho();
655 timeout(delay * 1000);
656 window=newwin(0, 0, 0, 0);
657 clear();
658
659 if(!get_stats()){
660 fprintf(stderr, "Failed to get all the stats. Please check correct permissions\n");
661 endwin();
662 return 1;
663 }
664
665 display_headings();
666
667 for(;;){
668 time_t now;
669 int ch = getch();
670
671 if (ch == 'q'){
672 break;
673 }
674
675 /* To keep the numbers slightly accurate we do not want them
676 * updating more frequently than once a second.
677 */
678 now = time(NULL);
679 if ((now - last_update) >= 1) {
680 get_stats();
681 }
682 last_update = now;
683
684 if(sig_winch_flag) {
685 clear();
686 display_headings();
687 sig_winch_flag = 0;
688 }
689
690 display_data(colouron);
691 }
692
693 endwin();
694 return 0;
695 }