Monitor source Part 6 of 9
jct
jct at jct.UUCP
Tue Jul 11 14:28:29 AEST 1989
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 6 (of 9)."
# Contents: help/monitor.hlp monitor1.c
# Wrapped by jct@ on Mon Jul 10 22:48:25 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'help/monitor.hlp' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'help/monitor.hlp'\"
else
echo shar: Extracting \"'help/monitor.hlp'\" \(23471 characters\)
sed "s/^X//" >'help/monitor.hlp' <<'END_OF_FILE'
X.XXIstandard 329 332
X.XXImenu 699 2029
X.XXIcpu 2035 3712
X.XXIdisk 3719 5451
X.XXIcapacity 5462 7283
X.XXIio 7288 9460
X.XXImisc 9467 11275
X.XXIproc 11282 22404
X.XXItop 22410 22843
X.XXIuser_name 22855 23471
X#standard
X))
X.XXW 11 25 5 40
X.XXC GREEN WHITE
X.XXT" Monitor Help Menu "
X.XXS"Monitor Menu" menu
X.XXS"CPU Monitor" cpu
X.XXS"Capacity Monitor" capacity
X.XXS"Disk Monitor" disk
X.XXS"IO Monitor" io
X.XXS"Miscellaneous Monitor" misc
X.XXS"User Process Monitor" proc
X.XXS"Top CPU Process Monitor" top
X........L.......T.......T.......T.......T.......T.......T.......T.......R......
X
X#menu
Help With Monitor Menu
X.XXW 10 60 10 10
X The monitor program is used to observe various computer "loads".
X These observations can help make decissions as to how busy the
X system is, how many more programs or users it can handle, how to
X speed up current usage and so forth.
X
X The menu presented by the monitor program is used to select a
X current type of computer activity you want to observe. Each of
X the several possibilities has its own activity that it monitors.
X You are free to move among any of them at will.
X
X The menu has a type ahead feature so that if you are familiar
X with the entries, you may make a choice without waiting for the
X menu to appear. The type ahead feature allows you 2 seconds
X before the menu is displayed.
X
X The screens that display the data automatically update with new
X information every 5 seconds. The data you see is thus the
X average over the last 5 seconds. A command line option "-i #"
X when you start monitor will change the update time interval to
X "#" seconds.
X
X A command line option "-a" will allow you to monitor all
X processes under the "User Process Monitor" menu selection,
X otherwise you may only monitor processes with your user id.
X))
X
X#cpu
Help With CPU Monitor
X.XXW 10 60 10 10
X The CPU monitor screen is used to monitor various parameters
X related to CPU usage. Each of these is explained below.
X
X CPU Idle - This monitors the percentage of time that the computer@@
X AAAAAAAA
X is not currently doing anything. This time is available for
X users to run more programs without slowing anything else down.
X
X CPU User - This monitors the percentage of time that the computer@@
X AAAAAAAA
X is currently spending running user programs. This is only the
X time actually running the users application, see CPU System below
X also.
X
X CPU System - This is the percentage of time the computer is@@
X AAAAAAAAAA
X currently spending using operating system services in support of
X the users application. System services are things like reading
X and writing to the disk or terminal.
X
X Wait IO - This is the time that user programs are suspended@@
X AAAAAAA
X awaiting completion of operating system provided input/output
X services.
X
X Wait Swap - The percentage of time that user programs are@@
X AAAAAAAAA
X suspended awaiting virtural memory swapping to and from the disk.
X
X Wait PIO - The percentage of time waiting on physical IO.@@
X AAAAAAAA
X))
X
X#disk
Help With Disk Monitor
X.XXW 10 60 10 10
X Reads / Second - This is the number of disk read services@@
X AAAAAAAAAAAAAA
X provided by the operating system.
X
X Writes / Second - The number of disk write services provided by@@
X AAAAAAAAAAAAAAA
X the operating ssystem.
X
X Read Cache - This is the percentage of time that disk reads were@@
X AAAAAAAAAA
X taken from the disk RAM cache thus not requiring a physical disk
X read. Reading fromn the cache is much faster then reading off
X the physical disk. The higher this percentage the better.
X
X Write Cache - This is the percentage of time that disk writes@@
X AAAAAAAAAAA
X were put into the disk RAM cache thus not requiring a physical
X disk write. The data is ultimetely written to the disk, but in
X this way several physical writes may all be done at once and this
X is faster than each done independently. The higher the
X percentage the better.
X
X Swap Ins / Second - This is the number of "blocks" taken from@@
X AAAAAAAAAAAAAAAAA
X disk and put into RAM for execution. This is a combination of
X initial program loadings and virtural memory swapping. Each
X "block" is 512 Bytes.
X
X Swap Outs / Second - This is the number of virtural memory@@
X AAAAAAAAAAAAAAAAAA
X "blocks" swapped out to the virtural memory area of the disk.
X))
X
X#capacity
Help With Capacity Monitor
X.XXW 10 60 10 10
X Free Memory In Bytes - This is the amount of RAM memory free@@
X AAAAAAAAAAAAAAAAAAAA
X for loading more programs or data. Once this area is depleted,
X swapping will begin and the word "Swap" will appear in the
X upper right corner of the box. To the right is shown the number
X of processes waiting on memory to become available along with the
X sizes of the 5 largest free memory areas.
X
X Process Count - The Total number of processes that are loaded.@@
X AAAAAAAAAAAAA
X The upper right corner shows the maximum number of process slots
X available. Once this number is exceeded, you will get an error
X message.
X
X Open Text Segment Count - Every process requires a text segment,@@
X AAAAAAAAAAAAAAAAAAAAAAA
X this are the instructions that tell the computer what to do. If
X multiple invocations of the same process are running they all can
X share the same text segment. The upper right corner shows the
X maximum number of text slots available. Once this number is
X exceeded, you will get an error message.
X
X Open File Count - The upper right corner shows the maximum number@@
X AAAAAAAAAAAAAAA
X of open file slots available. Once this number is exceeded, you
X will get an error message.
X
X Open Inode Count - The upper right corner shows the maximum@@
X AAAAAAAAAAAAAAAA
X number of inode slots available. Once this number is exceeded,
X you will get an error message.
X))
X
X#io
Help With IO Monitor
X.XXW 10 60 10 10
X Read Characters / Second - This is the count of individual@@
X AAAAAAAAAAAAAAAAAAAAAAAA
X characters read by operating system provided services. This is a
X combination of disk and terminal reads. Disk reads are normally
X done in blocks, see the disk monitor, but this monitors the total
X character count in the blocks. Thus a disk read of a 100
X character block shows up a 100 here and as 1 on the disk monitor.
X
X Write Characters / Second - This is the total count of characters@@
X AAAAAAAAAAAAAAAAAAAAAAAAA
X written by the operating system regardless of whether they are
X multiple character blocks written to disk or single characters
X written to a terminal.
X
X Read Interrupts / Second - The number of hardware interrupts@@
X AAAAAAAAAAAAAAAAAAAAAAAA
X received by the operating system for the input of block or
X character at a time data.
X
X Write Interrupts / Second - The number of hardware interrupts@@
X AAAAAAAAAAAAAAAAAAAAAAAAA
X received by the operating system for the purpose of writing data
X in block mode or character at a time.
X
X Read TTY Chars / Second - The number of characters read per@@
X AAAAAAAAAAAAAAAAAAAAAAA
X second from terminals lines. Terminal lines may include printers
X and other non-terminal devices. Compare this to Read Characters@@
X AAAAAAAAAAAAAAA
X / Second.@@
X AAAAAAAA
X
X Write TTY Chars / Second - The number of characters written per@@
X AAAAAAAAAAAAAAAAAAAAAAAA
X second to terminals lines. Terminal lines may include printers
X and other non-terminal devices. Compare this to Write Characters@@
X AAAAAAAAAAAAAAAA
X / Second.@@
X AAAAAAAA
X))
X
X#misc
Help With Miscellaneous Monitor
X.XXW 10 60 10 10
X System Calls / Second - The number of seperate operating system@@
X AAAAAAAAAAAAAAAAAAAAA
X calls that are requested each second. All operating system
X services are provided by various operating system calls.
X
X Process Switches / Second - The number of times each second that@@
X AAAAAAAAAAAAAAAAAAAAAAAAA
X the operating system changes from running one program to another.
X The more programs that are running, the higher this number will
X be.
X
X Iget / Second - The number of i-node "gets" per second. These@@
X AAAAAAAAAAAAA
X are internal operating system functions in support of user
X applications for disk operations. User applications never
X directly use i-node services.
X
X Namei / Second - The number of logical name to i-node conversions@@
X AAAAAAAAAAAAAA
X per second that the operating system provides. User
X applications always deal with logical name and the operating
X system always deals in i-nodes. The conversion is invisable to
X the user. See also Iget / Second.@@
X AAAAAAAAAAAAA
X
X Dirblk / Second - This is the rate of another internal operating@@
X AAAAAAAAAAAAAAA
X system service in support of disk operations. This deals with
X file directory operations and once again this is invisable to the
X user. See also Iget / Second and Namei / Second.@@
X AAAAAAAAAAAAA AAAAAAAAAAAAAA
X))
X
X#proc
Help With User Process Monitor
X.XXW 10 60 10 10
X The user process monitor selection will take you to a user
X process menu at first. Shown on the menu will be all processes
X that are owned by the user name you are monitoring, even if the
X processes are on another terminal. By default, your own user
X name will be used. If you are the 'root' user, then all
X processes without regard to owner are on the menu. The first
X column of each entry is the process id, next comes the percent
X CPU time the process used in the last sample interval followed by
X the process name. If the number of menu entries is greater than
X what can be shown at one time, the maximum is 16, then you may
X press 'S' to switch to the next menu of processes. There will be
X as many menus as required to list all processes. After the last
X menu, you will be switched back to the first menu. Note that
X since processes may be started or stopped at any time, the menus
X may not have the same entries every time. You may press 'U' to
X select a user login name whose processes you want to monitor and
X no others. The special name 'All' may be used to monitor all
X processes. The user you are currently monitoring is shown in the
X upper left corner of the menu screen. You may press 'Z' to zap
X (kill) the current menu entry, assuming you either own the process
X or you are root.
X
X After you have selected a process, it will be displayed on the
X screen in two windows. You may alternate windows by pressing 'S'
X for switch. You may press 'Z' for zap to kill that process, assuming
X you have privelege for that process.
X
X CPU User - This is the percentage of time the processes executed@@
X AAAAAAAA
X user code.
X
X CPU System - This is the percentage of time the process executed@@
X AAAAAAAAAA
X in system mode. That is whenever the process makes an operating
X system call, such as to read from a file or write to a printer.
X
X Average % CPU - The average combined user and system CPU@@
X AAAAAAAAAAAAA
X utilization since the process began.
X
X I/O Chars / Second - The number of characters read or written on@@
X AAAAAAAAAAAAAAAAAA
X average. It makes no difference what the source or destination
X of the data is.
X
X The following is shown in a textural format :
X
X Start Time - The time that the process began@@
X AAAAAAAAAA
X
X Start Date - The date the process began@@
X AAAAAAAAAA
X
X User - The real user name of the process owner and the@@
X AAAA
X effective user name
X
X Group - The real group name of the process owner and the@@
X AAAAA
X effective group name
X
X TTY - The terminal name the process is assigned to@@
X AAA
X
X Run Time - The number of seconds from the time the process@@
X AAAAAAAA
X began to now
X
X CPU Time - The number of CPU seconds, user and system@@
X AAAAAAAA
X combined, the process has used since it began
X
X CPU User Time - The number of CPU seconds in user mode@@
X AAAAAAAAAAAAA
X
X CPU Sys Time - The number of CPU seconds in system mode@@
X AAAAAAAAAAAA
X
X Open Files - The number of 'files' the process has open. Note@@
X AAAAAAAAAA
X that a file does not have to be a disk file. For example a pipe
X or a terminal is also a 'file'.
X
X Block Reads - The total number of block read operations@@
X AAAAAAAAAAA
X
X Block Writes - The total number of block write operations@@
X AAAAAAAAAAAA
X
X I/O Count - The total number of characters read and written by@@
X AAAAAAAAA
X this process. This includes both block oriented disk operations
X and character oriented terminal or communications operations.
X
X Process Status - Possible values are : Loaded - the process is@@
X AAAAAAAAAAAAAA AAAAAA
X in memory. Swapped - the process is swapped out to disk.@@
X AAAAAAA
X Scheduler - the process is the special task scheduler process.@@
X AAAAAAAAA
X Locked - the process is locked in memory, it can't be swapped to@@
X AAAAAA
X disk. Swapping - the process is being moved to/from the disk.@@
X AAAAAAAA
X Tracing - the process is being traced (debugged) by another@@
X AAAAAAA
X process. Valid - the process has completed intial loading from@@
X AAAAA
X disk at startup (this is not the same as swapping).
X
X Process Flags - Possible values are : Sleeping - the process is@@
X AAAAAAAAAAAAA AAAAAAAA
X currently not running (waiting for an IO or time event).
X Abandoned - This is not a valid process. Running - the process is@@
X AAAAAAAAA AAAAAAA
X currently executing. Unknown - This is bad.@@
X AAAAAAA
X
X Umask Value - The privilege bits that are automatically cleared@@
X AAAAAAAAAAA
X when a process creates a new file.
X
X Ulimit Value - The maximum file size (offset) the process may@@
X AAAAAAAAAAAA
X write to.
X
X Text Size - The size, in bytes, of the memory allocated to@@
X AAAAAAAAA
X storing the program code in memory while it runs. Note that if
X there are multiple copies of the same program, they all share the
X same text memory. The number of processes using the same text
X memory is shown after the '/'.
X
X Data Size - The number of bytes allocated to storing the programs@@
X AAAAAAAAA
X data. If there are multiple copies of the same program running,
X each has its own independent data memory.
X
X Stack Size - The number of bytes allocated to storing stack@@
X AAAAAAAAAA
X information. Each process, even if they are the same program,
X has its own stack.
X
X Curr Dir I-node - The i-node number of the current directory of@@
X AAAAAAAAAAAAAAA
X the process.
X
X Root Dir I-node - The i-node number of the "pathname" for the@@
X AAAAAAAAAAAAAAA
X processes root directory. A value of 0 means the root is the
X actual root "/".
X
X Priority - The execution priority of the process, the lower the@@
X AAAAAAAA
X number the more often it will run. Values can range from 0 to
X 127.
X
X Pending Signals - The signal names that are currently being sent@@
X AAAAAAAAAAAAAAA
X to the process.
X
X Time to Alarm - The number of seconds till the next alarm@@
X AAAAAAAAAAAAA
X signal, a value of 0 means no alarm is coming up.
X
X Open File Status - This section allows display of some of the@@
X AAAAAAAAAAAAAAAA
X details of currently open files for the user process. These
X details are : Fid - the file id number the user process knows@@
X AAA
X the file as a result of opening the file. Typ - The file type,@@
X AAA
X blank for plain file, 'C' for character special, 'B' for block
X special, 'CX' for multiplexed character special, 'BX' for
X multiplexed block special, 'D' for directory or 'P' for named
X pipe. Mode - the mode in which the file was opened, 'R' for read@@
X AAAA
X privilage, 'W' for write privelage, 'N' for no delay (if data
X cannot be read or written immediately upon request it returns
X with an error instead of waiting), 'A' for append writes to the
X end of file instead of overwriting current file contents. Cnt -@@
X AAA
X the number of times this file is currently open by this process
X or other processes. Offset - the current position in the file@@
X AAAAAA
X relative to the beginning. I-node - the i-node number that the@@
X AAAAAA
X operating system recognizes the file as. Note that currently
X there is only room to show 18 files, any open files beyond this
X are not shown.
X
X Signal Status - This section is not labeled but appears in the@@
X AAAAAAAAAAAAA
X lower left corner. If any of the possible signals are not under
X default control, they will be shown by their name and what the
X control is. The modified control conditions may be 'Ignored'
X which means that if a process receives a signal of that type, it
X will be ignored, or 'Trapped' which means the user process will
X intercept the signal and perform user defined action as a result.
X Any signal not shown is under default control which is to abort
X the user process upon receipt of the signal. Note that currently
X there is only room to show 7 signals, any non-default conditions
X beyond this are not shown.
X))
X
X#top
Help With Top CPU Process Monitor
X.XXW 10 60 10 10
X The top CPU process screen will show up to eight of the most
X active processes. The most active will be at the top of the bar
X graph and the least active will be at the bottom. The process
X name is shown at the far left with the process id after the name.
X
X Time spent not running any processes will show up as a process
X named 'idle'.
X))
X
X#user_name
Help With User Name Selection
X.XXW 10 60 12 10
X You may enter a user name you want to select processes for. The
X special name "All" will select all processes. The first
X character of the name must be a lower case letter, subsequent
X characters may be lower case letters or numbers. All other
X characters are ignored. You may enter an empty name to abandon.
X If you select an invalid name, you will get an error message and
X the current name will be unchanged. The current name will always
X be shown in the upper left corner of the process menu screen.
X))
END_OF_FILE
if test 23471 -ne `wc -c <'help/monitor.hlp'`; then
echo shar: \"'help/monitor.hlp'\" unpacked with wrong size!
fi
# end of 'help/monitor.hlp'
fi
if test -f 'monitor1.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'monitor1.c'\"
else
echo shar: Extracting \"'monitor1.c'\" \(22192 characters\)
sed "s/^X//" >'monitor1.c' <<'END_OF_FILE'
X/* System activity monitor */
X
X/*
X*/
X
X/*
X Created Sept 5, 1987 by JCT
X*/
X
X/*
X * Copyright (c) John C. Tompkins 1989
X * All rights reserved.
X *
X * Permission is granted to use this for any personal, noncommercial use.
X * You may not distribute source or executable code for profit, nor
X * may you distribute it with a commercial product without the prior
X * written consent of the author. Please send modifications to the
X * author for inclusion in updates to the program.
X */
X
X#include <stdio.h>
X#include <a.out.h>
X#include <fcntl.h>
X#include <pwd.h>
X
X#include <km/defs.h>
X#include <km/ascii.h>
X#include <km/scrio.h>
X#include <km/scrops.h>
X#include <km/rdspec.h>
X#include <km/string1.h>
X#include <km/string2.h>
X#include <km/monitor.h> /* must come after defs.h and scrops.h */
X
X#ifdef XENIX
X#define KERNEL "/xenix"
X#define DFILE "/usr/lib/ps/monitor.dat"
X#define O_SINFO "_sysinfo"
X#define O_SWPLO "_swplo"
X#define O_PROC "_proc"
X#define O_TEXT "_text"
X#define O_FILE "_file"
X#define O_INODE "_inode"
X#define O_V "_v"
X#define O_LBOLT "_lbolt"
X#define O_HZ "_Hz"
X#define O_TIMEZONE "_Timezon"
X#define O_DSTFLAG "_Dstflag"
X#define O_UTSNAME "_utsname"
X#define O_COREMAP "_coremap"
X#define O_END "_end"
X#else
X#define KERNEL "/unix"
X#define DFILE "/usr/lib/ps/monitor.dat"
X#define O_SINFO "sysinfo"
X#define O_SWPLO "swplo"
X#define O_PROC "proc"
X#define O_TEXT "text"
X#define O_FILE "file"
X#define O_INODE "inode"
X#define O_V "v"
X#define O_LBOLT "lbolt"
X#define O_HZ "Hz"
X#define O_TIMEZONE "Timezone"
X#define O_DSTFLAG "Dstflag"
X#define O_UTSNAME "utsname"
X#define O_GDSTAT "gdstat"
X#endif
X
int all_procs = FALSE, sample_interval = 5;
int kfd, sfd, mfd, ufd, mode, uid, gid, proc_size;
int text_size, file_size, inode_size;
int user = UNDETERMINED;
X#ifdef XENIX
int mapent_size;
X#endif
long lr_limit = 10, lw_limit = 10, si_limit = 10, so_limit = 10;
long rc_limit = 10, wc_limit = 10, rt_limit = 10, wt_limit = 10;
long ri_limit = 10, wi_limit = 10, ps_limit = 10;
long ni_limit = 10, db_limit = 10, sc_limit = 10, ig_limit = 10;
long nfile, ntext, ninode, nproc;
long in_limit = 10, of_limit = 10, tx_limit = 10, pr_limit = 10;
X#ifdef XENIX
long free_mem, free_max[5];
int free_wait;
long fm_limit = 10;
X#else
long sr_limit = 10, sw_limit = 10, sf_limit = 10, se_limit = 10;
long rq_limit = 10, sq_limit = 10, sm_limit = 10, mg_limit = 10;
long aq_limit = 10, as_limit = 10, aw_limit = 10, bc_limit = 10;
X#endif
X#ifdef SYSV
long idle_usage;
X#endif
OFFSETS offsets;
long cpu_total;
long last_time, new_time, llast_time, time_interval;
long lbolt, boot_time, curr_time;
char name_buf[500], *name_ptr, *proc_name, boot_when[40];
int hz, tz, dstflag;
struct utsname utsname;
daddr_t swplo;
struct tms tbuf;
struct sysinfo si_last, si_new, si_llast;
struct var v_buf;
struct user user_last, user_new, user_llast;
X#ifdef XENIX
struct map coremap;
X#endif
SPTR sptr;
struct proc *proc_buf;
struct file *file_buf;
X#ifdef SYSV
int disk = 0;
struct iotime io_last[DISKS], io_new[DISKS], io_llast[DISKS];
X#endif
X
struct nlist name_list[] =
X {
X#ifdef XENIX
X O_SINFO, 0, 0,
X O_SWPLO, 0, 0,
X O_V, 0, 0,
X O_PROC, 0, 0,
X O_TEXT, 0, 0,
X O_FILE, 0, 0,
X O_INODE, 0, 0,
X O_LBOLT, 0, 0,
X O_HZ, 0, 0,
X O_TIMEZONE, 0, 0,
X O_DSTFLAG, 0, 0,
X O_UTSNAME, 0, 0,
X O_COREMAP, 0, 0,
X O_END, 0, 0,
X "", 0, 0
X#else
X O_SINFO, 0, 0, 0, 0, 0,
X O_SWPLO, 0, 0, 0, 0, 0,
X O_V, 0, 0, 0, 0, 0,
X O_PROC, 0, 0, 0, 0, 0,
X O_TEXT, 0, 0, 0, 0, 0,
X O_FILE, 0, 0, 0, 0, 0,
X O_INODE, 0, 0, 0, 0, 0,
X O_LBOLT, 0, 0, 0, 0, 0,
X O_HZ, 0, 0, 0, 0, 0,
X O_TIMEZONE, 0, 0, 0, 0, 0,
X O_DSTFLAG, 0, 0, 0, 0, 0,
X O_UTSNAME, 0, 0, 0, 0, 0,
X O_GDSTAT, 0, 0, 0, 0, 0,
X "", 0, 0, 0, 0, 0
X#endif
X };
X
extern int show_time ();
X
X#ifdef SYSV
SCR_ENTRY disk_list[] =
X {
X 0, "Hard drive one", do_disk, 0, 0, "hdisk", SCR_NPARM, 0,
X 0, "Hard drive two", do_disk, 1, 0, "hdisk", SCR_NPARM, 0,
X UNDETERMINED, 0, 0, 0, 0, 0, 0, 0
X };
X
SCR disk_menu =
X {
X 0, /* window */
X " Hard Disk Monitor Menu ", /* head */
X 0, /* entry function */
X show_time, /* loop function */
X 0, /* check key function */
X 0, /* prompt */
X disk_list, /* entry */
X 0, /* active entry */
X 0, /* last active */
X 10, /* get key timeout */
X "/usr/lib/help/monitor.hlp", /* help file */
X "hdisk", /* help section */
X (SCR_MENU | SCR_TYPE_AHEAD), /* flags */
X 0, /* local flags */
X 0 /* color */
X };
X#endif
X
SCR_ENTRY menu_list[] =
X {
X 0, "CPU Monitor", mode_CPU, 0, 0, "cpu", 0, 0,
X 0, "Disk Monitor", mode_disk, 0, 0, "disk", 0, 0,
X 0, "I/O Monitor", mode_IO, 0, 0, "io", 0, 0,
X 0, "Capacity Monitor", mode_capacity, 0, 0, "capacity", 0, 0,
X#ifdef SYSV
X 0, "System Call Monitor", mode_scall, 0, 0, "scall", 0, 0,
X 0, "Hard Disk Monitor", mode_HD, 0, 0, "hdisk", 0, 0,
X 0, "IPC monitor", mode_IPC, 0, 0, "ipc", 0, 0,
X#endif
X 0, "Miscellaneous Monitor", mode_misc, 0, 0, "misc", 0, 0,
X 0, "User Process Monitor", mode_proc, 0, 0, "proc", 0, 0,
X 0, "Top CPU Process Monitor", mode_top, 0, 0, "top", 0, 0,
X 0, "Configuration monitor", mode_config, 0, 0, "config", 0, 0,
X UNDETERMINED, 0, 0, 0, 0, 0, 0, 0
X };
X
SCR main_menu =
X {
X 0, /* window */
X " System Monitor Menu ", /* head */
X 0, /* entry function */
X show_time, /* loop function */
X 0, /* check key function */
X 0, /* prompt */
X menu_list, /* entry */
X 0, /* active entry */
X 0, /* last active */
X 10, /* get key timeout */
X "/usr/lib/help/monitor.hlp", /* help file */
X "menu", /* help section */
X (SCR_MENU | SCR_TYPE_AHEAD | SCR_NO_REFRESH), /* flags */
X 0, /* local flags */
X 0 /* color */
X };
X
X/*
X Declare extern UNIX functions
X*/
X
extern long lseek();
extern long time();
extern long times();
extern char *malloc();
extern char *getenv();
extern char *basename();
extern int atoi();
extern struct passwd *getpwnam();
extern struct passwd *getpwuid();
extern unsigned short getuid();
extern unsigned short getgid();
X
void put_scale(y, x, limit)
X int y;
X int x;
X long limit;
X{
X int i;
X long temp;
X char data[20];
X
X move(y + 3, x + 2);
X addch('0');
X for (i = 1; i <= 5; i++)
X {
X move(y + 3, x + (i * 6));
X if (limit > 1000000L)
X temp = ((limit / 5) * i);
X else
X temp = ((limit * i) / 5);
X sprintf(data, "%ld", temp);
X switch (strlen(data))
X {
X case 1 :
X addch(' ');
X addch(' ');
X addstr(data);
X addch(' ');
X break;
X case 2 :
X addch(' ');
X addch(' ');
X addstr(data);
X break;
X case 3 :
X addch(' ');
X addstr(data);
X break;
X case 4 :
X addch(' ');
X addch(' ');
X addch(data[0]);
X addch('K');
X break;
X case 5 :
X addch(' ');
X addch(data[0]);
X addch(data[1]);
X addch('K');
X break;
X case 6 :
X addch(data[0]);
X addch(data[1]);
X addch(data[2]);
X addch('K');
X break;
X case 7 :
X addch(' ');
X addch(' ');
X addch(data[0]);
X addch('M');
X break;
X case 8 :
X addch(' ');
X addch(data[0]);
X addch(data[1]);
X addch('M');
X break;
X case 9 :
X addch(data[0]);
X addch(data[1]);
X addch(data[2]);
X addch('M');
X break;
X case 10 :
X addch(' ');
X addch(' ');
X addch(data[0]);
X addch('G');
X break;
X }
X }
X}
X
void put_chart(y, x, name, limit, cols)
X int y;
X int x;
X char *name;
X long limit;
X int cols;
X{
X int i;
X
X draw_box(stdscr, y, x, y + 4, x + 34);
X move(y, x + 2);
X addch('(');
X for (i = 0; i < (cols - 1); i++)
X addch(' ');
X addch('0');
X addch(')');
X move(y + 4, (x + (34 - strlen(name)) / 2));
X addch(' ');
X addstr(name);
X addch(' ');
X put_scale(y, x, limit);
X move(y + 2, x + 2);
X for (i = 0; i <= 30; i++)
X {
X if (i == 0)
X addgraphic(G_LL);
X else if (i == 30)
X addgraphic(G_LR);
X else if ((i % 6) == 0)
X addgraphic(G_UT);
X else
X addgraphic(G_H);
X }
X}
X
void chart_absolute(y, x, name, limit)
X int y;
X int x;
X char *name;
X long limit;
X{
X put_chart(y, x, name, limit, 10);
X}
X
void chart_capacity(y, x, name, limit, capacity)
X int y;
X int x;
X char *name;
X long limit;
X long capacity;
X{
X put_chart(y, x, name, limit, 10);
X move(y, x + 21);
X printw("(%10ld)", capacity);
X}
X
void chart_percent(y, x, name)
X int y;
X int x;
X char *name;
X{
X put_chart(y, x, name, 100L, 3);
X}
X
void bar_plot(y, x, cols)
X int y;
X int x;
X int cols;
X{
X int i;
X
X move(y + 1, x + 2);
X if (cols > 31)
X cols = 31;
X if (have_standout)
X {
X standout();
X for (i = 0; i < cols; i++)
X addch(' ');
X standend();
X }
X else
X {
X for (i = 0; i < cols; i++)
X addch('X');
X }
X for ( ; i < 31; i++)
X addch(' ');
X}
X
void bar_percent(y, x, data, total)
X int y;
X int x;
X long data;
X long total;
X{
X int temp, percent;
X
X if (data > 1000000L)
X {
X data /= 1000;
X total /= 1000;
X }
X if (total)
X {
X percent = (100 * data) / total;
X temp = (31 * data) / total;
X if ((((100 * data) / total) % 4) >= 2)
X temp++;
X }
X else
X {
X percent = 0;
X temp = 0;
X }
X move(y, x + 3);
X printw("%3d", percent);
X bar_plot(y, x, temp);
X}
X
int rescale(data, limit, minimum)
X long data;
X long *limit;
X long minimum;
X{
X int changed = FALSE;
X
X while ((*limit > minimum) && (data < (*limit / 10)))
X {
X *limit /= 10;
X changed = TRUE;
X }
X while (data > *limit)
X {
X *limit *= 10;
X changed = TRUE;
X }
X return(changed);
X}
X
void bar_persec(y, x, data, limit, minimum)
X int y;
X int x;
X long data;
X long *limit;
X long minimum;
X{
X int temp;
X long calc_data;
X
X calc_data = (data * hz) / time_interval;
X if (rescale(calc_data, limit, minimum))
X put_scale(y, x, *limit);
X if (data)
X temp = (31 * calc_data) / *limit + 1;
X else
X temp = 0;
X move(y, x + 3);
X printw("%10ld", calc_data);
X bar_plot(y, x, temp);
X}
X
void bar_absolute(y, x, data, limit, minimum)
X int y;
X int x;
X long data;
X long *limit;
X long minimum;
X{
X int temp;
X long max, real_data;
X
X if (rescale(data, limit, minimum))
X put_scale(y, x, *limit);
X max = *limit;
X real_data = data;
X if (data > 1000000L)
X {
X data /= 1000;
X max /= 1000;
X }
X if (data)
X temp = (31 * data) / max + 1;
X else
X temp = 0;
X move(y, x + 3);
X printw("%10ld", real_data);
X bar_plot(y, x, temp);
X}
X
int read_mapent()
X{
X lseek(kfd, offsets.coremap, 0);
X read(kfd, &coremap, sizeof(coremap));
X if (sptr.what == SPTR_MAPENT)
X return(TRUE);
X sptr.what = SPTR_MAPENT;
X lseek(kfd, offsets.mapent, 0);
X if (read(kfd, sptr.where.mapent, mapent_size) == mapent_size)
X return(TRUE);
X return(FALSE);
X}
X
int read_text()
X{
X if (sptr.what == SPTR_TEXT)
X return(TRUE);
X sptr.what = SPTR_TEXT;
X lseek(kfd, offsets.text, 0);
X if (read(kfd, sptr.where.text, text_size) == text_size)
X return(TRUE);
X return(FALSE);
X}
X
int read_file()
X{
X#ifdef XENIX
X lseek(mfd, offsets.file, 0);
X if (read(mfd, file_buf, file_size) == file_size)
X#else
X lseek(kfd, offsets.file, 0);
X if (read(kfd, file_buf, file_size) == file_size)
X#endif
X return(TRUE);
X return(FALSE);
X}
X
int read_inode()
X{
X if (sptr.what == SPTR_INODE)
X return(TRUE);
X sptr.what = SPTR_INODE;
X#ifdef XENIX
X lseek(mfd, offsets.inode, 0);
X if (read(mfd, sptr.where.inode, inode_size) == inode_size)
X#else
X lseek(kfd, offsets.inode, 0);
X if (read(kfd, sptr.where.inode, inode_size) == inode_size)
X#endif
X return(TRUE);
X return(FALSE);
X}
X
int read_data(immediate)
X int immediate;
X{
X REGISTER int i;
X int j, k;
X long now;
X REGISTER SPTR ptr;
X#ifdef SYSV
X long idle_time;
X#endif
X
X static long count = 0;
X
X now = times(&tbuf);
X count++;
X if (!immediate && (((now - last_time) / hz) < 1) && (count > 2))
X return(FALSE);
X si_llast = si_last;
X#ifdef SYSV
X for (i = 0; i < DISKS; i++)
X io_llast[i] = io_last[i];
X#endif
X llast_time = last_time;
X si_last = si_new;
X#ifdef SYSV
X for (i = 0; i < DISKS; i++)
X io_last[i] = io_new[i];
X#endif
X last_time = new_time;
X new_time = now;
X time_interval = new_time - last_time;
X curr_time = time((long*)0);
X lseek(kfd, offsets.sysinfo, 0);
X read(kfd, &si_new, sizeof(si_new));
X#ifdef XENIX
X read_mapent();
X ptr = sptr;
X free_mem = 0;
X for (i = 0; i < 5; i++)
X free_max[i] = 0;
X free_wait = coremap.nwaiting;
X for (i = coremap.ncells; i; i--)
X {
X for (j = 0; j < 5; j++)
X {
X if (ptr.where.mapent->m_size > free_max[j])
X {
X for (k = 4; k > j; k--)
X free_max[k] = free_max[k - 1];
X free_max[j] = ptr.where.mapent->m_size;
X break;
X }
X }
X free_mem += (ptr.where.mapent++)->m_size;
X }
X free_mem = mstob(free_mem);
X for (i = 0; i < 5; i++)
X free_max[i] = mstob(free_max[i]);
X#endif
X read_text();
X ptr = sptr;
X ntext = 0;
X for (i = v_buf.v_text; i; i--)
X {
X if ((ptr.where.text++)->x_iptr)
X ntext++;
X }
X read_file();
X ptr.where.file = file_buf;
X nfile = 0;
X for (i = v_buf.v_file; i; i--)
X {
X if ((ptr.where.file++)->f_count)
X nfile++;
X }
X read_inode();
X ptr = sptr;
X ninode = 0;
X for (i = v_buf.v_inode; i; i--)
X {
X if ((ptr.where.inode++)->i_count)
X ninode++;
X }
X ptr.where.proc = proc_buf;
X lseek(kfd, offsets.proc, 0);
X read(kfd, ptr.where.proc, proc_size);
X nproc = 0;
X cpu_total = 0;
X for (i = v_buf.v_proc; i; i--)
X {
X if (ptr.where.proc->p_stat)
X {
X nproc++;
X cpu_total += ptr.where.proc->p_cpu;
X }
X ptr.where.proc++;
X }
X#ifdef SYSV
X idle_time = si_new.cpu[CPU_IDLE] - si_last.cpu[CPU_IDLE];
X if (time_interval - idle_time)
X idle_usage = (idle_time * cpu_total) / (time_interval - idle_time);
X else
X idle_usage = 1000000; /* swamp anything else */
X cpu_total += idle_usage;
X lseek(kfd, offsets.gdstat, 0);
X read(kfd, io_new, sizeof(io_new));
X#endif
X return(TRUE);
X}
X
int show_time ()
X{
X if (main_menu.lflags & SCR_DISPLAY)
X {
X curr_time = time((long*)0);
X put_when(0, COLS - 24, curr_time, 0, FALSE);
X move(LINES - 1, 0);
X refresh();
X }
X return (TRUE);
X}
X
void errexit(data)
X{
X fprintf(stderr, "%s", data);
X exit(1);
X}
X
int get_offset()
X{
X int have_it = FALSE, dfd = ERROR;
X unsigned int temp;
X struct stat dstat, kstat;
X long max_size;
X#ifdef SYSV
X int i;
X#endif
X
X if ((dfd = open(DFILE, O_RDWR)) != ERROR)
X {
X if ((fstat(dfd, &dstat) != ERROR) && (stat(KERNEL, &kstat) != ERROR))
X {
X if (dstat.st_mtime >= kstat.st_mtime)
X {
X if (read(dfd, &offsets, sizeof(offsets)) == sizeof(offsets))
X {
X close(dfd);
X have_it = TRUE;
X }
X else
X lseek(dfd, 0L, 0);
X }
X }
X }
X if (!have_it)
X {
X if (nlist(KERNEL, name_list) == ERROR)
X errexit("could not get name list\n");
X if (!(offsets.sysinfo = name_list[0].n_value))
X errexit("sysinfo not found\n");
X if (!(offsets.swplo = name_list[1].n_value))
X errexit("swplo not found\n");
X if (!(offsets.v = name_list[2].n_value))
X errexit("v not found\n");
X if (!(offsets.proc = name_list[3].n_value))
X errexit("proc not found\n");
X if (!(offsets.text = name_list[4].n_value))
X errexit("text not found\n");
X if (!(offsets.file = name_list[5].n_value))
X errexit("file not found\n");
X if (!(offsets.inode = name_list[6].n_value))
X errexit("inode not found\n");
X if (!(offsets.lbolt = name_list[7].n_value))
X errexit("lbolt not found\n");
X if (!(offsets.hz = name_list[8].n_value))
X errexit("hz not found\n");
X if (!(offsets.timezone = name_list[9].n_value))
X errexit("timezone not found\n");
X if (!(offsets.dstflag = name_list[10].n_value))
X errexit("dstflag not found\n");
X if (!(offsets.utsname = name_list[11].n_value))
X errexit("utsname not found\n");
X#ifdef XENIX
X if (!(offsets.coremap = name_list[12].n_value))
X errexit("coremap not found\n");
X if (!(offsets.end = name_list[13].n_value))
X errexit("end not found\n");
X
X/*
X Offsets.mem is the "offset" between the same physical address in
X /dev/kmem and /dev/mem. Some parameters on the 286 are NOT kept in near
X memory (kmem), they are in far memory depending on how large other
X system data areas are configured. Knowing this offset and always reading
X the possibly "far" data in /dev/mem removes the problem. The number
X used works on all the systems I've tried, your system may vary but its
X not likely. I discovered the value by brute force testing!
X*/
X
X offsets.mem = 0x0800L; /* cheating for now */
X#else
X if (!(offsets.gdstat = name_list[12].n_value))
X errexit("gdstat not found\n");
X#endif
X if ((dfd != ERROR) || ((dfd = open(DFILE, (O_RDWR | O_CREAT), 0644)) != ERROR))
X {
X write(dfd, &offsets, sizeof(offsets));
X close(dfd);
X }
X }
X llast_time = times(&tbuf);
X if ((lseek(kfd, offsets.sysinfo, 0) != ERROR) &&
X (read(kfd, &si_llast, sizeof(si_llast)) != ERROR) &&
X (lseek(kfd, offsets.swplo, 0) != ERROR) &&
X (read(kfd, &swplo, sizeof(swplo)) != ERROR) &&
X (lseek(kfd, offsets.v, 0) != ERROR) &&
X (read(kfd, &v_buf, sizeof(v_buf)) != ERROR) &&
X (lseek(kfd, offsets.lbolt, 0) != ERROR) &&
X (read(kfd, &lbolt, sizeof(lbolt)) != ERROR) &&
X (lseek(kfd, offsets.hz, 0) != ERROR) &&
X (read(kfd, &hz, sizeof(hz)) != ERROR) &&
X (lseek(kfd, offsets.timezone, 0) != ERROR) &&
X (read(kfd, &tz, sizeof(tz)) != ERROR) &&
X (lseek(kfd, offsets.dstflag, 0) != ERROR) &&
X (read(kfd, &dstflag, sizeof(dstflag)) != ERROR) &&
X (lseek(kfd, offsets.utsname, 0) != ERROR) &&
X (read(kfd, &utsname, sizeof(utsname)) != ERROR) &&
X#ifdef XENIX
X (lseek(kfd, offsets.coremap, 0) != ERROR) &&
X (read(kfd, &coremap, sizeof(coremap)) != ERROR))
X#else
X (lseek(kfd, offsets.gdstat, 0) != ERROR) &&
X (read(kfd, io_llast, sizeof(io_llast)) != ERROR))
X#endif
X {
X curr_time = time((long*)0);
X boot_time = curr_time - (lbolt / hz);
X strtime(boot_when, boot_time);
X strcat(boot_when, " ");
X strdate(strend(boot_when), boot_time);
X proc_size = v_buf.v_proc * sizeof(struct proc);
X if (!(proc_buf = (struct proc*)malloc(proc_size)))
X return(FALSE);
X file_size = v_buf.v_file * sizeof(struct file);
X if (!(file_buf = (struct file*)malloc(file_size)))
X return(FALSE);
X text_size = v_buf.v_text * sizeof(struct text);
X#ifdef XENIX
X temp = (unsigned int)coremap.mpent;
X offsets.mapent = (long)temp;
X mapent_size = coremap.ncells * sizeof(struct mapent);
X offsets.file += offsets.end + offsets.mem;
X offsets.inode += offsets.end + offsets.mem;
X#endif
X inode_size = v_buf.v_inode * sizeof(struct inode);
X max_size = text_size;
X if (inode_size > max_size)
X max_size = inode_size;
X#ifdef XENIX
X if (mapent_size > max_size)
X max_size = mapent_size;
X#endif
X if (!(sptr.where.ptr = malloc(max_size)))
X return(FALSE);
X sptr.what = UNDETERMINED;
X si_new = si_llast;
X#ifdef SYSV
X for (i = 0; i < DISKS; i++)
X io_new[i] = io_llast[i];
X#endif
X new_time = llast_time;
X return(TRUE);
X }
X else
X return(FALSE);
X}
X
int getcolor()
X{
X if (get_sspec())
X return(get_color(sspec));
X return(UNDETERMINED);
X}
X
void rdspec()
X{
X int status = FALSE;
X char *home, filename[50];
X struct passwd *pwent;
X
X if (home = getenv("HOME"))
X {
X strncpy(filename, home, sizeof(filename) - 1);
X strncat(filename, "/.monitorc", sizeof(filename) - 1);
X filename[49] = '\0';
X status = open_spec(filename);
X }
X if (!status)
X status = open_spec("/etc/monitorc");
X if (!status)
X return;
X while (get_lspec())
X {
X if (get_sspec())
X {
X if (streq(sspec, "FG", TRUE))
X def_fg = getcolor();
X else if (streq(sspec, "BG", TRUE))
X def_bg = getcolor();
X else if (streq(sspec, "HELP_FG", TRUE))
X help_fg = getcolor();
X else if (streq(sspec, "HELP_BG", TRUE))
X help_bg = getcolor();
X else if (streq(sspec, "USER", TRUE))
X {
X if (get_sspec())
X {
X if (streq(sspec, "ALL", TRUE))
X all_procs = TRUE;
X else
X {
X if (pwent = getpwnam(strlwr(sspec)))
X user = pwent->pw_uid;
X }
X }
X }
X else if (streq(sspec, "INTERVAL", TRUE))
X {
X if (get_ispec())
X sample_interval = ispec;
X }
X }
X }
X close_spec();
X}
X
int main(argc, argv)
X int argc;
X char *argv[];
X{
X int c, errflg = 0;
X struct passwd *pwent;
X
X extern char *optarg;
X
X rdspec();
X while ((c = getopt(argc, argv, "ai:u:")) != EOF)
X {
X switch (c)
X {
X case 'a' :
X all_procs = TRUE;
X break;
X case 'i' :
X sample_interval = atoi(optarg);
X break;
X case 'u' :
X if (streq(optarg, "ALL", TRUE))
X all_procs = TRUE;
X else if (pwent = getpwnam(strlwr(optarg)))
X user = pwent->pw_uid;
X break;
X case '?' :
X errflg++;
X break;
X }
X }
X if (errflg)
X {
X fprintf(stderr, "usage: %s [-a] [-i sample interval] [-u user name]\n", basename(argv[0]));
X exit(1);
X }
X if (((kfd = open("/dev/kmem", O_RDONLY)) != ERROR) &&
X ((sfd = open("/dev/swap", O_RDONLY)) != ERROR) &&
X ((mfd = open("/dev/mem", O_RDONLY)) != ERROR))
X {
X if (get_offset())
X {
X setuid(uid = getuid());
X setgid(gid = getgid());
X if (uid == 0)
X all_procs = TRUE;
X if (user != UNDETERMINED)
X {
X uid = user;
X all_procs = FALSE;
X }
X setup();
X do_scr(&main_menu);
X setdown();
X close(kfd);
X close(sfd);
X close(mfd);
X }
X else
X fprintf(stderr, "could not get offset\n");
X }
X else
X fprintf(stderr, "could not open device files\n");
X}
X
END_OF_FILE
if test 22192 -ne `wc -c <'monitor1.c'`; then
echo shar: \"'monitor1.c'\" unpacked with wrong size!
fi
# end of 'monitor1.c'
fi
echo shar: End of archive 6 \(of 9\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 9 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
More information about the Comp.unix.xenix
mailing list