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