956 lines
21 KiB
C
956 lines
21 KiB
C
/*
|
|
* File system buffer cache display for Irix.
|
|
*
|
|
* Converted from top(1) users/processes display for Unix
|
|
* Version 3
|
|
*
|
|
* This program may be freely redistributed,
|
|
* but this entire comment MUST remain intact.
|
|
*
|
|
* Copyright (c) 1984, 1989, William LeFebvre, Rice University
|
|
* Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
|
|
*/
|
|
|
|
/*
|
|
* This file contains "main" and other high-level routines.
|
|
*/
|
|
|
|
/*
|
|
* The following preprocessor variables, when defined, are used to
|
|
* distinguish between different Unix implementations:
|
|
*
|
|
* SIGHOLD - use SVR4 sighold function when defined
|
|
* SIGRELSE - use SVR4 sigrelse function when defined
|
|
*/
|
|
|
|
#include "os.h"
|
|
#include <signal.h>
|
|
#include <setjmp.h>
|
|
#include <ctype.h>
|
|
#include <sys/time.h>
|
|
|
|
/* includes specific to bufview */
|
|
#include "display.h" /* interface to display package */
|
|
#include "screen.h" /* interface to screen package */
|
|
#include "bv.h"
|
|
#include "boolean.h"
|
|
#include "machine.h"
|
|
#include "utils.h"
|
|
|
|
/* Size of the stdio buffer given to stdout */
|
|
#define Buffersize 2048
|
|
|
|
/* The buffer that stdio will use */
|
|
char stdoutbuf[Buffersize];
|
|
|
|
/* build Signal masks */
|
|
#define Smask(s) (1 << ((s) - 1))
|
|
|
|
/* for system errors */
|
|
extern int errno;
|
|
|
|
/* for getopt: */
|
|
extern int optind;
|
|
extern char *optarg;
|
|
|
|
/* imported from screen.c */
|
|
extern int overstrike;
|
|
|
|
/* signal handling routines */
|
|
sigret_t leave();
|
|
sigret_t onalrm();
|
|
sigret_t tstop();
|
|
#ifdef SIGWINCH
|
|
sigret_t mywinch(); /* Ariel: curses name space pollution: winch->mywinch */
|
|
#endif
|
|
|
|
/* internal routines */
|
|
void quit();
|
|
void show_help(void);
|
|
|
|
/* values which need to be accessed by signal handlers */
|
|
static int max_topn; /* maximum displayable processes */
|
|
|
|
/* miscellaneous things */
|
|
char *myname = "bufview";
|
|
jmp_buf jmp_int;
|
|
struct system_info system_info;
|
|
struct buffer_select bst;
|
|
|
|
void
|
|
usage()
|
|
{
|
|
fprintf(stderr,
|
|
"Usage: %s [-SDb] [-d x] [-s x] [-o sort-specifier] [-n number] [-f buffer-flags]\n",
|
|
myname);
|
|
fprintf(stderr,
|
|
" -S -- don't display System buffers\n");
|
|
fprintf(stderr,
|
|
" -D -- don't display Data buffers\n");
|
|
fprintf(stderr,
|
|
" -b -- use batch (non-interactive) mode\n");
|
|
fprintf(stderr,
|
|
" -s x -- update the display every x seconds\n");
|
|
fprintf(stderr,
|
|
" -d x -- update the display only x times then exit\n");
|
|
fprintf(stderr,
|
|
" -n x -- display only x buffers\n");
|
|
fprintf(stderr,
|
|
" -o o -- use specified sort order to display buffers\n");
|
|
fprintf(stderr,
|
|
" m -- display objects with most buffers\n");
|
|
fprintf(stderr,
|
|
" l -- display objects with least buffers\n");
|
|
fprintf(stderr,
|
|
" b -- display biggest buffers first\n");
|
|
fprintf(stderr,
|
|
" s -- display smallest buffers first\n");
|
|
fprintf(stderr,
|
|
" n -- display newest buffers first\n");
|
|
fprintf(stderr,
|
|
" o -- display oldest buffers first\n");
|
|
fprintf(stderr,
|
|
" -f flag -- display only buffers with specified flags\n");
|
|
fprintf(stderr,
|
|
" dw -- delayed write buffer (B_DELWRI)\n");
|
|
fprintf(stderr,
|
|
" bsy -- buffer in use (B_BUSY)\n");
|
|
fprintf(stderr,
|
|
" swp -- buffer swapping user pages (B_SWAP)\n");
|
|
fprintf(stderr,
|
|
" da -- backing store not allocated (B_DELALLOC)\n");
|
|
fprintf(stderr,
|
|
" as -- asynchronous read/write (B_ASYNC)\n");
|
|
fprintf(stderr,
|
|
" nc -- uncommitted NFS data (B_NFS_UNSTABLE)\n");
|
|
fprintf(stderr,
|
|
" na -- asynchronous NFS read/write (B_NFS_ASYNC)\n");
|
|
fprintf(stderr,
|
|
" inact -- buffer removed from buffer pools (B_INACTIVE)\n");
|
|
fprintf(stderr,
|
|
" -- system buffer subtype flags\n");
|
|
fprintf(stderr,
|
|
" ino -- inodes (B_FS_INO)\n");
|
|
fprintf(stderr,
|
|
" inomap -- inode map (B_FS_INOMAP)\n");
|
|
fprintf(stderr,
|
|
" dir_bt -- directory btree (B_FS_DIR_BTREE)\n");
|
|
fprintf(stderr,
|
|
" map -- map (B_FS_MAP)\n");
|
|
fprintf(stderr,
|
|
" attr_bt -- attribute btree (B_FS_ATTR_BTREE)\n");
|
|
fprintf(stderr,
|
|
" agi -- agi (B_FS_AGI)\n");
|
|
fprintf(stderr,
|
|
" agf -- agf (B_FS_AGF)\n");
|
|
fprintf(stderr,
|
|
" agfl -- agfl (B_FS_AGFL)\n");
|
|
fprintf(stderr,
|
|
" dquot -- quota buffer (B_FS_DQUOT)\n");
|
|
}
|
|
|
|
/*
|
|
* routines that don't return int and are not declared in standard headers
|
|
*/
|
|
|
|
void get_buffer_info(struct system_info *);
|
|
|
|
/* display routines that need to be predeclared */
|
|
int i_sysbufs();
|
|
int u_sysbufs();
|
|
int i_databufs();
|
|
int u_databufs();
|
|
int i_emptybufs();
|
|
int u_emptybufs();
|
|
int i_getbufs();
|
|
int u_getbufs();
|
|
int i_order();
|
|
int u_order();
|
|
int i_message();
|
|
int u_message();
|
|
int i_header();
|
|
int u_header();
|
|
int i_buffers();
|
|
int u_buffers();
|
|
|
|
/* pointers to display routines */
|
|
int (*d_sysbufs)() = i_sysbufs;
|
|
int (*d_databufs)() = i_databufs;
|
|
int (*d_emptybufs)() = i_emptybufs;
|
|
int (*d_getbufs)() = i_getbufs;
|
|
int (*d_order)() = i_order;
|
|
int (*d_message)() = i_message;
|
|
int (*d_header)() = i_header;
|
|
int (*d_buffers)() = i_buffers;
|
|
|
|
|
|
main(int argc, char *argv[])
|
|
{
|
|
int i;
|
|
int active_users;
|
|
int change;
|
|
|
|
static char tempbuf[50];
|
|
int old_sigmask; /* only used for BSD-style signals */
|
|
int topn = Default_TOPN;
|
|
int delay = Default_DELAY;
|
|
int displays = 0; /* indicates unspecified */
|
|
time_t curr_time;
|
|
char *env_bufview;
|
|
char **preset_argv;
|
|
int preset_argc = 0;
|
|
char **av;
|
|
int ac;
|
|
char interactive = Maybe;
|
|
char warnings = 0;
|
|
#if Default_TOPN == Infinity
|
|
char topn_specified = No;
|
|
#endif
|
|
char ch;
|
|
char *iptr;
|
|
char no_command = 1;
|
|
extern void display_message(void);
|
|
|
|
static char command_chars[] = "\n\f qh?sdSDofFmM";
|
|
/* these defines enumerate the "strchr"s of the commands in command_chars */
|
|
#define CMD_noop 0
|
|
#define CMD_redraw 1
|
|
#define CMD_update 2
|
|
#define CMD_quit 3
|
|
#define CMD_help1 4
|
|
#define CMD_help2 5
|
|
#define CMD_OSLIMIT 5 /* terminals with OS can only handle commands */
|
|
#define CMD_delay 6
|
|
#define CMD_displays 7
|
|
#define CMD_systemtog 8
|
|
#define CMD_datatog 9
|
|
#define CMD_order 10
|
|
#define CMD_flag 11
|
|
#define CMD_dflag 12
|
|
#define CMD_device 13
|
|
#define CMD_alldevices 14
|
|
|
|
/* set the buffer for stdout */
|
|
#ifdef DEBUG
|
|
setbuffer(stdout, NULL, 0);
|
|
#else
|
|
setbuffer(stdout, stdoutbuf, Buffersize);
|
|
#endif
|
|
|
|
sortlist_init();
|
|
devlist_init();
|
|
|
|
/* get our name */
|
|
if (argc > 0) {
|
|
if ((myname = strrchr(argv[0], '/')) == 0) {
|
|
myname = argv[0];
|
|
} else {
|
|
myname++;
|
|
}
|
|
}
|
|
|
|
/* initialize some selection options */
|
|
bst.system = Yes;
|
|
bst.fsdata = Yes;
|
|
|
|
/* get preset options from the environment */
|
|
if ((env_bufview = getenv("BUFVIEW")) != NULL)
|
|
{
|
|
av = preset_argv = argparse(env_bufview, &preset_argc);
|
|
ac = preset_argc;
|
|
|
|
/*
|
|
* set the dummy argument to an explanatory message, in case
|
|
* getopt encounters a bad argument
|
|
*/
|
|
preset_argv[0] = "while processing environment";
|
|
}
|
|
|
|
/* process options */
|
|
do {
|
|
/*
|
|
* if we're done doing the presets,
|
|
* then process the real arguments
|
|
*/
|
|
if (preset_argc == 0)
|
|
{
|
|
ac = argc;
|
|
av = argv;
|
|
|
|
/* this should keep getopt happy... */
|
|
optind = 1;
|
|
}
|
|
|
|
while ((i = getopt(ac, av, "SDbo:f:n:s:d:")) != EOF)
|
|
{
|
|
switch(i)
|
|
{
|
|
case 'S':
|
|
/* do not show system buffers */
|
|
bst.system = 0;
|
|
break;
|
|
|
|
case 'D':
|
|
/* do not show data buffers */
|
|
bst.fsdata = 0;
|
|
break;
|
|
|
|
case 'o':
|
|
if (!sortlist_reorder(*optarg))
|
|
{
|
|
fprintf(stderr,
|
|
"%s: warning: unknown display order specification %s -- ignored\n",
|
|
myname, optarg);
|
|
warnings++;
|
|
}
|
|
break;
|
|
|
|
case 'f':
|
|
if (!sortlist_bprune(optarg))
|
|
{
|
|
fprintf(stderr,
|
|
"%s: warning: unknown buffer flag %s -- ignored\n",
|
|
myname, optarg);
|
|
warnings++;
|
|
}
|
|
break;
|
|
|
|
case 'b': /* interactive off */
|
|
interactive = No;
|
|
break;
|
|
|
|
case 'd': /* number of displays to show */
|
|
if ((i = atoiwi(optarg)) == Invalid || i == 0)
|
|
{
|
|
fprintf(stderr,
|
|
"%s: warning: display count should be positive -- option ignored\n",
|
|
myname);
|
|
warnings++;
|
|
}
|
|
else
|
|
{
|
|
displays = i;
|
|
}
|
|
break;
|
|
|
|
case 's':
|
|
if ((delay = atoi(optarg)) < 0)
|
|
{
|
|
fprintf(stderr,
|
|
"%s: warning: seconds delay should be non-negative -- using default\n",
|
|
myname);
|
|
delay = Default_DELAY;
|
|
warnings++;
|
|
}
|
|
break;
|
|
|
|
case 'n':
|
|
/* get count of top buffer holders to display (if any) */
|
|
if ((topn = atoiwi(optarg)) == Invalid)
|
|
{
|
|
fprintf(stderr,
|
|
"%s: warning: buffer use display count should be non-negative -- using default\n",
|
|
myname);
|
|
warnings++;
|
|
}
|
|
#if Default_TOPN == Infinity
|
|
else
|
|
{
|
|
topn_specified = Yes;
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
usage();
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
/* tricky: remember old value of preset_argc & set preset_argc = 0 */
|
|
i = preset_argc;
|
|
preset_argc = 0;
|
|
|
|
/* repeat only if we really did the preset arguments */
|
|
} while (i != 0);
|
|
|
|
/* initialize the kernel memory interface */
|
|
if (machine_init() == -1)
|
|
{
|
|
exit(1);
|
|
}
|
|
|
|
/* initialize termcap */
|
|
init_termcap(interactive);
|
|
|
|
/* initialize display interface */
|
|
if ((max_topn = display_init()) == -1)
|
|
{
|
|
fprintf(stderr, "%s: can't allocate sufficient memory\n",
|
|
myname);
|
|
exit(4);
|
|
}
|
|
|
|
/* print warning if user requested more processes than we can display */
|
|
if (topn > max_topn)
|
|
{
|
|
fprintf(stderr,
|
|
"%s: warning: this terminal can only display %d buffer users.\n",
|
|
myname, max_topn);
|
|
warnings++;
|
|
}
|
|
|
|
/* adjust for topn == Infinity */
|
|
if (topn == Infinity)
|
|
{
|
|
/*
|
|
* For smart terminals, infinity really means everything that
|
|
* can be displayed, or Largest. On dumb terminals, infinity
|
|
* means every process in the system! We only really want to
|
|
* do that if it was explicitly specified. This is always the
|
|
* case when "Default_TOPN != Infinity". But if topn wasn't
|
|
* explicitly specified and we are on a dumb terminal and
|
|
* the default is Infinity, then (and only then) we use
|
|
* "Nominal_TOPN" instead.
|
|
*/
|
|
#if Default_TOPN == Infinity
|
|
topn = smart_terminal ? Largest :
|
|
(topn_specified ? Largest : Nominal_TOPN);
|
|
#else
|
|
topn = Largest;
|
|
#endif
|
|
}
|
|
|
|
/* set header display accordingly */
|
|
display_header(topn > 0);
|
|
|
|
/* determine interactive state */
|
|
if (interactive == Maybe)
|
|
{
|
|
interactive = smart_terminal;
|
|
}
|
|
|
|
/* if # of displays not specified, fill it in */
|
|
if (displays == 0)
|
|
{
|
|
displays = smart_terminal ? Infinity : 1;
|
|
}
|
|
|
|
/*
|
|
* hold interrupt signals while setting up the screen and the handlers
|
|
*/
|
|
#ifdef SIGHOLD
|
|
sighold(SIGINT);
|
|
sighold(SIGQUIT);
|
|
sighold(SIGTSTP);
|
|
#else
|
|
old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));
|
|
#endif
|
|
init_screen();
|
|
(void) signal(SIGINT, leave);
|
|
(void) signal(SIGQUIT, leave);
|
|
(void) signal(SIGTSTP, tstop);
|
|
#ifdef SIGWINCH
|
|
(void) signal(SIGWINCH, mywinch);
|
|
#endif
|
|
#ifdef SIGRELSE
|
|
sigrelse(SIGINT);
|
|
sigrelse(SIGQUIT);
|
|
sigrelse(SIGTSTP);
|
|
#else
|
|
(void) sigsetmask(old_sigmask);
|
|
#endif
|
|
if (warnings)
|
|
{
|
|
fputs("....", stderr);
|
|
fflush(stderr); /* why must I do this? */
|
|
sleep((unsigned)(3 * warnings));
|
|
fputc('\n', stderr);
|
|
}
|
|
|
|
/* setup the jump buffer for stops */
|
|
if (setjmp(jmp_int) != 0)
|
|
{
|
|
/* control ends up here after an interrupt */
|
|
reset_display();
|
|
}
|
|
|
|
/*
|
|
* main loop -- repeat while display count is positive or while it
|
|
* indicates infinity.
|
|
*/
|
|
|
|
while ((displays == Infinity) || (displays-- > 0))
|
|
{
|
|
/* get the current set of processes */
|
|
get_buffer_info(&system_info);
|
|
|
|
/* get the current stats */
|
|
get_system_info(&system_info);
|
|
|
|
/* display system buffers */
|
|
(*d_sysbufs)();
|
|
|
|
/* display the current time */
|
|
time(&curr_time);
|
|
i_timeofday(&curr_time);
|
|
|
|
/* display data buffers */
|
|
(*d_databufs)();
|
|
|
|
/* display empty buffers */
|
|
(*d_emptybufs)();
|
|
|
|
/* display get buffers */
|
|
(*d_getbufs)();
|
|
|
|
/* display read/write stats */
|
|
(*d_order)();
|
|
|
|
/* handle message area */
|
|
(*d_message)();
|
|
|
|
/* update the header area */
|
|
(*d_header)();
|
|
|
|
if (topn > 0)
|
|
{
|
|
/* determine number of processes to actually display
|
|
* this number will be the smallest of: active processes,
|
|
* number user requested, number current screen accomodates
|
|
*/
|
|
active_users = system_info.si_busers;
|
|
if (active_users > topn)
|
|
{
|
|
active_users = topn;
|
|
}
|
|
if (active_users > max_topn)
|
|
{
|
|
active_users = max_topn;
|
|
}
|
|
|
|
/* now show the top "n" buffer users. */
|
|
display_buffer_users(active_users, d_buffers);
|
|
|
|
i = active_users; /* for endscreen */
|
|
}
|
|
else
|
|
{
|
|
i = 0;
|
|
}
|
|
|
|
/* do end-screen processing */
|
|
u_endscreen(i);
|
|
|
|
/* now, flush the output buffer */
|
|
fflush(stdout);
|
|
|
|
/* only do the rest if we have more displays to show */
|
|
if (displays)
|
|
{
|
|
/* switch out for new display on smart terminals */
|
|
if (smart_terminal)
|
|
{
|
|
if (overstrike)
|
|
{
|
|
reset_display();
|
|
}
|
|
else
|
|
{
|
|
d_sysbufs = u_sysbufs;
|
|
d_databufs = u_databufs;
|
|
d_emptybufs = u_emptybufs;
|
|
d_getbufs = u_getbufs;
|
|
d_order = u_order;
|
|
d_message = u_message;
|
|
d_header = u_header;
|
|
d_buffers = u_buffers;
|
|
}
|
|
}
|
|
|
|
no_command = Yes;
|
|
if (!interactive)
|
|
{
|
|
/* set up alarm */
|
|
(void) signal(SIGALRM, onalrm);
|
|
(void) alarm((unsigned)delay);
|
|
|
|
/* wait for the rest of it .... */
|
|
pause();
|
|
}
|
|
else while (no_command)
|
|
{
|
|
fd_set readfds;
|
|
struct timeval timeout;
|
|
|
|
/* assume valid command unless told otherwise */
|
|
no_command = No;
|
|
|
|
/* set up arguments for select with timeout */
|
|
FD_ZERO(&readfds);
|
|
FD_SET(0, &readfds); /* for standard input */
|
|
FD_SET(1, &readfds); /* for standard input */
|
|
timeout.tv_sec = delay;
|
|
timeout.tv_usec = 0;
|
|
|
|
/* wait for either input or the end of the delay period */
|
|
if (select(32, &readfds, (fd_set *)NULL, (fd_set *)NULL,
|
|
&timeout) > 0)
|
|
{
|
|
int newval;
|
|
|
|
/* something to read -- clear the message area first */
|
|
clear_message();
|
|
|
|
/* now read it and convert to command strchr */
|
|
/* (use "change" as a temporary to hold strchr) */
|
|
(void) read(0, &ch, 1);
|
|
if ((iptr = strchr(command_chars, ch)) == NULL)
|
|
{
|
|
/* illegal command */
|
|
new_message(MT_standout, " Command not understood");
|
|
putchar('\r');
|
|
no_command = Yes;
|
|
}
|
|
else
|
|
{
|
|
change = iptr - command_chars;
|
|
if (overstrike && change > CMD_OSLIMIT)
|
|
{
|
|
/* error */
|
|
new_message(MT_standout,
|
|
" Command cannot be handled by this terminal");
|
|
putchar('\r');
|
|
no_command = Yes;
|
|
}
|
|
else switch(change)
|
|
{
|
|
case CMD_redraw: /* redraw screen */
|
|
reset_display();
|
|
break;
|
|
|
|
case CMD_update: /* merely update display */
|
|
case CMD_noop:
|
|
fflush(stdout);
|
|
break;
|
|
|
|
case CMD_quit: /* quit */
|
|
quit(0);
|
|
/*NOTREACHED*/
|
|
break;
|
|
|
|
case CMD_help1: /* help */
|
|
case CMD_help2:
|
|
reset_display();
|
|
clear();
|
|
show_help();
|
|
standout("Hit any key to continue: ");
|
|
fflush(stdout);
|
|
reset_display();
|
|
(void) read(0, &ch, 1);
|
|
break;
|
|
|
|
case CMD_delay: /* new seconds delay */
|
|
new_message(MT_standout, "Seconds to delay: ");
|
|
if ((i = readline(tempbuf, 8, Yes)) > -1)
|
|
{
|
|
delay = i;
|
|
}
|
|
clear_message();
|
|
break;
|
|
|
|
case CMD_displays: /* change display count */
|
|
new_message(MT_standout,
|
|
"Displays to show (currently %s): ",
|
|
displays == Infinity ? "infinite" :
|
|
itoa(displays));
|
|
|
|
if ((i = readline(tempbuf, 10, Yes)) > 0)
|
|
{
|
|
displays = i;
|
|
}
|
|
else if (i == 0)
|
|
{
|
|
quit(0);
|
|
}
|
|
clear_message();
|
|
break;
|
|
|
|
case CMD_systemtog:
|
|
bst.system = !bst.system;
|
|
display_message();
|
|
break;
|
|
|
|
case CMD_datatog:
|
|
bst.fsdata = !bst.fsdata;
|
|
display_message();
|
|
putchar('\r');
|
|
break;
|
|
|
|
case CMD_order:
|
|
new_message(MT_standout,
|
|
"Display order specifier: ");
|
|
if ((i = readline(tempbuf, 10, No)) > 0)
|
|
{
|
|
char *msg =
|
|
sortlist_reorder(tempbuf[0]);
|
|
clear_message();
|
|
new_message(MT_standout | MT_delayed,
|
|
"First order: %s",
|
|
msg ? msg :
|
|
"unknown order specifier");
|
|
reset_display();
|
|
}
|
|
break;
|
|
|
|
case CMD_flag:
|
|
new_message(MT_standout,
|
|
"Buffer flags to display: ");
|
|
if ((i = readline(tempbuf, 12, No)) > 0)
|
|
{
|
|
char *msg =
|
|
sortlist_bprune(tempbuf);
|
|
clear_message();
|
|
if (msg)
|
|
new_message(MT_standout | MT_delayed,
|
|
"Will show only buffers with flag: %s", msg);
|
|
else
|
|
new_message(MT_standout | MT_delayed,
|
|
"unknown flag specifier");
|
|
reset_display();
|
|
}
|
|
break;
|
|
|
|
case CMD_dflag:
|
|
bst.bflags = 0;
|
|
bst.bvtype = 0;
|
|
reset_display();
|
|
new_message(MT_standout | MT_delayed,
|
|
"Ignoring buffer flags in sort pruning");
|
|
putchar('\r');
|
|
break;
|
|
|
|
case CMD_device:
|
|
new_message(MT_standout,
|
|
"Display only mounted device: ");
|
|
if ((i = readline(tempbuf, 12, No)) > 0)
|
|
{
|
|
display_only_dev(tempbuf);
|
|
reset_display();
|
|
}
|
|
break;
|
|
|
|
case CMD_alldevices:
|
|
display_all_devs();
|
|
reset_display();
|
|
new_message(MT_standout | MT_delayed,
|
|
"Displaying all mounted devices");
|
|
putchar('\r');
|
|
break;
|
|
|
|
default:
|
|
new_message(MT_standout, " BAD CASE IN SWITCH!");
|
|
putchar('\r');
|
|
}
|
|
}
|
|
|
|
/* flush out stuff that may have been written */
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
quit(0);
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
/*
|
|
* reset_display() - reset all the display routine pointers so that entire
|
|
* screen will get redrawn.
|
|
*/
|
|
void
|
|
reset_display(void)
|
|
{
|
|
d_sysbufs = i_sysbufs;
|
|
d_databufs = i_databufs;
|
|
d_emptybufs = i_emptybufs;
|
|
d_getbufs = i_getbufs;
|
|
d_order = i_order;
|
|
d_message = i_message;
|
|
d_header = i_header;
|
|
d_buffers = i_buffers;
|
|
}
|
|
|
|
/*
|
|
* signal handlers
|
|
*/
|
|
|
|
sigret_t
|
|
leave(void) /* exit under normal conditions -- INT handler */
|
|
{
|
|
end_screen();
|
|
exit(0);
|
|
}
|
|
|
|
sigret_t
|
|
tstop(void) /* SIGTSTP handler */
|
|
{
|
|
/* move to the lower left */
|
|
end_screen();
|
|
fflush(stdout);
|
|
|
|
/* default the signal handler action */
|
|
(void) signal(SIGTSTP, SIG_DFL);
|
|
|
|
/* unblock the signal and send ourselves one */
|
|
#ifdef SIGRELSE
|
|
sigrelse(SIGTSTP);
|
|
#else
|
|
(void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
|
|
#endif
|
|
(void) kill(0, SIGTSTP);
|
|
|
|
/* reset the signal handler */
|
|
(void) signal(SIGTSTP, tstop);
|
|
|
|
/* reinit screen */
|
|
reinit_screen();
|
|
|
|
/* jump to appropriate place */
|
|
longjmp(jmp_int, 1);
|
|
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
#ifdef SIGWINCH
|
|
sigret_t
|
|
mywinch(void) /* SIGWINCH handler */
|
|
{
|
|
/* reascertain the screen dimensions */
|
|
get_screensize();
|
|
|
|
/* tell display to resize */
|
|
max_topn = display_resize();
|
|
|
|
/* reset the signal handler */
|
|
(void) signal(SIGWINCH, mywinch);
|
|
|
|
/* jump to appropriate place */
|
|
longjmp(jmp_int, 1);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
quit(int status) /* exit under duress */
|
|
{
|
|
end_screen();
|
|
exit(status);
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
sigret_t
|
|
onalrm(void) /* SIGALRM handler */
|
|
{
|
|
/* this is only used in batch mode to break out of the pause() */
|
|
/* return; */
|
|
}
|
|
|
|
void
|
|
display_message()
|
|
{
|
|
char msg_buffer[64];
|
|
|
|
if (bst.system && bst.fsdata)
|
|
{
|
|
sprintf(msg_buffer,
|
|
"%s", "Displaying system and fsdata buffers");
|
|
}
|
|
else if (!bst.system && !bst.fsdata)
|
|
{
|
|
sprintf(msg_buffer,
|
|
"%s", "Not displaying system or fsdata buffers");
|
|
}
|
|
else if (bst.system)
|
|
{
|
|
sprintf(msg_buffer,
|
|
"%s", "Displaying only system buffers");
|
|
}
|
|
else
|
|
{
|
|
sprintf(msg_buffer,
|
|
"%s", "Displaying only fsdata buffers");
|
|
}
|
|
|
|
new_message(MT_standout | MT_delayed, " %s", msg_buffer);
|
|
putchar('\r');
|
|
}
|
|
|
|
/*
|
|
* show_help() - display the help screen; invoked in response to
|
|
* either 'h' or '?'.
|
|
*/
|
|
void
|
|
show_help(void)
|
|
{
|
|
printf("bufview -- A file system buffer cache display for the Irix Operating System\n\
|
|
\n\
|
|
These single-character commands are available:\n\
|
|
\n\
|
|
^L - redraw screen\n\
|
|
q - quit\n\
|
|
h or ? - help; show this text\n");
|
|
|
|
/*
|
|
* not all commands are available with overstrike terminals
|
|
*/
|
|
if (overstrike)
|
|
{
|
|
printf("\n\
|
|
Other commands are also available, but this terminal is not\n\
|
|
sophisticated enough to handle those commands gracefully.\n\n");
|
|
}
|
|
else
|
|
{
|
|
printf("\
|
|
\n\
|
|
These commands require arguments:\n\
|
|
\n\
|
|
d - change number of displays to show\n\
|
|
s - change time interval (in seconds) between updates\n\
|
|
S - toggle displaying system control buffers\n\
|
|
D - toggle displaying data buffers\n\
|
|
o - push sort specifier to top of sort list\n\
|
|
[m]ost - display files/devices with most buffers mapped\n\
|
|
[l]east - display files/devices with least buffers mapped\n\
|
|
[b]iggest - display biggest buffers first\n\
|
|
[s]mallest - display smallest buffers first\n\
|
|
[n]ewest - display newest buffers first\n\
|
|
[o]ldest - display oldest buffers first\n\
|
|
f - display only those buffers with specified flags\n\
|
|
dw (B_DELWRI) -- delayed write buffer\n\
|
|
bsy (B_BUSY) -- buffer in use\n\
|
|
swp (B_SWAP) -- buffer being used to swap user pages\n\
|
|
da (B_DELALLOC) -- backing store not yet allocated [XFS]\n\
|
|
as (B_ASYNC) -- asynchronous read/write\n\
|
|
nc (B_NFS_UNSTABLE) -- dirty NFS data not yet committed to backing store\n\
|
|
na (B_NFS_ASYNC) -- asynchronous NFS read/write\n\
|
|
inact (B_INACTIVE) -- temporarily removed from buffer pool\n\
|
|
ino (B_FS_INO) -- inodes\n\
|
|
inomap (B_FS_INOMAP) -- inode map\n\
|
|
dir_bt (B_FS_DIR_BTREE) -- directory btree\n\
|
|
map (B_FS_MAP) -- map\n\
|
|
attr_bt (B_FS_ATTR_BTREE) -- attribute btree\n\
|
|
agi (B_FS_AGI) -- agi\n\
|
|
agf (B_FS_AGF) -- agf\n\
|
|
agfl (B_FS_AGFL) -- agfl\n\
|
|
dquot (B_FS_DQUOT) -- quota buffer\n\
|
|
F - disregard flags when selecting buffers to display\n\
|
|
m - only show buffers mapping specified mounted file system\n\
|
|
M - show buffers mapping all mounted file systems\n\
|
|
\n\n");
|
|
}
|
|
}
|
|
|