jct@jct.UUCP (jct) (07/11/89)
#! /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
jimh1@.UUCP (jimh1 is ACK alter ego) (07/19/89)
Monitor part 6 of 9 crept past me like the hint of juleps in the night with barren thoughts I ask Billy Budd, the sly tounged devil to post or e-mail me the missing Monitor 6 of 9. Can you afford the e-stamp, Billy? Jim Hinds Verifone, Mililani, HI