ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/saidar/saidar.c
Revision: 1.37
Committed: Fri Dec 1 00:38:39 2006 UTC (17 years, 11 months ago) by tdb
Content type: text/plain
Branch: MAIN
Changes since 1.36: +7 -2 lines
Log Message:
Standout doesn't work on all displays, so use bold too.

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