main.c revision 1.40
1/* $Id: main.c,v 1.40 2008/06/13 10:06:14 deraadt 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, now; 90 order_type *ordering; 91 int start = dispstart + 1, end = dispstart + maxprint; 92 extern int ucount(); 93 char tbuf[26]; 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 113 time(&now); 114 strlcpy(tbuf, ctime(&now), sizeof tbuf); 115 tbprintf(" %d users", ucount()); 116 tbprintf(" Load %.2f %.2f %.2f", avenrun[0], avenrun[1], avenrun[2]); 117 if (num_disp && (start > 1 || end != num_disp)) 118 tbprintf(" (%u-%u of %u)", start, end, num_disp); 119 120 if (paused) 121 tbprintf(" PAUSED"); 122 123 if (rawmode) 124 printf("\n\n%s\n", tmp_buf); 125 else 126 mvprintw(0, 0, "%s", tmp_buf); 127 128 mvprintw(0, TIMEPOS, "%s", tbuf); 129 130 131 return (1); 132} 133 134/* compatibility functions, rearrange later */ 135void 136error(const char *fmt, ...) 137{ 138 va_list ap; 139 char buf[MAX_LINE_BUF]; 140 141 va_start(ap, fmt); 142 vsnprintf(buf, sizeof buf, fmt, ap); 143 va_end(ap); 144 145 message_set(buf); 146} 147 148void 149nlisterr(struct nlist namelist[]) 150{ 151 int i, n; 152 153 n = 0; 154 clear(); 155 mvprintw(2, 10, "systat: nlist: can't find following symbols:"); 156 for (i = 0; 157 namelist[i].n_name != NULL && *namelist[i].n_name != '\0'; i++) 158 if (namelist[i].n_value == 0) 159 mvprintw(2 + ++n, 10, "%s", namelist[i].n_name); 160 move(CMDLINE, 0); 161 clrtoeol(); 162 refresh(); 163 endwin(); 164 exit(1); 165} 166 167void 168die(void) 169{ 170 if (!rawmode) 171 endwin(); 172 exit(0); 173} 174 175 176int 177prefix(char *s1, char *s2) 178{ 179 180 while (*s1 == *s2) { 181 if (*s1 == '\0') 182 return (1); 183 s1++, s2++; 184 } 185 return (*s1 == '\0'); 186} 187 188/* calculate number of users on the system */ 189int 190ucount(void) 191{ 192 int nusers = 0; 193 struct utmp utmp; 194 195 if (ut < 0) 196 return (0); 197 lseek(ut, (off_t)0, SEEK_SET); 198 while (read(ut, &utmp, sizeof(utmp))) 199 if (utmp.ut_name[0] != '\0') 200 nusers++; 201 202 return (nusers); 203} 204 205/* main program functions */ 206 207void 208usage() 209{ 210 extern char *__progname; 211 fprintf(stderr, "usage: %s [-abhir] [-c cache] [-d cnt]", __progname); 212 fprintf(stderr, " [-o field] [-s time] [-w width] [view] [num]\n"); 213 exit(1); 214} 215 216 217void 218add_view_tb(field_view *v) 219{ 220 if (curr_view == v) 221 tbprintf("[%s] ", v->name); 222 else 223 tbprintf("%s ", v->name); 224} 225 226void 227show_help(void) 228{ 229 int line = 0; 230 231 if (rawmode) 232 return; 233 234 tb_start(); 235 foreach_view(add_view_tb); 236 tb_end(); 237 message_set(tmp_buf); 238 239#if 0 240 erase(); 241 mvprintw(line, 2, "Systat Help"); 242 line += 2; 243 mvprintw(line, 5, " h - Help (this page)"); 244 mvprintw(line++, 40, " l - set number of Lines"); 245 mvprintw(line, 5, " p - Pause display"); 246 mvprintw(line++, 40, " s - Set update interval"); 247 mvprintw(line, 5, " v - next View"); 248 mvprintw(line++, 40, " q - Quit"); 249 line++; 250 mvprintw(line++, 5, "0-7 - select view directly"); 251 mvprintw(line++, 5, "SPC - update immediately"); 252 mvprintw(line++, 5, "^L - refresh display"); 253 line++; 254 mvprintw(line++, 5, "cursor keys - scroll display"); 255 line++; 256 mvprintw(line++, 3, "Netstat specific keys::"); 257 mvprintw(line, 5, " t - toggle TCP display"); 258 mvprintw(line++, 40, " u - toggle UDP display"); 259 mvprintw(line++, 5, " n - toggle Name resolution"); 260 line++; 261 mvprintw(line++, 3, "Ifstat specific keys::"); 262 mvprintw(line, 5, " r - initialize RUN mode"); 263 mvprintw(line++, 40, " b - set BOOT mode"); 264 mvprintw(line, 5, " t - set TIME mode (default)"); 265 line++; 266 line++; 267 mvprintw(line++, 3, "VMstat specific keys::"); 268 mvprintw(line, 5, " r - initialize RUN mode"); 269 mvprintw(line++, 40, " b - set BOOT mode"); 270 mvprintw(line, 5, " t - set TIME mode (default)"); 271 mvprintw(line++, 40, " z - zero in RUN mode"); 272 line++; 273 mvprintw(line++, 6, "press any key to continue ..."); 274 275 while (getch() == ERR) { 276 if (gotsig_close) 277 break; 278 } 279#endif 280} 281 282void 283cmd_compat(void) 284{ 285 char *s; 286 287 if (strcasecmp(cmdbuf, "help") == 0) { 288 show_help(); 289 need_update = 1; 290 return; 291 } 292 if (strcasecmp(cmdbuf, "quit") == 0) { 293 gotsig_close = 1; 294 return; 295 } 296 297 for (s = cmdbuf; *s && strchr("0123456789+-.eE", *s) != NULL; s++) 298 ; 299 if (*s) { 300 if (set_view(cmdbuf)) 301 error("Invalid/ambigious view: %s", cmdbuf); 302 } else 303 cmd_delay(); 304} 305 306void 307cmd_delay(void) 308{ 309 double del; 310 del = atof(cmdbuf); 311 312 if (del > 0) { 313 udelay = (useconds_t)(del * 1000000); 314 gotsig_alarm = 1; 315 naptime = del; 316 } 317} 318 319void 320cmd_count(void) 321{ 322 int ms; 323 ms = atoi(cmdbuf); 324 325 if (ms <= 0 || ms > lines - HEADER_LINES) 326 maxprint = lines - HEADER_LINES; 327 else 328 maxprint = ms; 329} 330 331 332int 333keyboard_callback(int ch) 334{ 335 switch (ch) { 336 case '?': 337 /* FALLTHROUGH */ 338 case 'h': 339 show_help(); 340 need_update = 1; 341 break; 342 case 'l': 343 command_set(&cm_count, NULL); 344 break; 345 case 's': 346 command_set(&cm_delay, NULL); 347 break; 348 case ':': 349 command_set(&cm_compat, NULL); 350 break; 351 default: 352 return 0; 353 }; 354 355 return 1; 356} 357 358void 359initialize(void) 360{ 361 engine_initialize(); 362 363 initvmstat(); 364 initpigs(); 365 initifstat(); 366 initiostat(); 367 initsensors(); 368 initmembufs(); 369 initnetstat(); 370 initswap(); 371 initpftop(); 372 initpf(); 373} 374 375void 376gethz(void) 377{ 378 struct clockinfo cinf; 379 size_t size = sizeof(cinf); 380 int mib[2]; 381 382 mib[0] = CTL_KERN; 383 mib[1] = KERN_CLOCKRATE; 384 if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1) 385 return; 386 stathz = cinf.stathz; 387 hz = cinf.hz; 388} 389 390int 391main(int argc, char *argv[]) 392{ 393 char errbuf[_POSIX2_LINE_MAX]; 394 extern char *optarg; 395 extern int optind; 396 double delay = 5; 397 398 char *viewstr = NULL; 399 400 gid_t gid; 401 int countmax = 0; 402 int maxlines = 0; 403 404 int ch; 405 406 ut = open(_PATH_UTMP, O_RDONLY); 407 if (ut < 0) { 408 warn("No utmp"); 409 } 410 411 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); 412 if (kd == NULL) 413 warnx("kvm_openfiles: %s", errbuf); 414 415 gid = getgid(); 416 if (setresgid(gid, gid, gid) == -1) 417 err(1, "setresgid"); 418 419 while ((ch = getopt(argc, argv, "abd:hins:S:w:")) != -1) { 420 switch (ch) { 421 case 'a': 422 maxlines = -1; 423 break; 424 case 'b': 425 rawmode = 1; 426 interactive = 0; 427 break; 428 case 'd': 429 countmax = atoi(optarg); 430 if (countmax < 0) 431 countmax = 0; 432 break; 433 case 'i': 434 interactive = 1; 435 break; 436 case 'n': 437 nflag = 1; 438 break; 439 case 's': 440 delay = atof(optarg); 441 if (delay <= 0) 442 delay = 5; 443 break; 444 case 'S': 445 dispstart = atoi(optarg); 446 if (dispstart < 0) 447 dispstart = 0; 448 break; 449 case 'w': 450 rawwidth = atoi(optarg); 451 if (rawwidth < 1) 452 rawwidth = DEFAULT_WIDTH; 453 if (rawwidth >= MAX_LINE_BUF) 454 rawwidth = MAX_LINE_BUF - 1; 455 break; 456 case 'h': 457 /* FALLTHROUGH */ 458 default: 459 usage(); 460 /* NOTREACHED */ 461 } 462 } 463 464 argc -= optind; 465 argv += optind; 466 467 if (argc == 1) { 468 double del = atof(argv[0]); 469 if (del == 0) 470 viewstr = argv[0]; 471 else 472 delay = del; 473 } else if (argc == 2) { 474 viewstr = argv[0]; 475 delay = atof(argv[1]); 476 } 477 478 udelay = (useconds_t)(delay * 1000000.0); 479 if (udelay < 1) 480 udelay = 1; 481 482 naptime = (double)udelay / 1000000.0; 483 484 gethostname(hostname, sizeof (hostname)); 485 gethz(); 486 487 initialize(); 488 489 set_order(NULL); 490 if (viewstr && set_view(viewstr)) { 491 fprintf(stderr, "Unknown/ambigious view name: %s\n", viewstr); 492 return 1; 493 } 494 495 if (!isatty(STDOUT_FILENO)) { 496 rawmode = 1; 497 interactive = 0; 498 } 499 500 setup_term(maxlines); 501 502 if (rawmode && countmax == 0) 503 countmax = 1; 504 505 gotsig_alarm = 1; 506 507 engine_loop(countmax); 508 509 return 0; 510} 511