1
0

Source code upload

This commit is contained in:
calmsacibis995
2022-09-29 17:59:04 +03:00
parent 72fa9da3d7
commit 8fc8fa8089
33399 changed files with 11964078 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
#!smake
#
# Makefile for bufview
include $(ROOT)/usr/include/make/commondefs
COMMANDS=bufview
# Values for the two defaults in "bufview":
# TOPN - default number of buffers to display
# DELAY - default delay between updates
#
# set TOPN to -1 to indicate infinity (so that bufview will display as many
# as the screen will hold).
TARGETS=bufview
TOPN = -1
DELAY = 3
CFILES = bv.c display.c screen.c utils.c machine.c
OBJECTS = bv.o display.o screen.o utils.o machine.o
LLDLIBS+= -lcurses
LCOPTS+= -fullwarn
LCDEFS+= -D_OLD_TERMIOS -D_BSD_SIGNALS
LCFLAGS = -n32 -mips3
default: $(TARGETS)
bufview: $(OBJECTS)
$(CCF) $(OBJECTS) $(LDFLAGS) -o $@
clobber:
rm -f *.o bufview core core.*
install: default
$(INSTALL) -F /usr/sbin -m 2755 -O $(IDB_TAG32) bufview
+5
View File
@@ -0,0 +1,5 @@
/* My favorite names for boolean values */
#define No 0
#define Yes 1
#define Maybe 2 /* tri-state boolean, actually */
+955
View File
@@ -0,0 +1,955 @@
/*
* 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");
}
}
+35
View File
@@ -0,0 +1,35 @@
/*
* bufview - display file sytem buffer cache
*
* General (global) definitions
*/
/* Maximum number of columns allowed for display */
#define MAX_COLS 128
/* Special atoi routine returns either a non-negative number or one of: */
#define Infinity -1
#define Invalid -2
/* maximum number we can have */
#define Largest 0x7fffffff
/*
* "Nominal_TOPN" is used as the default TOPN when Default_TOPN is Infinity
* and the output is a dumb terminal. If we didn't do this, then
* installations who use a default TOPN of Infinity will get every
* process in the system when running top on a dumb terminal (or redirected
* to a file). Note that Nominal_TOPN is a default: it can still be
* overridden on the command line, even with the value "infinity".
*/
#ifndef Nominal_TOPN
#define Nominal_TOPN 40
#endif
#ifndef Default_TOPN
#define Default_TOPN -1
#endif
#ifndef Default_DELAY
#define Default_DELAY 3
#endif
+906
View File
@@ -0,0 +1,906 @@
/*
* 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 the routines that display information on the screen.
* Each section of the screen has two routines: one for initially writing
* all constant and dynamic text, and one for only updating the text that
* changes. The prefix "i_" is used on all the "initial" routines and the
* prefix "u_" is used for all the "updating" routines.
*
* ASSUMPTIONS:
* None of the "i_" routines use any of the termcap capabilities.
* In this way, those routines can be safely used on terminals that
* have minimal (or nonexistant) terminal capabilities.
*
* The routines are called in this order:
*/
#include "os.h"
#include <ctype.h>
#include <time.h>
#include "screen.h" /* interface to screen package */
#include "layout.h" /* defines for screen position layout */
#include "display.h"
#include "bv.h"
#include "boolean.h"
#include "machine.h" /* we should eliminate this!!! */
#include "utils.h"
#ifdef DEBUG
FILE *debug;
#endif
/* imported from screen.c */
extern int overstrike;
static int last_hi = 0; /* used in u_process and u_endscreen */
static int lastline = 0;
static int display_width = MAX_COLS;
#define lineindex(l) ((l)*display_width)
/* things initialized by display_init and used thruout */
/* buffer of proc information lines for display updating */
char *screenbuf = NULL;
static int num_sysstats;
static int num_datastats;
static int num_emptystats;
static int num_getstats;
int *sysbuf_stats, *lsysbuf_stats;
int *databuf_stats, *ldatabuf_stats;
int *databuf_stats, *ldatabuf_stats;
int *emptybuf_stats, *lemptybuf_stats;
int *getbuf_stats, *lgetbuf_stats;
static enum { OFF, ON, ERASE } header_status = ON;
static void summary_format();
static int string_count(char **);
static void line_update();
int
display_resize(void)
{
register int lines;
/* first, deallocate any previous buffer that may have been there */
if (screenbuf != NULL)
{
free(screenbuf);
}
/* calculate the current dimensions */
/* if operating in "dumb" mode, we only need one line */
lines = smart_terminal ? screen_length - Header_lines : 1;
/* we don't want more than MAX_COLS columns, since the machine-
* dependent modules make static allocations based on MAX_COLS
* and we don't want to run off the end of their buffers
*/
display_width = screen_width;
if (display_width >= MAX_COLS)
{
display_width = MAX_COLS - 1;
}
/* now, allocate space for the screen buffer */
screenbuf = (char *)malloc(lines * display_width);
if (screenbuf == (char *)NULL)
{
/* oops! */
return(-1);
}
/* return number of lines available */
/* for dumb terminals, pretend like we can show any amount */
return(smart_terminal ? lines : Largest);
}
int
display_init(void)
{
int lines;
/* call resize to do the dirty work */
lines = display_resize();
/* only do the rest if we need to */
if (lines > -1)
{
num_sysstats = string_count(sysbuf_names);
sysbuf_stats = (int *)malloc(num_sysstats * sizeof(int));
lsysbuf_stats = (int *)malloc(num_sysstats * sizeof(int));
num_datastats = string_count(databuf_names);
databuf_stats = (int *)malloc(num_datastats * sizeof(int));
ldatabuf_stats = (int *)malloc(num_datastats * sizeof(int));
num_emptystats = string_count(emptybuf_names);
emptybuf_stats = (int *)malloc(num_emptystats * sizeof(int));
lemptybuf_stats = (int *)malloc(num_emptystats * sizeof(int));
num_getstats = string_count(getbuf_names);
getbuf_stats = (int *)malloc(num_getstats * sizeof(int));
lgetbuf_stats = (int *)malloc(num_getstats * sizeof(int));
}
/* return number of lines available */
return(lines);
}
void
i_timeofday(time_t *tod)
{
extern long nticks;
if (smart_terminal)
Move_to(x_ticks, y_ticks);
printf("tick: %10d", nticks);
/*
* Display the current time.
* "ctime" always returns a string that looks like this:
*
* Sun Sep 16 01:03:52 1973
* 012345678901234567890123
* 1 2
*
* We want indices 11 thru 18 (length 8).
*/
if (smart_terminal)
{
Move_to(screen_width - 8, 0);
}
else
{
fputs(" ", stdout);
}
printf("%-8.8s\n", &(ctime(tod)[11]));
lastline = 1;
}
static char sysbufstats_buffer[MAX_COLS];
/*
* i_sysbufs() - print the system buffers line
*
* Assumptions: cursor is at the beginning of the line on entry
* lastline is valid
*/
void
i_sysbufs(void)
{
/*
* clear the screen since this is first
*/
if (smart_terminal)
clear();
/* format and print the system buffer statistics summary */
summary_format(sysbufstats_buffer, sysbuf_stats, sysbuf_names);
fputs(sysbufstats_buffer, stdout);
/* save the numbers for next time */
memcpy(lsysbuf_stats, sysbuf_stats, num_sysstats * sizeof(int));
}
void
u_sysbufs(void)
{
char new[MAX_COLS];
/* see if any of the state numbers has changed */
if (memcmp(lsysbuf_stats, sysbuf_stats, num_sysstats * sizeof(int)))
{
/* format and update the line */
summary_format(new, sysbuf_stats, sysbuf_names);
line_update(sysbufstats_buffer, new, x_sysstat, y_sysstat);
memcpy(lsysbuf_stats, sysbuf_stats, num_sysstats * sizeof(int));
}
}
static char databufstats_buffer[MAX_COLS];
void
i_databufs(void)
{
/* format and print the data buffer statistics summary */
summary_format(databufstats_buffer, databuf_stats, databuf_names);
fputs(databufstats_buffer, stdout);
/* save the numbers for next time */
memcpy(ldatabuf_stats, databuf_stats, num_datastats * sizeof(int));
}
void
u_databufs(void)
{
char new[MAX_COLS];
/* see if any of the state numbers has changed */
if (memcmp(ldatabuf_stats, databuf_stats, num_datastats * sizeof(int)))
{
/* format and update the line */
summary_format(new, databuf_stats, databuf_names);
line_update(databufstats_buffer, new, x_datastat, y_datastat);
memcpy(ldatabuf_stats, databuf_stats,
num_datastats * sizeof(int));
}
}
static char emptybufstats_buffer[MAX_COLS];
void
i_emptybufs(void)
{
fputs("\n", stdout);
lastline++;
/* format and print the empty buffer statistics summary */
summary_format(emptybufstats_buffer, emptybuf_stats, emptybuf_names);
fputs(emptybufstats_buffer, stdout);
/* save the numbers for next time */
memcpy(lemptybuf_stats, emptybuf_stats, num_emptystats * sizeof(int));
}
void
u_emptybufs(void)
{
char new[MAX_COLS];
/* see if any of the state numbers has changed */
if (memcmp(lemptybuf_stats, emptybuf_stats, num_emptystats*sizeof(int)))
{
/* format and update the line */
summary_format(new, emptybuf_stats, emptybuf_names);
line_update(emptybufstats_buffer, new,
x_emptystat, y_emptystat);
memcpy(lemptybuf_stats, emptybuf_stats,
num_emptystats * sizeof(int));
}
}
static char getbufstats_buffer[MAX_COLS];
void
i_getbufs(void)
{
fputs("\n", stdout);
lastline++;
/* format and print the get-buffer statistics summary */
summary_format(getbufstats_buffer, getbuf_stats, getbuf_names);
fputs(getbufstats_buffer, stdout);
/* save the numbers for next time */
memcpy(lgetbuf_stats, getbuf_stats, num_getstats * sizeof(int));
}
void
u_getbufs(void)
{
char new[MAX_COLS];
/* see if any of the state numbers has changed */
if (memcmp(lgetbuf_stats, getbuf_stats, num_getstats * sizeof(int)))
{
/* format and update the line */
summary_format(new, getbuf_stats, getbuf_names);
line_update(getbufstats_buffer, new, x_getstat, y_getstat);
memcpy(lgetbuf_stats, getbuf_stats,
num_getstats * sizeof(int));
}
}
char order_buffer[MAX_COLS];
void
i_order(void)
{
static int old_size;
int n;
fputs("\n", stdout);
lastline++;
n = printf("Order: %s", display_order());
n += display_devs();
if (bst.bflags || bst.bvtype)
n += printf(" Display flags: %s",
display_flags(bst.bflags, bst.bvtype, ", "));
if (old_size > n)
(void) clear_eol(old_size);
old_size = n;
}
void
u_order(void)
{
}
/*
* *_message() - print the next pending message line, or erase the one
* that is there.
*
* Note that u_message is (currently) the same as i_message.
*
* Assumptions: lastline is consistent
*/
/*
* i_message is funny because it gets its message asynchronously (with
* respect to screen updates).
*/
static char next_msg[MAX_COLS + 5];
static int msglen = 0;
/*
* Invariant: msglen is always the length of the message currently displayed
* on the screen (even when next_msg doesn't contain that message).
*/
void
i_message()
{
while (lastline < y_message)
{
fputc('\n', stdout);
lastline++;
}
if (next_msg[0] != '\0')
{
standout(next_msg);
msglen = strlen(next_msg);
next_msg[0] = '\0';
}
else if (msglen > 0)
{
(void) clear_eol(msglen);
msglen = 0;
}
}
void
u_message()
{
i_message();
}
static int header_length;
/*
* *_header(text) - print the header for the buffer entries
*
* Assumptions: cursor is on the previous line and lastline is consistent
*/
void
i_header(void)
{
extern char header_separate[];
extern char header_aggregate[];
if (header_status == ON)
{
putchar('\n');
if (bst.separate)
{
header_length = strlen(header_separate);
standout(header_separate);
}
else
{
header_length = strlen(header_aggregate);
standout(header_aggregate);
}
lastline++;
}
else if (header_status == ERASE)
{
header_status = OFF;
}
}
/*ARGSUSED*/
void
u_header(void)
{
if (header_status == ERASE)
{
putchar('\n');
lastline++;
clear_eol(header_length);
header_status = OFF;
}
}
void
u_endscreen(int hi)
{
register int screen_line = hi + Header_lines;
register int i;
if (smart_terminal)
{
if (hi < last_hi)
{
/* need to blank the remainder of the screen */
/* but only if there is any screen left below this line */
if (lastline + 1 < screen_length)
{
/* efficiently move to the end of currently displayed info */
if (screen_line - lastline < 5)
{
while (lastline < screen_line)
{
putchar('\n');
lastline++;
}
}
else
{
Move_to(0, screen_line);
lastline = screen_line;
}
if (clear_to_end)
{
/* we can do this the easy way */
putcap(clear_to_end);
}
else
{
/* use clear_eol on each line */
i = hi;
while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi)
{
putchar('\n');
}
}
}
}
last_hi = hi;
/* move the cursor to a pleasant place */
Move_to(x_idlecursor, y_idlecursor);
lastline = y_idlecursor;
}
else
{
/* separate this display from the next with some vertical room */
fputs("\n\n", stdout);
}
}
void
display_header(int t)
{
if (t)
{
header_status = ON;
}
else if (header_status == ON)
{
header_status = ERASE;
}
}
/*VARARGS2*/
void
new_message(int type, char *msgfmt, char *a1, char *a2, char *a3)
{
register int i;
/* first, format the message */
(void) sprintf(next_msg, msgfmt, a1, a2, a3);
if (msglen > 0)
{
/* message there already -- can we clear it? */
if (!overstrike)
{
/* yes -- write it and clear to end */
i = strlen(next_msg);
if ((type & MT_delayed) == 0)
{
type & MT_standout ? standout(next_msg) :
fputs(next_msg, stdout);
(void) clear_eol(msglen - i);
msglen = i;
next_msg[0] = '\0';
}
}
}
else
{
if ((type & MT_delayed) == 0)
{
type & MT_standout ? standout(next_msg) : fputs(next_msg, stdout);
msglen = strlen(next_msg);
next_msg[0] = '\0';
}
}
}
void
clear_message(void)
{
if (clear_eol(msglen) == 1)
{
putchar('\r');
}
}
int
readline(char *buffer, int size, int numeric)
{
register char *ptr = buffer;
register char ch;
register char cnt = 0;
register char maxcnt = 0;
/* allow room for null terminator */
size -= 1;
/* read loop */
while ((fflush(stdout), read(0, ptr, 1) > 0))
{
/* newline means we are done */
if ((ch = *ptr) == '\n')
{
break;
}
/* handle special editing characters */
if (ch == ch_kill)
{
/* kill line -- account for overstriking */
if (overstrike)
{
msglen += maxcnt;
}
/* return null string */
*buffer = '\0';
putchar('\r');
return(-1);
}
else if (ch == ch_erase)
{
/* erase previous character */
if (cnt <= 0)
{
/* none to erase! */
putchar('\7');
}
else
{
fputs("\b \b", stdout);
ptr--;
cnt--;
}
}
/* check for character validity and buffer overflow */
else if (cnt == size || (numeric && !isdigit(ch)) ||
!isprint(ch))
{
/* not legal */
putchar('\7');
}
else
{
/* echo it and store it in the buffer */
putchar(ch);
ptr++;
cnt++;
if (cnt > maxcnt)
{
maxcnt = cnt;
}
}
}
/* all done -- null terminate the string */
*ptr = '\0';
/* account for the extra characters in the message area */
/* (if terminal overstrikes, remember the furthest they went) */
msglen += overstrike ? maxcnt : cnt;
/* return either inputted number or string length */
putchar('\r');
return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
}
/*
* *_buffers(line, thisline) - print one buffer usage line
*
* Assumptions: lastline is consistent
*/
void
i_buffers(int line, char *thisline)
{
register char *p;
register char *base;
/* make sure we are on the correct line */
while (lastline < y_buffers + line)
{
putchar('\n');
lastline++;
}
/* truncate the line to conform to our current screen width */
thisline[display_width] = '\0';
/* write the line out */
fputs(thisline, stdout);
/* copy it in to our buffer */
base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;
p = strecpy(base, thisline);
/* zero fill the rest of it */
memzero(p, display_width - (p - base));
}
void
u_buffers(int line, char *newline)
{
register char *optr;
register int screen_line = line + Header_lines;
register char *bufferline;
/* remember a pointer to the current line in the screen buffer */
bufferline = &screenbuf[lineindex(line)];
/* truncate the line to conform to our current screen width */
newline[display_width] = '\0';
/* is line higher than we went on the last display? */
if (line >= last_hi)
{
/* yes, just ignore screenbuf and write it out directly */
/* get positioned on the correct line */
if (screen_line - lastline == 1)
{
putchar('\n');
lastline++;
}
else
{
Move_to(0, screen_line);
lastline = screen_line;
}
/* now write the line */
fputs(newline, stdout);
/* copy it in to the buffer */
optr = strecpy(bufferline, newline);
/* zero fill the rest of it */
memzero(optr, display_width - (optr - bufferline));
}
else
{
line_update(bufferline, newline, 0, line + Header_lines);
}
}
static int
string_count(char **pp)
{
int cnt = 0;
while (*pp++ != NULL) {
cnt++;
}
return cnt;
}
static void
summary_format(char *str, int *numbers, char **names)
{
int64_t num;
char *p;
char *thisname;
static char buffer[24];
/* format each number followed by its string */
p = str;
while ((thisname = *names++) != NULL)
{
/* get the number to format */
num = *numbers++;
/* is this number in pages? */
if (thisname[0] == 'P')
{
/* yes: format it as a memory value */
p = strecpy(p, konvert(num * pagesize));
/* skip over the P */
p = strecpy(p, thisname+1);
}
else if (thisname[0] == 'K')
{
/* yes: format it as a memory value */
p = strecpy(p, konvert(num));
/* skip over the K */
p = strecpy(p, thisname+1);
}
else if (thisname[0] == 'J')
{
/* yes: format it as a memory value */
sprintf(buffer, "%6lld", num);
p = strecpy(p, buffer);
/* skip over the J */
p = strecpy(p, thisname+1);
}
else if (thisname[0] == 'F')
{
/* format it as a float value */
sprintf(buffer, "%5.1f", (float)num);
p = strecpy(p, buffer);
/* skip over the F */
p = strecpy(p, thisname+1);
}
else
{
p = strecpy(p, itoa(num));
p = strecpy(p, thisname);
}
}
/* if the last two characters in the string are ", ", delete them */
p -= 2;
if (p >= str && p[0] == ',' && p[1] == ' ')
{
*p = '\0';
}
}
static void
line_update(char * old, char * new, int start, int line)
{
int ch;
int diff;
int newcol = start + 1;
int lastcol = start;
char cursor_on_line = No;
char *current;
/* compare the two strings and only rewrite what has changed */
current = old;
#ifdef DEBUG
fprintf(debug, "line_update, starting at %d\n", start);
fputs(old, debug);
fputc('\n', debug);
fputs(new, debug);
fputs("\n-\n", debug);
#endif
/* start things off on the right foot */
/* this is to make sure the invariants get set up right */
if ((ch = *new++) != *old)
{
if (line - lastline == 1 && start == 0)
{
putchar('\n');
}
else
{
Move_to(start, line);
}
cursor_on_line = Yes;
putchar(ch);
*old = ch;
lastcol = 1;
}
old++;
/*
* main loop -- check each character. If the old and new aren't the
* same, then update the display. When the distance from the
* current cursor position to the new change is small enough,
* the characters that belong there are written to move the
* cursor over.
*
* Invariants:
* lastcol is the column where the cursor currently is sitting
* (always one beyond the end of the last mismatch).
*/
do /* yes, a do...while */
{
if ((ch = *new++) != *old)
{
/* new character is different from old */
/* make sure the cursor is on top of this character */
diff = newcol - lastcol;
if (diff > 0)
{
/* some motion is required--figure out which is shorter */
if (diff < 6 && cursor_on_line)
{
/* overwrite old stuff--get it out of the old buffer */
printf("%.*s", diff, &current[lastcol-start]);
}
else
{
/* use cursor addressing */
Move_to(newcol, line);
cursor_on_line = Yes;
}
/* remember where the cursor is */
lastcol = newcol + 1;
}
else
{
/* already there, update position */
lastcol++;
}
/* write what we need to */
if (ch == '\0')
{
/* at the end--terminate with a clear-to-end-of-line */
(void) clear_eol(strlen(old));
}
else
{
/* write the new character */
putchar(ch);
}
/* put the new character in the screen buffer */
*old = ch;
}
/* update working column and screen buffer pointer */
newcol++;
old++;
} while (ch != '\0');
/* zero out the rest of the line buffer -- MUST BE DONE! */
diff = display_width - newcol;
if (diff > 0)
{
memzero(old, diff);
}
/* remember where the current line is */
if (cursor_on_line)
{
lastline = line;
}
}
+10
View File
@@ -0,0 +1,10 @@
/* constants needed for display.c */
/* "type" argument for new_message function */
#define MT_standout 1
#define MT_delayed 2
void reset_display(void);
char *display_order(void);
char *display_flags(uint64_t, uint64_t, char *);
+31
View File
@@ -0,0 +1,31 @@
/*
* bufview - display file system buffer cache activity
*
* This file defines the locations on the screen for various parts of the
* display. These definitions are used by the routines in "display.c" for
* cursor addressing.
*/
#define x_ticks 53
#define y_ticks 0
#define y_sysstat 0
#define y_datastat 1
#define y_emptystat 2
#define y_getstat 3
#define y_message 5
#define x_sysstat 0
#define x_datastat 0
#define x_emptystat 0
#define x_getstat 0
#define x_header 0
#define y_header 6 /* unused */
#define x_idlecursor 0
#define y_idlecursor 5
#define y_buffers 7
/* Number of lines of header information on the standard screen */
#define Header_lines 7
File diff suppressed because it is too large Load Diff
+154
View File
@@ -0,0 +1,154 @@
/*
* This file defines the interface between bufview and the machine-dependent
* module.
*/
#include <mntent.h>
#include <sys/fstyp.h>
#include <sys/buf.h>
extern char *sysbuf_names[];
extern char *databuf_names[];
extern char *emptybuf_names[];
extern char *getbuf_names[];
extern int *sysbuf_stats;
extern int *databuf_stats;
extern int *databuf_stats;
extern int *emptybuf_stats;
extern int *getbuf_stats;
extern int pagesize;
/*
* the system_info struct is filled in by a machine dependent routine.
*/
struct system_info
{
struct bnode *si_bufs; /* pointer to bnode tree */
int si_busers; /* number of bnodes */
int si_fusers; /* number of bnodes */
int si_fsbufs; /* number of file-system buffers */
int si_metabufs; /* number of fs ctl buffers */
int si_emptybufs; /* number of empty buffers */
int si_inactivebufs;/* number of inactive buffers */
int si_busybufs; /* number of busy buffers */
__int64_t si_fssize; /* mem size of file-system buffers */
__int64_t si_fsdsize; /* mem size of delwri file-system buffers */
__int64_t si_metasize; /* mem size of fs ctl buffers */
__int64_t si_metadsize; /* mem size of delwri fs ctl buffers */
};
extern struct system_info system_info;
extern int n_bufs;
#define NE_NAME 24
typedef struct bnode {
struct bnode * bn_prev;
struct bnode * bn_next;
uint64_t bn_key; /* for sorting -- vnumber or dev */
uint64_t bn_vnumber;
int64_t bn_mem;
int64_t bn_dmem;
int64_t bn_low;
int64_t bn_high;
char bn_fname[NE_NAME+1];
char bn_fpass;
char bn_bvtype;
clock_t bn_start;
int bn_bufcnt;
char * bn_devname;
char * bn_fstype;
uint64_t bn_flags;
} bnode_t;
#define ME_NAME 8
typedef struct mnt_entry {
struct mnt_entry * me_next;
char me_name[ME_NAME+1];
char me_fstype[FSTYPSZ];
dev_t me_dev;
} mnt_entry_t;
/*
* the buffer_select struct tells buffer sorting routines what
* buffers we are interested in seeing
*/
struct buffer_select
{
int system; /* show system buffers? */
int fsdata; /* show data buffers? */
int separate; /* don't show aggregated buffers */
uint64_t bflags; /* show only those buffers with these flags */
uint64_t bvtype; /* show only those remapped bvtypes */
};
extern struct buffer_select bst;
typedef int sltag_t;
typedef struct slist {
sltag_t (*sl_routine)(bnode_t *, bnode_t *, sltag_t);
sltag_t sl_tag;
short sl_attr;
char * sl_sup;
char * sl_inf;
struct slist * sl_next;
struct slist * sl_prev;
} slist_t;
#define SL_CMP_EQ 0
#define SL_CMP_LT -1
#define SL_CMP_GT 1
#define SF_NONE 0x0
#define SF_AGG 0x1 /* aggregate buffer info */
#define SF_IND 0x2 /* independent buffer stats */
extern sltag_t s_nbuf(bnode_t *, bnode_t *, sltag_t cmp);
extern sltag_t s_size(bnode_t *, bnode_t *, sltag_t cmp);
extern sltag_t s_key(bnode_t *, bnode_t *, sltag_t cmp);
extern sltag_t s_age(bnode_t *, bnode_t *, sltag_t cmp);
typedef struct bprune {
int bp_index;
uint64_t bp_remap;
uint64_t bp_flag;
const char * bp_match;
} bprune_t;
/*
* Flags for buffer usage statistics (bufview).
* Stored in b_bvtype.
*/
#define BV_FS_NONE 0x00000LL
#define BV_FS_INO 0x00001LL
#define BV_FS_INOMAP 0x00002LL
#define BV_FS_DIR_BTREE 0x00004LL
#define BV_FS_MAP 0x00008LL
#define BV_FS_ATTR_BTREE 0x00010LL
#define BV_FS_AGI 0x00020LL
#define BV_FS_AGF 0x00040LL
#define BV_FS_AGFL 0x00080LL
#define BV_FS_DQUOT 0x00100LL
#define REMAPFLAG (bflag_list[bp->bn_bvtype].bp_remap)
/* routines defined by the machine dependent module */
char *format_header();
void sortlist_init(void);
char *sortlist_reorder(char);
char *sortlist_bprune(char *);
int prune_dev(char *);
int display_devs(void);
void display_only_dev(char *);
void display_all_devs(void);
void devlist_destroy(void);
+10
View File
@@ -0,0 +1,10 @@
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#define setbuffer(f, b, s) setvbuf((f), (b), (b) ? _IOFBF : _IONBF, (s))
#include <string.h>
#include <memory.h>
#include <stdlib.h>
#define memzero(a, b) memset((a), 0, (b))
typedef void sigret_t;
+483
View File
@@ -0,0 +1,483 @@
/*
* Top 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 the routines that interface to termcap and stty/gtty.
*
* Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
*
* I put in code to turn on the TOSTOP bit while top was running, but I
* didn't really like the results. If you desire it, turn on the
* preprocessor variable "TOStop". --wnl
*/
#include "os.h"
#include "bv.h"
#include <sys/ioctl.h>
#ifdef CBREAK
# include <sgtty.h>
# define SGTTY
#else
# ifdef TCGETA
# define TERMIO
# include <termio.h>
# else
# define TERMIOS
# include <termios.h>
# endif
#endif
#if defined(TERMIO) || defined(TERMIOS)
# ifndef TAB3
# ifdef OXTABS
# define TAB3 OXTABS
# else
# define TAB3 0
# endif
# endif
#endif
#include "screen.h"
#include "boolean.h"
extern char *myname;
int overstrike;
int screen_length;
int screen_width;
char ch_erase;
char ch_kill;
char smart_terminal;
char PC;
short ospeed;
char *tgetstr();
char *tgoto();
char termcap_buf[1024];
char string_buffer[1024];
char home[15];
char lower_left[15];
char *clear_line;
char *clear_screen;
char *clear_to_end;
char *cursor_motion;
char *start_standout;
char *end_standout;
char *terminal_init;
char *terminal_end;
#ifdef SGTTY
static struct sgttyb old_settings;
static struct sgttyb new_settings;
#endif
#ifdef TERMIO
static struct termio old_settings;
static struct termio new_settings;
#endif
#ifdef TERMIOS
static struct termios old_settings;
static struct termios new_settings;
#endif
static char is_a_terminal = No;
#ifdef TOStop
static int old_lword;
static int new_lword;
#endif
#define STDIN 0
#define STDOUT 1
#define STDERR 2
void get_screensize()
{
#ifdef TIOCGWINSZ
struct winsize ws;
if (ioctl (1, TIOCGWINSZ, &ws) != -1)
{
if (ws.ws_row != 0)
{
screen_length = ws.ws_row;
}
if (ws.ws_col != 0)
{
screen_width = ws.ws_col - 1;
}
}
#else
#ifdef TIOCGSIZE
struct ttysize ts;
if (ioctl (1, TIOCGSIZE, &ts) != -1)
{
if (ts.ts_lines != 0)
{
screen_length = ts.ts_lines;
}
if (ts.ts_cols != 0)
{
screen_width = ts.ts_cols - 1;
}
}
#endif /* TIOCGSIZE */
#endif /* TIOCGWINSZ */
(void) strcpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1));
}
void
init_termcap(int interactive)
{
char *bufptr;
char *PCptr;
char *term_name;
char *getenv();
int status;
/* set defaults in case we aren't smart */
screen_width = MAX_COLS;
screen_length = 0;
if (!interactive)
{
/* pretend we have a dumb terminal */
smart_terminal = No;
return;
}
/* assume we have a smart terminal until proven otherwise */
smart_terminal = Yes;
/* get the terminal name */
term_name = getenv("TERM");
/* if there is no TERM, assume it's a dumb terminal */
if (term_name == NULL)
{
smart_terminal = No;
return;
}
/* now get the termcap entry */
if ((status = tgetent(termcap_buf, term_name)) != 1)
{
if (status == -1)
{
fprintf(stderr, "%s: can't open termcap file\n", myname);
}
else
{
fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
myname, term_name);
}
/* pretend it's dumb and proceed */
smart_terminal = No;
return;
}
/* "hardcopy" immediately indicates a very stupid terminal */
if (tgetflag("hc"))
{
smart_terminal = No;
return;
}
/* set up common terminal capabilities */
if ((screen_length = tgetnum("li")) <= 0)
{
screen_length = smart_terminal = 0;
return;
}
/* screen_width is a little different */
if ((screen_width = tgetnum("co")) == -1)
{
screen_width = 79;
}
else
{
screen_width -= 1;
}
/* terminals that overstrike need special attention */
overstrike = tgetflag("os");
/* initialize the pointer into the termcap string buffer */
bufptr = string_buffer;
/* get "ce", clear to end */
if (!overstrike)
{
clear_line = tgetstr("ce", &bufptr);
}
/* get necessary capabilities */
if ((clear_screen = tgetstr("cl", &bufptr)) == NULL ||
(cursor_motion = tgetstr("cm", &bufptr)) == NULL)
{
smart_terminal = No;
return;
}
/* get some more sophisticated stuff -- these are optional */
clear_to_end = tgetstr("cd", &bufptr);
terminal_init = tgetstr("ti", &bufptr);
terminal_end = tgetstr("te", &bufptr);
start_standout = tgetstr("so", &bufptr);
end_standout = tgetstr("se", &bufptr);
/* pad character */
PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
/* set convenience strings */
(void) strcpy(home, tgoto(cursor_motion, 0, 0));
/* (lower_left is set in get_screensize) */
/* get the actual screen size with an ioctl, if needed */
/* This may change screen_width and screen_length, and it always
sets lower_left. */
get_screensize();
/* if stdout is not a terminal, pretend we are a dumb terminal */
#ifdef SGTTY
if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
{
smart_terminal = No;
}
#endif
#ifdef TERMIO
if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
{
smart_terminal = No;
}
#endif
#ifdef TERMIOS
if (tcgetattr(STDOUT, &old_settings) == -1)
{
smart_terminal = No;
}
#endif
}
void
init_screen(void)
{
/* get the old settings for safe keeping */
#ifdef SGTTY
if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
{
/* copy the settings so we can modify them */
new_settings = old_settings;
/* turn on CBREAK and turn off character echo and tab expansion */
new_settings.sg_flags |= CBREAK;
new_settings.sg_flags &= ~(ECHO|XTABS);
(void) ioctl(STDOUT, TIOCSETP, &new_settings);
/* remember the erase and kill characters */
ch_erase = old_settings.sg_erase;
ch_kill = old_settings.sg_kill;
#ifdef TOStop
/* get the local mode word */
(void) ioctl(STDOUT, TIOCLGET, &old_lword);
/* modify it */
new_lword = old_lword | LTOSTOP;
(void) ioctl(STDOUT, TIOCLSET, &new_lword);
#endif
/* remember that it really is a terminal */
is_a_terminal = Yes;
/* send the termcap initialization string */
putcap(terminal_init);
}
#endif
#ifdef TERMIO
if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
{
/* copy the settings so we can modify them */
new_settings = old_settings;
/* turn off ICANON, character echo and tab expansion */
new_settings.c_lflag &= ~(ICANON|ECHO);
new_settings.c_oflag &= ~(TAB3);
new_settings.c_cc[VMIN] = 1;
new_settings.c_cc[VTIME] = 0;
(void) ioctl(STDOUT, TCSETA, &new_settings);
/* remember the erase and kill characters */
ch_erase = old_settings.c_cc[VERASE];
ch_kill = old_settings.c_cc[VKILL];
/* remember that it really is a terminal */
is_a_terminal = Yes;
/* send the termcap initialization string */
putcap(terminal_init);
}
#endif
#ifdef TERMIOS
if (tcgetattr(STDOUT, &old_settings) != -1)
{
/* copy the settings so we can modify them */
new_settings = old_settings;
/* turn off ICANON, character echo and tab expansion */
new_settings.c_lflag &= ~(ICANON|ECHO);
new_settings.c_oflag &= ~(TAB3);
new_settings.c_cc[VMIN] = 1;
new_settings.c_cc[VTIME] = 0;
(void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
/* remember the erase and kill characters */
ch_erase = old_settings.c_cc[VERASE];
ch_kill = old_settings.c_cc[VKILL];
/* remember that it really is a terminal */
is_a_terminal = Yes;
/* send the termcap initialization string */
putcap(terminal_init);
}
#endif
if (!is_a_terminal)
{
/* not a terminal at all---consider it dumb */
smart_terminal = No;
}
}
void
end_screen(void)
{
/* move to the lower left, clear the line and send "te" */
if (smart_terminal)
{
putcap(lower_left);
putcap(clear_line);
fflush(stdout);
putcap(terminal_end);
}
/* if we have settings to reset, then do so */
if (is_a_terminal)
{
#ifdef SGTTY
(void) ioctl(STDOUT, TIOCSETP, &old_settings);
#ifdef TOStop
(void) ioctl(STDOUT, TIOCLSET, &old_lword);
#endif
#endif
#ifdef TERMIO
(void) ioctl(STDOUT, TCSETA, &old_settings);
#endif
#ifdef TERMIOS
(void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
#endif
}
}
void
reinit_screen()
{
/* install our settings if it is a terminal */
if (is_a_terminal)
{
#ifdef SGTTY
(void) ioctl(STDOUT, TIOCSETP, &new_settings);
#ifdef TOStop
(void) ioctl(STDOUT, TIOCLSET, &new_lword);
#endif
#endif
#ifdef TERMIO
(void) ioctl(STDOUT, TCSETA, &new_settings);
#endif
#ifdef TERMIOS
(void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
#endif
}
/* send init string */
if (smart_terminal)
{
putcap(terminal_init);
}
}
void
standout(char *msg)
{
if (smart_terminal)
{
putcap(start_standout);
fputs(msg, stdout);
putcap(end_standout);
}
else
{
fputs(msg, stdout);
}
}
void
clear(void)
{
if (smart_terminal)
{
putcap(clear_screen);
}
}
int
clear_eol(int len)
{
if (smart_terminal && !overstrike && len > 0)
{
if (clear_line)
{
putcap(clear_line);
return(0);
}
else
{
while (len-- > 0)
{
putchar(' ');
}
return(1);
}
}
return(-1);
}
void
go_home(void)
{
if (smart_terminal)
{
putcap(home);
}
}
/* This has to be defined as a subroutine for tputs (instead of a macro) */
void
putstdout(char ch)
{
putchar(ch);
}
+32
View File
@@ -0,0 +1,32 @@
/*
* bufview
*
* This file contains all the definitions necessary to use the hand-written
* screen package in "screen.c"
*/
#define TCputs(str) tputs(str, 1, putstdout)
#define putcap(str) (void)((str) != NULL ? TCputs(str) : 0)
#define Move_to(x, y) TCputs(tgoto(cursor_motion, x, y))
/* declare return values for termcap functions */
char *tgetstr();
char *tgoto();
extern char ch_erase; /* set to the user's erase character */
extern char ch_kill; /* set to the user's kill character */
extern char smart_terminal; /* set if the terminal has sufficient termcap
capabilities for normal operation */
/* These are some termcap strings for use outside of "screen.c" */
extern char *cursor_motion;
extern char *clear_line;
extern char *clear_to_end;
/* rows and columns on the screen according to termcap */
extern int screen_length;
extern int screen_width;
/* a function that puts a single character on stdout */
void putstdout();
+215
View File
@@ -0,0 +1,215 @@
/*
* Buffer cache viewing program based on top.
*
* 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 various handy utilities used by top.
*/
#include "bv.h"
#include "os.h"
int
atoiwi(char *str)
{
register int len;
len = strlen(str);
if (len != 0)
{
if (strncmp(str, "infinity", len) == 0 ||
strncmp(str, "all", len) == 0 ||
strncmp(str, "maximum", len) == 0)
{
return(Infinity);
}
else
if (str[0] == '-') {
return(Invalid);
}
else
{
return(atoi(str));
}
}
return(0);
}
/*
* itoa - convert integer (decimal) to ascii string for positive numbers
* only (we don't bother with negative numbers since we know we
* don't use them).
*/
#define ITOARRAY 24
char *
itoa(uint64_t val)
{
static char array[ITOARRAY][8];
static int aindex = 0;
char *ptr;
ptr = array[aindex];
aindex = (aindex + 1) % 8;
ptr += ITOARRAY;
*--ptr = '\0';
if (val == 0)
{
*--ptr = '0';
}
else while (val != 0)
{
*--ptr = (val % 10) + '0';
val /= 10;
}
return(ptr);
}
/*
* strecpy(to, from) - copy string "from" into "to" and return a pointer
* to the END of the string "to".
*/
char *
strecpy(char *to, char *from)
{
while ((*to++ = *from++) != '\0')
;
return(--to);
}
/*
* string_index(string, array) - find string in array and return index
* Ariel: made it more friendly allowing to compare string prefixes
*/
int
string_index(char *string, char **array)
{
int i = 0;
int len = strlen(string);
while (*array != NULL)
{
if (strncmp(string, *array, len) == 0)
{
return i;
}
array++;
i++;
}
return -1;
}
/*
* argparse(line, cntp) - parse arguments in string "line", separating them
* out into an argv-like array, and setting *cntp to the number of
* arguments encountered. This is a simple parser that doesn't understand
* squat about quotes.
*/
char **
argparse(char *line, int *cntp)
{
register char *from;
register char *to;
register int cnt;
register int ch;
int length;
int lastch;
register char **argv;
char **argarray;
char *args;
/* unfortunately, the only real way to do this is to go thru the
input string twice. */
/* step thru the string counting the white space sections */
from = line;
lastch = cnt = length = 0;
while ((ch = *from++) != '\0')
{
length++;
if (ch == ' ' && lastch != ' ')
{
cnt++;
}
lastch = ch;
}
/* add three to the count: one for the initial "dummy" argument,
one for the last argument and one for NULL */
cnt += 3;
/* allocate a char * array to hold the pointers */
argarray = (char **)malloc(cnt * sizeof(char *));
/* allocate another array to hold the strings themselves */
args = (char *)malloc(length+2);
/* initialization for main loop */
from = line;
to = args;
argv = argarray;
lastch = '\0';
/* create a dummy argument to keep getopt happy */
*argv++ = to;
*to++ = '\0';
cnt = 2;
/* now build argv while copying characters */
*argv++ = to;
while ((ch = *from++) != '\0')
{
if (ch != ' ')
{
if (lastch == ' ')
{
*to++ = '\0';
*argv++ = to;
cnt++;
}
*to++ = ch;
}
lastch = ch;
}
*to++ = '\0';
/* set cntp and return the allocated array */
*cntp = cnt;
return(argarray);
}
# define MAXKBUF 16
# define kilo 1024
# define mega (kilo*kilo)
# define giga (kilo*kilo*kilo)
char *
konvert(uint64_t val)
{
static char retarray[MAXKBUF][8];
static int index = 0;
char *p;
p = retarray[index];
index = (index + 1) % 8;
if (val >= giga)
sprintf(p, "%5.1fG", ((float)val) / giga);
else if (val >= mega)
sprintf(p, "%5.1fM", ((float)val) / mega);
else if (val >= kilo)
sprintf(p, "%5.1fK", ((float)val) / kilo);
else
sprintf(p, "%6lld", val);
return(p);
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Top 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
*/
/* prototypes for functions found in utils.c */
int atoiwi();
char *itoa();
char *strecpy();
char **argparse();
char *konvert(uint64_t);