v29i103: top-3.4 - top process display, V3.4, Part02/22

2 views
Skip to first unread message

William Lefebvre

unread,
Sep 1, 1996, 3:00:00 AM9/1/96
to

Submitted-By: w...@groupsys.com (William Lefebvre)
Posting-Number: Volume 29, Issue 103
Archive-Name: top-3.4/part02

#! /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 2 (of 22)."
# Contents: top-3.4/INSTALL top-3.4/Porting top-3.4/README
# top-3.4/m-template top-3.4/machine/m_next32.man top-3.4/screen.c
# top-3.4/username.c
# Wrapped by lefebvre@acapulco on Fri Aug 30 12:35:49 1996
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'top-3.4/INSTALL' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'top-3.4/INSTALL'\"
else
echo shar: Extracting \"'top-3.4/INSTALL'\" \(7482 characters\)
sed "s/^X//" >'top-3.4/INSTALL' <<'END_OF_FILE'
X TOP
X Version 3.4
X
X William LeFebvre
X and a cast of dozens
X
XINSTALLATION
X
XConfiguration and installation of top is very straightforward. After
Xunpacking the sources, run the script "Configure". It will present you
Xwith a series of questions, all of which should be explained in the
Xpresentation. After you have answered all the questions, "Configure" will
Xperform all the necessary configuration. Once this is finished, type
X"make install". Make will compile the sources then install the resulting
Xexecutable and manual page in the appropriate places.
X
XThe most difficult step in the configuration is the choice of an
Xappropriate machine-specific module. The Configure script gives you a
Xlist of choices complete with brief descriptions of when each choice is
Xappropriate. Each module is contained in a separate c file in the
Xdirectory "machine". The module contains all of the machine-specific code
Xthat makes top work correctly on the architecture in question. All of the
Xcode in the top-level directory is machine-independent (or at least
Xstrives to be). Hints for some module choices that are not obvious are
Xgiven at the end of this file.
X
XThe first comment in each c file in that directory contains the synopsis
XAND a detailed description of the machines for which that module is
Xappropriate. It also contains a list of authors for that module. If you
Xare really stumped in this choice, use grep to find your machine
Xmanufacturer's name or operating system name in machine/*.c. If you still
Xcan't find one that is appropriate, then chances are very good that one
Xhasn't been written yet. If that is the case, then you are out of luck.
X
XHANDLING MULTIPLE ARCHITECTURES
X
XIf you need to recompile top for a different architecture (that is, using
Xa different module) you need to reconfigure top. A short cut is available
Xto make this a little easier. If all of your previous answers to the
Xconfiguration questions (except for the module name of course) are
Xadequate for the new architecture, then you can just use the command
X"Configure <modulename>". The configuration script will reconfigure top
Xusing the new module and all the answers you gave last time. It will
Xfinish with a "make clean". Once that completes, type "make install"
Xand make will compile the sources and do the installation.
X
XHANDLING MULTIPLE OS VERSIONS
X
XBy far the most frequently received bug report for top is something like
Xthis: "We just upgraded our operating system to version 99.9.9.9 and top
Xbroke. What should we do?" The simple answer is "recompile".
X
XTop is very sensitive to changes in internal kernel data structures
X(especially the proc and user structures). Some operating systems
X(especially SunOS) are notorious for changing these structure in every
Xminor release of the OS. This means that a top executable made under one
Xversion of the OS will not always work correctly (if even at all) under
Xanother version. This is just one of those tough facts of life. There is
Xreally no way around it.
X
XTo make life even worse, some operating systems (SunOS again) will use
Xslightly different proc and user structures on different models. For
Xexample, "top" built on a SparcStation 2 will not run correctly on a
XSparcStation 10, even if they are both running SunOS 4.1.3. These
Xunfortunate circumstances make maintaining top very difficult, especially
Xin an environment that runs several different versions of the same
Xoperating system.
X
XBut there is hope. If your operating system has a properly functioning
X"uname" command then you can handle this problem rather gracefully.
XIncluded in the distribution is a shell file called "metatop". All this
Xshell file does is:
X
X exec top-`uname -m`-`uname -r` "$@"
X
XSo when you run this script, it execs a filename that is unique to your
Xspecific machine architecture and your OS revision number.
X
XTo use "metatop", do the following:
X
X . on any machine, run Configure and choose the module that is
X appropriate for the machine
X . for all machines which use the same module:
X . group machines according to machine architecture AND OS
X revision number (i.e.: sun4-4.1.1, sun4c-4.1.1, sun4c-4.1.2,
X sun4-4.1.3, sun4c-4.1.3, sun4m-4.1.3, ...)
X . for each group, choose one machine from that group and on it
X run "make clean; make installmeta".
X
X
XThe "installmeta" rule in the makefile will insure that top is compiled,
Xinstall the shell file "metatop" as "top", then install the executable
X"top" with a name appropriate to the machine architecture and OS revision.
X
X
XHINTS FOR CHOOSING THE CORRECT MODULE:
X
XSOLARIS 2.x
X
XFor Solaris versions 2.0 thru 2.3, use the module sunos5. For Solaris
Xversions 2.4 and higher (including 2.5 and 2.5.1) use the module sunos54.
X
XSUNOS 4.x AND MULTIPROCESSOR ARCHITECTURES
X
XFirst, we need to be speaking the same language:
X
Xsun4 a regular sparc sun 4 architecture machine (sparc station 1,
X sparc station 2, IPC, SLC, etc.)
X
Xsun4m a multiprocessor sparc (Sparc 10, 4/670, 4/690)
X
XI intended to write the sunos4 module so that an executable compiled on a
Xsun4m machine would work correctly on a sun4 machine. Unfortunately my
Xexperiments indicate that this cannot be done. It turns out that the user
Xstructure is so different between these two architectures that nothing
Xshort of a serious hack will make the same executable work correctly on
Xboth machines. I recommend that you use the separate module "sunos4mp"
Xwhen making an executable for a sun4m architecture, and use "sunos4" when
Xmaking an executable for sun4 or sun4c architectures.
X
XDIGITAL UNIX V4.0
X
XThis is the successor to DECOSF/1. Use the module decosf1.
X
XSOLBOURNE OPERATING SYSTEM (OS/MP)
X
XIf you are running OS/MP version 4.1A, then use the module "osmp4.1a".
X
XIf you are running a version of OS/MP OLDER than 4.1A (that is, one
Xof its predecessors), use the module "sunos4".
X
XIf you are running OS/MP 4.1B or LATER, use the module "sunos4mp".
X
XHP/UX OPERATING SYSTEM
X
XThe module hpux8 works on all version 8 systems. Some say that it works
Xwith version 9 as well, but one user did send me a separate module for
Xversion 9. This module has only been tested on series 800 machines. I
Xwould recommend the following for those running version 9: try hpux9 and
Xif it doesn't work then try hpux8. If neither work, then send mail to me
Xand/or the modules' authors. Another note: we have a model 730 supposedly
Xrunning version 9.01. The module hpux9 did not compile successfully, but
Xthe module hpux8 worked fine. The module hpux10 works on all revisions of
XHP/UX 10 except 10.10, where HP removed the definition of the proc structure
Xfrom the system include files.
X
XNET/2 386BSD SYSTEMS
X
XIf your version of the operating system has patchkit 2.4 installed,
Xthen you will need to modify machine/m_386bsd.c and uncomment the
Xdefinition of PATCHED_KVM. This patchkit makes what more than a few
Xpeople believe to be a wholly unnecessary patch to the way the kvm
Xroutines work.
X
XA/UX SYSTEMS
X
XThere is a module for A/UX 3.0 and 3.1. Whether or not it works for
Xany other version is not known. Proceed at your own risk.
X
XAlthough AUX does not generally have a renice systemcall, it can be
Ximplemented by tweeking kernel memory. The flag IMPLEMENT_SETPRIORITY
Xcontrols the inclusion of this code. It is off be default. While
Xsuch a simple hack should not be difficult to get right, USE THIS
XFEATURE AT YOUR OWN RISK!
X
END_OF_FILE
if test 7482 -ne `wc -c <'top-3.4/INSTALL'`; then
echo shar: \"'top-3.4/INSTALL'\" unpacked with wrong size!
fi
# end of 'top-3.4/INSTALL'
fi
if test -f 'top-3.4/Porting' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'top-3.4/Porting'\"
else
echo shar: Extracting \"'top-3.4/Porting'\" \(7062 characters\)
sed "s/^X//" >'top-3.4/Porting' <<'END_OF_FILE'
XInstructions for porting top to other architectures.
X
XThis is still a preliminary document. Suggestions for improvement are
Xmost welcome.
X
XMy address is now "lefe...@dis.anl.gov".
X
XBefore you embark on a port, please send me a mail message telling me
Xwhat platform you are porting top to. There are three reasons for
Xthis: (1) I may already have a port, (2) module naming needs to be
Xcentralized, (3) I want to loosely track the various porting efforts.
XYou do not need to wait for an "okay", but I do want to know that you
Xare working on it. And of course, once it is finished, please send me
Xthe module files so that I can add them to the main distribution!
X
X----------
X
XThere is one set of functions which extract all the information that
Xtop needs for display. These functions are collected in to one file.
XTo make top work on a different architecture simply requires a
Xdifferent implementation of these functions. The functions for a
Xgiven architecture "foo" are stored in a file called "m_foo.c". The
XConfigure script looks for these files and lets the configurer choose
Xone of them. This file is called a "module". The idea is that making
Xtop work on a different machine only requires one additional file and
Xdoes not require changes to any existing files.
X
XA module template is included in the distribution, called "m-template".
XTo write your own module, it is a good idea to start with this template.
XIf you architecture is similar to one for which a module already
Xexists, then you can start with that module instead. If you do so,
Xremember to change the "AUTHOR" section at the top!
X
XThe first comment in a module contains information which is extracted
Xand used by Configure. This information is marked with words in all
Xcapitals (such as "SYNOPSIS:" and "LIBS:"). Go look at m-template: it
Xis fairly self-explanatory. The text after "LIBS:" (on the same line)
Xis extracted and included in the LIBS definition of the Makefile so
Xthat extra libraries which may be necessary on some machines (such as
X"-lkvm") can be specified in the module. The text after "CFLAGS:"
X(on the same line) is extracted and included as flags in the "CFLAGS"
Xdefinition of the Makefile (thus in every compilation step). This is
Xused for rare circumstances only: please don't abuse this hook.
X
XSome operating systems have idiosyncrasies which will affect the form
Xand/or content of the information top displays. You may wish to
Xdocument such anomalies in the top man page. This can be done by adding
Xa file called m_{modulename}.man (where {modulename} is replaced with
Xthe name of the module). Configure will automatically add this file to
Xthe end of the man page. See m_sunos4.man for an example.
X
XA module is concerned with two structures:
X
XThe statics struct is filled in by machine_init. Each item is a
Xpointer to a list of character pointers. The list is terminated
Xwith a null pointer.
X
Xstruct statics
X{
X char **procstate_names; /* process state names */
X char **cpustate_names; /* cpu state names */
X char **memory_names; /* memory information names */
X};
X
XThe system_info struct is filled in by get_system_info and
Xget_process_info.
X
Xstruct system_info
X{
X int last_pid; /* last pid assigned (0 means non-sequential assignment) */
X double load_avg[NUM_AVERAGES]; /* see below */
X int p_total; /* total number of processes */
X int p_active; /* number of procs considered "active" */
X int *procstates; /* array of process state counters */
X int *cpustates; /* array of cpustate counters */
X int *memory; /* memory information */
X};
X
XThe last three pointers each point to an array of integers. The
Xlength of the array is determined by the length of the corresponding
X_names array in the statics structure. Furthermore, if an entry in a
X_names array is the empty string ("") then the corresponding value in
Xthe value array will be skipped over. The display routine displays,
Xfor example, the string procstate_names[0] then the number
Xprocstates[0], then procstate_names[1], procstates[1], etc. until
Xprocstate_names[N] == NULL. This allows for a tremendous amount of
Xflexibility in labeling the displayed values.
X
X"procstates" and "memory" are displayed as straight integer values.
XValues in "cpustates" are displayed as a percentage * 10. For
Xexample, the (integer) value 105 is displayed as 10.5%.
X
XThese routines must be defined by the machine dependent module.
X
Xint machine_init(struct statics *)
X
X returns 0 on success and -1 on failure,
X prints error messages
X
Xchar *format_header(char *)
X
X Returns a string which should be used as the header for the
X process display area. The argument is a string used to label
X the username column (either "USERNAME" or "UID") and is always
X 8 characters in length.
X
Xvoid get_system_info(struct system_info *)
X
Xcaddr_t get_process_info(struct system_info *, int, int, int (*func)())
X
X returns a handle to use with format_next_process
X
Xchar *format_next_process(caddr_t, char *(*func)())
X
X returns string which describes next process
X
Xint proc_compare(caddr_t, caddr_t)
X
X qsort comparison function
X
Xuid_t proc_owner(pid_t)
X
X Returns the uid owner of the process specified by the pid argument.
X This function is VERY IMPORTANT. If it fails to do its job, then
X top may pose a security risk.
X
X
Xget_process_info is called immediately after get_system_info. In
Xfact, the two functions could be rolled in to one. The reason they
Xare not is mostly historical.
X
XTop relies on the existence of a function called "setpriority" to
Xchange a process's priority. This exists as a kernel call on most 4.3
XBSD derived Unixes. If neither your operating system nor your C
Xlibrary supplies such a function, then you will need to add one to the
Xmodule. It is defined as follows:
X
X int setpriority (int dummy, int who, int niceval)
X
X For the purposes of top, the first argument is meaningless.
X The second is the pid and the third is the new nice value.
X This function should behave just like a kernel call, setting
X errno and returning -1 in case of an error. This function MUST
X check to make sure that a non-root user does not specify a nice
X value less than the process's current value. If it detects such
X a condition, it should set errno to EACCES and return -1.
X Other possible ERRNO values: ESRCH when pid "who" does not exist,
X EPERM when the invoker is not root and not the same as the
X process owner.
X
XNote that top checks process ownership and should never call setpriority
Xwhen the invoker's uid is not root and not the same as the process's owner
Xuid.
X
X
XThe file "machine.h" contains definitions which are useful to modules
Xand to top.c (such as the structure definitions). You SHOULD NOT need
Xto change it when porting to a new platform.
X
XPorting to a new platform should NOT require any changes to existing
Xfiles. You should only need to add m_ files. If you feel you need a
Xchange in one of the existing files, please contact me so that we can
Xdiscuss the details. I want to keep such changes as general as
Xpossible.
X
END_OF_FILE
if test 7062 -ne `wc -c <'top-3.4/Porting'`; then
echo shar: \"'top-3.4/Porting'\" unpacked with wrong size!
fi
# end of 'top-3.4/Porting'
fi
if test -f 'top-3.4/README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'top-3.4/README'\"
else
echo shar: Extracting \"'top-3.4/README'\" \(7331 characters\)
sed "s/^X//" >'top-3.4/README' <<'END_OF_FILE'
X TOP
X Version 3.4
X
X William LeFebvre
X and a cast of dozens
X
X
XIf you do not want to read this entire file, then at least read
Xthe section at the end entitled "KNOWN PROBLEMS".
X
XIf you are having any problems getting top to work, please read the
Xfile "FAQ" *before* contacting me. Thank you.
X
X"top" is a program that will give continual reports about the state of
Xthe system, including a list of the top cpu using processes. Version 3
Xof "top" has three primary design goals: provide an accurate snapshot of
Xthe system and process state, not be one of the top processes itself, be
Xas portable as possible.
X
XVersion 3 has many bug fixes from version 2.5, and it has also been
Xreorganized in a major way to make it easy to port to other platforms.
XAll system dependent code is now contained in one file.
X
XTop now includes a configuration script called "Configure". It helps
Xthe installer choose the correct parameters for this particular
Xinstallation. This script MUST be run before attempting to compile top.
X
XTop requires read access to the memory files "/dev/kmem" and "/dev/mem"
Xas well as the system image "/vmunix". Some installations have these
Xfiles protected from general access. These sites would have to install
Xthis program in the same way that programs such as "ps" are installed.
XIn addition, on those Unix variants that support the proc filesystem
X(such as SVR4 and Solaris 2), top requires read access to all the files
Xin /proc: typically dictating that top be installed setuid to root.
X
XCAVEAT: version 3 of top has internal commands that kill and renice
Xprocesses. Although I have taken steps to insure that top makes
Xappropriate checks with these commands, I cannot guarantee that these
Xinternal commands are totally secure. IF YOU INSTALL top as a SETUID
Xprogram, you do so AT YOUR OWN RISK! I realize that some operating
Xsystems will require top to run setuid, and I will do everything I can
Xto make sure that top is a secure setuid program.
X
XConfigure will ask you to input values for certain parameters. Before
Xeach parameter, Configure will display a description of what the
Xparameter does. Read the description and choose an appropriate value.
XSometimes a default will appear in brackets. Typing just return will
Xchoose the default.
X
XSystem support now takes the form of "modules". Adding support for
Xa different architecture requires only adding a module. Configure
Xasks which module to use when it is configuring top. See the file
X"Porting" for a description of how to write your own module.
X
XTo compile and install "top", read the file "INSTALL" and follow the
Xdirections and advice contained therein.
X
XOnce you have created a binary for one particular type of machine, you
Xcan reconfigure for another type with "./Configure modulename" where
X"modulename" is replaced with the appropriate module name. All other
Xparameter values are kept the same. Note that in some cases this may
Xnot be appropriate.
X
XIf you make any kind of change to "top" that you feel would be
Xbeneficial to others who use this program, or if you find and fix a bug,
Xplease send me the change.
X
XBe sure to read the FAQ enclosed with the distrubution. It contains
Xanswers to the most commonly asked questions about the configuration,
Xinstallation, and operation of top.
X
XAVAILABILITY
X
XThe latest version of "top" is now being made available via anonymous
XFTP from the host "ftp.groupsys.com" in the directory "/pub/top".
XAdditional modules will be made available in the directory
X"/pub/top/m". The site "eecs.nwu.edu" will continue to house copies
Xof the distribution as well.
X
XHere are HTML links for the two best "top" archive sites:
X
X<A HREF="ftp://ftp.groupsys.com/pub/top>Top archive (groupsys.com)</A>
X<A HREF="ftp://eecs.nwu.edu/pub/top>Top archive (eecs.nwu.edu)</A>
X
XNew releases will be posted to comp.sources.unix as they become
Xavailable. Sites which arhive that newsgroup will also contain copies
Xof the distribution.
X
XKNOWN PROBLEMS:
X
XGnu CC
X
XCompiling via Gnu CC continued to be the source of most of the
Xquestions I receive. By far the most common mistake made by those
Xattempting to compile top with Gnu CC is out of date include files.
XWhen the operating system is upgraded, the include files that are part
Xof the gcc package MUST also be updated. Gcc maintains its own
Xinclude files. Even a minor OS upgrade can involve changes to some of
Xthe kernel's internal data structures, which are defined in include
Xfiles in "sys". Top is very sensitive to these changes. If you are
Xcompiling with gcc and experience any sort of strange problems, please
Xmake sure the include files you are using are up to date BEFORE
Xsending me a bug report. Look in the gcc source distribution for the
Xshell script "fixincludes".
X
XHP/UX 10.10
X
XIn their infinite wisdom, the folks at HP have decided that mere mortals
Xsuch as you and I don't need to know what the kernel's proc structure looks
Xlike. To that end, they have removed all useful content from the include
Xfile <sys/proc.h> in version 10.10. As a result, top will not compile
Xunder 10.10. What HP is trying to accomplish with this move is to force
Xiconoclasts such as myself to use "pstat" for collecting all process
Xinformation. I have no immediate solution for this problem, but hope to
Xobtain a sufficiently complete definition of "struct proc" at some point in
Xthe near future. Stay tuned.
X
XDIGITAL UNIX 4.0 (DECOSF/1 V4.0)
X
XA user has reported that idle processes are not displayed regardless
Xof the flags used when invoking top. We have not had time to track
Xthis problem down.
X
XDECOSF/1 V3.0
X
XThere is a bug either in the module, in utils.c, or in DEC's optimizer that
Xis tickled by the decosf1 module when compiled under V3.0 (and perhaps
Xearlier versions). Top compiled using DEC's compiler with optimization
Xwill consistently produce a segmentation fault (in format_next_process
Xwhile calling sprintf). To work around this problem, either compile top
Xwith gcc or turn off optimization (compile without -O). We think that
Xone of the bugs fixed in utils.c fixed this problem as well, but we are
Xnot certain.
X
X
XSystem V R 4.2
X
XLoad average and memory displays do not work. The problem has been
Xtraced down to a potential bug in the "mem" driver. The author
Xof the svr42 module is working on a fix.
X
X
X
XGRATITUDE
X
XMy perpetual thanks to all the people who have helped me support top
Xon so many platforms. Without these people, top would not be what it
Xis. Here is a partial list of contributors and other individuals.
X
X Robert Boucher <bou...@sofkin.ca>
X Marc Cohen <ma...@aai.com>
X David Cutter <d...@grail.com>
X Casper Dik <cas...@fwi.uva.nl>
X Charles Hedrick <hed...@geneva.rutgers.edu>
X Andrew Herbert <and...@werple.apana.org.au>
X Jeff Janvrin <jeff.j...@columbiasc.ncr.com>
X Torsten Kasch <tor...@techfak.uni-bielefeld.de>
X Petri Kutvonen <kutv...@cs.helsinki.fi>
X William L. Jones <jones@chpc>
X Tim Pugh <tp...@oce.orst.edu>
X Steve Scherf <sch...@swdc.stratus.com>
X Phillip Wu <pw...@qantek.com.au>
X
X(My apologies if I missed anyone.)
X
X
XAUTHOR
X
X William LeFebvre
X Group sys Consulting
X w...@groupsys.com
X
X
X U.S. Mail address:
X William LeFebvre
X 170 Colton Crest Drive
X Alpharetta, GA 30202
X (770) 813-3224
END_OF_FILE
if test 7331 -ne `wc -c <'top-3.4/README'`; then
echo shar: \"'top-3.4/README'\" unpacked with wrong size!
fi
# end of 'top-3.4/README'
fi
if test -f 'top-3.4/m-template' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'top-3.4/m-template'\"
else
echo shar: Extracting \"'top-3.4/m-template'\" \(5276 characters\)
sed "s/^X//" >'top-3.4/m-template' <<'END_OF_FILE'
X/*
X * top - a top users display for Unix
X *
X * THIS IS A TEMPLATE FILE FOR A MACHINE DEPENDENT (m_...c) FILE
X *
X * SYNOPSIS: one line description of machine this module works with
X *
X * DESCRIPTION:
X * Detailed description of this machine dependent module.
X * It can be multiple lines, but a blank comment line (one with only an
X * asterisk) is considered to end it. Place here a complete list of
X * the machines and OS versions that this module works on.
X *
X * LIBS: list of special libraries to include at link step (REMOVE THIS LINE IF NOT NEEDED)
X *
X * AUTHOR: your name and <yo...@internet.address>
X */
X
X#include "top.h"
X#include "machine.h"
X
X
X/*
X * These definitions control the format of the per-process area
X */
X
Xstatic char header[] =
X " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
X/* 0123456 -- field to fill in starts at header+6 */
X#define UNAME_START 6
X
X#define Proc_format \
X "%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %5.2f%% %5.2f%% %.14s"
X
X/* these are for detailing the process states */
X
Xint process_states[?];
Xchar *procstatenames[] = {
X "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
X " zombie, ", " stopped, ",
X NULL
X};
X
X/* these are for detailing the cpu states */
X
Xint cpu_states[?];
Xchar *cpustatenames[] = {
X "user", "nice", "system", "idle",
X NULL
X};
X
X/* these are for detailing the memory statistics */
X
Xint memory_stats[?];
Xchar *memorynames[] = {
X "K available, ", "K in use, ", "K free, ", "K locked", NULL
X};
X
X/* useful externals */
Xextern int errno;
Xextern char *sys_errlist[];
X
Xlong lseek();
Xlong time();
Xlong percentages();
X
Xmachine_init(statics)
X
Xstruct statics *statics;
X
X{
X return(0);
X}
X
Xchar *format_header(uname_field)
X
Xregister char *uname_field;
X
X{
X register char *ptr;
X
X ptr = header + UNAME_START;
X while (*uname_field != '\0')
X {
X *ptr++ = *uname_field++;
X }
X
X return(header);
X}
X
Xget_system_info(si)
X
Xstruct system_info *si;
X
X{
X}
X
Xstatic struct handle handle;
X
Xcaddr_t get_process_info(si, sel, compare)
X
Xstruct system_info *si;
Xstruct process_select *sel;
Xint (*compare)();
X
X{
X return((caddr_t)&handle);
X}
X
Xchar fmt[128]; /* static area where result is built */
X
X/* define what weighted cpu is. */
X#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
X ((pct) / (1.0 - exp((pp)->p_time * logcpu))))
X
Xchar *format_next_process(handle, get_userid)
X
Xcaddr_t handle;
Xchar *(*get_userid)();
X
X{
X return(fmt);
X}
X
X/*
X * getkval(offset, ptr, size, refstr) - get a value out of the kernel.
X * "offset" is the byte offset into the kernel for the desired value,
X * "ptr" points to a buffer into which the value is retrieved,
X * "size" is the size of the buffer (and the object to retrieve),
X * "refstr" is a reference string used when printing error meessages,
X * if "refstr" starts with a '!', then a failure on read will not
X * be fatal (this may seem like a silly way to do things, but I
X * really didn't want the overhead of another argument).
X *
X */
X
Xgetkval(offset, ptr, size, refstr)
X
Xunsigned long offset;
Xint *ptr;
Xint size;
Xchar *refstr;
X
X{
X if (kvm_read(kd, offset, ptr, size) != size)
X {
X if (*refstr == '!')
X {
X return(0);
X }
X else
X {
X fprintf(stderr, "top: kvm_read for %s: %s\n",
X refstr, sys_errlist[errno]);
X quit(23);
X }
X }
X return(1);
X}
X
X/* comparison routine for qsort */
X/* NOTE: this is specific to the BSD proc structure, but it should
X give you a good place to start. */
X
X/*
X * proc_compare - comparison function for "qsort"
X * Compares the resource consumption of two processes using five
X * distinct keys. The keys (in descending order of importance) are:
X * percent cpu, cpu ticks, state, resident set size, total virtual
X * memory usage. The process states are ordered as follows (from least
X * to most important): WAIT, zombie, sleep, stop, start, run. The
X * array declaration below maps a process state index into a number
X * that reflects this ordering.
X */
X
Xstatic unsigned char sorted_state[] =
X{
X 0, /* not used */
X 3, /* sleep */
X 1, /* ABANDONED (WAIT) */
X 6, /* run */
X 5, /* start */
X 2, /* zombie */
X 4 /* stop */
X};
X
Xproc_compare(pp1, pp2)
X
Xstruct proc **pp1;
Xstruct proc **pp2;
X
X{
X register struct proc *p1;
X register struct proc *p2;
X register int result;
X register pctcpu lresult;
X
X /* remove one level of indirection */
X p1 = *pp1;
X p2 = *pp2;
X
X /* compare percent cpu (pctcpu) */
X if ((lresult = p2->p_pctcpu - p1->p_pctcpu) == 0)
X {
X /* use cpticks to break the tie */
X if ((result = p2->p_cpticks - p1->p_cpticks) == 0)
X {
X /* use process state to break the tie */
X if ((result = sorted_state[p2->p_stat] -
X sorted_state[p1->p_stat]) == 0)
X {
X /* use priority to break the tie */
X if ((result = p2->p_pri - p1->p_pri) == 0)
X {
X /* use resident set size (rssize) to break the tie */
X if ((result = p2->p_rssize - p1->p_rssize) == 0)
X {
X /* use total memory to break the tie */
X result = PROCSIZE(p2) - PROCSIZE(p1);
X }
X }
X }
X }
X }
X else
X {
X result = lresult < 0 ? -1 : 1;
X }
X
X return(result);
X}
X
Xproc_owner(pid)
X
Xint pid;
X
X{
X /* returns uid of owner of process pid */
X return(uid);
X}
X
END_OF_FILE
if test 5276 -ne `wc -c <'top-3.4/m-template'`; then
echo shar: \"'top-3.4/m-template'\" unpacked with wrong size!
fi
# end of 'top-3.4/m-template'
fi
if test -f 'top-3.4/machine/m_next32.man' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'top-3.4/machine/m_next32.man'\"
else
echo shar: Extracting \"'top-3.4/machine/m_next32.man'\" \(4550 characters\)
sed "s/^X//" >'top-3.4/machine/m_next32.man' <<'END_OF_FILE'
X.SH "NEXTSTEP DIFFERENCES"
XNEXTSTEP v.0.4 of TOP - 2/22/1996 tpugh
X.br
XThe NEXTSTEP port includes reports on the number of threads per process which appears under the heading "THR".
X.PP
XThe field "%WCPU" has been removed until we can figure out how to calculate the weighted CPU time with the given process information.
X.PP
XMemory statistics show the total RAM for the system, and the number of active, inactive, wired, and free Mach virtual memory pages (in bytes). Also shown is the number of bytes moving into and out of virtual memory.
X.PP
XThe NEXTSTEP port was written by Tim Pugh <tp...@oce.orst.edu>.
X.PP
X.SH COMPATIBILITY - next32
X.br
XThis is the machine-dependent module for NEXTSTEP v3.x
X.br
XReported to work for NEXTSTEP v3.0, v3.2, and v3.3 Mach OS:
X.br
X NEXTSTEP v3.0 on Motorola machines.
X.br
X NEXTSTEP v3.2 on Intel and Motorola machines.
X.br
X NEXTSTEP v3.3 on Intel and Motorola machines.
X.br
XProblem with command column for (Choose next40 for fix):
X.br
X NEXTSTEP v3.2 on HP machines.
X.br
X NEXTSTEP v3.3 on HP and Sparc machines.
X.br
XHas not been tested for NEXTSTEP v2.x machines, although it should work.
X.br
XHas not been tested for NEXTSTEP v3.1 machines, although it should work.
X.PP
X.SH COMPATIBILITY - next40
X.br
XThis is the machine-dependent module for NEXTSTEP v3.x/4.x
X.br
XReported to work for:
X.br
X NEXTSTEP v3.2 on HP machines.
X.br
X NEXTSTEP v3.3 on HP and Sparc machines.
X.br
XHas not been tested for NEXTSTEP v4.0 machines, although it should work.
X.PP
X.SH HISTORY
X.br
X* 9/8/95 tpugh. Removed the %WCPU field, no support for it.
X.br
X* 9/8/95 tpugh. Removed all C++ style comments from machine.c to be
XANSI C compatible.
X.br
X* 2/13/96 tpugh. Fixed command name display problem for hppa and sparc machines,and NS4.0 alpha machines. NeXT changed the task structure, so top could not find utask structure. <mach/task.h> is not shipped with any NEXTSTEP system.
X.br
X* 2/14/96 tpugh. Reduced line length to less than 80 columns. Some commands are long and will extend beyond 80 colums.
X.br
X* 2/14/96 tpugh. Fixed "top -U" fails with bus error. In special cases where only a specific user is displayed, the process index variable was being improperly advanced, resulting in invalid process addresses and bus errors.
X.br
X* 2/14/96 tpugh. Eliminated the text artifact in the command column.
X.br
X* 2/22/96 tpugh. Fixed problem with quiting the program. When quiting the program, a message "nobody" was printed and the cursor was not placed at the bottom of the screen. The hash_table was corrupting memory when hashit(uid=-2) = -2 or any negative number.
X.br
X* 2/22/96 tpugh. Fixed incorrect load average display. Incorrect scaling of the kernel load average fixed-point values.
X.PP
X.SH FREQUENTLY ASKED QUESTIONS
X.br
X#1: top 3.3 (after configuring for next32 with all defaults) on my i386 running NEXTSTEP 3.3, I get:
X.br
XError calling task_by_unix_pid(): failure(5)
X.PP
XAnswer:
X.br
XThe call is failing due to TOP file permission problems. The user must be the superuser, root, or the program must have root privileges to work properly. So install "top" with the permissions 4755. Setting the group sticky bit for kmem does not work, because TOP needs to communicate with the Mach kernal for task and thread info, which requires root privileges.
X.PP
XAs root, do the following:
X.br
Xhostname# chown root.kmem top
X.br
Xhostname# chmod 4755 top
X.br
Xhostname# ls -lg top
X.br
X-rwsr-xr-x 1 root kmem 121408 Sep 1 10:14 top*
X.PP
X#2: How to compile top to create a multiple architecture binary file?
X.PP
XAnswer:
X.br
XAdd the -arch flags to the Makefile. Due to the task.h file differences between (m68k,Intel) and (sparc,hppa) NEXTSTEP 3.x operating systems, a single binary file can not be generated.
X.br
XChange line 61 to:
X.br
X CDEFS = -O -arch m68k -arch i386 -arch hppa -arch sparc
X.PP
XAdd $(CFLAGS) to link command. Change line 79 to:
X.br
X $(CC) $(CFLAGS) -o top $(OBJS) -ltermcap -lm $(LIBS)
X.PP
X#3: I installed 'top' chmod 4711, chown root.kmem, but cannot use the '-q'
Xflag unless I am logged in as 'root'
X.br
X"top: warning: `-q' option can only be used by root"
X.br
XThis seems to indicate that the setuid to root isn't being recognized
Xcorrectly.
X.PP
XAnswer:
X.br
XIn order to run top with the "-q" command, top currently requires the user to be logged in a root because top checks the uid of the user logged in, not the effective uid of the file. Why? To not allow regular users to swamp the system with a high-priority process. Imagine what a regular user could do with "top -q -s0 all"!
X.PP
END_OF_FILE
if test 4550 -ne `wc -c <'top-3.4/machine/m_next32.man'`; then
echo shar: \"'top-3.4/machine/m_next32.man'\" unpacked with wrong size!
fi
# end of 'top-3.4/machine/m_next32.man'
fi
if test -f 'top-3.4/screen.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'top-3.4/screen.c'\"
else
echo shar: Extracting \"'top-3.4/screen.c'\" \(9664 characters\)
sed "s/^X//" >'top-3.4/screen.c' <<'END_OF_FILE'
X/*
X * Top users/processes display for Unix
X * Version 3
X *
X * This program may be freely redistributed,
X * but this entire comment MUST remain intact.
X *
X * Copyright (c) 1984, 1989, William LeFebvre, Rice University
X * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
X */
X
X/* This file contains the routines that interface to termcap and stty/gtty.
X *
X * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
X *
X * I put in code to turn on the TOSTOP bit while top was running, but I
X * didn't really like the results. If you desire it, turn on the
X * preprocessor variable "TOStop". --wnl
X */
X
X#include "os.h"
X#include "top.h"
X
X#include <sys/ioctl.h>
X#ifdef CBREAK
X# include <sgtty.h>
X# define SGTTY
X#else
X# ifdef TCGETA
X# define TERMIO
X# include <termio.h>
X# else
X# define TERMIOS
X# include <termios.h>
X# endif
X#endif
X#if defined(TERMIO) || defined(TERMIOS)
X# ifndef TAB3
X# ifdef OXTABS
X# define TAB3 OXTABS
X# else
X# define TAB3 0
X# endif
X# endif
X#endif
X#include "screen.h"
X#include "boolean.h"
X
Xextern char *myname;
X
Xint putstdout();
X
Xint overstrike;
Xint screen_length;
Xint screen_width;
Xchar ch_erase;
Xchar ch_kill;
Xchar smart_terminal;
Xchar PC;
Xchar *tgetstr();
Xchar *tgoto();
Xchar termcap_buf[1024];
Xchar string_buffer[1024];
Xchar home[15];
Xchar lower_left[15];
Xchar *clear_line;
Xchar *clear_screen;
Xchar *clear_to_end;
Xchar *cursor_motion;
Xchar *start_standout;
Xchar *end_standout;
Xchar *terminal_init;
Xchar *terminal_end;
Xshort ospeed;
X
X#ifdef SGTTY
Xstatic struct sgttyb old_settings;
Xstatic struct sgttyb new_settings;
X#endif
X#ifdef TERMIO
Xstatic struct termio old_settings;
Xstatic struct termio new_settings;
X#endif
X#ifdef TERMIOS
Xstatic struct termios old_settings;
Xstatic struct termios new_settings;
X#endif
Xstatic char is_a_terminal = No;
X#ifdef TOStop
Xstatic int old_lword;
Xstatic int new_lword;
X#endif
X
X#define STDIN 0
X#define STDOUT 1
X#define STDERR 2
X
Xinit_termcap(interactive)
X
Xint interactive;
X
X{
X char *bufptr;
X char *PCptr;
X char *term_name;
X char *getenv();
X int status;
X
X /* set defaults in case we aren't smart */
X screen_width = MAX_COLS;
X screen_length = 0;
X
X if (!interactive)
X {
X /* pretend we have a dumb terminal */
X smart_terminal = No;
X return;
X }
X
X /* assume we have a smart terminal until proven otherwise */
X smart_terminal = Yes;
X
X /* get the terminal name */
X term_name = getenv("TERM");
X
X /* if there is no TERM, assume it's a dumb terminal */
X /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
X if (term_name == NULL)
X {
X smart_terminal = No;
X return;
X }
X
X /* now get the termcap entry */
X if ((status = tgetent(termcap_buf, term_name)) != 1)
X {
X if (status == -1)
X {
X fprintf(stderr, "%s: can't open termcap file\n", myname);
X }
X else
X {
X fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
X myname, term_name);
X }
X
X /* pretend it's dumb and proceed */
X smart_terminal = No;
X return;
X }
X
X /* "hardcopy" immediately indicates a very stupid terminal */
X if (tgetflag("hc"))
X {
X smart_terminal = No;
X return;
X }
X
X /* set up common terminal capabilities */
X if ((screen_length = tgetnum("li")) <= 0)
X {
X screen_length = smart_terminal = 0;
X return;
X }
X
X /* screen_width is a little different */
X if ((screen_width = tgetnum("co")) == -1)
X {
X screen_width = 79;
X }
X else
X {
X screen_width -= 1;
X }
X
X /* terminals that overstrike need special attention */
X overstrike = tgetflag("os");
X
X /* initialize the pointer into the termcap string buffer */
X bufptr = string_buffer;
X
X /* get "ce", clear to end */
X if (!overstrike)
X {
X clear_line = tgetstr("ce", &bufptr);
X }
X
X /* get necessary capabilities */
X if ((clear_screen = tgetstr("cl", &bufptr)) == NULL ||
X (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
X {
X smart_terminal = No;
X return;
X }
X
X /* get some more sophisticated stuff -- these are optional */
X clear_to_end = tgetstr("cd", &bufptr);
X terminal_init = tgetstr("ti", &bufptr);
X terminal_end = tgetstr("te", &bufptr);
X start_standout = tgetstr("so", &bufptr);
X end_standout = tgetstr("se", &bufptr);
X
X /* pad character */
X PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
X
X /* set convenience strings */
X (void) strcpy(home, tgoto(cursor_motion, 0, 0));
X /* (lower_left is set in get_screensize) */
X
X /* get the actual screen size with an ioctl, if needed */
X /* This may change screen_width and screen_length, and it always
X sets lower_left. */
X get_screensize();
X
X /* if stdout is not a terminal, pretend we are a dumb terminal */
X#ifdef SGTTY
X if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
X {
X smart_terminal = No;
X }
X#endif
X#ifdef TERMIO
X if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
X {
X smart_terminal = No;
X }
X#endif
X#ifdef TERMIOS
X if (tcgetattr(STDOUT, &old_settings) == -1)
X {
X smart_terminal = No;
X }
X#endif
X}
X
Xinit_screen()
X
X{
X /* get the old settings for safe keeping */
X#ifdef SGTTY
X if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
X {
X /* copy the settings so we can modify them */
X new_settings = old_settings;
X
X /* turn on CBREAK and turn off character echo and tab expansion */
X new_settings.sg_flags |= CBREAK;
X new_settings.sg_flags &= ~(ECHO|XTABS);
X (void) ioctl(STDOUT, TIOCSETP, &new_settings);
X
X /* remember the erase and kill characters */
X ch_erase = old_settings.sg_erase;
X ch_kill = old_settings.sg_kill;
X
X#ifdef TOStop
X /* get the local mode word */
X (void) ioctl(STDOUT, TIOCLGET, &old_lword);
X
X /* modify it */
X new_lword = old_lword | LTOSTOP;
X (void) ioctl(STDOUT, TIOCLSET, &new_lword);
X#endif
X /* remember that it really is a terminal */
X is_a_terminal = Yes;
X
X /* send the termcap initialization string */
X putcap(terminal_init);
X }
X#endif
X#ifdef TERMIO
X if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
X {
X /* copy the settings so we can modify them */
X new_settings = old_settings;
X
X /* turn off ICANON, character echo and tab expansion */
X new_settings.c_lflag &= ~(ICANON|ECHO);
X new_settings.c_oflag &= ~(TAB3);
X new_settings.c_cc[VMIN] = 1;
X new_settings.c_cc[VTIME] = 0;
X (void) ioctl(STDOUT, TCSETA, &new_settings);
X
X /* remember the erase and kill characters */
X ch_erase = old_settings.c_cc[VERASE];
X ch_kill = old_settings.c_cc[VKILL];
X
X /* remember that it really is a terminal */
X is_a_terminal = Yes;
X
X /* send the termcap initialization string */
X putcap(terminal_init);
X }
X#endif
X#ifdef TERMIOS
X if (tcgetattr(STDOUT, &old_settings) != -1)
X {
X /* copy the settings so we can modify them */
X new_settings = old_settings;
X
X /* turn off ICANON, character echo and tab expansion */
X new_settings.c_lflag &= ~(ICANON|ECHO);
X new_settings.c_oflag &= ~(TAB3);
X new_settings.c_cc[VMIN] = 1;
X new_settings.c_cc[VTIME] = 0;
X (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
X
X /* remember the erase and kill characters */
X ch_erase = old_settings.c_cc[VERASE];
X ch_kill = old_settings.c_cc[VKILL];
X
X /* remember that it really is a terminal */
X is_a_terminal = Yes;
X
X /* send the termcap initialization string */
X putcap(terminal_init);
X }
X#endif
X
X if (!is_a_terminal)
X {
X /* not a terminal at all---consider it dumb */
X smart_terminal = No;
X }
X}
X
Xend_screen()
X
X{
X /* move to the lower left, clear the line and send "te" */
X if (smart_terminal)
X {
X putcap(lower_left);
X putcap(clear_line);
X fflush(stdout);
X putcap(terminal_end);
X }
X
X /* if we have settings to reset, then do so */
X if (is_a_terminal)
X {
X#ifdef SGTTY
X (void) ioctl(STDOUT, TIOCSETP, &old_settings);
X#ifdef TOStop
X (void) ioctl(STDOUT, TIOCLSET, &old_lword);
X#endif
X#endif
X#ifdef TERMIO
X (void) ioctl(STDOUT, TCSETA, &old_settings);
X#endif
X#ifdef TERMIOS
X (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
X#endif
X }
X}
X
Xreinit_screen()
X
X{
X /* install our settings if it is a terminal */
X if (is_a_terminal)
X {
X#ifdef SGTTY
X (void) ioctl(STDOUT, TIOCSETP, &new_settings);
X#ifdef TOStop
X (void) ioctl(STDOUT, TIOCLSET, &new_lword);
X#endif
X#endif
X#ifdef TERMIO
X (void) ioctl(STDOUT, TCSETA, &new_settings);
X#endif
X#ifdef TERMIOS
X (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
X#endif
X }
X
X /* send init string */
X if (smart_terminal)
X {
X putcap(terminal_init);
X }
X}
X
Xget_screensize()
X
X{
X
X#ifdef TIOCGWINSZ
X
X struct winsize ws;
X
X if (ioctl (1, TIOCGWINSZ, &ws) != -1)
X {
X if (ws.ws_row != 0)
X {
X screen_length = ws.ws_row;
X }
X if (ws.ws_col != 0)
X {
X screen_width = ws.ws_col - 1;
X }
X }
X
X#else
X#ifdef TIOCGSIZE
X
X struct ttysize ts;
X
X if (ioctl (1, TIOCGSIZE, &ts) != -1)
X {
X if (ts.ts_lines != 0)
X {
X screen_length = ts.ts_lines;
X }
X if (ts.ts_cols != 0)
X {
X screen_width = ts.ts_cols - 1;
X }
X }
X
X#endif /* TIOCGSIZE */
X#endif /* TIOCGWINSZ */
X
X (void) strcpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1));
X}
X
Xstandout(msg)
X
Xchar *msg;
X
X{
X if (smart_terminal)
X {
X putcap(start_standout);
X fputs(msg, stdout);
X putcap(end_standout);
X }
X else
X {
X fputs(msg, stdout);
X }
X}
X
Xclear()
X
X{
X if (smart_terminal)
X {
X putcap(clear_screen);
X }
X}
X
Xclear_eol(len)
X
Xint len;
X
X{
X if (smart_terminal && !overstrike && len > 0)
X {
X if (clear_line)
X {
X putcap(clear_line);
X return(0);
X }
X else
X {
X while (len-- > 0)
X {
X putchar(' ');
X }
X return(1);
X }
X }
X return(-1);
X}
X
Xgo_home()
X
X{
X if (smart_terminal)
X {
X putcap(home);
X }
X}
X
X/* This has to be defined as a subroutine for tputs (instead of a macro) */
X
Xputstdout(ch)
X
Xchar ch;
X
X{
X putchar(ch);
X}
X
END_OF_FILE
if test 9664 -ne `wc -c <'top-3.4/screen.c'`; then
echo shar: \"'top-3.4/screen.c'\" unpacked with wrong size!
fi
# end of 'top-3.4/screen.c'
fi
if test -f 'top-3.4/username.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'top-3.4/username.c'\"
else
echo shar: Extracting \"'top-3.4/username.c'\" \(5012 characters\)
sed "s/^X//" >'top-3.4/username.c' <<'END_OF_FILE'
X/*
X * Top users/processes display for Unix
X * Version 3
X *
X * This program may be freely redistributed,
X * but this entire comment MUST remain intact.
X *
X * Copyright (c) 1984, 1989, William LeFebvre, Rice University
X * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
X */
X
X/*
X * Username translation code for top.
X *
X * These routines handle uid to username mapping.
X * They use a hashing table scheme to reduce reading overhead.
X * For the time being, these are very straightforward hashing routines.
X * Maybe someday I'll put in something better. But with the advent of
X * "random access" password files, it might not be worth the effort.
X *
X * Changes to these have been provided by John Gilmore (g...@toad.com).
X *
X * The hash has been simplified in this release, to avoid the
X * table overflow problems of previous releases. If the value
X * at the initial hash location is not right, it is replaced
X * by the right value. Collisions will cause us to call getpw*
X * but hey, this is a cache, not the Library of Congress.
X * This makes the table size independent of the passwd file size.
X */
X
X#include <stdio.h>
X#include <pwd.h>
X
X#include "top.local.h"
X#include "utils.h"
X
Xstruct hash_el {
X int uid;
X char name[9];
X};
X
X#define is_empty_hash(x) (hash_table[x].name[0] == 0)
X
X/* simple minded hashing function */
X/* Uid "nobody" is -2 results in hashit(-2) = -2 which is out of bounds for
X the hash_table. Applied abs() function to fix. 2/16/96 tpugh
X*/
X#define hashit(i) (abs(i) % Table_size)
X
X/* K&R requires that statically declared tables be initialized to zero. */
X/* We depend on that for hash_table and YOUR compiler had BETTER do it! */
Xstruct hash_el hash_table[Table_size];
X
Xinit_hash()
X
X{
X /*
X * There used to be some steps we had to take to initialize things.
X * We don't need to do that anymore, but we will leave this stub in
X * just in case future changes require initialization steps.
X */
X}
X
Xchar *username(uid)
X
Xregister int uid;
X
X{
X register int hashindex;
X
X hashindex = hashit(uid);
X if (is_empty_hash(hashindex) || (hash_table[hashindex].uid != uid))
X {
X /* not here or not right -- get it out of passwd */
X hashindex = get_user(uid);
X }
X return(hash_table[hashindex].name);
X}
X
Xint userid(username)
X
Xchar *username;
X
X{
X struct passwd *pwd;
X
X /* Eventually we want this to enter everything in the hash table,
X but for now we just do it simply and remember just the result.
X */
X
X if ((pwd = getpwnam(username)) == NULL)
X {
X return(-1);
X }
X
X /* enter the result in the hash table */
X enter_user(pwd->pw_uid, username, 1);
X
X /* return our result */
X return(pwd->pw_uid);
X}
X
Xint enter_user(uid, name, wecare)
X
Xregister int uid;
Xregister char *name;
Xint wecare; /* 1 = enter it always, 0 = nice to have */
X
X{
X register int hashindex;
X
X#ifdef DEBUG
X fprintf(stderr, "enter_hash(%d, %s, %d)\n", uid, name, wecare);
X#endif
X
X hashindex = hashit(uid);
X
X if (!is_empty_hash(hashindex))
X {
X if (!wecare)
X return 0; /* Don't clobber a slot for trash */
X if (hash_table[hashindex].uid == uid)
X return(hashindex); /* Fortuitous find */
X }
X
X /* empty or wrong slot -- fill it with new value */
X hash_table[hashindex].uid = uid;
X (void) strncpy(hash_table[hashindex].name, name, 8);
X return(hashindex);
X}
X
X/*
X * Get a userid->name mapping from the system.
X * If the passwd database is hashed (#define RANDOM_PW), we
X * just handle this uid. Otherwise we scan the passwd file
X * and cache any entries we pass over while looking.
X */
X
Xint get_user(uid)
X
Xregister int uid;
X
X{
X struct passwd *pwd;
X
X#ifdef RANDOM_PW
X /* no performance penalty for using getpwuid makes it easy */
X if ((pwd = getpwuid(uid)) != NULL)
X {
X return(enter_user(pwd->pw_uid, pwd->pw_name, 1));
X }
X#else
X
X int from_start = 0;
X
X /*
X * If we just called getpwuid each time, things would be very slow
X * since that just iterates through the passwd file each time. So,
X * we walk through the file instead (using getpwent) and cache each
X * entry as we go. Once the right record is found, we cache it and
X * return immediately. The next time we come in, getpwent will get
X * the next record. In theory, we never have to read the passwd file
X * a second time (because we cache everything we read). But in
X * practice, the cache may not be large enough, so if we don't find
X * it the first time we have to scan the file a second time. This
X * is not very efficient, but it will do for now.
X */
X
X while (from_start++ < 2)
X {
X while ((pwd = getpwent()) != NULL)
X {
X if (pwd->pw_uid == uid)
X {
X return(enter_user(pwd->pw_uid, pwd->pw_name, 1));
X }
X (void) enter_user(pwd->pw_uid, pwd->pw_name, 0);
X }
X /* try again */
X setpwent();
X }
X#endif
X /* if we can't find the name at all, then use the uid as the name */
X return(enter_user(uid, itoa7(uid), 1));
X}
END_OF_FILE
if test 5012 -ne `wc -c <'top-3.4/username.c'`; then
echo shar: \"'top-3.4/username.c'\" unpacked with wrong size!
fi
# end of 'top-3.4/username.c'
fi
echo shar: End of archive 2 \(of 22\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 22 archives.
echo "Now read README and INSTALL, then run Configure"
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


Reply all
Reply to author
Forward
0 new messages