main.c revision 1.39
1/* $Id: main.c,v 1.39 2008/06/13 01:24:55 canacar Exp $ */ 2/* 3 * Copyright (c) 2001, 2007 Can Erkin Acar 4 * Copyright (c) 2001 Daniel Hartmeier 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 */ 32 33#include <sys/types.h> 34#include <sys/param.h> 35#include <sys/sysctl.h> 36 37 38#include <ctype.h> 39#include <curses.h> 40#include <err.h> 41#include <errno.h> 42#include <fcntl.h> 43#include <limits.h> 44#include <netdb.h> 45#include <signal.h> 46#include <stdio.h> 47#include <stdlib.h> 48#include <string.h> 49#include <stdarg.h> 50#include <unistd.h> 51#include <utmp.h> 52 53#include "engine.h" 54#include "systat.h" 55 56double dellave; 57 58kvm_t *kd; 59char *nlistf = NULL; 60char *memf = NULL; 61double avenrun[3]; 62double naptime = 5.0; 63int verbose = 1; /* to report kvm read errs */ 64int nflag = 1; 65int ut, hz, stathz; 66char hostname[MAXHOSTNAMELEN]; 67WINDOW *wnd; 68int CMDLINE; 69 70#define TIMEPOS 55 71 72/* command prompt */ 73 74void cmd_delay(void); 75void cmd_count(void); 76void cmd_compat(void); 77 78struct command cm_compat = {"Command", cmd_compat}; 79struct command cm_delay = {"Seconds to delay", cmd_delay}; 80struct command cm_count = {"Number of lines to display", cmd_count}; 81 82 83/* display functions */ 84 85int 86print_header(void) 87{ 88 struct tm *tp; 89 time_t t; 90 order_type *ordering; 91 92 int start = dispstart + 1; 93 int end = dispstart + maxprint; 94 95 if (end > num_disp) 96 end = num_disp; 97 98 tb_start(); 99 100#if 0 101 if (curr_mgr && curr_mgr->sort_fn != NULL) { 102 ordering = curr_mgr->order_curr; 103 if (ordering != NULL) { 104 tbprintf(", Order: %s", ordering->name); 105 if (sortdir < 0 && ordering->func != NULL) 106 tbprintf(" (rev)"); 107 } 108 } 109#endif 110 111 getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); 112 extern int ucount(); 113 char tbuf[26]; 114 time_t now; 115 116 time(&now); 117 strlcpy(tbuf, ctime(&now), sizeof tbuf); 118 tbprintf(" %d users", ucount()); 119 tbprintf(" Load %.2f %.2f %.2f", avenrun[0], avenrun[1], avenrun[2]); 120 if (num_disp && (start > 1 || end != num_disp)) 121 tbprintf(" (%u-%u of %u)", start, end, num_disp); 122 123 if (paused) 124 tbprintf(" PAUSED"); 125 126 if (rawmode) 127 printf("\n\n%s\n", tmp_buf); 128 else 129 mvprintw(0, 0, "%s", tmp_buf); 130 131 mvprintw(0, TIMEPOS, "%s", tbuf); 132 133 134 return (1); 135} 136 137/* compatibility functions, rearrange later */ 138void 139error(const char *fmt, ...) 140{ 141 va_list ap; 142 char buf[MAX_LINE_BUF]; 143 144 va_start(ap, fmt); 145 vsnprintf(buf, sizeof buf, fmt, ap); 146 va_end(ap); 147 148 message_set(buf); 149} 150 151void 152nlisterr(struct nlist namelist[]) 153{ 154 int i, n; 155 156 n = 0; 157 clear(); 158 mvprintw(2, 10, "systat: nlist: can't find following symbols:"); 159 for (i = 0; 160 namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++) 161 if (namelist[i].n_value == 0) 162 mvprintw(2 + ++n, 10, "%s", namelist[i].n_name); 163 move(CMDLINE, 0); 164 clrtoeol(); 165 refresh(); 166 endwin(); 167 exit(1); 168} 169 170void 171die(void) 172{ 173 if (!rawmode) 174 endwin(); 175 exit(0); 176} 177 178 179int 180prefix(char *s1, char *s2) 181{ 182 183 while (*s1 == *s2) { 184 if (*s1 == '\0') 185 return (1); 186 s1++, s2++; 187 } 188 return (*s1 == '\0'); 189} 190 191/* calculate number of users on the system */ 192int 193ucount(void) 194{ 195 int nusers = 0; 196 struct utmp utmp; 197 198 if (ut < 0) 199 return (0); 200 lseek(ut, (off_t)0, SEEK_SET); 201 while (read(ut, &utmp, sizeof(utmp))) 202 if (utmp.ut_name[0] != '\0') 203 nusers++; 204 205 return (nusers); 206} 207 208/* main program functions */ 209 210void 211usage() 212{ 213 extern char *__progname; 214 fprintf(stderr, "usage: %s [-abhir] [-c cache] [-d cnt]", __progname); 215 fprintf(stderr, " [-o field] [-s time] [-w width] [view] [num]\n"); 216 exit(1); 217} 218 219 220void 221add_view_tb(field_view *v) 222{ 223 if (curr_view == v) 224 tbprintf("[%s] ", v->name); 225 else 226 tbprintf("%s ", v->name); 227} 228 229void 230show_help(void) 231{ 232 int line = 0; 233 234 if (rawmode) 235 return; 236 237 tb_start(); 238 foreach_view(add_view_tb); 239 tb_end(); 240 message_set(tmp_buf); 241 242#if 0 243 erase(); 244 mvprintw(line, 2, "Systat Help"); 245 line += 2; 246 mvprintw(line, 5, " h - Help (this page)"); 247 mvprintw(line++, 40, " l - set number of Lines"); 248 mvprintw(line, 5, " p - Pause display"); 249 mvprintw(line++, 40, " s - Set update interval"); 250 mvprintw(line, 5, " v - next View"); 251 mvprintw(line++, 40, " q - Quit"); 252 line++; 253 mvprintw(line++, 5, "0-7 - select view directly"); 254 mvprintw(line++, 5, "SPC - update immediately"); 255 mvprintw(line++, 5, "^L - refresh display"); 256 line++; 257 mvprintw(line++, 5, "cursor keys - scroll display"); 258 line++; 259 mvprintw(line++, 3, "Netstat specific keys::"); 260 mvprintw(line, 5, " t - toggle TCP display"); 261 mvprintw(line++, 40, " u - toggle UDP display"); 262 mvprintw(line++, 5, " n - toggle Name resolution"); 263 line++; 264 mvprintw(line++, 3, "Ifstat specific keys::"); 265 mvprintw(line, 5, " r - initialize RUN mode"); 266 mvprintw(line++, 40, " b - set BOOT mode"); 267 mvprintw(line, 5, " t - set TIME mode (default)"); 268 line++; 269 line++; 270 mvprintw(line++, 3, "VMstat specific keys::"); 271 mvprintw(line, 5, " r - initialize RUN mode"); 272 mvprintw(line++, 40, " b - set BOOT mode"); 273 mvprintw(line, 5, " t - set TIME mode (default)"); 274 mvprintw(line++, 40, " z - zero in RUN mode"); 275 line++; 276 mvprintw(line++, 6, "press any key to continue ..."); 277 278 while (getch() == ERR) { 279 if (gotsig_close) 280 break; 281 } 282#endif 283} 284 285void 286cmd_compat(void) 287{ 288 char *s; 289 290 if (strcasecmp(cmdbuf, "help") == 0) { 291 show_help(); 292 need_update = 1; 293 return; 294 } 295 if (strcasecmp(cmdbuf, "quit") == 0) { 296 gotsig_close = 1; 297 return; 298 } 299 300 for (s = cmdbuf; *s && strchr("0123456789+-.eE", *s) != NULL; s++) 301 ; 302 if (*s) { 303 if (set_view(cmdbuf)) 304 error("Invalid/ambigious view: %s", cmdbuf); 305 } else 306 cmd_delay(); 307} 308 309void 310cmd_delay(void) 311{ 312 double del; 313 del = atof(cmdbuf); 314 315 if (del > 0) { 316 udelay = (useconds_t)(del * 1000000); 317 gotsig_alarm = 1; 318 naptime = del; 319 } 320} 321 322void 323cmd_count(void) 324{ 325 int ms; 326 ms = atoi(cmdbuf); 327 328 if (ms <= 0 || ms > lines - HEADER_LINES) 329 maxprint = lines - HEADER_LINES; 330 else 331 maxprint = ms; 332} 333 334 335int 336keyboard_callback(int ch) 337{ 338 switch (ch) { 339 case '?': 340 /* FALLTHROUGH */ 341 case 'h': 342 show_help(); 343 need_update = 1; 344 break; 345 case 'l': 346 command_set(&cm_count, NULL); 347 break; 348 case 's': 349 command_set(&cm_delay, NULL); 350 break; 351 case ':': 352 command_set(&cm_compat, NULL); 353 break; 354 default: 355 return 0; 356 }; 357 358 return 1; 359} 360 361void 362initialize(void) 363{ 364 engine_initialize(); 365 366 initvmstat(); 367 initpigs(); 368 initifstat(); 369 initiostat(); 370 initsensors(); 371 initmembufs(); 372 initnetstat(); 373 initswap(); 374 initpftop(); 375 initpf(); 376} 377 378void 379gethz(void) 380{ 381 struct clockinfo cinf; 382 size_t size = sizeof(cinf); 383 int mib[2]; 384 385 mib[0] = CTL_KERN; 386 mib[1] = KERN_CLOCKRATE; 387 if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1) 388 return; 389 stathz = cinf.stathz; 390 hz = cinf.hz; 391} 392 393int 394main(int argc, char *argv[]) 395{ 396 char errbuf[_POSIX2_LINE_MAX]; 397 extern char *optarg; 398 extern int optind; 399 double delay = 5; 400 401 char *viewstr = NULL; 402 403 gid_t gid; 404 int countmax = 0; 405 int maxlines = 0; 406 407 int ch; 408 409 ut = open(_PATH_UTMP, O_RDONLY); 410 if (ut < 0) { 411 warn("No utmp"); 412 } 413 414 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); 415 if (kd == NULL) 416 warnx("kvm_openfiles: %s", errbuf); 417 418 gid = getgid(); 419 if (setresgid(gid, gid, gid) == -1) 420 err(1, "setresgid"); 421 422 while ((ch = getopt(argc, argv, "abd:hins:S:w:")) != -1) { 423 switch (ch) { 424 case 'a': 425 maxlines = -1; 426 break; 427 case 'b': 428 rawmode = 1; 429 interactive = 0; 430 break; 431 case 'd': 432 countmax = atoi(optarg); 433 if (countmax < 0) 434 countmax = 0; 435 break; 436 case 'i': 437 interactive = 1; 438 break; 439 case 'n': 440 nflag = 1; 441 break; 442 case 's': 443 delay = atof(optarg); 444 if (delay <= 0) 445 delay = 5; 446 break; 447 case 'S': 448 dispstart = atoi(optarg); 449 if (dispstart < 0) 450 dispstart = 0; 451 break; 452 case 'w': 453 rawwidth = atoi(optarg); 454 if (rawwidth < 1) 455 rawwidth = DEFAULT_WIDTH; 456 if (rawwidth >= MAX_LINE_BUF) 457 rawwidth = MAX_LINE_BUF - 1; 458 break; 459 case 'h': 460 /* FALLTHROUGH */ 461 default: 462 usage(); 463 /* NOTREACHED */ 464 } 465 } 466 467 argc -= optind; 468 argv += optind; 469 470 if (argc == 1) { 471 double del = atof(argv[0]); 472 if (del == 0) 473 viewstr = argv[0]; 474 else 475 delay = del; 476 } else if (argc == 2) { 477 viewstr = argv[0]; 478 delay = atof(argv[1]); 479 } 480 481 udelay = (useconds_t)(delay * 1000000.0); 482 if (udelay < 1) 483 udelay = 1; 484 485 naptime = (double)udelay / 1000000.0; 486 487 gethostname(hostname, sizeof (hostname)); 488 gethz(); 489 490 initialize(); 491 492 set_order(NULL); 493 if (viewstr && set_view(viewstr)) { 494 fprintf(stderr, "Unknown/ambigious view name: %s\n", viewstr); 495 return 1; 496 } 497 498 if (!isatty(STDOUT_FILENO)) { 499 rawmode = 1; 500 interactive = 0; 501 } 502 503 setup_term(maxlines); 504 505 if (rawmode && countmax == 0) 506 countmax = 1; 507 508 gotsig_alarm = 1; 509 510 engine_loop(countmax); 511 512 return 0; 513} 514