main.c revision 1.38
1/* $Id: main.c,v 1.38 2008/06/12 22:26:01 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 error("delay: %g", del); 315 if (del > 0) { 316 udelay = (useconds_t)(del * 1000000); 317 gotsig_alarm = 1; 318 } 319} 320 321void 322cmd_count(void) 323{ 324 int ms; 325 ms = atoi(cmdbuf); 326 327 if (ms <= 0 || ms > lines - HEADER_LINES) 328 maxprint = lines - HEADER_LINES; 329 else 330 maxprint = ms; 331} 332 333 334int 335keyboard_callback(int ch) 336{ 337 switch (ch) { 338 case '?': 339 /* FALLTHROUGH */ 340 case 'h': 341 show_help(); 342 need_update = 1; 343 break; 344 case 'l': 345 command_set(&cm_count, NULL); 346 break; 347 case 's': 348 command_set(&cm_delay, NULL); 349 break; 350 case ':': 351 command_set(&cm_compat, NULL); 352 break; 353 default: 354 return 0; 355 }; 356 357 return 1; 358} 359 360void 361initialize(void) 362{ 363 engine_initialize(); 364 365 initvmstat(); 366 initpigs(); 367 initifstat(); 368 initiostat(); 369 initsensors(); 370 initmembufs(); 371 initnetstat(); 372 initswap(); 373 initpftop(); 374 initpf(); 375} 376 377void 378gethz(void) 379{ 380 struct clockinfo cinf; 381 size_t size = sizeof(cinf); 382 int mib[2]; 383 384 mib[0] = CTL_KERN; 385 mib[1] = KERN_CLOCKRATE; 386 if (sysctl(mib, 2, &cinf, &size, NULL, 0) == -1) 387 return; 388 stathz = cinf.stathz; 389 hz = cinf.hz; 390} 391 392int 393main(int argc, char *argv[]) 394{ 395 char errbuf[_POSIX2_LINE_MAX]; 396 extern char *optarg; 397 extern int optind; 398 double delay = 5; 399 400 char *viewstr = NULL; 401 402 gid_t gid; 403 int countmax = 0; 404 int maxlines = 0; 405 406 int ch; 407 408 ut = open(_PATH_UTMP, O_RDONLY); 409 if (ut < 0) { 410 warn("No utmp"); 411 } 412 413 kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); 414 if (kd == NULL) 415 warnx("kvm_openfiles: %s", errbuf); 416 417 gid = getgid(); 418 if (setresgid(gid, gid, gid) == -1) 419 err(1, "setresgid"); 420 421 while ((ch = getopt(argc, argv, "abd:hins:S:w:")) != -1) { 422 switch (ch) { 423 case 'a': 424 maxlines = -1; 425 break; 426 case 'b': 427 rawmode = 1; 428 interactive = 0; 429 break; 430 case 'd': 431 countmax = atoi(optarg); 432 if (countmax < 0) 433 countmax = 0; 434 break; 435 case 'i': 436 interactive = 1; 437 break; 438 case 'n': 439 nflag = 1; 440 break; 441 case 's': 442 delay = atof(optarg); 443 if (delay < 0) 444 delay = 5; 445 break; 446 case 'S': 447 dispstart = atoi(optarg); 448 if (dispstart < 0) 449 dispstart = 0; 450 break; 451 case 'w': 452 rawwidth = atoi(optarg); 453 if (rawwidth < 1) 454 rawwidth = DEFAULT_WIDTH; 455 if (rawwidth >= MAX_LINE_BUF) 456 rawwidth = MAX_LINE_BUF - 1; 457 break; 458 case 'h': 459 /* FALLTHROUGH */ 460 default: 461 usage(); 462 /* NOTREACHED */ 463 } 464 } 465 466 argc -= optind; 467 argv += optind; 468 469 if (argc == 1) { 470 double del = atof(argv[0]); 471 if (del == 0) 472 viewstr = argv[0]; 473 else 474 delay = del; 475 } else if (argc == 2) { 476 viewstr = argv[0]; 477 delay = atof(argv[1]); 478 } 479 480 udelay = (useconds_t)(delay * 1000000.0); 481 if (udelay < 1) 482 udelay = 1; 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