Page MenuHomeFreeBSD

D15387.id42750.diff
No OneTemporary

D15387.id42750.diff

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: head/contrib/top/ADVERTISEMENT
===================================================================
--- head/contrib/top/ADVERTISEMENT
+++ head/contrib/top/ADVERTISEMENT
@@ -1,28 +0,0 @@
- William LeFebvre
- Group sys Consulting
- wnl@groupsys.com
- +1-770-813-3224
-
-
-William LeFebvre is available for consulting and teaching engagements
-through the company Group sys Consulting. William's specialties are:
-
- Unix system administration issues
- Local area network design
- Design of safe connections to the Internet
- Domain Name Service
- Threaded programming with pthreads
- Netscape Server API plugins
- INN news server configuration
- SunOS to Solaris migration
- Troubleshooting
-
-
-Although located in the Atlanta metropolitan area, William can easily
-travel to any location in the United States and Canada. Trips to
-other countries can be arranged as well.
-
-If you are interested in having William work for your organization,
-contact him at +1-770-813-3224 or via the address "wnl@groupsys.com".
-You may also wish to visit the Group sys web page at www.groupsys.com.
-
Index: head/contrib/top/Changes
===================================================================
--- head/contrib/top/Changes
+++ head/contrib/top/Changes
@@ -1,632 +0,0 @@
-Thu Mar 30 2000 - wnl (3.5beta12)
- Updated modules: m_aix41.c, m_aix43.c, m_mtxinu.c, m_sco5.c,
- and m_ultrix4.c.
- Included m_irixsgi.c from some source that's been floating around
- SGI. Don't yet know how it compares to m_irix62.
-
-Fri Mar 10 2000 - wnl (3.5beta11)
- top.c: avoid potential loop if stdout gets closed, use macro
- for p_active to avoid collision with system macros.
- m_sunos5: widened some fields to accomodate 5.8.
- m_decosf1: added ordering support
- m_irix62_64: provides 64-bit module based on m_irix62.
- m_irix62: skip bogus files in /proc directory
- m_svr42MP and m_svr5: complete replacement with updated copies
- m_mtxinu: complete replacement with updated copies
- m_aix43: new module for 4.3
- getans: replaced with a Bourne shell script
-
-Mon Mar 6 2000 - wnl (3.5beta10)
- m_sunos5.c: workaround for curses bug: ensure that TERMINFO has
- a value.
-
-Fri Jan 15 1999 - wnl (3.5beta10)
- top.c: now check return code from read to avoid looping on eof.
- top.c: delay of 0 now only valid for root.
- decosf1.c: patches from Rainer Orth should fix most of the
- problems with this module (including the display of certain
- processes and runtime errors).
- sunos5.c: Rainer insisted on putting the slash back in the
- state field ("run/4") and widened the field to accomodate it.
- aix.c: widened PID field for 6-digit pids (shortened NICE field)
- module macosx added, thanks to Andrew Townley.
-
-Fri Dec 18 1998 - wnl (3.5beta9)
- Configure checks status of "make" and complains if it fails.
-
-Thu Dec 17 1998 - wnl (3.5beta9)
- Added module sco5 from Mike Hopkirk.
- Added module netbsd132 from moto kawasaki.
-
-Sun Oct 25 1998 - wnl (3.5beta9)
- Added Casper's patches for sunos5 for the following:
- produce same results as swap -s (5.5 and higher),
- don't use system_pages kstat when /dev/kmem can be opened,
- skip . and .. when reading /proc, replace use of SOLARIS24
- with OSREV.
-
-Fri Sep 11 1998 - wnl (3.5beta9)
- Added workaround to getans for the absence of $< in SCO Unix.
-
-Wed Jul 1 1998 - wnl (3.5beta9)
- Changed structure member "errno" to "errnum" in commands.c.
- Replaced hpux10 module with one from John Haxby.
-
-Fri Apr 17 1998 - wnl (3.5beta8)
- Moved definition of _KMEMUSER earlier in m_sunos5.c. This should
- fix the compilation problem with gnu 2.7.2.3, obviating the need
- for the fixinc.svr4 patch, but hopefully will not affect anything
- else.
- Added -DORDER to m_sunos4mp.c
-
-Tue Nov 18 1997 - wnl (3.5beta7)
- Added gcc 2.7.2.3 patch for fixinc.svr4 and changed INSTALL and
- FAQ to refer to it.
- Added NetBSD HP9000 fix. Hopefully it doesn't break other
- NetBSD platforms.
-
-Fri Oct 24 1997 - wnl (3.5beta7)
- Modified m_dcosx.c to change uses of procdir to xprocdir, avoiding
- a name clash with an include file (Bryn Parrott)
-
-Sat Oct 11 1997 - wnl (3.5beta6)
- Incorporated Casper's patches for Solaris 2.6 and for the multi-
- processor bug ("kstat finds too many cpus").
-
-Sun Jan 20 1996 - wnl (3.5beta5)
- Fixed Casper's m_sunos5 module: there was a poor interaction with
- his use of OSREV and SunOS 5.5.1.
-
-Fri Dec 20 1996 - wnl (3.5beta4)
- Replaced m_sunos5 with a reworked version by Casper Dik. This one
- should work under 2.6 and may not require that top be run setuid
- to root under 2.5 or 2.6. This also fixed a bug in m_sunos5 that
- was introduced in beta3.
- Fixed calculation of OSREV in Configure.
-
-Wed Nov 20 1996 - wnl (3.5beta3)
- Incorporated contributed fixes to: bsdos2, irix62, freebsd20,
- ultrix4, sunos5. Changed calculation of swap area in sunos5 (now
- uses swapctl). sunos5 now understands idled processors. Changed
- Configure to determine os revision using uname (when available)
- and adding it to machine.c compiliation in Makefile as -DOSREV.
- Changed calls to "exit" in modules to use "quit" instead.
-
-Oct 20 1996 - wnl (3.5beta3)
- Removed "time" from list of ordering choices: there's no easy way
- to get cpu time for all processes (it's in the u area).
-
-Fri Oct 18 1996 - wnl (3.5beta3)
- hpux10 and hpux9: using a better means for determining when a
- process is idle.
- decosf1 now includes utils.h.
-
-Fri Sep 13 1996 - wnl (3.5beta2)
- Fixed Configure to build Make.desc in such a way that doesn't
- require a long argument to sed.
-
-Thu Sep 12 1996 - wnl (3.5beta2)
- Fixed bug in display.c that affected empty cpustate names.
- Created hpux1010 module - a variant of hpux10 that does not use
- struct proc or struct user (suitable for HP/UX 10.10).
-
-Wed Sep 11 1996 - wnl (3.5beta2)
- Changes to sunos5 module: Removed WCPU column since it is meaningless
- on a SVR4-based system. Added THR column to show number of threads
- for each process. This was not straightforward: the information is
- not stored in prpsinfo but rather in prstatus.
-
-Tue Sep 10 1996 - wnl (3.5beta1)
- Added patches for sunos4mp to provide order support.
- Added irix62 module.
- Changed prime.c to include stdio.h for printf prototype.
- Added conditional code to os.h and utils.c to handle systems
- where sys_errlist is defined in stdio.h (such as NetBSD).
-
-Mon Sep 09 1996 - wnl (3.5beta1)
- Removed tar and shar rules from Makefile.X -- don't need them anymore.
- Added -v option to display version number. Updated man page.
-
-Thu Aug 29 1996 - wnl (3.4)
- Replaced modules (from Tim Pugh): next 32, next40.
- Fixed bug in username.c: hashing negative uids.
-
-Thu Aug 22 1996 - wnl (3.4beta3)
- Patched modules: ultrix4, sunos4, sunos5, utek, decosf1, irix5.
- Added modules: next40, next32.
- Fixed procstates update bug in display.c.
- Fixed divide by zero bug in utils.c.
- Fixed bad number in layout.h
- Minor fixes to Configure.
- Complete overhaul of FAQ.
-
-Tue Feb 13 1996 - wnl (3.4beta3)
- Added convex module from Warren Vosper (originally written by
- William Jones).
-
-Tue Feb 13 1996 - wnl (3.4beta2)
- Fixed format_k in utils.c to calculate K and M values correctly.
- Added check for gigabyte values ('G'). Changed sumamry_format
- in display.c to use format_k where appropriate.
- Changed creation of distribution tar file to place everything in
- a top level directory.
-
-Tue Jan 30 1996 - wnl (3.4beta2)
- Added m_aix41 module. Added new tag type to module comments:
- TERMCAP, which defined the library to use for a termcap library.
- If no TERMCAP tag is found in the module's initial comment, then
- Configure will default to "-ltermcap". AIX needs this since it
- put all the termcap routines in libcurses(!)
-
- Added m_bsdos2 (found lingering in my mailbox).
- Updated m_svr4 to include support for NCR multiprocessors.
- Fixed small bug in utils.c
-
-Thu Jan 25 1996 - wnl (3.4beta1)
- Fixed m_sunos5 invocation of gettimeofday to include "NULL" as
- second argument. This provides compatability with the Posix-
- compliant template provided with SunOS 5.5, but doesn't hurt
- previous versions since they do bother with a template for that
- function.
-
- Made changes (recommended by net users) to hpux10, ultrix4,
- netbsd10, aux3 (replaced aux31). Added module for linux.
-
-Fri Oct 10 1995 - wnl (3.4beta1)
- Added user-contributed modules for SCO Unix, IRIX 5, HP/UX 10,
- Pyramid DC/OSX. Changed Configure so that it runs in environments
- whose c-shells have no 'eval'(!). Added support for multiple sort
- ordering methods via the -o switch. This option requires support
- from the machine dependent module: such support was added to
- sunos5 (thus sunos54) and sunos4.
-
- display.c: Changed CPU states display line to shorten the leading
- tag if the data won't fit in the current width. Fixed a divide-by-
- zero bug that affected ultrasparc servers (and potentially other
- systems).
-
- m_sunos5.c: Now asks the system for the correct pagesize rather than
- assuming it is 4K.
-
-Thu Mar 2 1995 - wnl (3.3 RELEASE)
- Added module netbsd10 and renamed netbsd to netbsd08. Changed
- Configure so that it does not use an initial default module name.
- Made other compatability fixes to Configure. Added comments to
- decosf1 concerning optimizer bug. Other documentation changes.
- Added use of "prime.c" to Configure script.
-
-Tue Feb 7 1995 - wnl (3.3beta6)
- Still one more beta....
- Fixes for sunos5 2.4 gcc core dump (it was an alignment problem).
- Fixed and improvements for decosf1 (including use of format_k
- for proper SIZE column formatting). Added modules freebsd20 and
- ncr3000.
-
-Thu Feb 2 1995 - wnl (3.3beta5)
- One more beta....
- Fixed a few bugs in the sunos5 port pertaining to casting and
- very large memory counts. Added "ifndef HAVE_GETOPT" to getopt.c
- to provide for conditional compilation of the getopt function.
- Those systems that have getopt in libc can add -DHAVE_GETOPT to
- the CFLAGS line in the module to prevent the function from being
- compiled. Added sunos54 module to accomodate SunOS 5.4
- peculiarities. Added module for aux3.1.
-
-Wed Jan 4 1995 - wnl (3.3beta4)
- This is really taking too long......sigh.
- Fixed SIGWINCH handling once and for all. It now remembers the
- number of processes you want displayed even thru window resizes.
- Fixed buffer conflict in utils.c (itoa and itoa7).
- Lots of small improvements to the various modules were made over
- the past month: too numberous to list here. SunOS 5 module made
- more secure thru use of seteuid calls (other SVR4 modules should
- be modified similarly). One final MP fix to sunos5, too. Module
- for decosf1 was modified to accomodate V3.0.
-
-Mon Apr 18 1994 - wnl (3.3beta3)
- I think I finally got a sunos5 module that will work on MP
- machines. Fixed cpu states figure in osmp41a so that
- percentages never exceed 100%. Added shell script "install"
- since Unix vendors can't seem to make up their minds on what
- options they want to use for the one that comes with the OS.
- Added netbsd modules from Christos. Fixed lots of other little
- things over the past few months that I have long since forgotten.
-
-Wed Dec 15 1993 - wnl (3.3beta2)
- Added module patches from various users: hpux9, sunos5.
- Fixed bug with batch mode (screen_width wasn't getting set).
- Changes to accomodate 64 bit machines.
- Fixed some bugs in command parsing ("renice 19 " did something
- unexpected).
-
-Mon Aug 30 1993 - wnl (3.3beta)
- Added lots of little patches from various users.
- Added routines to utils.c for intelligent formatting of kilobytes
- and time. These are intended to be used in the modules when
- formatting a process line. Added code to "summary_format" in
- display.c to do intelligent formatting of memory quantities.
- Redid display.c to allow for varying line widths and dynamic
- reallocation of the screen buffer.
- Added a SIGWINCH handler to top.c!
- Added a constant, MAX_COLS, to top.h which defines the absolute
- widest line we will ever allow. Changed allocations of "char fmt"
- in all machine modules to use this constant rather than an abitrary
- number.
-
-Fri Aug 13 1993 - wnl (3.3)
- Changed return value definition of time-related functions in top.c,
- display.c, and m_ultrix4.c to time_t (stuart@coral.cs.jcu.edu.au).
- Fixed bug in display.c: line_update when start != 0.
-
-Wed Aug 4 1993 - wnl (3.2 release)
- Changes to Configure from Paul Vixie. Added modules for hpux9 and
- bsd386.
-
-Tue Jul 13 1993 - wnl (3.1 release)
- More small changes and minor bug fixes. Brought bsd44 up to date
- and added a module for svr4.2. Changed shar packaging to use Rich
- Salz's cshar stuff.
-
-Wed Jul 7 1993 - wnl (3.1BETA)
- More changes and bug fixes to Configure. Applied some other
- minor bug fixes and suggestions from the beta testers. Added
- the "metatop" shell script and the "installmeta" rule to the
- Makefile to make handling multiple machine models and OS versions
- easier. Added INSTALL and FAQ files.
-
-Tue May 18 1993 - wnl (3.1BETA)
- Changed Configure to be compatible with most SVR4 environments
- (differing output from "ls -lg"). Also changed Configure,
- Makefile.X, etc., to look for module files in the subdirectory
- "machine" (thanks to Christos Zoulas).
-
-Tue Apr 20 1993 - wnl (3.1BETA)
- Changed both occurences of "ls -1" in Configure to "ls". This
- SHOULD produce the same result, and has the advantage that it
- doesn't produce an error on a system 5 machine. Integrated other
- changes recommended in the first round of beta testing.
-
-Wed Mar 10 1993 - wnl (3.1BETA)
- MAJOR CHANGE: I have added a required function to all machine
- dependent modules, called proc_owner. It takes a pid as an argument
- and returns the uid of the process's owner. Such capability is
- necessary for top to run securely as a set-uid program, something
- that is needed for SVR4 implementations to read /proc. I have
- retrofitted all modules except dgux with this function, but was
- not able to test most of them. Top should now run securely as
- a setuid program. Added 386bsd and sunos5 modules. Added sunos4mp
- module for MP Suns.
-
-Sat Feb 20 1993 - wnl (3.1ALPHA)
- Modified top.c and commands.c to compile correctly on System V
- derived Unixes (especially SVR4), but in a way that doesn't rely
- on an oracle-like declaration (that is, I don't use "ifdef SYSV").
- Fixed some bugs in "Configure" and "getans". Added inspection of
- env variable "TOP" for options, and made -I default to showing
- idle processes. Added "u" command to change username restriction
- on the fly. Created shell script "suntop" for poor multi-version
- SunOS folks (like myself).
-
-Wed Jun 3 1992 - wnl (3.0)
- "max_topn" wasn't being used everywhere it was supposed to be
- in top.c. Many cosmetic changes, including copyright notices in
- all the .c files. Version number is now handled by version.c and
- reflects the current patchlevel (which is initially set to 0).
- Changed Configure and Makefile to allow configurable variables for
- certain commands: shell, cc, awk, install. Updated README and
- Porting. Ready to release to the world!
-
-Mon May 18 1992 - wnl (2.9BETA)
- Added modules provided by Christos Zoulas. Replaced screen.c
- with one modified by Christos and that will appropriately select
- and handle the sgtty, termio, or termios system. Integrated many
- other changes recommended by Christos. Fixed (I hope) the "-b"
- batch mode display bug. Had to change loadavg to load_avg to avoid
- a conflict with 4.4BSD.
-
-Mon Apr 27 1992 - wnl (2.8BETA)
- Added modules provided by Daniel Trinkle. Added patchlevel.h,
- but the patch level is not yet reflected in the version number.
- Cleaned up m_sunos4.c a little.
-
-Wed Apr 22 1992 - wnl (2.8BETA)
- Major internal reorganization. All of the system dependent stuff
- is now really and truly separated from everything else. The
- system dependent functions are contained in a separate .c file
- called a "module". The Configure script knows how to find and
- set up these modules, but the human installer still needs to tell
- Configure which module to use (no automagic determination of
- machine type---sorry). Added -U option to specify one user's
- processes, but there is no corresponding command...yet. Other
- changes and improvements too numerous to mention here. Currently
- there are only two modules: sunos4 and umax. But after this beta
- release is sent around, I expect more to be written. I just hope
- that the machine-dependent abstractions don't need to change in
- the process.
-
-Thu Mar 26 1992 - wnl (2.7BETA)
- Beta release with minimal architecture support. Updated README
- and added a first cut at a Porting guide. Added ioctl TIOCGWINSZ
- code from top2.5+ (courtesy of David MacKenzie). I didn't even
- try porting the Ultrix support since I don't have access to an
- Ultrix machine.
-
-Fri Oct 11 1991 - wnl (2.6)
- This version was not widely released. It contained many changes.
- Here are the major ones:
-
- Put in Vixie's idle process hack.
-
- Enhanced type field in new_message to handle delayed messages.
-
- Changed u_process to automatically adjust for varying lines of
- output. Management of screenbuf should now be completely contained
- in display.c. Removed now extraneous code from CMD_number[12]
- portion of command switch in top.c. This was the stuff that dealt
- with zeroing out lines in screenbuf.
-
- Finally made it all work correctly on a 386i. Problems I had to
- overcome: kvm_nlist doesn't return 0 on success as advertised (it
- returns 1 instead); the results of a kvm_nlist are different
- (n_type can be zero even for a symbol that exists).
-
- Serious rearrangement for processor dependent stuff. All nlists
- are now in separate files with the suffix ".nlist". Most machine
- specific code is in "machine.c" surrounded by appropriate ifdefs---
- the goal is to eventually have all machine specific code in this
- file. Managed to find a way to detect SunOS 4.x at compile-time:
- this is contained in the include file "sun.h". Completely changed
- the memory display line for SunOS 4.x---it now displays a far
- more appropriate report.
-
- Created the shell script "Configure" to aid in the configuration
- step.
-
- Fixed a bug in init_termcap: it will now tolerate an environment
- which does not have TERM defined (thanks to Sam Horrocks for
- pointing this out).
-
-Tue Aug 9 1988 - wnl (2.5)
- Added changes to make top work under version 4.0 of the Sun
- operating system. Changes were provided by Scott Alexander of the
- University of Pennsylvania. Thanks! Compile with "-Dsunos4" to
- get them. Virtual memory statistics are not readily accessible
- under 4.0, so they don't show up in the output.
-
-Thu Jul 31 1987 - wnl (2.4)
- Fixed a problem with the 4.0 Pyramid code. The label "cp_time"
- doesn't exist in the 4.0 kernel anymore. I think the code Carl
- sent me wants "percpu" instead. That is what I am using and it
- appears to work. 375 code is still untested (at least by me).
- Also picked a great deal of lint out of the source. Lint now only
- complains about a very few nitpicky things (there are far too many
- calls to "printf" to put a "(void)" in front of!), at least under
- SunOS.
-
-Tue Jul 28 1987 - wnl (2.4a)
- Added changes for a Symmetrics Computer Systems s/375 machine.
- Changes were provided by Paul Vixie. Thanks! According to Mr.
- Vixie: "These changes were not made at, by, or for SCS proper.
- SCS would probably be interested in them, but so far only the
- users' group has them. They were made in February, 1987, to
- version 2.1 of the program, by Paul Vixie
- (dual!ptsfa!vixie!paul@ucbvax.Berkeley.EDU)." His changes were
- integrated into version 2.3 to make version 2.4.
-
- The SCS peculiarities are summarized in Changes.scs.
-
-Tue Jun 9 1987 - wnl (2.3 for real)
- Changed the includes for the extra code Carl sent me to only
- compile on Version 4.0 Pyramid machines. This makes top still
- compilable on pre-4.0 Pyramids. Specifically, this code is only
- compiled when both "pyr" and "CPUFOUND" are defined.
-
-Wed Jun 3 1987 - wnl (2.3 with Pyramid additions)
- It's been a month and I still haven't done anything about
- distributing this version. However, Carl Gutekunst from Pyramid
- has sent me some extra patches for some of the Pyramid code. I
- just added those and will make them part of 2.3. This fixes the
- following Pyramid problems: adds the inclusion of <sys/systm.h>,
- uses the correct size for getting the kernel value _ccpu (this bug
- affected the Vax version as well), sums the elements of the percpu
- array to calculate a cp_time value (for OSx 4.0).
-
-Fri May 1 1987 - wnl (2.3)
- I have finally finished all the changes for better support of
- oddbal terminals. Added the low-level routine "clear_eol" which
- makes handling terminals without "ce" easy: it uses spaces
- instead. All direct uses of "clear_line" outside of screen.c have
- been changed to use this primitive. A terminal with "os" is now
- handled in such that all situations that need overwriting are
- completely avoided (including several commands). This required
- some changes to the way commands are translated into action (in
- "top.c"). Made several important changes to display.c to prevent
- overflowing of any of the fields. Specifically, more than 99
- total processes and a cpu state that reaches 100%. Had to make a
- small change to two casts in top.c, because the Sun 3.2 compiler
- was giving warnings on them. Added the "-q" option which lets
- root run top at a nice of -20 (in case he thinks he really needs it).
-
-Tue Dec 30 1986 - wnl (2.2)
- I think I fixed a bug reported by Julian Onions at Nottingham.
- Occasionally, top will core dump when the sprintf in either
- i_process or u_process overflows due to an exceptionally
- unrealistic time value. I think it highly unlikely that top can
- get a bad proc structure (although I suppose it is possible), but
- the process time is read from the user structure, and that can
- sometimes be part garbage. So, "get_ucpu" checks the value it
- returns to make sure its formatted form will not overflow the
- sprintf. If this doesn't fix the bug, then more drastic measures
- will be necessary. I plan to make this version the official
- "top 2.2". [[ This version was never distributed very widely. ]]
-
-Tue Dec 2 1986 - wnl (2.2c)
- Added to top.c the notion of a "failed command". When a command
- produces a message (on the message line), an update does not
- follow it. Before, the message was written and a new display was
- shown---purposefully not overwriting the message. But the
- improvements to handle overstriking terminals and terminals
- without "ce" clear the screen before every display, which would
- erase the message. Now, the message is displayed and top waits
- another full time interval before updating the display. This
- works much better all around.
-
-Mon Nov 24 1986 - wnl (2.2b)
- Created a new file, utils.c, and made appropriate changes to
- Makefile. This new file holds all utility functions that can and
- may be used by more than one "module". Improved i_memory and
- u_memory (display.c) so that screen updates for the values
- displayed are only changed when necessary. Also made the line
- look better: the last fixes made for a rather ugly display.
- Added the locally defined constant "LoadMax" and added code to
- top.c to send the cursor home after a space command is entered if
- the load average is higher than "LoadMax". This provides visual
- feedback on loaded systems.
-
-Mon Nov 3 1986 - wnl (2.2a)
- Widened the format for memory usage so that it can display 5
- digits. This makes that line look a little ugly---maybe I'll fix
- that later. Screen handling now understands "os" and a missing
- "ce". It treats them identically: clear the screen between each
- display. Screen handling code now uses "cd" when appropriate
- (i.e.: when user has shortened the screen). Made i_loadave clear
- then screen and took out most of the explicit calls to "clear" in
- top.c. This method is cleaner, especially in conjunction with
- "os" handling. Added preprocessor variable "RANDOM_PW" for
- systems that access the passwd file randomly (Sun's yp and 4.3).
- With "RANDOM_PW" set, "getpwuid" is used instead of "getpwnam",
- but uid->username mappings are still hashed internally (because
- that is still faster than going to disk).
-
-Mon Oct 6 1986 - wnl (2.1)
- A bug with the kill command was pointed out by "dciem!tim"---
- specifying a signal by name did not work correctly. This bug has
- been fixed with a simple change to commands.c. Another bug made
- the cpu state percentages incorrect the first time they were
- displayed. This bug has also been fixed (changed top.c).
-
-Thu Sep 4 1986 - wnl (2.0, at last)
- This is the version that will (hopefully) get released to the
- world as top 2.0.
- Added the "r" and "k" commands for renice and kill, respectively.
- This required adding a way to handle system call errors, and the
- addition of the "e" command. Help screen and manual page were
- changed to reflect this change. Changed all "#ifdef SUN" directives
- to "#ifdef sun", and changed all "#ifdef PYRAMID" directives to
- "#ifdef pyr". As much as I hate those choices of preprocessor
- names (they too easily conflict with real variable names), it does
- make automatic compilation possible---people don't have to change
- the Makefile anymore for specific machines. The manual page was
- changed to automatically incorporate the defaults as set in the
- Makefile (including an infinite value for TOPN) and the way the
- manual page is generated by the Makefile was changed to make
- maintenance of this information automatic.
-
-Mon Jul 28 1986 - wnl (still pre 2.0)
- Real close now. I put in a new definition for the macro "pagetok"
- that does an explicit shift of a constant expression involving
- PGSHIFT. Appropriate checks are made if PGSHIFT is to small.
- "pagetok" is now used exclusively everywhere to convert kernel
- clicks to kilobytes. I added a full blown interactive mode with
- the ability to change some of the runtime parameters (how many to
- display, time delay, etc.) while top is running. I also
- incorporated a few ideas from the net: control characters in the
- command name are replaced with '?'; the '-S' option makes the
- swapper and pager visible; options have been added to control the
- number of displays produced (this makes it easier to make
- performance snapshots with top). I have also added the notion of
- "infinite" values for number of processes and number of displays.
- I fixed a long-standing bug in the uid to username mapping code
- that was only aggravated on the pyramids: it was an ill-defined
- expression (akin to i = i++). I tweaked the proc_compar routine
- for qsort slightly so that stopped processes were more likely to
- show up. Manual page was updated to reflect all changes
- noticeable to the user.
-
-Tue Jul 1 1986 - wnl (pre 2.0 -- 1.9999?)
- In the process of major revamping on the way to version 2.0.
- I have completely done away with curses by adding my own screen
- management routines in a separate file (screen.c). The rationale
- for this is that top knows a whole lot more about what is and is
- not redundant on the screen and can compare simple integer values
- where curses would have to compare strings. This has turned out
- to be a very big win speed-wise. The proc_compar routine for
- sorting has been rewritten to include several more keys. I
- decided this was necessary when I noticed that the "top" process
- itself kept disappearing off the top 10 list on a Sun-3. All the
- processes had the same percentage (0%) and the sort wasn't really
- doing anything worthwhile. I changed the expression that computes
- memory usage to use the ctob macro instead of just assuming that
- pages were 512 bytes. More work still needs to be done before
- this version is usable. I changed options-processing to use
- getopt and added appropriate incantations to the Makefile.
-
-Wed Feb 20 1985 - wnl (still 1.8)
- Put in the ifdef FOUR_ONE statements to make top still compilable
- on a 4.1 system. Apparently, there are some users out there that
- need this functionality. Oh well. I don't guarantee any of it,
- since I can't test it. Made appropriate changes to README and
- final installation related changes to Makefile.
-
-Sat Feb 2 1985 - wnl (1.8)
- Removed all the ifdef FOUR_TWO statements and made "top" into a
- 4.2 only program. If someone really wants to still run it on 4.1,
- then they can do all the work. We don't have a 4.1 machine
- anymore, so I don't even know if the thing still works under 4.1.
- Cleaned up the Makefile and the README. Added installation rules
- to the Makefile, as requested by several sites. Fixed a very
- obscure divide-by-zero bug. Added a second "key" to the qsort
- comparison function (proc_compar) so that comparisons are based on
- cpu ticks if the percentages are equal (provided by Jonathon
- Feiber at Sun).
-
-Tue Dec 11 1984 - wnl (1.7)
- Added the virtual and real memory status line to the header area
- (provided by Jonathon Feiber at Sun)
-
-Tue Nov 20 1984 - wnl (1.6)
- Added an "exit" if sbrk's fail. Added changes from Jonathon
- Feiber at Sun: ifdef SUN to make top work on Suns (they don't use
- doubles in the proc structure), register declarations, check for
- getting a user structure that has disappeared since the proc array
- was read (it used to die, now it just shows the process as swapped).
-
-Tue Nov 13 1984 - wnl (1.5)
- If the number of displayable processes ("active_procs") was less
- than the number of requested processes ("topn"), top would
- segmentation fault. This bug has been fixed. Thanks to Prentiss
- Riddle at ut-sally for pointing out the existence of this bug.
-
-Tue Oct 23 1984 - wnl (1.4)
- Finally fixed the hash table bug that caused processes owned by
- root to sometimes appear with either no name or a different name
- that had UID 0 (such as "operator"). Removed all the ifdef DEBUG
- blocks to make top ready for distribution to the real world.
-
-Sun Apr 8 1984 - wnl (still 1.3)
- Made some slight changes to the display format. It now looks more
- aesthetically pleasing. Added some preprocessor constants so that
- the two defaults (number of processes and seconds of delay) easier
- to change.
-
-Thu Apr 5 1984 - wnl (1.3)
- Changed the order in which things are done at initialization time.
- This way, if an error occurs before starting the main loop, curses
- will never get started. Also changed other error handlers so that
- endwin() is called before any flavor of exit. Specifying a number
- of processes that is more than the screen can handle is no longer
- fatal. It displays a warning message and pretends the user
- specified the maximum for the screen. Finally cured all the TSTP
- blues (well, almost all). I removed my TSTP handler and convinced
- the system to always use the one that curses sets up. Turns out
- that "sleep" was stepping all over it during a pause. So, I don't
- use sleep anymore. The only problem that remains with it now is
- redrawing the old display before updating it after a pause.
-
-Tue Apr 3 1984 - wnl (from 1.0 to 1.2)
- I changed the format of the TIME column from just "seconds" to
- "minutes:seconds". I also made pausing work correctly. Screen
- redraws with an up to date display. For compatibility with 4.2, I
- changed the name of the "zero" function to "bzero". The makefile
- has been altered to handle versions for 4.1 and 4.2, and README
- has been updated to reflect these recent changes.
Index: head/contrib/top/Configure
===================================================================
--- head/contrib/top/Configure
+++ head/contrib/top/Configure
@@ -1,565 +0,0 @@
-#!/bin/csh -f
-#
-# Configuration script for top.
-#
-# Use with version 3.0 and higher.
-#
-set PRIME = "/usr/games/primes"
-set vars = (module LoadMax topn NominalTopn delay owner group mode random \
- TableSize bindir mandir manext mansty \
- Cmdshell Cmdcc Cmdawk Cmdinstall cdefs)
-set fastrack = 0
-set yesno = (no yes)
-
-onintr byebye
-
-# make sure that getans is there and ready
-if (! -e getans) then
- echo 'This package is not complete. The shell file "getans" is missing.'
- exit 10
-endif
-chmod +x getans
-
-if ($#argv > 0) then
-# fast track configuration
- set fastrack = 1
-else
-cat <<'EOF'
-Configuration for top, version 3.5
-
-One moment....
-'EOF'
-endif
-
-# collect file names and module names
-ls machine/m_*.c >$$.f
-ls machine/m_*.man >$$.m
-sed -e 's@^machine/m_@@' -e 's/.c$//' $$.f >$$.n
-
-# build Make.desc
-sed -e 's@\.c@.desc\\@' $$.f | sed -e '$s/\\//' >$$.a
-sed -e "/^DESCS/r $$.a" Make.desc.X >Make.desc
-
-# build desc files and SYNOPSIS as needed
-make -f Make.desc >/dev/null
-if ($status != 0) then
- echo "Unable to build the synopsis."
- echo 'Make sure the command "make" is on your path and try'
- echo 'running Configure again.'
- exit 1
-endif
-
-if (-e .defaults) then
- echo ""
- echo "Reading configuration from last time..."
- source .defaults
- set nodefaults = 0
- if ($fastrack == 1) then
- set module = $1
- endif
-else
- if ($fastrack == 1) then
- echo "No previous configuration was found."
- set fastrack = 0
- set module = $1
- else
- set module = ""
- endif
- set LoadMax = 5.0
- set topn = 15
- set NominalTopn = 18
- set delay = 5
- set TableSize = 0
- set bindir = /usr/local/bin
- set mandir = /usr/man/manl
- set manext = l
- set mansty = man
- set nodefaults = 1
- set Cmdshell = /bin/sh
- set Cmdawk = awk
- set Cmdinstall = ./install
- set Cmdcc = cc
- set cdefs = -O
-endif
-echo ""
-
-if ($fastrack == 1) then
- grep -s $module $$.n >/dev/null
- if ($status != 0) then
- echo "$module is not recognized. To see a list of available modules"
- echo 'run "Configure" with no arguments.'
- rm -f $$.[fmna]
- exit 1
- endif
- set random1 = `expr $random + 1`
- cat <<EOF
-Using these settings:
- Bourne Shell $Cmdshell
- C compiler $Cmdcc
- Compiler options $cdefs
- Awk command $Cmdawk
- Install command $Cmdinstall
-
- Module $module
- LoadMax $LoadMax
- Default TOPN $topn
- Nominal TOPN $NominalTopn
- Default Delay $delay
-Random passwd access $yesno[$random1]
- Table Size $TableSize
- Owner $owner
- Group Owner $group
- Mode $mode
- bin directory $bindir
- man directory $mandir
- man extension $manext
- man style $mansty
-
-EOF
- goto fast
-endif
-
-cat <<'EOF'
-You will be asked a series of questions. Each question will have a
-default answer enclosed in brackets, such as "[5.0]". In most cases,
-the default answer will work well. To use that value, merely press
-return.
-
-'EOF'
-
-# display synopses
-
-getmod:
-cat <<'EOF'
-
-The following machine-dependent modules are available:
-'EOF'
-awk -F: ' { printf "%-10s %s\n", $1, $2 }' SYNOPSIS
-echo ''
-./getans "What module is appropriate for this machine? " string "$module" .$$
-set module = `cat .$$`
-
-if ("$module" == "") then
- echo "Please specify a valid module name."
- goto getmod
-endif
-
-# is it a valid one?
-grep -s "$module" $$.n >/dev/null
-if ($status != 0) then
- echo "That is not a recognized module name."
- goto getmod
-endif
-
-# display a full description
-sed -e '1,/DESCRIPTION:/d' -e '/^$/,$d' machine/m_${module}.desc
-
-# verify it
-echo ""
-./getans "Is this what you want to use?" yesno 1 .$$
-if (`cat .$$` == 0) then
- goto getmod
-endif
-endif
-
-cat <<'EOF'
-
-First we need to find out a little bit about the executables needed to
-compile top.
-
-'EOF'
-./getans "What is the full path name for the Bourne shell" file "$Cmdshell" .$$
-set Cmdshell = `cat .$$`
-
-cat <<'EOF'
-
-Please supply the name of the appropriate command. It need not be a
-full path name, but the named command does need to exist somewhere on
-the current path.
-
-'EOF'
-./getans "AWK Interpreter" path "$Cmdawk" .$$
-set Cmdawk = `cat .$$`
-./getans "C Compiler" path "$Cmdcc" .$$
-set Cmdcc = `cat .$$`
-
-cat <<'EOF'
-
-The installer command needs to understand Berkeley-esque arguments:
-"-o" for owner, "-g" for group, and "-m" for mode. A shell script
-called "install" is distributed with top and is suitable for use by
-top. You can specify a different program here if you like, or use
-the shell script (the default).
-
-'EOF'
-./getans "Installer" path "$Cmdinstall" .$$
-set Cmdinstall = `cat .$$`
-
-cat <<EOF
-
-What other options should be used with the $Cmdcc command (use "none" to
-specify no options)?
-EOF
-./getans "Compiler options" string "$cdefs" .$$
-set cdefs = `cat .$$`
-if ("$cdefs" == "none") then
- set cdefs = ""
-endif
-
-cat <<'EOF'
-
-Now you need to answer some questions concerning the configuration of
-top itself.
-
-The space command forces an immediate update. Sometimes, on loaded
-systems, this update will take a significant period of time (because all
-the output is buffered). So, if the short-term load average is above
-"LoadMax", then top will put the cursor home immediately after the space
-is pressed before the next update is attempted. This serves as a visual
-acknowledgement of the command. "LoadMax" should always be specified as a
-floating point number.
-
-'EOF'
-./getans "LoadMax" number "$LoadMax" .$$
-set LoadMax = `cat .$$`
-
-cat <<'EOF'
-
-"Default TOPN" is the default number of processes to show. This is the
-number that will be used when the user does not specify the number of
-processes to show. If you want "all" (or infinity) as the default, use
-the value "-1".
-
-'EOF'
-
-./getans "Default TOPN" neginteger "$topn" .$$
-set topn = `cat .$$`
-
-cat <<'EOF'
-
-"Nominal_TOPN" is used as the default TOPN when Default_TOPN is Infinity
-and the output is a dumb terminal. If we didn't do this, then
-installations who use a default TOPN of Infinity will get every process in
-the system when running top on a dumb terminal (or redirected to a file).
-Note that Nominal_TOPN is a default: it can still be overridden on the
-command line, even with the value "infinity".
-
-'EOF'
-
-./getans "Nominal TOPN" integer "$NominalTopn" .$$
-set NominalTopn = `cat .$$`
-
-cat <<'EOF'
-
-Default Delay is the default number of seconds to wait between screen
-updates.
-
-'EOF'
-
-./getans "Default Delay" integer "$delay" .$$
-set delay = `cat .$$`
-
-echo ""
-
-set rand = 0
-if (-e /etc/nsswitch.conf) then
- set rand = `grep '^passwd:.*nis' /etc/nsswitch.conf | wc -l`
- if ($rand > 1) then
- set rand = 1
- endif
-else
- ypwhich >&/dev/null
- if ($status == 0 || -e /etc/passwd.dir || -e /etc/pwd.db) then
- set rand = 1
- endif
-endif
-
-if ($rand == 1) then
- echo "It looks like you have a passwd file that can be accessed at random."
- set pr = 'Do you want top to take advantage of this'
-else
- echo "It looks like you have conventional passwd file access. Top can take"
- echo "advantage of a random access passwd mechanism if such exists. Do"
- echo "you want top to assume that accesses to the file /etc/passwd are done"
- set pr = 'with random access rather than sequential'
-endif
-
-if ($nodefaults == 1) then
- set random = $rand
-endif
-
-./getans "${pr}?" yesno $random .$$
-set random = `cat .$$`
-
-echo ""
-echo "Compiling prime.c"
-$Cmdcc $cdefs -o prime prime.c -lm
-if ($status != 0) then
- echo "Oh well."
- rm -f prime
-endif
-
-echo ""
-
-ypcat passwd.byname >&/tmp/$$.a
-if ($status == 0) then
- set cnt = `wc -l </tmp/$$.a`
- set mapfile = "NIS map"
-else
- rm /tmp/$$.a
- niscat passwd.org_dir >&/tmp/$$.a
- if ($status == 0) then
- set cnt = `wc -l </tmp/$$.a`
- set mapfile = "NISPLUS map"
- else
- set cnt = `wc -l </etc/passwd`
- set mapfile = "file"
- endif
-endif
-rm /tmp/$$.a
-set double = `expr $cnt \* 2`
-echo "I found $cnt entries in your passwd $mapfile. Top hashes the username to"
-echo "uid mappings as it goes along and it needs a good guess on the size of"
-echo "that hash table. This number should be the next highest prime number"
-echo "after $double."
-echo ""
-if (-e prime) then
- set pr = `./prime $double`
- echo "I have calculated that to be $pr."
-else if (-e $PRIME) then
- set pr = `$PRIME $double | head -1`
- echo "I have calculated that to be $pr."
-else
- set pr = $double
- echo "I cannot calculate that prime number, so you will need to provide it for me."
-endif
-
-if ($TableSize == 0) then
- set TableSize = $pr
-endif
-
-./getans "Enter the hash table size" integer "$TableSize" .$$
-set TableSize = `cat .$$`
-
-echo ""
-
-# !!! I need to fix this: /dev/kmem might not exist on some machines !!!
-
-# determine the right way to invoke ls to get full output
-set ls = "ls -l"
-if (`$ls getans | wc -w` < 9) then
- set ls = "ls -lg"
-endif
-
-set t_owner = root
-set t_group = `$ls -d /usr/bin | awk ' { print $4 }'`
-if (-e /proc) then
- cat <<EOF
-I see /proc out there. Many Unix variants provide the /proc file
-system as a mechanism to get to a process's address space. This
-directory is typically only accessible by root. However, there are a
-few systems (such as DG/UX) on which this directory exists, but isn't
-used.
-
-EOF
- if (-r /proc/0/psinfo) then
- set t_mode = 2711
- set mode = 2711
- set t_group = sys
- set group = sys
- cat <<EOF
-It looks like this system is running Solaris 2.6 or greater. If this
-is the case, then top can function just fine installed set group id to
-sys. It does not need to be installed set-uid to root.
-
-EOF
- else
- set t_mode = 4711
- set mode = 4711
- cat <<EOF
-I'm going to assume that top needs to run setuid to root, but you
-should double check and use mode 2755 (set group id) if top doesn't
-really need root access. If you are running SunOS 5.0 through SunOS
-5.5.1 (that's Solaris 2.0 through Solaris 2.5.1) then you will need to
-install top setuid root (owner root and mode 4711). In SunOS 5.6
-and higher top only requires set group id sys permissions.
-
-EOF
- endif
-else if (-e /dev/kmem) then
- $ls /dev/kmem >/tmp/$$.b
- grep '^....r..r..' /tmp/$$.b >&/dev/null
- if ($status == 1) then
- grep '^....r..-..' /tmp/$$.b >&/dev/null
- if ($status == 0) then
- set t_group = `awk ' { print $4 }' /tmp/$$.b`
- set t_mode = 2755
- echo "It looks like only group $t_group can read the memory devices."
- else
- set t_mode = 4755
- echo "It looks like only root can read the memory devices."
- endif
- else
- set t_mode = 755
- echo "It looks like anybody can read the memory devices."
- endif
-else
- echo "It looks like there are no memory device special files."
- set t_mode = 755
-endif
-if ($nodefaults) then
- set owner = $t_owner
- set group = $t_group
- set mode = $t_mode
-endif
-echo "Tell me how to set the following when top is installed:"
-./getans "Owner" user "$owner" .$$
-set owner = `cat .$$`
-./getans "Group owner" group "$group" .$$
-set group = `cat .$$`
-./getans "Mode" integer "$mode" .$$
-set mode = `cat .$$`
-rm -f /tmp/$$.b
-
-echo ""
-./getans "Install the executable in this directory" file "$bindir" .$$
-set bindir = `cat .$$`
-
-echo ""
-./getans "Install the manual page in this directory" file "$mandir" .$$
-set mandir = `cat .$$`
-
-echo ""
-./getans "Install the manual page with this extension" string "$manext" .$$
-set manext = `cat .$$`
-
-echo ""
-./getans "Install the manual page as 'man' or 'catman'" string "$mansty" .$$
-set mansty = `cat .$$`
-
-echo ""
-echo "We are done with the questions."
-
-# Some Unix environments are so poor that their csh doesn't even support
-# the "eval" builtin. Check for this before relying on its use to save
-# the current configuration.
-/bin/csh -fc "eval echo foo" >&/dev/null
-if ($status == 1) then
- echo "Can't save configuration (nonfatal)"
-else
- echo "Saving configuration..."
-# save settings to use as defaults the next time
- rm -f .defaults
- touch .defaults
- foreach v ($vars)
- set tmp = `eval echo \$$v`
- echo set $v = "'$tmp'" >>.defaults
- end
-endif
-
-fast:
-
-# clean up
-rm -f $$.[fmna]
-
-# set the link for machine.c
-rm -f machine.c machine.o
-ln -s machine/m_${module}.c machine.c
-
-# get definitions out of the module file
-set libs = `grep LIBS: machine/m_${module}.desc | sed -e 's/^.[^:]*: *//'`
-set cflgs = `grep CFLAGS: machine/m_${module}.desc | sed -e 's/^.[^:]*: *//'`
-set tcap = `grep TERMCAP: machine/m_${module}.desc | sed -e 's/^.[^:]*: *//'`
-set math = `grep MATH: machine/m_${module}.desc | sed -e 's/^.[^:]*: *//'`
-
-# get osrev defition, if we can
-set uname=""
-if (-e /usr/bin/uname) then
- set uname=/usr/bin/uname
-else if (-e /bin/uname) then
- set uname=/bin/uname
-endif
-
-if ("$uname" != "") then
-# different versions of tr can't agree on the way to specify ranges, so
-# we will have to give the range explicitly.....sigh.
- set osrev="-DOSREV=`$uname -r | tr -cd ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`"
-else
- set osrev=""
-endif
-
-# default for tcap (termcap)
-if ("$tcap" == "") then
- set tcap="-ltermcap"
-else if ("$tcap" == "none") then
- set tcap=""
-endif
-
-# allow for the module to override or remove -lm
-if ("$math" == "") then
- set math="-lm"
-else if ("$math" == "none") then
- set math=""
-endif
-
-if ( { grep -s SIGKILL /usr/include/signal.h } ) then
- set signal="/usr/include/signal.h"
-else
- set signal="/usr/include/sys/signal.h"
-endif
-
-
-echo "Building Makefile..."
-sed -e "s|%topn%|$topn|" \
- -e "s|%delay%|$delay|" \
- -e "s|%owner%|$owner|" \
- -e "s|%group%|$group|" \
- -e "s|%mode%|$mode|" \
- -e "s|%bindir%|$bindir|" \
- -e "s|%mandir%|$mandir|" \
- -e "s|%manext%|$manext|" \
- -e "s|%mansty%|$mansty|" \
- -e "s|%tablesize%|$TableSize|" \
- -e "s|%libs%|$libs|" \
- -e "s|%cflgs%|$cflgs|" \
- -e "s|%termcap%|$tcap|" \
- -e "s|%math%|$math|" \
- -e "s|%cdefs%|$cdefs|" \
- -e "s|%signal%|$signal|" \
- -e "s|%cc%|$Cmdcc|" \
- -e "s|%awk%|$Cmdawk|" \
- -e "s|%install%|$Cmdinstall|" \
- -e "s|%shell%|$Cmdshell|" \
- -e "s|%osrev%|$osrev|" \
- Makefile.X >Makefile
-
-echo "Building top.local.h..."
-sed -e "s|%LoadMax%|$LoadMax|" \
- -e "s|%TableSize%|$TableSize|" \
- -e "s|%NominalTopn%|$NominalTopn|" \
- -e "s|%topn%|$topn|" \
- -e "s|%delay%|$delay|" \
- -e "s|%random%|$random|" \
- top.local.H >top.local.h
-
-echo "Building top.1..."
-sed -e "s|%topn%|$topn|" \
- -e "s|%delay%|$delay|" \
- top.X >top.1
-if (-e machine/m_${module}.man ) then
- cat machine/m_${module}.man >>top.1
-endif
-
-# clean up
-rm -f .$$
-
-echo 'Doing a "make clean".'
-make clean
-
-echo 'To create the executable, type "make".'
-echo 'To install the executable, type "make install".'
-exit 0
-
-byebye:
-rm -f .$$ $$.[fmna] /tmp/$$.[ab]
-exit 1
Index: head/contrib/top/DISCLAIMER
===================================================================
--- head/contrib/top/DISCLAIMER
+++ head/contrib/top/DISCLAIMER
@@ -1,31 +0,0 @@
-DISCLAIMER
-
-"top" is distributed free of charge. It should not be considered an
-official product of Group sys Consulting. William LeFebvre supports
-"top" in his spare time and as time permits.
-
-NO WARRANTY:
-
-BECAUSE "top" IS DISTRIBUTED FREE OF CHARGE, THERE IS ABSOLUTELY NO
-WARRANTY PROVIDED, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING, GROUP SYS CONSULTING, ARGONNE
-NATIONAL LABORATORY, NORTHWESTERN UNIVERSITY, WILLIAM N. LeFEBVRE
-AND/OR OTHER PARTIES PROVIDE "top" "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-PROGRAM IS WITH YOU. SHOULD THE "top" PROGRAM PROVE DEFECTIVE, YOU
-ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-IN NO EVENT WILL GROUP SYS CONSULTING, ARGONNE NATIONAL LABORATORY,
-NORTHWESTERN UNIVERSITY, WILLIAM N. LeFEBVRE, AND/OR ANY OTHER PARTY
-WHO MAY MODIFY AND REDISTRIBUTE "top", BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL
-OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
-(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
-INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
-PROGRAM TO OPERATE WITH OTHER PROGRAMS) THE PROGRAM, EVEN IF YOU HAVE
-BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY
-ANY OTHER PARTY.
-
-So there!
Index: head/contrib/top/FAQ
===================================================================
--- head/contrib/top/FAQ
+++ head/contrib/top/FAQ
@@ -1,264 +0,0 @@
- TOP
- Version 3.5
- Beta Release 11
-
- William LeFebvre
- with much help from others
-
-
-FREQUENTLY ASKED QUESTIONS AND THEIR ANSWERS
-
-This FAQ is broken out in to several topics.
-
-
-GENERAL
-
- 1. "Where do I get the latest version of top?"
-
-The official site for top is "ftp.groupsys.com" in the directory
-"/pub/top". It is also available from the following mirror sites:
-"pharos.dgim.doc.ca" in /packages/top, "uiarchive.uiuc.edu" in
-/pub/packages/top, "sunsite.auc.dk" in /pub/unix/top. European
-users should consider using the Denmark (dk) site.
-
- 2. "Is there a web page for top?"
-
-Yes. Point your browser at http://www.groupsys.com/top. It includes
-all documentation, a nice interactive display which describes the
-various components of the output of top, web-based retrieval of the
-package, year 2000 information, and pointers to the mailing list.
-
- 3. "Is there a mailing list for top?"
-
-The official list for announcements is "top-announce@groupsys.com".
-This list is managed by "majordomo@groupsys.com". Announcements of
-importance to all top users will be sent to this list, including new
-releases, availability of beta test versions, emergency revisions and
-patches, etc. Anyone is welcome to join top-announce. This is a
-read-only list. The list of subscribers will not (intentionally) be
-made available, and postings to the list are limited.
-
-In addition, there is a top developers mailing list that is used by
-beta testers and other people who help me port the program to various
-machines. Membership to this list is solely at my discretion. If you
-feel qualified to act as a beta tester, or if you are doing development
-work on top (such as porting to a new platform), you may submit a
-request by sending a message to "top-spinners-request@groupsys.com"
-containing the word "subscribe". I will contact you within a few days,
-as my schedule permits.
-
- 4. "What about Year 2000 compliance"?
-
-Top should not experience any problems with the transition to the year
-2000. A full statement concerning top and the year 2000 can be found
-in the file "Y2K" included with the distribution.
-
-
- 5. "Why does it take so long for a new version of top to go through the
- beta test process?"
-
-This is completely my fault. I have just not had the time to give top
-the attention it deserves. I thank everyone for their patience, and I
-hope that with the recent changes in the direction of my career that I
-can spend more time on this.
-
- 6. "Top is not written in ANSI C. Do you ever plan to change that?"
-
-Top predates ANSI C by about 5 years. Yeah, it'll get "fixed" eventually.
-Probably in 3.6.
-
-
-CONFIGURING
-
- 7. "Configure said that it saw /proc and is recommending that I install top
- setuid root. Is there any way around this? Is it safe?"
-
-There is no way around it. Complain to POSIX. Every effort has been made
-to make top a secure setuid program. However, we cannot guarantee that
-there are no security problems associated with this configuration. The
-places where top is most vulnerable are the builtin kill and renice
-commands. There is no internal top command that causes top to start a shell
-as a subprocess. Some SVR4 systems may contain a bug that enables a user to
-renice his own processes downward (to lower nice values that are more
-favorable for the process). This problem has been fixed for the Solaris 2.x
-modules, but may still exist in others. We will hopefully fix this up in
-the next release.
-
- 8. "Why is Configure a c-shell script? I thought c-shell scripts were
- evil?"
-
-They are. :-) I'll probably be rewriting the Configure script for the
-next release, or switching to something like Gnu configure.
-
-
-COMPILING
-
- 9. "We just upgraded our operating system to a new version and top broke.
- What should we do?"
-
-Recompile it. Top is very sensitive to changes in internal kernel data
-structures. It is not uncommon for a new version of the operating system to
-include changes to kernel data structures.
-
-
-RUNNING
-
-10. "I just finished compiling top and it works fine for root, but when
- I try to run it as a regular user it either complains about files
- it can't open or it doesn't display all the information it should.
- Did I do something wrong?"
-
-Well, you're just not done. On many operating systems today, access to
-many of the kernel memory devices and other system files is restricted to
-either root or a particular group. The Configure script figures this out
-(usually) and makes sure that the "intsall" rule in the Makefile will
-install top so that anyone can run it successfully. However, you have to
-*install* it first. Do this with the command "make install".
-
-11. "Top is (not) displaying idle processes and I don't (do) want it to."
-
-This default has only changed about a dozen times, and I finally got tired
-of people whining about it. Go read the manual page for the current version
-and pay special attention to the description of the "TOP" environment
-variable.
-
-12. "We have so much memory in our machine that the memory status display
- (the fourth line) ends up being longer than 80 characters. This
- completely messes up top's output. Is there a patch?"
-
-Most modules have been changed to use new memory formatting functions which
-will display large values in terms of megabytes instead of kilobytes. This
-should fix all occurences of this problem. If you encounter a system where
-this large memory display overflow is still occurring, please let me know
-(send mail to <wnl@groupsys.com>). Also note that newer versions of top can
-use columns beyond 79, and understand window resizes. So you can always
-make your window bigger.
-
-13. "I tried to compile top with gcc and it doesn't work. I get
- compilation errors in the include files, or I get an executable that
- dumps core, or top displays incorrect numbers in some of the displays.
- What's wrong?"
-
-Gnu CC likes very much to use its own include files. Not being a gcc
-expert, I can't explain why it does this. But I can tell you that if
-you upgrade your operating system (say from Solaris 2.4 to Solaris
-2.5) after installing gcc, then the include files that gcc uses will
-be incorrect, especially those found in the "sys" directory. Your
-choices are: (1) rebuild and reinstall the "standard" include files
-for gcc (look for scripts in the distribution called "fixincludes" and
-"fixinc.svr4"), (2) compile machine.c with "CFLAGS=-I/usr/include"
-then make the rest of the object files normally, or (3) use "cc".
-Solaris 2.6 users should also consult FAQ #20.
-
-14. "The cpu state percentages are all wrong, indicating that my machine is
- using 95% system time when it is clearly idle. What's wrong?"
-
-This can happen if you compiled with gcc using the wrong include files.
-See the previous question.
-
-
-SUNOS PROBLEMS
-
-15. "I tried compiling top under SunOS version 4.1.x and it got compile time
- errors. Is there a patch?"
-
-If you try compiling top in a "System V environment" under SunOS (that is,
-/usr/5bin is before /usr/bin on your path) then the compilation may fail.
-This is mostly due to the fact that top thinks its being compiled on a
-System V machine when it really isn't. The only solution is to put /usr/bin
-and /usr/ucb before /usr/5bin on your path and try again.
-
-
-SVR4-derived PROBLEMS
-
-16. "When I run top on my SVR4-derived operating system, it displays all
- the system information at the top but does not display any process
- information (or only displayes process information for my own
- processes). Yet when I run it as root, everything works fine."
-
-Your system probably uses the pseudo file system "/proc", which is by
-default only accessible by root. Top needs to be installed setuid root on
-such systems if it is going to function correctly for normal users.
-
-
-SOLARIS PROBLEMS
-
-17. "Under Solaris 2, when I run top as root it only shows root processes,
- or it only shows processes with a PID less than 1000. It refuses to
- show anything else. What do I do?"
-
-You probably compiled it with /usr/ucb/cc instead of the real C compiler.
-/usr/ucb/cc is a cc front end that compiles programs in BSD source-level
-compatability mode. You do not want that. Make sure that /usr/ucb is not
-on your path and try compiling top again.
-
-18. "Under Solaris 2, I compiled top using what I am sure is the correct
- compiler but when I try to run it it complains about missing dynamic
- libraries. What is wrong?"
-
-Check to see if you have LD_LIBRARY_PATH defined in your shell. If you do,
-make sure that /usr/ucblib is not on the path anywhere. Then try compiling
-top again.
-
-19. "Under Solaris 2, when I try to run top it complains that it can't open
- the library "libucb.so.1". So I changed the LIBS line in m_sunos5.c
- to include -R/usr/ucblib to make sure that the dynamic linker will look
- there when top runs. I figured this was just an oversight. Was I
- right?"
-
-No, you were not right. As distributed, top requires NO alterations
-for successful compilation and operations under any release of Solaris
-2. You probably compiled top with /usr/ucb/cc instead of the real C
-compiler. See FAQ #10 for more details.
-
-20. "When I try to compile top under Solaris 2.6 using gcc I get compile
- time errors. There appear to be problems with the include files,
- such as 'u_rlimit has incomplete type' and/or 'u_saved_rlimit has
- incomplete type'. I've already run fixinc.svr4 as per FAQ #13.
- Why didn't that fix it?"
-
-Only top versions 3.5 and later are compatible with Solaris 2.6. Make
-sure you are using the most up-to-date version. Earlier beta release
-copies of version 3.5 had additional problems when compiled with gcc.
-Retrieve the official version 3.5 (non-beta) release from one of the
-sites listed in FAQ #1 or FAQ #2.
-
-
-SCO PROBLEMS
-
-21. "When I try to run Configure, it complains about a syntax error."
-
-Some versions of SCO's csh do not understand the syntax "$<". Earlier
-releases of top depended on this syntax to read input from the installer's
-terminal during the installation process. Version 3.5 fixes this.
-
-
-SVR42 PROBLEMS
-
-22. "The memory display doesn't work right. Why?"
-
-This is a known bug with the svr42 module. The problem has been traced down
-to a potential bug in the "mem" driver. The author of the svr42 module is
-working on a fix.
-
-
-STILL STUCK
-
-23. I'm still stuck. To whom do I report problems with top?"
-
-The most common problems are caused by top's sensitivity to internal kernel
-data structures. So make sure that you are using the right include files,
-and make sure that you test out top on the same machine where you compiled
-it. Sun's BSD Source Compatability Mode is also a common culprit. Make
-sure you aren't using either /usr/ucb/cc or any of the libraries in
-/usr/ucblib. Finally, make sure you are using the correct module. If there
-does not appear to be one appropriate for your computer, then top probably
-will not work on your system.
-
-If after reading all of this file and checking everything you can you are
-still stuck, then send mail to "wnl@groupsys.com". I will answer your mail
-when I have time. Please bear with me in that regard! If it looks like the
-problem is machine-specific, I will forward the report along to the module's
-author. If you would like to converse directly with the module author, the
-authors' names are listed at the beginning of the module .c file in the
-"machine" directory.
Index: head/contrib/top/FREEBSD-upgrade
===================================================================
--- head/contrib/top/FREEBSD-upgrade
+++ head/contrib/top/FREEBSD-upgrade
@@ -1,22 +0,0 @@
-$FreeBSD$
-
-This file contains notes regarding the upgrade of top(1). See the vendor
-import instructions at:
-
- https://www.freebsd.org/doc/en/articles/committers-guide/subversion-primer.html#svn-advanced-use-vendor-imports
-
-The upstream project pages for top(1) are:
-
- http://www.unixtop.org/
-
- https://sourceforge.net/projects/unixtop/
-
-contrib/top/machine.h specifies an interface that must be provided by the
-target OS. That interface is implemented in usr.bin/top/machine.c
-
-To enable building on case-insensitive filesystems, the following files were
-renamed:
-
- contrib/top/top.X -> contrib/top/top.xs
- contrib/top/top.local.H -> contrib/top/top.local.hs
-
Index: head/contrib/top/INSTALL
===================================================================
--- head/contrib/top/INSTALL
+++ head/contrib/top/INSTALL
@@ -1,166 +0,0 @@
- TOP
- Version 3.5
-
- William LeFebvre
- and a cast of many
-
-INSTALLATION
-
-Configuration and installation of top is very straightforward. After
-unpacking the sources, run the script "Configure". It will present you
-with a series of questions, all of which should be explained in the
-presentation. After you have answered all the questions, "Configure" will
-perform all the necessary configuration. Once this is finished, type
-"make install". Make will compile the sources then install the resulting
-executable and manual page in the appropriate places.
-
-The most difficult step in the configuration is the choice of an
-appropriate machine-specific module. The Configure script gives you a
-list of choices complete with brief descriptions of when each choice is
-appropriate. Each module is contained in a separate c file in the
-directory "machine". The module contains all of the machine-specific code
-that makes top work correctly on the architecture in question. All of the
-code in the top-level directory is machine-independent (or at least
-strives to be). Hints for some module choices that are not obvious are
-given at the end of this file.
-
-The first comment in each c file in that directory contains the synopsis
-AND a detailed description of the machines for which that module is
-appropriate. It also contains a list of authors for that module. If you
-are really stumped in this choice, use grep to find your machine
-manufacturer's name or operating system name in machine/*.c. If you still
-can't find one that is appropriate, then chances are very good that one
-hasn't been written yet. If that is the case, then you are out of luck.
-
-HANDLING MULTIPLE ARCHITECTURES
-
-If you need to recompile top for a different architecture (that is, using
-a different module) you need to reconfigure top. A short cut is available
-to make this a little easier. If all of your previous answers to the
-configuration questions (except for the module name of course) are
-adequate for the new architecture, then you can just use the command
-"Configure <modulename>". The configuration script will reconfigure top
-using the new module and all the answers you gave last time. It will
-finish with a "make clean". Once that completes, type "make install"
-and make will compile the sources and do the installation.
-
-HANDLING MULTIPLE OS VERSIONS
-
-By far the most frequently received bug report for top is something like
-this: "We just upgraded our operating system to version 99.9.9.9 and top
-broke. What should we do?" The simple answer is "recompile".
-
-Top is very sensitive to changes in internal kernel data structures
-(especially the proc and user structures). Some operating systems
-(especially SunOS) are notorious for changing these structure in every
-minor release of the OS. This means that a top executable made under one
-version of the OS will not always work correctly (if even at all) under
-another version. This is just one of those tough facts of life. There is
-really no way around it.
-
-To make life even worse, some operating systems (SunOS again) will use
-slightly different proc and user structures on different models. For
-example, "top" built on a SparcStation 2 will not run correctly on a
-SparcStation 10, even if they are both running SunOS 4.1.3. These
-unfortunate circumstances make maintaining top very difficult, especially
-in an environment that runs several different versions of the same
-operating system.
-
-But there is hope. If your operating system has a properly functioning
-"uname" command then you can handle this problem rather gracefully.
-Included in the distribution is a shell file called "metatop". All this
-shell file does is:
-
- exec top-`uname -m`-`uname -r` "$@"
-
-So when you run this script, it execs a filename that is unique to your
-specific machine architecture and your OS revision number.
-
-To use "metatop", do the following:
-
- . on any machine, run Configure and choose the module that is
- appropriate for the machine
- . for all machines which use the same module:
- . group machines according to machine architecture AND OS
- revision number (i.e.: sun4-4.1.1, sun4c-4.1.1, sun4c-4.1.2,
- sun4-4.1.3, sun4c-4.1.3, sun4m-4.1.3, ...)
- . for each group, choose one machine from that group and on it
- run "make clean; make installmeta".
-
-
-The "installmeta" rule in the makefile will insure that top is compiled,
-install the shell file "metatop" as "top", then install the executable
-"top" with a name appropriate to the machine architecture and OS revision.
-
-
-HINTS FOR CHOOSING THE CORRECT MODULE:
-
-SOLARIS 2.x
-
-All versions of Solaris will now work with the module sunos5. Version
-specific modules (such as sunos54) no longer exist.
-
-
-SUNOS 4.x AND MULTIPROCESSOR ARCHITECTURES
-
-First, we need to be speaking the same language:
-
-sun4 a regular sparc sun 4 architecture machine (sparc station 1,
- sparc station 2, IPC, SLC, etc.)
-
-sun4m a multiprocessor sparc (Sparc 10, 4/670, 4/690)
-
-I intended to write the sunos4 module so that an executable compiled on a
-sun4m machine would work correctly on a sun4 machine. Unfortunately my
-experiments indicate that this cannot be done. It turns out that the user
-structure is so different between these two architectures that nothing
-short of a serious hack will make the same executable work correctly on
-both machines. I recommend that you use the separate module "sunos4mp"
-when making an executable for a sun4m architecture, and use "sunos4" when
-making an executable for sun4 or sun4c architectures.
-
-DIGITAL UNIX V4.0
-
-This is the successor to DECOSF/1. Use the module decosf1.
-
-SOLBOURNE OPERATING SYSTEM (OS/MP)
-
-If you are running OS/MP version 4.1A, then use the module "osmp4.1a".
-
-If you are running a version of OS/MP OLDER than 4.1A (that is, one
-of its predecessors), use the module "sunos4".
-
-If you are running OS/MP 4.1B or LATER, use the module "sunos4mp".
-
-HP/UX OPERATING SYSTEM
-
-The module hpux8 works on all version 8 systems. Some say that it works
-with version 9 as well, but one user did send me a separate module for
-version 9. This module has only been tested on series 800 machines. I
-would recommend the following for those running version 9: try hpux9 and
-if it doesn't work then try hpux8. If neither work, then send mail to me
-and/or the modules' authors. Another note: we have a model 730 supposedly
-running version 9.01. The module hpux9 did not compile successfully, but
-the module hpux8 worked fine. The module hpux10 works on all revisions of
-HP/UX 10 except 10.10, where HP removed the definition of the proc structure
-from the system include files.
-
-NET/2 386BSD SYSTEMS
-
-If your version of the operating system has patchkit 2.4 installed,
-then you will need to modify machine/m_386bsd.c and uncomment the
-definition of PATCHED_KVM. This patchkit makes what more than a few
-people believe to be a wholly unnecessary patch to the way the kvm
-routines work.
-
-A/UX SYSTEMS
-
-There is a module for A/UX 3.0 and 3.1. Whether or not it works for
-any other version is not known. Proceed at your own risk.
-
-Although AUX does not generally have a renice systemcall, it can be
-implemented by tweeking kernel memory. The flag IMPLEMENT_SETPRIORITY
-controls the inclusion of this code. It is off be default. While
-such a simple hack should not be difficult to get right, USE THIS
-FEATURE AT YOUR OWN RISK!
-
Index: head/contrib/top/Make.desc.X
===================================================================
--- head/contrib/top/Make.desc.X
+++ head/contrib/top/Make.desc.X
@@ -1,24 +0,0 @@
-# Makefile for .desc files
-
-# This makefile is the prototype for "Make.desc", which is used by
-# top's Configure script to build .desc files and the SYNOPSIS file.
-# Configure then uses these files to ask appropriate questions.
-
-# Written by William LeFebvre, Group sys Consulting
-# (formerly of Northwestern University and Rice University)
-
-# DO NOT EDIT "Make.desc"!!! Make changes to "Make.desc.X",
-# then "make veryclean", then run "Configure".
-
-# The list of .desc files will be inserted after this next line:
-DESCS=\
-
-.SUFFIXES: .desc
-
-.c.desc:
- sed -e '/^$$/,$$d' -e 's,^[/ *]*,,' $< > $@
-
-all: SYNOPSIS
-
-SYNOPSIS: $(DESCS)
- grep SYNOPSIS: $(DESCS) | sed -e 's@^machine/m_@@' -e 's@.desc:.[^:]*: *@:@' >SYNOPSIS
Index: head/contrib/top/Makefile.X
===================================================================
--- head/contrib/top/Makefile.X
+++ head/contrib/top/Makefile.X
@@ -1,117 +0,0 @@
-# Makefile for "top", a top 10 process display for Unix
-#
-# This makefile is for top, version 3
-#
-# Written by William LeFebvre, Group sys Consulting
-# (formerly of Northwestern University and Rice University)
-
-# DO NOT EDIT "Makefile"!!!! Make changes to "Makefile.X" and rerun
-# Configure.
-
-# Executables (these should be obvious):
-
-SHELL = %shell%
-CC = %cc%
-AWK = %awk%
-INSTALL = %install%
-
-# installation information:
-# OWNER - name (or uid) for the installed executable's owner
-# GROUP - group name (or gid) for the installed executable's group
-# MODE - mode for the installed executable (should start with a 0)
-# BINDIR - directory where the executable should live
-# MANDIR - directory where the manual page should live
-# MANEXT - installed man pages end in .$(MANEXT)
-# MANSTY - "man" or "catman" depending on what's to be installed
-# SIGNAL - <signal.h> or <sys/signal.h>; the one with signal definitions
-# TROFF - most appropriate troff command
-
-OWNER = %owner%
-GROUP = %group%
-MODE = %mode%
-BINDIR = %bindir%
-MANDIR = %mandir%
-MANEXT = %manext%
-MANSTY = %mansty%
-SIGNAL = %signal%
-
-# Values for the two defaults in "top":
-# TOPN - default number of processes to display
-# DELAY - default delay between updates
-#
-# set TOPN to -1 to indicate infinity (so that top will display as many
-# as the screen will hold).
-
-TOPN = %topn%
-DELAY = %delay%
-
-CFILES = top.c commands.c display.c screen.c username.c \
- utils.c version.c getopt.c machine.c
-OBJS = top.o commands.o display.o screen.o username.o \
- utils.o version.o getopt.o machine.o
-
-CDEFS = %cdefs%
-LIBS = %libs%
-TERMCAP = %termcap%
-MATH = %math%
-
-CFLAGS = %cflgs% $(CDEFS)
-LINTFLAGS = -x $(CDEFS)
-
-all: Makefile top.local.h top
-
-Makefile: Makefile.X
- @echo 'You need to run the script "Configure" before running "make".'
- exit 10
-
-top.local.h: top.local.H
- @echo 'You need to run the script "Configure" before running "make".'
- exit 10
-
-top: $(OBJS)
- rm -f top
- $(CC) $(CDEFS) -o top $(OBJS) $(TERMCAP) $(MATH) $(LIBS)
-
-lint: sigdesc.h
- $(LINT) $(LINTFLAGS) $(CFILES)
-
-# include file dependencies
-top.o: boolean.h display.h screen.h top.h top.local.h utils.h machine.h
-commands.o: boolean.h sigdesc.h top.h utils.h
-display.o: boolean.h display.h layout.h screen.h top.h top.local.h utils.h
-screen.o: boolean.h screen.h
-utils.o: top.h
-version.o: top.h patchlevel.h
-username.o: top.local.h utils.h
-
-# when compiling machine.c, include os revision definition
-machine.o: machine.c top.h machine.h utils.h
- $(CC) "%osrev%" $(CFLAGS) -c machine.c
-
-# automatically built include file
-sigdesc.h: sigconv.awk $(SIGNAL)
- $(AWK) -f sigconv.awk $(SIGNAL) >sigdesc.h
-
-clean:
- rm -f *.o top core core.* sigdesc.h
-
-veryclean: clean
- rm -f Make.desc machine/*.desc .defaults top.tar SYNOPSIS Makefile top.local.h top.1 machine.c prime
-
-install: top top.1 install-top install-$(MANSTY)
-
-install-top:
- $(INSTALL) -o $(OWNER) -m $(MODE) -g $(GROUP) top $(BINDIR)
-
-install-man:
- $(INSTALL) top.1 $(MANDIR)/top.$(MANEXT)
-
-install-catman:
- tbl top.1 | nroff -man > $(MANDIR)/top.$(MANEXT)
-
-installmeta: top top.1
- $(INSTALL) -o $(OWNER) -m 755 -g $(GROUP) metatop $(BINDIR)/top
- @echo $(INSTALL) -o $(OWNER) -m $(MODE) -g $(GROUP) top $(BINDIR)/top-`uname -m`-`uname -r`
- @$(INSTALL) -o $(OWNER) -m $(MODE) -g $(GROUP) \
- top $(BINDIR)/top-`uname -m`-`uname -r`
- $(INSTALL) top.1 $(MANDIR)/top.$(MANEXT)
Index: head/contrib/top/Porting
===================================================================
--- head/contrib/top/Porting
+++ head/contrib/top/Porting
@@ -1,165 +0,0 @@
-Instructions for porting top to other architectures.
-
-This is still a preliminary document. Suggestions for improvement are
-most welcome.
-
-My address is now "wnl@groupsys.com".
-
-Before you embark on a port, please send me a mail message telling me
-what platform you are porting top to. There are three reasons for
-this: (1) I may already have a port, (2) module naming needs to be
-centralized, (3) I want to loosely track the various porting efforts.
-You do not need to wait for an "okay", but I do want to know that you
-are working on it. And of course, once it is finished, please send me
-the module files so that I can add them to the main distribution!
-
-----------
-
-There is one set of functions which extract all the information that
-top needs for display. These functions are collected in to one file.
-To make top work on a different architecture simply requires a
-different implementation of these functions. The functions for a
-given architecture "foo" are stored in a file called "m_foo.c". The
-Configure script looks for these files and lets the configurer choose
-one of them. This file is called a "module". The idea is that making
-top work on a different machine only requires one additional file and
-does not require changes to any existing files.
-
-A module template is included in the distribution, called "m-template".
-To write your own module, it is a good idea to start with this template.
-If you architecture is similar to one for which a module already
-exists, then you can start with that module instead. If you do so,
-remember to change the "AUTHOR" section at the top!
-
-The first comment in a module contains information which is extracted
-and used by Configure. This information is marked with words in all
-capitals (such as "SYNOPSIS:" and "LIBS:"). Go look at m-template: it
-is fairly self-explanatory. The text after "LIBS:" (on the same line)
-is extracted and included in the LIBS definition of the Makefile so
-that extra libraries which may be necessary on some machines (such as
-"-lkvm") can be specified in the module. The text after "CFLAGS:"
-(on the same line) is extracted and included as flags in the "CFLAGS"
-definition of the Makefile (thus in every compilation step). This is
-used for rare circumstances only: please don't abuse this hook.
-
-Some operating systems have idiosyncrasies which will affect the form
-and/or content of the information top displays. You may wish to
-document such anomalies in the top man page. This can be done by adding
-a file called m_{modulename}.man (where {modulename} is replaced with
-the name of the module). Configure will automatically add this file to
-the end of the man page. See m_sunos4.man for an example.
-
-A module is concerned with two structures:
-
-The statics struct is filled in by machine_init. Each item is a
-pointer to a list of character pointers. The list is terminated
-with a null pointer.
-
-struct statics
-{
- char **procstate_names; /* process state names */
- char **cpustate_names; /* cpu state names */
- char **memory_names; /* memory information names */
-};
-
-The system_info struct is filled in by get_system_info and
-get_process_info.
-
-struct system_info
-{
- int last_pid; /* last pid assigned (0 means non-sequential assignment) */
- double load_avg[NUM_AVERAGES]; /* see below */
- int p_total; /* total number of processes */
- int p_active; /* number of procs considered "active" */
- int *procstates; /* array of process state counters */
- int *cpustates; /* array of cpustate counters */
- int *memory; /* memory information */
-};
-
-The last three pointers each point to an array of integers. The
-length of the array is determined by the length of the corresponding
-_names array in the statics structure. Furthermore, if an entry in a
-_names array is the empty string ("") then the corresponding value in
-the value array will be skipped over. The display routine displays,
-for example, the string procstate_names[0] then the number
-procstates[0], then procstate_names[1], procstates[1], etc. until
-procstate_names[N] == NULL. This allows for a tremendous amount of
-flexibility in labeling the displayed values.
-
-"procstates" and "memory" are displayed as straight integer values.
-Values in "cpustates" are displayed as a percentage * 10. For
-example, the (integer) value 105 is displayed as 10.5%.
-
-These routines must be defined by the machine dependent module.
-
-int machine_init(struct statics *)
-
- returns 0 on success and -1 on failure,
- prints error messages
-
-char *format_header(char *)
-
- Returns a string which should be used as the header for the
- process display area. The argument is a string used to label
- the username column (either "USERNAME" or "UID") and is always
- 8 characters in length.
-
-void get_system_info(struct system_info *)
-
-caddr_t get_process_info(struct system_info *, int, int, int (*func)())
-
- returns a handle to use with format_next_process
-
-char *format_next_process(caddr_t, char *(*func)())
-
- returns string which describes next process
-
-int proc_compare(caddr_t, caddr_t)
-
- qsort comparison function
-
-uid_t proc_owner(pid_t)
-
- Returns the uid owner of the process specified by the pid argument.
- This function is VERY IMPORTANT. If it fails to do its job, then
- top may pose a security risk.
-
-
-get_process_info is called immediately after get_system_info. In
-fact, the two functions could be rolled in to one. The reason they
-are not is mostly historical.
-
-Top relies on the existence of a function called "setpriority" to
-change a process's priority. This exists as a kernel call on most 4.3
-BSD derived Unixes. If neither your operating system nor your C
-library supplies such a function, then you will need to add one to the
-module. It is defined as follows:
-
- int setpriority (int dummy, int who, int niceval)
-
- For the purposes of top, the first argument is meaningless.
- The second is the pid and the third is the new nice value.
- This function should behave just like a kernel call, setting
- errno and returning -1 in case of an error. This function MUST
- check to make sure that a non-root user does not specify a nice
- value less than the process's current value. If it detects such
- a condition, it should set errno to EACCES and return -1.
- Other possible ERRNO values: ESRCH when pid "who" does not exist,
- EPERM when the invoker is not root and not the same as the
- process owner.
-
-Note that top checks process ownership and should never call setpriority
-when the invoker's uid is not root and not the same as the process's owner
-uid.
-
-
-The file "machine.h" contains definitions which are useful to modules
-and to top.c (such as the structure definitions). You SHOULD NOT need
-to change it when porting to a new platform.
-
-Porting to a new platform should NOT require any changes to existing
-files. You should only need to add m_ files. If you feel you need a
-change in one of the existing files, please contact me so that we can
-discuss the details. I want to keep such changes as general as
-possible.
-
Index: head/contrib/top/README
===================================================================
--- head/contrib/top/README
+++ head/contrib/top/README
@@ -1,192 +0,0 @@
- TOP
- Version 3.5
-
- William LeFebvre
- and a cast of dozens
-
-
-If you do not want to read this entire file, then at least read
-the section at the end entitled "KNOWN PROBLEMS".
-
-If you are having any problems getting top to work, please read the
-file "FAQ" *before* contacting me. Thank you.
-
-"top" is a program that will give continual reports about the state of
-the system, including a list of the top cpu using processes. Version 3
-of "top" has three primary design goals: provide an accurate snapshot of
-the system and process state, not be one of the top processes itself, be
-as portable as possible.
-
-Version 3 has many bug fixes from version 2.5, and it has also been
-reorganized in a major way to make it easy to port to other platforms.
-All system dependent code is now contained in one file.
-
-Top now includes a configuration script called "Configure". It helps
-the installer choose the correct parameters for this particular
-installation. This script MUST be run before attempting to compile top.
-
-Top requires read access to the memory files "/dev/kmem" and "/dev/mem"
-as well as the system image "/vmunix". Some installations have these
-files protected from general access. These sites would have to install
-this program in the same way that programs such as "ps" are installed.
-In addition, on those Unix variants that support the proc filesystem
-(such as SVR4 and Solaris 2), top requires read access to all the files
-in /proc: typically dictating that top be installed setuid to root.
-
-CAVEAT: version 3 of top has internal commands that kill and renice
-processes. Although I have taken steps to insure that top makes
-appropriate checks with these commands, I cannot guarantee that these
-internal commands are totally secure. IF YOU INSTALL top as a SETUID
-program, you do so AT YOUR OWN RISK! I realize that some operating
-systems will require top to run setuid, and I will do everything I can
-to make sure that top is a secure setuid program.
-
-Configure will ask you to input values for certain parameters. Before
-each parameter, Configure will display a description of what the
-parameter does. Read the description and choose an appropriate value.
-Sometimes a default will appear in brackets. Typing just return will
-choose the default.
-
-System support now takes the form of "modules". Adding support for
-a different architecture requires only adding a module. Configure
-asks which module to use when it is configuring top. See the file
-"Porting" for a description of how to write your own module.
-
-To compile and install "top", read the file "INSTALL" and follow the
-directions and advice contained therein.
-
-Once you have created a binary for one particular type of machine, you
-can reconfigure for another type with "./Configure modulename" where
-"modulename" is replaced with the appropriate module name. All other
-parameter values are kept the same. Note that in some cases this may
-not be appropriate.
-
-If you make any kind of change to "top" that you feel would be
-beneficial to others who use this program, or if you find and fix a bug,
-please send me the change.
-
-Be sure to read the FAQ enclosed with the distrubution. It contains
-answers to the most commonly asked questions about the configuration,
-installation, and operation of top.
-
-
-AVAILABILITY
-
-The latest version of "top" is now being made available via anonymous
-FTP from the host "ftp.groupsys.com" in the directory "/pub/top".
-Additional modules will be made available in the directory
-"/pub/top/m". The site "eecs.nwu.edu" will continue to house copies
-of the distribution as well.
-
-Here are HTML links for the four best "top" archive sites:
-
-<A HREF="ftp://ftp.groupsys.com/pub/top">Top archive (groupsys.com)</A>
-<A HREF="ftp://eecs.nwu.edu/pub/top">Top archive (eecs.nwu.edu)</A>
-<A HREF="ftp://pharos.dgim.doc.ca/packages/top"> Top mirror (dgim.doc.ca)</A>
-<A HREF="ftp://uiarchive.uiuc.edu/pub/packages/top/">Top mirror (uiuc.edu)</A>
-
-New releases will be posted to comp.sources.unix as they become
-available. Sites which arhive that newsgroup will also contain copies
-of the distribution.
-
-Announcements about availability will be made to the mailing list
-"top-announce@groupsys.com". This is an open list maintained by
-majordomo. To join the list, send a message containing the word
-"subscribe" to "top-announce-request@groupsys.com". Addresses of
-subscribers to this list are kept confidential and will never be used
-for any purpose other than as recipients of announements concerning
-this software.
-
-
-KNOWN PROBLEMS:
-
-Gnu CC
-
-Compiling via Gnu CC continued to be the source of most of the
-questions I receive. By far the most common mistake made by those
-attempting to compile top with Gnu CC is out of date include files.
-When the operating system is upgraded, the include files that are part
-of the gcc package MUST also be updated. Gcc maintains its own
-include files. Even a minor OS upgrade can involve changes to some of
-the kernel's internal data structures, which are defined in include
-files in "sys". Top is very sensitive to these changes. If you are
-compiling with gcc and experience any sort of strange problems, please
-make sure the include files you are using are up to date BEFORE
-sending me a bug report. Look in the gcc source distribution for the
-shell script "fixincludes".
-
-HP/UX 10.10
-
-In their infinite wisdom, the folks at HP have decided that mere mortals
-such as you and I don't need to know what the kernel's proc structure looks
-like. To that end, they have removed all useful content from the include
-file <sys/proc.h> in version 10.10. As a result, top will not compile
-under 10.10. What HP is trying to accomplish with this move is to force
-iconoclasts such as myself to use "pstat" for collecting all process
-information. I have no immediate solution for this problem, but hope to
-obtain a sufficiently complete definition of "struct proc" at some point in
-the near future. Stay tuned.
-
-DIGITAL UNIX 4.0 (DECOSF/1 V4.0)
-
-A user has reported that idle processes are not displayed regardless
-of the flags used when invoking top. We have not had time to track
-this problem down.
-
-DECOSF/1 V3.0
-
-There is a bug either in the module, in utils.c, or in DEC's optimizer that
-is tickled by the decosf1 module when compiled under V3.0 (and perhaps
-earlier versions). Top compiled using DEC's compiler with optimization
-will consistently produce a segmentation fault (in format_next_process
-while calling sprintf). To work around this problem, either compile top
-with gcc or turn off optimization (compile without -O). We think that
-one of the bugs fixed in utils.c fixed this problem as well, but we are
-not certain.
-
-
-System V R 4.2
-
-Load average and memory displays do not work. The problem has been
-traced down to a potential bug in the "mem" driver. The author
-of the svr42 module is working on a fix.
-
-
-
-GRATITUDE
-
-My perpetual thanks to all the people who have helped me support top
-on so many platforms. Without these people, top would not be what it
-is. Here is a partial list of contributors and other individuals.
-
- Robert Boucher <boucher@sofkin.ca>
- Marc Cohen <marc@aai.com>
- David Cutter <dpc@grail.com>
- Casper Dik <Casper.Dik@Sun.COM>
- Charles Hedrick <hedrick@geneva.rutgers.edu>
- Andrew Herbert <andrew@werple.apana.org.au>
- Jeff Janvrin <jeff.janvrin@columbiasc.ncr.com>
- Torsten Kasch <torsten@techfak.uni-bielefeld.de>
- Petri Kutvonen <kutvonen@cs.helsinki.fi>
- William L. Jones <jones@chpc>
- Tim Pugh <tpugh@oce.orst.edu>
- Steve Scherf <scherf@swdc.stratus.com>
- Phillip Wu <pwu01@qantek.com.au>
-
-(My apologies if I missed anyone.)
-
-
-AUTHOR
-
- William LeFebvre
- Group sys Consulting
- wnl@groupsys.com
-
-
- U.S. Mail address:
- William LeFebvre
- Group sys Consulting
- 11585 Jones Bridge Road
- Suite 420-139
- Alpharetta, GA 30022
- (770) 813-3224
Index: head/contrib/top/Y2K
===================================================================
--- head/contrib/top/Y2K
+++ head/contrib/top/Y2K
@@ -1,26 +0,0 @@
-Top and the Year 2000
-
-The software package top will not be affected by years numbering
-between 2000 and 2037. No portion of the top code stores dates on
-disk. All date processing in top is performed with functions from the
-Unix C library and Unix kernel. The specific functions are: time(2)
-and ctime(3S). These functions deal exclusively with conventional
-Unix time values (number of seconds since Midnight January 1, 1970
-GMT) and produce strings with a 4-digit year. At no point in the code
-for top are the last two digits used to represent a year.
-
-Top and the Year 2038
-
-In the year 2038 top will fail to represent the time of day correctly
-on 32-bit Unix operating systems. This is due to a limitation in the
-way Unix represents time. Top will only work on systems whose kernel
-call "time" and C library call "ctime" have been adjusted to represent
-time with a value greater than 32 bits. The exact date and time of
-this failure is 3:14:08 January 19, 2038 GMT. Note that this failure
-will only affect the display of the current time in the output from
-top.
-
-
-THERE IS ABSOLUTELY NO WARRANTY PROVIDED WITH THIS SOFTWARE.
-Please see the contents of the file "DISCLAIMER" for further
-information.
Index: head/contrib/top/boolean.h
===================================================================
--- head/contrib/top/boolean.h
+++ head/contrib/top/boolean.h
@@ -1,5 +0,0 @@
-/* My favorite names for boolean values */
-#define No 0
-#define Yes 1
-#define Maybe 2 /* tri-state boolean, actually */
-
Index: head/contrib/top/commands.h
===================================================================
--- head/contrib/top/commands.h
+++ head/contrib/top/commands.h
@@ -1,21 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- * Copyright (c) 2016, Randy Westlund
- *
- * $FreeBSD$
- */
-#ifndef COMMANDS_H
-#define COMMANDS_H
-
-void show_errors(void);
-int error_count(void);
-void show_help(void);
-
-#endif /* COMMANDS_H */
Index: head/contrib/top/commands.c
===================================================================
--- head/contrib/top/commands.c
+++ head/contrib/top/commands.c
@@ -1,542 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- *
- * $FreeBSD$
- */
-
-/*
- * This file contains the routines that implement some of the interactive
- * mode commands. Note that some of the commands are implemented in-line
- * in "main". This is necessary because they change the global state of
- * "top" (i.e.: changing the number of processes to display).
- */
-
-#include "os.h"
-
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include "commands.h"
-#include "sigdesc.h" /* generated automatically */
-#include "top.h"
-#include "boolean.h"
-#include "utils.h"
-#include "machine.h"
-
-extern int errno;
-
-extern char *copyright;
-
-/* imported from screen.c */
-extern int overstrike;
-
-int err_compar();
-char *err_string();
-static int str_adderr(char *str, int len, int err);
-static int str_addarg(char *str, int len, char *arg, int first);
-
-/*
- * show_help() - display the help screen; invoked in response to
- * either 'h' or '?'.
- */
-
-void
-show_help()
-
-{
- printf("Top version %s, %s\n", version_string(), copyright);
- fputs("\n\n\
-A top users display for Unix\n\
-\n\
-These single-character commands are available:\n\
-\n\
-^L - redraw screen\n\
-q - quit\n\
-h or ? - help; show this text\n", stdout);
-
- /* not all commands are availalbe with overstrike terminals */
- if (overstrike)
- {
- fputs("\n\
-Other commands are also available, but this terminal is not\n\
-sophisticated enough to handle those commands gracefully.\n\n", stdout);
- }
- else
- {
- fputs("\
-C - toggle the displaying of weighted CPU percentage\n\
-d - change number of displays to show\n\
-e - list errors generated by last \"kill\" or \"renice\" command\n\
-H - toggle the displaying of threads\n\
-i or I - toggle the displaying of idle processes\n\
-j - toggle the displaying of jail ID\n\
-J - display processes for only one jail (+ selects all jails)\n\
-k - kill processes; send a signal to a list of processes\n\
-m - toggle the display between 'cpu' and 'io' modes\n\
-n or # - change number of processes to display\n", stdout);
-#ifdef ORDER
- if (displaymode == DISP_CPU)
- fputs("\
-o - specify sort order (pri, size, res, cpu, time, threads, jid, pid)\n",
- stdout);
- else
- fputs("\
-o - specify sort order (vcsw, ivcsw, read, write, fault, total, jid, pid)\n",
- stdout);
-#endif
- fputs("\
-P - toggle the displaying of per-CPU statistics\n\
-r - renice a process\n\
-s - change number of seconds to delay between updates\n\
-S - toggle the displaying of system processes\n\
-a - toggle the displaying of process titles\n\
-t - toggle the display of this process\n\
-u - display processes for only one user (+ selects all users)\n\
-w - toggle the display of swap use for each process\n\
-z - toggle the displaying of the system idle process\n\
-\n\
-\n", stdout);
- }
-}
-
-/*
- * Utility routines that help with some of the commands.
- */
-
-char *next_field(str)
-
-register char *str;
-
-{
- if ((str = strchr(str, ' ')) == NULL)
- {
- return(NULL);
- }
- *str = '\0';
- while (*++str == ' ') /* loop */;
-
- /* if there is nothing left of the string, return NULL */
- /* This fix is dedicated to Greg Earle */
- return(*str == '\0' ? NULL : str);
-}
-
-int
-scanint(str, intp)
-
-char *str;
-int *intp;
-
-{
- register int val = 0;
- register char ch;
-
- /* if there is nothing left of the string, flag it as an error */
- /* This fix is dedicated to Greg Earle */
- if (*str == '\0')
- {
- return(-1);
- }
-
- while ((ch = *str++) != '\0')
- {
- if (isdigit(ch))
- {
- val = val * 10 + (ch - '0');
- }
- else if (isspace(ch))
- {
- break;
- }
- else
- {
- return(-1);
- }
- }
- *intp = val;
- return(0);
-}
-
-/*
- * Some of the commands make system calls that could generate errors.
- * These errors are collected up in an array of structures for later
- * contemplation and display. Such routines return a string containing an
- * error message, or NULL if no errors occurred. The next few routines are
- * for manipulating and displaying these errors. We need an upper limit on
- * the number of errors, so we arbitrarily choose 20.
- */
-
-#define ERRMAX 20
-
-struct errs /* structure for a system-call error */
-{
- int errnum; /* value of errno (that is, the actual error) */
- char *arg; /* argument that caused the error */
-};
-
-static struct errs errs[ERRMAX];
-static int errcnt;
-static char *err_toomany = " too many errors occurred";
-static char *err_listem =
- " Many errors occurred. Press `e' to display the list of errors.";
-
-/* These macros get used to reset and log the errors */
-#define ERR_RESET errcnt = 0
-#define ERROR(p, e) if (errcnt >= ERRMAX) \
- { \
- return(err_toomany); \
- } \
- else \
- { \
- errs[errcnt].arg = (p); \
- errs[errcnt++].errnum = (e); \
- }
-
-/*
- * err_string() - return an appropriate error string. This is what the
- * command will return for displaying. If no errors were logged, then
- * return NULL. The maximum length of the error string is defined by
- * "STRMAX".
- */
-
-#define STRMAX 80
-
-char *err_string()
-
-{
- register struct errs *errp;
- register int cnt = 0;
- register int first = Yes;
- register int currerr = -1;
- int stringlen; /* characters still available in "string" */
- static char string[STRMAX];
-
- /* if there are no errors, return NULL */
- if (errcnt == 0)
- {
- return(NULL);
- }
-
- /* sort the errors */
- qsort((char *)errs, errcnt, sizeof(struct errs), err_compar);
-
- /* need a space at the front of the error string */
- string[0] = ' ';
- string[1] = '\0';
- stringlen = STRMAX - 2;
-
- /* loop thru the sorted list, building an error string */
- while (cnt < errcnt)
- {
- errp = &(errs[cnt++]);
- if (errp->errnum != currerr)
- {
- if (currerr != -1)
- {
- if ((stringlen = str_adderr(string, stringlen, currerr)) < 2)
- {
- return(err_listem);
- }
- (void) strcat(string, "; "); /* we know there's more */
- }
- currerr = errp->errnum;
- first = Yes;
- }
- if ((stringlen = str_addarg(string, stringlen, errp->arg, first)) ==0)
- {
- return(err_listem);
- }
- first = No;
- }
-
- /* add final message */
- stringlen = str_adderr(string, stringlen, currerr);
-
- /* return the error string */
- return(stringlen == 0 ? err_listem : string);
-}
-
-/*
- * str_adderr(str, len, err) - add an explanation of error "err" to
- * the string "str".
- */
-
-static int
-str_adderr(str, len, err)
-
-char *str;
-int len;
-int err;
-
-{
- register char *msg;
- register int msglen;
-
- msg = err == 0 ? "Not a number" : errmsg(err);
- msglen = strlen(msg) + 2;
- if (len <= msglen)
- {
- return(0);
- }
- (void) strcat(str, ": ");
- (void) strcat(str, msg);
- return(len - msglen);
-}
-
-/*
- * str_addarg(str, len, arg, first) - add the string argument "arg" to
- * the string "str". This is the first in the group when "first"
- * is set (indicating that a comma should NOT be added to the front).
- */
-
-static int
-str_addarg(str, len, arg, first)
-
-char *str;
-int len;
-char *arg;
-int first;
-
-{
- register int arglen;
-
- arglen = strlen(arg);
- if (!first)
- {
- arglen += 2;
- }
- if (len <= arglen)
- {
- return(0);
- }
- if (!first)
- {
- (void) strcat(str, ", ");
- }
- (void) strcat(str, arg);
- return(len - arglen);
-}
-
-/*
- * err_compar(p1, p2) - comparison routine used by "qsort"
- * for sorting errors.
- */
-
-int
-err_compar(p1, p2)
-
-register struct errs *p1, *p2;
-
-{
- register int result;
-
- if ((result = p1->errnum - p2->errnum) == 0)
- {
- return(strcmp(p1->arg, p2->arg));
- }
- return(result);
-}
-
-/*
- * error_count() - return the number of errors currently logged.
- */
-
-int
-error_count()
-
-{
- return(errcnt);
-}
-
-/*
- * show_errors() - display on stdout the current log of errors.
- */
-
-void
-show_errors()
-
-{
- register int cnt = 0;
- register struct errs *errp = errs;
-
- printf("%d error%s:\n\n", errcnt, errcnt == 1 ? "" : "s");
- while (cnt++ < errcnt)
- {
- printf("%5s: %s\n", errp->arg,
- errp->errnum == 0 ? "Not a number" : errmsg(errp->errnum));
- errp++;
- }
-}
-
-/*
- * kill_procs(str) - send signals to processes, much like the "kill"
- * command does; invoked in response to 'k'.
- */
-
-char *kill_procs(str)
-
-char *str;
-
-{
- register char *nptr;
- int signum = SIGTERM; /* default */
- int procnum;
- struct sigdesc *sigp;
- int uid;
-
- /* reset error array */
- ERR_RESET;
-
- /* remember our uid */
- uid = getuid();
-
- /* skip over leading white space */
- while (isspace(*str)) str++;
-
- if (str[0] == '-')
- {
- /* explicit signal specified */
- if ((nptr = next_field(str)) == NULL)
- {
- return(" kill: no processes specified");
- }
-
- if (isdigit(str[1]))
- {
- (void) scanint(str + 1, &signum);
- if (signum <= 0 || signum >= NSIG)
- {
- return(" invalid signal number");
- }
- }
- else
- {
- /* translate the name into a number */
- for (sigp = sigdesc; sigp->name != NULL; sigp++)
- {
- if (strcmp(sigp->name, str + 1) == 0)
- {
- signum = sigp->number;
- break;
- }
- }
-
- /* was it ever found */
- if (sigp->name == NULL)
- {
- return(" bad signal name");
- }
- }
- /* put the new pointer in place */
- str = nptr;
- }
-
- /* loop thru the string, killing processes */
- do
- {
- if (scanint(str, &procnum) == -1)
- {
- ERROR(str, 0);
- }
- else
- {
- /* check process owner if we're not root */
- if (uid && (uid != proc_owner(procnum)))
- {
- ERROR(str, EACCES);
- }
- /* go in for the kill */
- else if (kill(procnum, signum) == -1)
- {
- /* chalk up an error */
- ERROR(str, errno);
- }
- }
- } while ((str = next_field(str)) != NULL);
-
- /* return appropriate error string */
- return(err_string());
-}
-
-/*
- * renice_procs(str) - change the "nice" of processes, much like the
- * "renice" command does; invoked in response to 'r'.
- */
-
-char *renice_procs(str)
-
-char *str;
-
-{
- register char negate;
- int prio;
- int procnum;
- int uid;
-
- ERR_RESET;
- uid = getuid();
-
- /* allow for negative priority values */
- if ((negate = (*str == '-')) != 0)
- {
- /* move past the minus sign */
- str++;
- }
-
- /* use procnum as a temporary holding place and get the number */
- procnum = scanint(str, &prio);
-
- /* negate if necessary */
- if (negate)
- {
- prio = -prio;
- }
-
-#if defined(PRIO_MIN) && defined(PRIO_MAX)
- /* check for validity */
- if (procnum == -1 || prio < PRIO_MIN || prio > PRIO_MAX)
- {
- return(" bad priority value");
- }
-#endif
-
- /* move to the first process number */
- if ((str = next_field(str)) == NULL)
- {
- return(" no processes specified");
- }
-
- /* loop thru the process numbers, renicing each one */
- do
- {
- if (scanint(str, &procnum) == -1)
- {
- ERROR(str, 0);
- }
-
- /* check process owner if we're not root */
- else if (uid && (uid != proc_owner(procnum)))
- {
- ERROR(str, EACCES);
- }
- else if (setpriority(PRIO_PROCESS, procnum, prio) == -1)
- {
- ERROR(str, errno);
- }
- } while ((str = next_field(str)) != NULL);
-
- /* return appropriate error string */
- return(err_string());
-}
-
Index: head/contrib/top/display.h
===================================================================
--- head/contrib/top/display.h
+++ head/contrib/top/display.h
@@ -1,43 +0,0 @@
-/* constants needed for display.c */
-
-/* "type" argument for new_message function */
-
-#define MT_standout 1
-#define MT_delayed 2
-
-#include "machine.h"
-
-int display_updatecpus(struct statics *statics);
-void clear_message(void);
-int display_resize(void);
-void i_header(char *text);
-char *printable(char *string);
-char *cpustates_tag(void);
-void display_header(int t);
-int display_init(struct statics *statics);
-void i_arc(int *stats);
-void i_carc(int *stats);
-void i_cpustates(int *states);
-void i_loadave(int mpid, double *avenrun);
-void i_memory(int *stats);
-void i_message(void);
-void i_process(int line, char *thisline);
-void i_procstates(int total, int *brkdn);
-void i_swap(int *stats);
-void i_timeofday(time_t *tod);
-void i_uptime(struct timeval *bt, time_t *tod);
-void new_message();
-int readline(char *buffer, int size, int numeric);
-char *trim_header(char *text);
-void u_arc(int *stats);
-void u_carc(int *stats);
-void u_cpustates(int *states);
-void u_endscreen(int hi);
-void u_header(char *text);
-void u_loadave(int mpid, double *avenrun);
-void u_memory(int *stats);
-void u_message(void);
-void u_process(int line, char *newline);
-void u_procstates(int total, int *brkdn);
-void u_swap(int *stats);
-void z_cpustates(void);
Index: head/contrib/top/display.c
===================================================================
--- head/contrib/top/display.c
+++ head/contrib/top/display.c
@@ -1,1455 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- *
- * $FreeBSD$
- */
-
-/*
- * This file contains the routines that display information on the screen.
- * Each section of the screen has two routines: one for initially writing
- * all constant and dynamic text, and one for only updating the text that
- * changes. The prefix "i_" is used on all the "initial" routines and the
- * prefix "u_" is used for all the "updating" routines.
- *
- * ASSUMPTIONS:
- * None of the "i_" routines use any of the termcap capabilities.
- * In this way, those routines can be safely used on terminals that
- * have minimal (or nonexistant) terminal capabilities.
- *
- * The routines are called in this order: *_loadave, i_timeofday,
- * *_procstates, *_cpustates, *_memory, *_message, *_header,
- * *_process, u_endscreen.
- */
-
-#include "os.h"
-
-#include <sys/time.h>
-
-#include <curses.h>
-#include <ctype.h>
-#include <termcap.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "screen.h" /* interface to screen package */
-#include "layout.h" /* defines for screen position layout */
-#include "display.h"
-#include "top.h"
-#include "top.local.h"
-#include "boolean.h"
-#include "machine.h" /* we should eliminate this!!! */
-#include "utils.h"
-
-#ifdef DEBUG
-FILE *debug;
-#endif
-
-/* imported from screen.c */
-extern int overstrike;
-
-static int lmpid = 0;
-static int last_hi = 0; /* used in u_process and u_endscreen */
-static int lastline = 0;
-static int display_width = MAX_COLS;
-
-#define lineindex(l) ((l)*display_width)
-
-
-/* things initialized by display_init and used thruout */
-
-/* buffer of proc information lines for display updating */
-char *screenbuf = NULL;
-
-static char **procstate_names;
-static char **cpustate_names;
-static char **memory_names;
-static char **arc_names;
-static char **carc_names;
-static char **swap_names;
-
-static int num_procstates;
-static int num_cpustates;
-static int num_memory;
-static int num_swap;
-
-static int *lprocstates;
-static int *lcpustates;
-static int *lmemory;
-static int *lswap;
-
-static int num_cpus;
-static int *cpustate_columns;
-static int cpustate_total_length;
-static int cpustates_column;
-
-static enum { OFF, ON, ERASE } header_status = ON;
-
-static int string_count();
-static void summary_format();
-static void line_update();
-
-int x_lastpid = 10;
-int y_lastpid = 0;
-int x_loadave = 33;
-int x_loadave_nompid = 15;
-int y_loadave = 0;
-int x_procstate = 0;
-int y_procstate = 1;
-int x_brkdn = 15;
-int y_brkdn = 1;
-int x_mem = 5;
-int y_mem = 3;
-int x_arc = 5;
-int y_arc = 4;
-int x_carc = 5;
-int y_carc = 5;
-int x_swap = 6;
-int y_swap = 4;
-int y_message = 5;
-int x_header = 0;
-int y_header = 6;
-int x_idlecursor = 0;
-int y_idlecursor = 5;
-int y_procs = 7;
-
-int y_cpustates = 2;
-int Header_lines = 7;
-
-int display_resize()
-
-{
- register int lines;
-
- /* first, deallocate any previous buffer that may have been there */
- if (screenbuf != NULL)
- {
- free(screenbuf);
- }
-
- /* calculate the current dimensions */
- /* if operating in "dumb" mode, we only need one line */
- lines = smart_terminal ? screen_length - Header_lines : 1;
-
- if (lines < 0)
- lines = 0;
- /* we don't want more than MAX_COLS columns, since the machine-dependent
- modules make static allocations based on MAX_COLS and we don't want
- to run off the end of their buffers */
- display_width = screen_width;
- if (display_width >= MAX_COLS)
- {
- display_width = MAX_COLS - 1;
- }
-
- /* now, allocate space for the screen buffer */
- screenbuf = (char *)malloc(lines * display_width);
- if (screenbuf == (char *)NULL)
- {
- /* oops! */
- return(-1);
- }
-
- /* return number of lines available */
- /* for dumb terminals, pretend like we can show any amount */
- return(smart_terminal ? lines : Largest);
-}
-
-int display_updatecpus(statics)
-
-struct statics *statics;
-
-{
- register int *lp;
- register int lines;
- register int i;
-
- /* call resize to do the dirty work */
- lines = display_resize();
- if (pcpu_stats)
- num_cpus = statics->ncpus;
- else
- num_cpus = 1;
- cpustates_column = 5; /* CPU: */
- if (num_cpus != 1)
- cpustates_column += 2; /* CPU 0: */
- for (i = num_cpus; i > 9; i /= 10)
- cpustates_column++;
-
- /* fill the "last" array with all -1s, to insure correct updating */
- lp = lcpustates;
- i = num_cpustates * num_cpus;
- while (--i >= 0)
- {
- *lp++ = -1;
- }
-
- return(lines);
-}
-
-int display_init(statics)
-
-struct statics *statics;
-
-{
- register int lines;
- register char **pp;
- register int *ip;
- register int i;
-
- lines = display_updatecpus(statics);
-
- /* only do the rest if we need to */
- if (lines > -1)
- {
- /* save pointers and allocate space for names */
- procstate_names = statics->procstate_names;
- num_procstates = string_count(procstate_names);
- lprocstates = (int *)malloc(num_procstates * sizeof(int));
-
- cpustate_names = statics->cpustate_names;
-
- swap_names = statics->swap_names;
- num_swap = string_count(swap_names);
- lswap = (int *)malloc(num_swap * sizeof(int));
- num_cpustates = string_count(cpustate_names);
- lcpustates = (int *)malloc(num_cpustates * sizeof(int) * statics->ncpus);
- cpustate_columns = (int *)malloc(num_cpustates * sizeof(int));
-
- memory_names = statics->memory_names;
- num_memory = string_count(memory_names);
- lmemory = (int *)malloc(num_memory * sizeof(int));
-
- arc_names = statics->arc_names;
- carc_names = statics->carc_names;
-
- /* calculate starting columns where needed */
- cpustate_total_length = 0;
- pp = cpustate_names;
- ip = cpustate_columns;
- while (*pp != NULL)
- {
- *ip++ = cpustate_total_length;
- if ((i = strlen(*pp++)) > 0)
- {
- cpustate_total_length += i + 8;
- }
- }
- }
-
- /* return number of lines available */
- return(lines);
-}
-
-void
-i_loadave(mpid, avenrun)
-
-int mpid;
-double *avenrun;
-
-{
- register int i;
-
- /* i_loadave also clears the screen, since it is first */
- top_clear();
-
- /* mpid == -1 implies this system doesn't have an _mpid */
- if (mpid != -1)
- {
- printf("last pid: %5d; ", mpid);
- }
-
- printf("load averages");
-
- for (i = 0; i < 3; i++)
- {
- printf("%c %5.2f",
- i == 0 ? ':' : ',',
- avenrun[i]);
- }
- lmpid = mpid;
-}
-
-void
-u_loadave(mpid, avenrun)
-
-int mpid;
-double *avenrun;
-
-{
- register int i;
-
- if (mpid != -1)
- {
- /* change screen only when value has really changed */
- if (mpid != lmpid)
- {
- Move_to(x_lastpid, y_lastpid);
- printf("%5d", mpid);
- lmpid = mpid;
- }
-
- /* i remembers x coordinate to move to */
- i = x_loadave;
- }
- else
- {
- i = x_loadave_nompid;
- }
-
- /* move into position for load averages */
- Move_to(i, y_loadave);
-
- /* display new load averages */
- /* we should optimize this and only display changes */
- for (i = 0; i < 3; i++)
- {
- printf("%s%5.2f",
- i == 0 ? "" : ", ",
- avenrun[i]);
- }
-}
-
-void
-i_timeofday(tod)
-
-time_t *tod;
-
-{
- /*
- * Display the current time.
- * "ctime" always returns a string that looks like this:
- *
- * Sun Sep 16 01:03:52 1973
- * 012345678901234567890123
- * 1 2
- *
- * We want indices 11 thru 18 (length 8).
- */
-
- if (smart_terminal)
- {
- Move_to(screen_width - 8, 0);
- }
- else
- {
- fputs(" ", stdout);
- }
-#ifdef DEBUG
- {
- char *foo;
- foo = ctime(tod);
- fputs(foo, stdout);
- }
-#endif
- printf("%-8.8s\n", &(ctime(tod)[11]));
- lastline = 1;
-}
-
-static int ltotal = 0;
-static char procstates_buffer[MAX_COLS];
-
-/*
- * *_procstates(total, brkdn, names) - print the process summary line
- *
- * Assumptions: cursor is at the beginning of the line on entry
- * lastline is valid
- */
-
-void
-i_procstates(total, brkdn)
-
-int total;
-int *brkdn;
-
-{
- register int i;
-
- /* write current number of processes and remember the value */
- printf("%d processes:", total);
- ltotal = total;
-
- /* put out enough spaces to get to column 15 */
- i = digits(total);
- while (i++ < 4)
- {
- putchar(' ');
- }
-
- /* format and print the process state summary */
- summary_format(procstates_buffer, brkdn, procstate_names);
- fputs(procstates_buffer, stdout);
-
- /* save the numbers for next time */
- memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
-}
-
-void
-u_procstates(total, brkdn)
-
-int total;
-int *brkdn;
-
-{
- static char new[MAX_COLS];
- register int i;
-
- /* update number of processes only if it has changed */
- if (ltotal != total)
- {
- /* move and overwrite */
-#if (x_procstate == 0)
- Move_to(x_procstate, y_procstate);
-#else
- /* cursor is already there...no motion needed */
- /* assert(lastline == 1); */
-#endif
- printf("%d", total);
-
- /* if number of digits differs, rewrite the label */
- if (digits(total) != digits(ltotal))
- {
- fputs(" processes:", stdout);
- /* put out enough spaces to get to column 15 */
- i = digits(total);
- while (i++ < 4)
- {
- putchar(' ');
- }
- /* cursor may end up right where we want it!!! */
- }
-
- /* save new total */
- ltotal = total;
- }
-
- /* see if any of the state numbers has changed */
- if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
- {
- /* format and update the line */
- summary_format(new, brkdn, procstate_names);
- line_update(procstates_buffer, new, x_brkdn, y_brkdn);
- memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
- }
-}
-
-#ifdef no_more
-/*
- * *_cpustates(states, names) - print the cpu state percentages
- *
- * Assumptions: cursor is on the PREVIOUS line
- */
-
-/* cpustates_tag() calculates the correct tag to use to label the line */
-
-char *cpustates_tag()
-
-{
- register char *use;
-
- static char *short_tag = "CPU: ";
- static char *long_tag = "CPU states: ";
-
- /* if length + strlen(long_tag) >= screen_width, then we have to
- use the shorter tag (we subtract 2 to account for ": ") */
- if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width)
- {
- use = short_tag;
- }
- else
- {
- use = long_tag;
- }
-
- /* set cpustates_column accordingly then return result */
- cpustates_column = strlen(use);
- return(use);
-}
-#endif
-
-void
-i_cpustates(states)
-
-int *states;
-
-{
- register int i = 0;
- register int value;
- register char **names;
- register char *thisname;
- int cpu;
-
-for (cpu = 0; cpu < num_cpus; cpu++) {
- names = cpustate_names;
-
- /* print tag and bump lastline */
- if (num_cpus == 1)
- printf("\nCPU: ");
- else {
- value = printf("\nCPU %d: ", cpu);
- while (value++ <= cpustates_column)
- printf(" ");
- }
- lastline++;
-
- /* now walk thru the names and print the line */
- while ((thisname = *names++) != NULL)
- {
- if (*thisname != '\0')
- {
- /* retrieve the value and remember it */
- value = *states++;
-
- /* if percentage is >= 1000, print it as 100% */
- printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
- (i++ % num_cpustates) == 0 ? "" : ", ",
- ((float)value)/10.,
- thisname);
- }
- }
-}
-
- /* copy over values into "last" array */
- memcpy(lcpustates, states, num_cpustates * sizeof(int) * num_cpus);
-}
-
-void
-u_cpustates(states)
-
-int *states;
-
-{
- register int value;
- register char **names;
- register char *thisname;
- register int *lp;
- register int *colp;
- int cpu;
-
-for (cpu = 0; cpu < num_cpus; cpu++) {
- names = cpustate_names;
-
- Move_to(cpustates_column, y_cpustates + cpu);
- lastline = y_cpustates + cpu;
- lp = lcpustates + (cpu * num_cpustates);
- colp = cpustate_columns;
-
- /* we could be much more optimal about this */
- while ((thisname = *names++) != NULL)
- {
- if (*thisname != '\0')
- {
- /* did the value change since last time? */
- if (*lp != *states)
- {
- /* yes, move and change */
- Move_to(cpustates_column + *colp, y_cpustates + cpu);
- lastline = y_cpustates + cpu;
-
- /* retrieve value and remember it */
- value = *states;
-
- /* if percentage is >= 1000, print it as 100% */
- printf((value >= 1000 ? "%4.0f" : "%4.1f"),
- ((double)value)/10.);
-
- /* remember it for next time */
- *lp = value;
- }
- }
-
- /* increment and move on */
- lp++;
- states++;
- colp++;
- }
-}
-}
-
-void
-z_cpustates()
-
-{
- register int i = 0;
- register char **names;
- register char *thisname;
- register int *lp;
- int cpu, value;
-
-for (cpu = 0; cpu < num_cpus; cpu++) {
- names = cpustate_names;
-
- /* show tag and bump lastline */
- if (num_cpus == 1)
- printf("\nCPU: ");
- else {
- value = printf("\nCPU %d: ", cpu);
- while (value++ <= cpustates_column)
- printf(" ");
- }
- lastline++;
-
- while ((thisname = *names++) != NULL)
- {
- if (*thisname != '\0')
- {
- printf("%s %% %s", (i++ % num_cpustates) == 0 ? "" : ", ", thisname);
- }
- }
-}
-
- /* fill the "last" array with all -1s, to insure correct updating */
- lp = lcpustates;
- i = num_cpustates * num_cpus;
- while (--i >= 0)
- {
- *lp++ = -1;
- }
-}
-
-/*
- * *_memory(stats) - print "Memory: " followed by the memory summary string
- *
- * Assumptions: cursor is on "lastline"
- * for i_memory ONLY: cursor is on the previous line
- */
-
-char memory_buffer[MAX_COLS];
-
-void
-i_memory(stats)
-
-int *stats;
-
-{
- fputs("\nMem: ", stdout);
- lastline++;
-
- /* format and print the memory summary */
- summary_format(memory_buffer, stats, memory_names);
- fputs(memory_buffer, stdout);
-}
-
-void
-u_memory(stats)
-
-int *stats;
-
-{
- static char new[MAX_COLS];
-
- /* format the new line */
- summary_format(new, stats, memory_names);
- line_update(memory_buffer, new, x_mem, y_mem);
-}
-
-/*
- * *_arc(stats) - print "ARC: " followed by the ARC summary string
- *
- * Assumptions: cursor is on "lastline"
- * for i_arc ONLY: cursor is on the previous line
- */
-char arc_buffer[MAX_COLS];
-
-void
-i_arc(stats)
-
-int *stats;
-
-{
- if (arc_names == NULL)
- return;
-
- fputs("\nARC: ", stdout);
- lastline++;
-
- /* format and print the memory summary */
- summary_format(arc_buffer, stats, arc_names);
- fputs(arc_buffer, stdout);
-}
-
-void
-u_arc(stats)
-
-int *stats;
-
-{
- static char new[MAX_COLS];
-
- if (arc_names == NULL)
- return;
-
- /* format the new line */
- summary_format(new, stats, arc_names);
- line_update(arc_buffer, new, x_arc, y_arc);
-}
-
-
-/*
- * *_carc(stats) - print "Compressed ARC: " followed by the summary string
- *
- * Assumptions: cursor is on "lastline"
- * for i_carc ONLY: cursor is on the previous line
- */
-char carc_buffer[MAX_COLS];
-
-void
-i_carc(stats)
-
-int *stats;
-
-{
- if (carc_names == NULL)
- return;
-
- fputs("\n ", stdout);
- lastline++;
-
- /* format and print the memory summary */
- summary_format(carc_buffer, stats, carc_names);
- fputs(carc_buffer, stdout);
-}
-
-void
-u_carc(stats)
-
-int *stats;
-
-{
- static char new[MAX_COLS];
-
- if (carc_names == NULL)
- return;
-
- /* format the new line */
- summary_format(new, stats, carc_names);
- line_update(carc_buffer, new, x_carc, y_carc);
-}
-
-/*
- * *_swap(stats) - print "Swap: " followed by the swap summary string
- *
- * Assumptions: cursor is on "lastline"
- * for i_swap ONLY: cursor is on the previous line
- */
-
-char swap_buffer[MAX_COLS];
-
-void
-i_swap(stats)
-
-int *stats;
-
-{
- fputs("\nSwap: ", stdout);
- lastline++;
-
- /* format and print the swap summary */
- summary_format(swap_buffer, stats, swap_names);
- fputs(swap_buffer, stdout);
-}
-
-void
-u_swap(stats)
-
-int *stats;
-
-{
- static char new[MAX_COLS];
-
- /* format the new line */
- summary_format(new, stats, swap_names);
- line_update(swap_buffer, new, x_swap, y_swap);
-}
-
-/*
- * *_message() - print the next pending message line, or erase the one
- * that is there.
- *
- * Note that u_message is (currently) the same as i_message.
- *
- * Assumptions: lastline is consistent
- */
-
-/*
- * i_message is funny because it gets its message asynchronously (with
- * respect to screen updates).
- */
-
-static char next_msg[MAX_COLS + 5];
-static int msglen = 0;
-/* Invariant: msglen is always the length of the message currently displayed
- on the screen (even when next_msg doesn't contain that message). */
-
-void
-i_message()
-
-{
- while (lastline < y_message)
- {
- fputc('\n', stdout);
- lastline++;
- }
- if (next_msg[0] != '\0')
- {
- top_standout(next_msg);
- msglen = strlen(next_msg);
- next_msg[0] = '\0';
- }
- else if (msglen > 0)
- {
- (void) clear_eol(msglen);
- msglen = 0;
- }
-}
-
-void
-u_message()
-
-{
- i_message();
-}
-
-static int header_length;
-
-/*
- * Trim a header string to the current display width and return a newly
- * allocated area with the trimmed header.
- */
-
-char *
-trim_header(text)
-
-char *text;
-
-{
- char *s;
- int width;
-
- s = NULL;
- width = display_width;
- header_length = strlen(text);
- if (header_length >= width) {
- s = malloc((width + 1) * sizeof(char));
- if (s == NULL)
- return (NULL);
- strncpy(s, text, width);
- s[width] = '\0';
- }
- return (s);
-}
-
-/*
- * *_header(text) - print the header for the process area
- *
- * Assumptions: cursor is on the previous line and lastline is consistent
- */
-
-void
-i_header(text)
-
-char *text;
-
-{
- char *s;
-
- s = trim_header(text);
- if (s != NULL)
- text = s;
-
- if (header_status == ON)
- {
- putchar('\n');
- fputs(text, stdout);
- lastline++;
- }
- else if (header_status == ERASE)
- {
- header_status = OFF;
- }
- free(s);
-}
-
-/*ARGSUSED*/
-void
-u_header(text)
-
-char *text __unused; /* ignored */
-
-{
-
- if (header_status == ERASE)
- {
- putchar('\n');
- lastline++;
- clear_eol(header_length);
- header_status = OFF;
- }
-}
-
-/*
- * *_process(line, thisline) - print one process line
- *
- * Assumptions: lastline is consistent
- */
-
-void
-i_process(line, thisline)
-
-int line;
-char *thisline;
-
-{
- register char *p;
- register char *base;
-
- /* make sure we are on the correct line */
- while (lastline < y_procs + line)
- {
- putchar('\n');
- lastline++;
- }
-
- /* truncate the line to conform to our current screen width */
- thisline[display_width] = '\0';
-
- /* write the line out */
- fputs(thisline, stdout);
-
- /* copy it in to our buffer */
- base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;
- p = strecpy(base, thisline);
-
- /* zero fill the rest of it */
- memzero(p, display_width - (p - base));
-}
-
-void
-u_process(line, newline)
-
-int line;
-char *newline;
-
-{
- register char *optr;
- register int screen_line = line + Header_lines;
- register char *bufferline;
-
- /* remember a pointer to the current line in the screen buffer */
- bufferline = &screenbuf[lineindex(line)];
-
- /* truncate the line to conform to our current screen width */
- newline[display_width] = '\0';
-
- /* is line higher than we went on the last display? */
- if (line >= last_hi)
- {
- /* yes, just ignore screenbuf and write it out directly */
- /* get positioned on the correct line */
- if (screen_line - lastline == 1)
- {
- putchar('\n');
- lastline++;
- }
- else
- {
- Move_to(0, screen_line);
- lastline = screen_line;
- }
-
- /* now write the line */
- fputs(newline, stdout);
-
- /* copy it in to the buffer */
- optr = strecpy(bufferline, newline);
-
- /* zero fill the rest of it */
- memzero(optr, display_width - (optr - bufferline));
- }
- else
- {
- line_update(bufferline, newline, 0, line + Header_lines);
- }
-}
-
-void
-u_endscreen(hi)
-
-int hi;
-
-{
- register int screen_line = hi + Header_lines;
- register int i;
-
- if (smart_terminal)
- {
- if (hi < last_hi)
- {
- /* need to blank the remainder of the screen */
- /* but only if there is any screen left below this line */
- if (lastline + 1 < screen_length)
- {
- /* efficiently move to the end of currently displayed info */
- if (screen_line - lastline < 5)
- {
- while (lastline < screen_line)
- {
- putchar('\n');
- lastline++;
- }
- }
- else
- {
- Move_to(0, screen_line);
- lastline = screen_line;
- }
-
- if (clear_to_end)
- {
- /* we can do this the easy way */
- putcap(clear_to_end);
- }
- else
- {
- /* use clear_eol on each line */
- i = hi;
- while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi)
- {
- putchar('\n');
- }
- }
- }
- }
- last_hi = hi;
-
- /* move the cursor to a pleasant place */
- Move_to(x_idlecursor, y_idlecursor);
- lastline = y_idlecursor;
- }
- else
- {
- /* separate this display from the next with some vertical room */
- fputs("\n\n", stdout);
- }
-}
-
-void
-display_header(t)
-
-int t;
-
-{
- if (t)
- {
- header_status = ON;
- }
- else if (header_status == ON)
- {
- header_status = ERASE;
- }
-}
-
-/*VARARGS2*/
-void
-new_message(type, msgfmt, a1, a2, a3)
-
-int type;
-char *msgfmt;
-caddr_t a1, a2, a3;
-
-{
- register int i;
-
- /* first, format the message */
- (void) snprintf(next_msg, sizeof(next_msg), msgfmt, a1, a2, a3);
-
- if (msglen > 0)
- {
- /* message there already -- can we clear it? */
- if (!overstrike)
- {
- /* yes -- write it and clear to end */
- i = strlen(next_msg);
- if ((type & MT_delayed) == 0)
- {
- type & MT_standout ? top_standout(next_msg) :
- fputs(next_msg, stdout);
- (void) clear_eol(msglen - i);
- msglen = i;
- next_msg[0] = '\0';
- }
- }
- }
- else
- {
- if ((type & MT_delayed) == 0)
- {
- type & MT_standout ? top_standout(next_msg) : fputs(next_msg, stdout);
- msglen = strlen(next_msg);
- next_msg[0] = '\0';
- }
- }
-}
-
-void
-clear_message()
-
-{
- if (clear_eol(msglen) == 1)
- {
- putchar('\r');
- }
-}
-
-int
-readline(buffer, size, numeric)
-
-char *buffer;
-int size;
-int numeric;
-
-{
- register char *ptr = buffer;
- register char ch;
- register char cnt = 0;
- register char maxcnt = 0;
-
- /* allow room for null terminator */
- size -= 1;
-
- /* read loop */
- while ((fflush(stdout), read(0, ptr, 1) > 0))
- {
- /* newline means we are done */
- if ((ch = *ptr) == '\n' || ch == '\r')
- {
- break;
- }
-
- /* handle special editing characters */
- if (ch == ch_kill)
- {
- /* kill line -- account for overstriking */
- if (overstrike)
- {
- msglen += maxcnt;
- }
-
- /* return null string */
- *buffer = '\0';
- putchar('\r');
- return(-1);
- }
- else if (ch == ch_erase)
- {
- /* erase previous character */
- if (cnt <= 0)
- {
- /* none to erase! */
- putchar('\7');
- }
- else
- {
- fputs("\b \b", stdout);
- ptr--;
- cnt--;
- }
- }
- /* check for character validity and buffer overflow */
- else if (cnt == size || (numeric && !isdigit(ch)) ||
- !isprint(ch))
- {
- /* not legal */
- putchar('\7');
- }
- else
- {
- /* echo it and store it in the buffer */
- putchar(ch);
- ptr++;
- cnt++;
- if (cnt > maxcnt)
- {
- maxcnt = cnt;
- }
- }
- }
-
- /* all done -- null terminate the string */
- *ptr = '\0';
-
- /* account for the extra characters in the message area */
- /* (if terminal overstrikes, remember the furthest they went) */
- msglen += overstrike ? maxcnt : cnt;
-
- /* return either inputted number or string length */
- putchar('\r');
- return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
-}
-
-/* internal support routines */
-
-static int string_count(pp)
-
-register char **pp;
-
-{
- register int cnt;
-
- cnt = 0;
- while (*pp++ != NULL)
- {
- cnt++;
- }
- return(cnt);
-}
-
-static void summary_format(str, numbers, names)
-
-char *str;
-int *numbers;
-register char **names;
-
-{
- register char *p;
- register int num;
- register char *thisname;
- register int useM = No;
- char rbuf[6];
-
- /* format each number followed by its string */
- p = str;
- while ((thisname = *names++) != NULL)
- {
- /* get the number to format */
- num = *numbers++;
-
- /* display only non-zero numbers */
- if (num > 0)
- {
- /* is this number in kilobytes? */
- if (thisname[0] == 'K')
- {
- /* yes: format it as a memory value */
- p = strecpy(p, format_k(num));
-
- /* skip over the K, since it was included by format_k */
- p = strecpy(p, thisname+1);
- }
- /* is this number a ratio? */
- else if (thisname[0] == ':')
- {
- (void) snprintf(rbuf, sizeof(rbuf), "%.2f",
- (float)*(numbers - 2) / (float)num);
- p = strecpy(p, rbuf);
- p = strecpy(p, thisname);
- }
- else
- {
- p = strecpy(p, itoa(num));
- p = strecpy(p, thisname);
- }
- }
-
- /* ignore negative numbers, but display corresponding string */
- else if (num < 0)
- {
- p = strecpy(p, thisname);
- }
- }
-
- /* if the last two characters in the string are ", ", delete them */
- p -= 2;
- if (p >= str && p[0] == ',' && p[1] == ' ')
- {
- *p = '\0';
- }
-}
-
-static void line_update(old, new, start, line)
-
-register char *old;
-register char *new;
-int start;
-int line;
-
-{
- register int ch;
- register int diff;
- register int newcol = start + 1;
- register int lastcol = start;
- char cursor_on_line = No;
- char *current;
-
- /* compare the two strings and only rewrite what has changed */
- current = old;
-#ifdef DEBUG
- fprintf(debug, "line_update, starting at %d\n", start);
- fputs(old, debug);
- fputc('\n', debug);
- fputs(new, debug);
- fputs("\n-\n", debug);
-#endif
-
- /* start things off on the right foot */
- /* this is to make sure the invariants get set up right */
- if ((ch = *new++) != *old)
- {
- if (line - lastline == 1 && start == 0)
- {
- putchar('\n');
- }
- else
- {
- Move_to(start, line);
- }
- cursor_on_line = Yes;
- putchar(ch);
- *old = ch;
- lastcol = 1;
- }
- old++;
-
- /*
- * main loop -- check each character. If the old and new aren't the
- * same, then update the display. When the distance from the
- * current cursor position to the new change is small enough,
- * the characters that belong there are written to move the
- * cursor over.
- *
- * Invariants:
- * lastcol is the column where the cursor currently is sitting
- * (always one beyond the end of the last mismatch).
- */
- do /* yes, a do...while */
- {
- if ((ch = *new++) != *old)
- {
- /* new character is different from old */
- /* make sure the cursor is on top of this character */
- diff = newcol - lastcol;
- if (diff > 0)
- {
- /* some motion is required--figure out which is shorter */
- if (diff < 6 && cursor_on_line)
- {
- /* overwrite old stuff--get it out of the old buffer */
- printf("%.*s", diff, &current[lastcol-start]);
- }
- else
- {
- /* use cursor addressing */
- Move_to(newcol, line);
- cursor_on_line = Yes;
- }
- /* remember where the cursor is */
- lastcol = newcol + 1;
- }
- else
- {
- /* already there, update position */
- lastcol++;
- }
-
- /* write what we need to */
- if (ch == '\0')
- {
- /* at the end--terminate with a clear-to-end-of-line */
- (void) clear_eol(strlen(old));
- }
- else
- {
- /* write the new character */
- putchar(ch);
- }
- /* put the new character in the screen buffer */
- *old = ch;
- }
-
- /* update working column and screen buffer pointer */
- newcol++;
- old++;
-
- } while (ch != '\0');
-
- /* zero out the rest of the line buffer -- MUST BE DONE! */
- diff = display_width - newcol;
- if (diff > 0)
- {
- memzero(old, diff);
- }
-
- /* remember where the current line is */
- if (cursor_on_line)
- {
- lastline = line;
- }
-}
-
-/*
- * printable(str) - make the string pointed to by "str" into one that is
- * printable (i.e.: all ascii), by converting all non-printable
- * characters into '?'. Replacements are done in place and a pointer
- * to the original buffer is returned.
- */
-
-char *printable(str)
-
-char *str;
-
-{
- register char *ptr;
- register char ch;
-
- ptr = str;
- while ((ch = *ptr) != '\0')
- {
- if (!isprint(ch))
- {
- *ptr = '?';
- }
- ptr++;
- }
- return(str);
-}
-
-void
-i_uptime(bt, tod)
-
-struct timeval* bt;
-time_t *tod;
-
-{
- time_t uptime;
- int days, hrs, mins, secs;
-
- if (bt->tv_sec != -1) {
- uptime = *tod - bt->tv_sec;
- days = uptime / 86400;
- uptime %= 86400;
- hrs = uptime / 3600;
- uptime %= 3600;
- mins = uptime / 60;
- secs = uptime % 60;
-
- /*
- * Display the uptime.
- */
-
- if (smart_terminal)
- {
- Move_to((screen_width - 24) - (days > 9 ? 1 : 0), 0);
- }
- else
- {
- fputs(" ", stdout);
- }
- printf(" up %d+%02d:%02d:%02d", days, hrs, mins, secs);
- }
-}
Index: head/contrib/top/getans
===================================================================
--- head/contrib/top/getans
+++ head/contrib/top/getans
@@ -1,118 +0,0 @@
-#!/bin/sh
-# getans prompt type default results_filename
-# type is one of
-# number
-# integer
-# neginteger
-# file default=default filename
-# path
-# yesno default=0,1 corres yes or no
-# string (default)
-
-RAWPMPT=$1
-TYP=$2
-DFLT=$3
-OFNM=$4
-
-ny0="no"; ny1="yes"
-if [ ${TYP} = "yesno" ]; then
- eval ny=\$ny${DFLT}
- pmpt="${RAWPMPT} [$ny]: "
-else
- if [ -z "${DFLT}" ]; then
- pmpt="${RAWPMPT}"
- else
- pmpt="${RAWPMPT} [${DFLT}]: "
- fi
-fi
-if [ x"`echo -n`" = x-n ]
-then
- c=\\c
-else
- n=-n
-fi
-
-while :
-do
- echo $n "$pmpt"$c
- read input
- case "$TYP" in
- number)
- tmp=`echo $input | tr -d 0123456789.`
- if [ -n "$tmp" ]; then
- echo "Invalid number. Please try again."
- continue
- fi
- ;;
-
- integer)
- tmp=`echo $input | tr -d 0123456789`
- if [ -n "$tmp" ]; then
- echo "Invalid integer. Please try again."
- continue
- fi
- ;;
-
- neginteger)
- if [ "x$input" != "x-1" ]; then
- tmp=`echo $input | tr -d 0123456789`
- if [ -n "$tmp" ]; then
- echo "Invalid integer. Please try again."
- continue
- fi
- fi
- ;;
-
- file)
- if [ -z "$input" ]; then
- input=${DFLT}
- fi
- if [ ! -f "$input" -a ! -d "$input" ]; then
- echo "The file $input does not exist. Please try again."
- continue
- fi
- ;;
-
- path)
- if [ -z "$input" ]; then
- input="${DFLT}"
- fi
- if [ ! -f "$input" ]; then
- path=`echo $PATH | sed -e s'/::/ . /g' -e 's/:/ /g'`
- x=
- for elt in $path; do
- if [ -f "$elt/$input" ]; then x=1; break; fi
- done
- if [ -z "$x" ] ;then
- echo "The command $input was not found. Please try again."
- continue
- fi
- fi
- ;;
-
- yesno)
- if [ -z "$input" ]; then
- input="${DFLT}"
- else
- case $input in
- y | yes)
- input=1 ;;
- n | no)
- input=0 ;;
- *)
- echo 'Please answer "yes" or "no".'
- continue ;;
- esac
- fi
- ;;
-
- *) ;;
- esac
- break
-done
-
-if [ -z "$input" ]; then
- input="${DFLT}"
-fi
-
-echo $input > ${OFNM}
Index: head/contrib/top/getopt.c
===================================================================
--- head/contrib/top/getopt.c
+++ head/contrib/top/getopt.c
@@ -1,90 +0,0 @@
-/*
- * "getopt" routine customized for top.
- */
-
-/*
- * Many modern-day Unix implementations already have this function
- * in libc. The standard "getopt" is perfectly sufficient for top's
- * needs. If such a function exists in libc then you certainly don't
- * need to compile this one in. To prevent this function from being
- * compiled, define "HAVE_GETOPT". This is usually done in the "CFLAGS"
- * line of the corresponding machine module.
- */
-
-/*
- * This empty declaration exists solely to placate overexhuberant C
- * compilers that like to warn you about content-free files.
- */
-static void __empty();
-
-#ifndef HAVE_GETOPT
-
-/*LINTLIBRARY*/
-
-#include "os.h"
-#ifndef NULL
-#define NULL 0
-#endif
-#ifndef EOF
-#define EOF (-1)
-#endif
-#define ERR(s, c) if(opterr){\
- extern int write();\
- char errbuf[2];\
- errbuf[0] = c; errbuf[1] = '\n';\
- (void) write(2, argv[0], strlen(argv[0]));\
- (void) write(2, s, strlen(s));\
- (void) write(2, errbuf, 2);}
-
-
-int opterr = 1;
-int optind = 1;
-int optopt;
-char *optarg;
-
-int
-getopt(argc, argv, opts)
-int argc;
-char **argv, *opts;
-{
- static int sp = 1;
- register int c;
- register char *cp;
-
- if(sp == 1)
- if(optind >= argc ||
- argv[optind][0] != '-' || argv[optind][1] == '\0')
- return(EOF);
- else if(strcmp(argv[optind], "--") == 0) {
- optind++;
- return(EOF);
- }
- optopt = c = argv[optind][sp];
- if(c == ':' || (cp=strchr(opts, c)) == NULL) {
- ERR(": unknown option, -", c);
- if(argv[optind][++sp] == '\0') {
- optind++;
- sp = 1;
- }
- return('?');
- }
- if(*++cp == ':') {
- if(argv[optind][sp+1] != '\0')
- optarg = &argv[optind++][sp+1];
- else if(++optind >= argc) {
- ERR(": argument missing for -", c);
- sp = 1;
- return('?');
- } else
- optarg = argv[optind++];
- sp = 1;
- } else {
- if(argv[optind][++sp] == '\0') {
- sp = 1;
- optind++;
- }
- optarg = NULL;
- }
- return(c);
-}
-#endif /* HAVE_GETOPT */
Index: head/contrib/top/install-sh
===================================================================
--- head/contrib/top/install-sh
+++ head/contrib/top/install-sh
@@ -1,69 +0,0 @@
-#!/bin/sh
-#
-# this shell script is amazingly similar to the old and lamented
-# BSD "install" command. It recognized the following options:
-#
-# -o target file owner
-# -m target file mode
-# -g target file group owner
-#
-#
-# scan the options
-#
-while [ $# -gt 0 ]; do
- case $1 in
- -o)
- owner=$2
- shift ; shift
- ;;
-
- -m)
- mode=$2
- shift; shift
- ;;
-
- -g)
- group=$2
- shift ; shift
- ;;
-
- -*)
- echo "install: unknown option $1"
- exit
- ;;
-
- *)
- break
- ;;
- esac
-done
-#
-# we need two more: filename and destination
-#
-if [ $# -ne 2 ]; then
- echo "Usage: install [ -o owner ] [ -m mode ] [ -g group ] file destination"
- exit
-fi
-#
-# first, copy
-#
-cp $1 $2
-#
-# normalize the name
-#
-dest=$2
-if [ -d $2 ]; then
- dest=$2/`basename $1`
-fi
-#
-# do optional things
-#
-if [ "$owner" ]; then
- chown $owner $dest
-fi
-if [ "$group" ]; then
- chgrp $group $dest
-fi
-if [ "$mode" ]; then
- chmod $mode $dest
-fi
Index: head/contrib/top/layout.h
===================================================================
--- head/contrib/top/layout.h
+++ head/contrib/top/layout.h
@@ -1,35 +0,0 @@
-/*
- * Top - a top users display for Berkeley Unix
- *
- * This file defines the locations on tne screen for various parts of the
- * display. These definitions are used by the routines in "display.c" for
- * cursor addressing.
- *
- * $FreeBSD$
- */
-
-extern int x_lastpid; /* 10 */
-extern int y_lastpid; /* 0 */
-extern int x_loadave; /* 33 */
-extern int x_loadave_nompid; /* 15 */
-extern int y_loadave; /* 0 */
-extern int x_procstate; /* 0 */
-extern int y_procstate; /* 1 */
-extern int x_brkdn; /* 15 */
-extern int y_brkdn; /* 1 */
-extern int x_mem; /* 5 */
-extern int y_mem; /* 3 */
-extern int x_arc; /* 5 */
-extern int y_arc; /* 4 */
-extern int x_carc; /* 5 */
-extern int y_carc; /* 5 */
-extern int x_swap; /* 6 */
-extern int y_swap; /* 4 */
-extern int y_message; /* 5 */
-extern int x_header; /* 0 */
-extern int y_header; /* 6 */
-extern int x_idlecursor; /* 0 */
-extern int y_idlecursor; /* 5 */
-extern int y_procs; /* 7 */
-
-extern int y_cpustates; /* 2 */
Index: head/contrib/top/loadavg.h
===================================================================
--- head/contrib/top/loadavg.h
+++ head/contrib/top/loadavg.h
@@ -1,57 +0,0 @@
-/*
- * Top - a top users display for Berkeley Unix
- *
- * Defines required to access load average figures.
- *
- * This include file sets up everything we need to access the load average
- * values in the kernel in a machine independent way. First, it sets the
- * typedef "load_avg" to be either double or long (depending on what is
- * needed), then it defines these macros appropriately:
- *
- * loaddouble(la) - convert load_avg to double.
- * intload(i) - convert integer to load_avg.
- */
-
-/*
- * We assume that if FSCALE is defined, then avenrun and ccpu are type long.
- * If your machine is an exception (mips, perhaps?) then make adjustments
- * here.
- *
- * Defined types: load_avg for load averages, pctcpu for cpu percentages.
- */
-#if defined(__mips__) && !(defined(__NetBSD__) || defined(__FreeBSD__))
-# include <sys/fixpoint.h>
-# if defined(FBITS) && !defined(FSCALE)
-# define FSCALE (1 << FBITS) /* RISC/os on mips */
-# endif
-#endif
-
-#ifdef FSCALE
-# define FIXED_LOADAVG FSCALE
-# define FIXED_PCTCPU FSCALE
-#endif
-
-#ifdef ibm032
-# undef FIXED_LOADAVG
-# undef FIXED_PCTCPU
-# define FIXED_PCTCPU PCT_SCALE
-#endif
-
-
-#ifdef FIXED_PCTCPU
- typedef long pctcpu;
-# define pctdouble(p) ((double)(p) / FIXED_PCTCPU)
-#else
-typedef double pctcpu;
-# define pctdouble(p) (p)
-#endif
-
-#ifdef FIXED_LOADAVG
- typedef fixpt_t load_avg;
-# define loaddouble(la) ((double)(la) / FIXED_LOADAVG)
-# define intload(i) ((int)((i) * FIXED_LOADAVG))
-#else
- typedef double load_avg;
-# define loaddouble(la) (la)
-# define intload(i) ((double)(i))
-#endif
Index: head/contrib/top/m-template
===================================================================
--- head/contrib/top/m-template
+++ head/contrib/top/m-template
@@ -1,241 +0,0 @@
-/*
- * top - a top users display for Unix
- *
- * THIS IS A TEMPLATE FILE FOR A MACHINE DEPENDENT (m_...c) FILE
- *
- * SYNOPSIS: one line description of machine this module works with
- *
- * DESCRIPTION:
- * Detailed description of this machine dependent module.
- * It can be multiple lines, but a blank comment line (one with only an
- * asterisk) is considered to end it. Place here a complete list of
- * the machines and OS versions that this module works on.
- *
- * LIBS: list of special libraries to include at link step (REMOVE THIS LINE IF NOT NEEDED)
- *
- * AUTHOR: your name and <your@internet.address>
- */
-
-#include "top.h"
-#include "machine.h"
-
-
-/*
- * These definitions control the format of the per-process area
- */
-
-static char header[] =
- " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
-/* 0123456 -- field to fill in starts at header+6 */
-#define UNAME_START 6
-
-#define Proc_format \
- "%5d %-8.8s %3d %4d%6dK %4dK %-5s%4d:%02d %5.2f%% %5.2f%% %.14s"
-
-/* these are for detailing the process states */
-
-int process_states[?];
-char *procstatenames[] = {
- "", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
- " zombie, ", " stopped, ",
- NULL
-};
-
-/* these are for detailing the cpu states */
-
-int cpu_states[?];
-char *cpustatenames[] = {
- "user", "nice", "system", "idle",
- NULL
-};
-
-/* these are for detailing the memory statistics */
-
-int memory_stats[?];
-char *memorynames[] = {
- "K available, ", "K in use, ", "K free, ", "K locked", NULL
-};
-
-/* useful externals */
-extern int errno;
-extern char *sys_errlist[];
-
-long lseek();
-long time();
-long percentages();
-
-machine_init(statics)
-
-struct statics *statics;
-
-{
- return(0);
-}
-
-char *format_header(uname_field)
-
-register char *uname_field;
-
-{
- register char *ptr;
-
- ptr = header + UNAME_START;
- while (*uname_field != '\0')
- {
- *ptr++ = *uname_field++;
- }
-
- return(header);
-}
-
-get_system_info(si)
-
-struct system_info *si;
-
-{
-}
-
-static struct handle handle;
-
-caddr_t get_process_info(si, sel, compare)
-
-struct system_info *si;
-struct process_select *sel;
-int (*compare)();
-
-{
- return((caddr_t)&handle);
-}
-
-char fmt[128]; /* static area where result is built */
-
-/* define what weighted cpu is. */
-#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
- ((pct) / (1.0 - exp((pp)->p_time * logcpu))))
-
-char *format_next_process(handle, get_userid)
-
-caddr_t handle;
-char *(*get_userid)();
-
-{
- return(fmt);
-}
-
-/*
- * getkval(offset, ptr, size, refstr) - get a value out of the kernel.
- * "offset" is the byte offset into the kernel for the desired value,
- * "ptr" points to a buffer into which the value is retrieved,
- * "size" is the size of the buffer (and the object to retrieve),
- * "refstr" is a reference string used when printing error meessages,
- * if "refstr" starts with a '!', then a failure on read will not
- * be fatal (this may seem like a silly way to do things, but I
- * really didn't want the overhead of another argument).
- *
- */
-
-getkval(offset, ptr, size, refstr)
-
-unsigned long offset;
-int *ptr;
-int size;
-char *refstr;
-
-{
- if (kvm_read(kd, offset, ptr, size) != size)
- {
- if (*refstr == '!')
- {
- return(0);
- }
- else
- {
- fprintf(stderr, "top: kvm_read for %s: %s\n",
- refstr, sys_errlist[errno]);
- quit(23);
- }
- }
- return(1);
-}
-
-/* comparison routine for qsort */
-/* NOTE: this is specific to the BSD proc structure, but it should
- give you a good place to start. */
-
-/*
- * proc_compare - comparison function for "qsort"
- * Compares the resource consumption of two processes using five
- * distinct keys. The keys (in descending order of importance) are:
- * percent cpu, cpu ticks, state, resident set size, total virtual
- * memory usage. The process states are ordered as follows (from least
- * to most important): WAIT, zombie, sleep, stop, start, run. The
- * array declaration below maps a process state index into a number
- * that reflects this ordering.
- */
-
-static unsigned char sorted_state[] =
-{
- 0, /* not used */
- 3, /* sleep */
- 1, /* ABANDONED (WAIT) */
- 6, /* run */
- 5, /* start */
- 2, /* zombie */
- 4 /* stop */
-};
-
-proc_compare(pp1, pp2)
-
-struct proc **pp1;
-struct proc **pp2;
-
-{
- register struct proc *p1;
- register struct proc *p2;
- register int result;
- register pctcpu lresult;
-
- /* remove one level of indirection */
- p1 = *pp1;
- p2 = *pp2;
-
- /* compare percent cpu (pctcpu) */
- if ((lresult = p2->p_pctcpu - p1->p_pctcpu) == 0)
- {
- /* use cpticks to break the tie */
- if ((result = p2->p_cpticks - p1->p_cpticks) == 0)
- {
- /* use process state to break the tie */
- if ((result = sorted_state[p2->p_stat] -
- sorted_state[p1->p_stat]) == 0)
- {
- /* use priority to break the tie */
- if ((result = p2->p_pri - p1->p_pri) == 0)
- {
- /* use resident set size (rssize) to break the tie */
- if ((result = p2->p_rssize - p1->p_rssize) == 0)
- {
- /* use total memory to break the tie */
- result = PROCSIZE(p2) - PROCSIZE(p1);
- }
- }
- }
- }
- }
- else
- {
- result = lresult < 0 ? -1 : 1;
- }
-
- return(result);
-}
-
-proc_owner(pid)
-
-int pid;
-
-{
- /* returns uid of owner of process pid */
- return(uid);
-}
-
Index: head/contrib/top/machine.h
===================================================================
--- head/contrib/top/machine.h
+++ head/contrib/top/machine.h
@@ -1,96 +0,0 @@
-/*
- * $FreeBSD$
- */
-
-/*
- * This file defines the interface between top and the machine-dependent
- * module. It is NOT machine dependent and should not need to be changed
- * for any specific machine.
- */
-#ifndef MACHINE_H
-#define MACHINE_H
-
-#include "top.h"
-
-/*
- * the statics struct is filled in by machine_init
- */
-struct statics
-{
- char **procstate_names;
- char **cpustate_names;
- char **memory_names;
- char **arc_names;
- char **carc_names;
- char **swap_names;
-#ifdef ORDER
- char **order_names;
-#endif
- int ncpus;
-};
-
-/*
- * the system_info struct is filled in by a machine dependent routine.
- */
-
-#ifdef p_active /* uw7 define macro p_active */
-#define P_ACTIVE p_pactive
-#else
-#define P_ACTIVE p_active
-#endif
-
-struct system_info
-{
- int last_pid;
- double load_avg[NUM_AVERAGES];
- int p_total;
- int P_ACTIVE; /* number of procs considered "active" */
- int *procstates;
- int *cpustates;
- int *memory;
- int *arc;
- int *carc;
- int *swap;
- struct timeval boottime;
- int ncpus;
-};
-
-/* cpu_states is an array of percentages * 10. For example,
- the (integer) value 105 is 10.5% (or .105).
- */
-
-/*
- * the process_select struct tells get_process_info what processes we
- * are interested in seeing
- */
-
-struct process_select
-{
- int idle; /* show idle processes */
- int self; /* show self */
- int system; /* show system processes */
- int thread; /* show threads */
-#define TOP_MAX_UIDS 8
- int uid[TOP_MAX_UIDS]; /* only these uids (unless uid[0] == -1) */
- int wcpu; /* show weighted cpu */
- int jid; /* only this jid (unless jid == -1) */
- int jail; /* show jail ID */
- int swap; /* show swap usage */
- int kidle; /* show per-CPU idle threads */
- char *command; /* only this command (unless == NULL) */
-};
-
-/* routines defined by the machine dependent module */
-
-char *format_header(char *uname_field);
-char *format_next_process(caddr_t handle, char *(*get_userid)(int),
- int flags);
-void toggle_pcpustats(void);
-void get_system_info(struct system_info *si);
-int machine_init(struct statics *statics, char do_unames);
-int proc_owner(int pid);
-
-/* non-int routines typically used by the machine dependent module */
-char *printable(char *string);
-
-#endif /* MACHINE_H */
Index: head/contrib/top/metatop
===================================================================
--- head/contrib/top/metatop
+++ head/contrib/top/metatop
@@ -1,25 +0,0 @@
-#! /bin/sh
-#
-# Top is very sensitive to differences in the kernel, so much so that an
-# executable created on one sub-architecture may not work on others. It
-# is also quite common for a minor OS revision to require recompilation of
-# top. Both of these problems are especially prevalent on Suns. For
-# example, a top executable made under SunOS 4.1.1 will not run correctly
-# under SunOS 4.1.2, and vice versa. "metatop" attempts to solve this
-# problem by choosing one of several possible top executables to run then
-# executing it.
-#
-# To use metatop your operating system needs to have the command "uname"
-# as part of the standard OS release. MAKE SURE IT DOES before proceeding.
-# It will try to execute the command "top-`uname -m`-`uname -r`" For
-# example, on a sparcstation 1 running SunOS 4.1.1, it will try to run
-# "top-sun4c-4.1.1".
-#
-# INSTALLATION is easy. Just compile top as normal. Then use the command
-# "make metainstall" (on the same machine!) instead of the usual. "make"
-# will insure that this shell script is installed correctly then will install
-# the most recently made top executable with the correct name. Remember:
-# you will need to "make clean" and "make metainstall" on every different
-# combination of sub-architecture and OS version that you have.
-#
-exec $0-`uname -m`-`uname -r` "$@"
Index: head/contrib/top/os.h
===================================================================
--- head/contrib/top/os.h
+++ head/contrib/top/os.h
@@ -1,38 +0,0 @@
-#include <sys/types.h>
-#include <sys/param.h> /* This defines BSD */
-#if defined(BSD) && !defined(BSD4_4) && !defined(__osf__)
-# include <stdio.h>
-# include <strings.h>
-# define strchr(a, b) index((a), (b))
-# define strrchr(a, b) rindex((a), (b))
-# define memcpy(a, b, c) bcopy((b), (a), (c))
-# define memzero(a, b) bzero((a), (b))
-# define memcmp(a, b, c) bcmp((a), (b), (c))
-#if defined(NeXT)
- typedef void sigret_t;
-#else
- typedef int sigret_t;
-#endif
-
-/* system routines that don't return int */
-char *getenv();
-caddr_t malloc();
-
-#else
-# include <stdio.h>
-# define setbuffer(f, b, s) setvbuf((f), (b), (b) ? _IOFBF : _IONBF, (s))
-# include <string.h>
-# include <memory.h>
-# include <stdlib.h>
-# define memzero(a, b) memset((a), 0, (b))
- typedef void sigret_t;
-#endif
-
-/* some systems declare sys_errlist in stdio.h! */
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#if !defined(__m68k__)
-# if !defined(__NetBSD132__)
-#define SYS_ERRLIST_DECLARED
-# endif /* __NetBSD132__ */
-#endif
-#endif
Index: head/contrib/top/patchlevel.h
===================================================================
--- head/contrib/top/patchlevel.h
+++ head/contrib/top/patchlevel.h
@@ -1,2 +0,0 @@
-#define PATCHLEVEL 5
-#define BETA "beta12"
Index: head/contrib/top/prime.c
===================================================================
--- head/contrib/top/prime.c
+++ head/contrib/top/prime.c
@@ -1,41 +0,0 @@
-/*
- * Prime number generator. It prints on stdout the next prime number
- * higher than the number specified as argv[1].
- */
-
-#include <stdio.h>
-#include <math.h>
-
-main(argc, argv)
-
-int argc;
-char *argv[];
-
-{
- double i, j;
- int f;
-
- if (argc < 2)
- {
- exit(1);
- }
-
- i = atoi(argv[1]);
- while (i++)
- {
- f=1;
- for (j=2; j<i; j++)
- {
- if ((i/j)==floor(i/j))
- {
- f=0;
- break;
- }
- }
- if (f)
- {
- printf("%.0f\n", i);
- exit(0);
- }
- }
-}
Index: head/contrib/top/screen.h
===================================================================
--- head/contrib/top/screen.h
+++ head/contrib/top/screen.h
@@ -1,41 +0,0 @@
-/*
- * top - a top users display for Unix 4.2
- *
- * This file contains all the definitions necessary to use the hand-written
- * screen package in "screen.c"
- */
-
-#define TCputs(str) tputs(str, 1, putstdout)
-#define putcap(str) (void)((str) != NULL ? TCputs(str) : 0)
-#define Move_to(x, y) TCputs(tgoto(cursor_motion, x, y))
-
-/* declare return values for termcap functions */
-char *tgetstr();
-char *tgoto();
-
-extern char ch_erase; /* set to the user's erase character */
-extern char ch_kill; /* set to the user's kill character */
-extern char smart_terminal; /* set if the terminal has sufficient termcap
- capabilities for normal operation */
-
-/* These are some termcap strings for use outside of "screen.c" */
-extern char *cursor_motion;
-extern char *clear_line;
-extern char *clear_to_end;
-
-/* rows and columns on the screen according to termcap */
-extern int screen_length;
-extern int screen_width;
-
-/* a function that puts a single character on stdout */
-int putstdout(int ch);
-int clear_eol(int len);
-void top_standout(char *msg);
-void top_clear(void);
-void go_home(void);
-void reinit_screen(void);
-void get_screensize(void);
-void init_termcap(int interactive);
-void end_screen(void);
-void init_screen(void);
-
Index: head/contrib/top/screen.c
===================================================================
--- head/contrib/top/screen.c
+++ head/contrib/top/screen.c
@@ -1,498 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- *
- * $FreeBSD$
- */
-
-/* This file contains the routines that interface to termcap and stty/gtty.
- *
- * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
- *
- * I put in code to turn on the TOSTOP bit while top was running, but I
- * didn't really like the results. If you desire it, turn on the
- * preprocessor variable "TOStop". --wnl
- */
-
-#include "os.h"
-#include "top.h"
-
-#include <sys/ioctl.h>
-#ifdef CBREAK
-# include <sgtty.h>
-# define SGTTY
-#else
-# ifdef TCGETA
-# define TERMIO
-# include <termio.h>
-# else
-# define TERMIOS
-# include <termios.h>
-# endif
-#endif
-#if defined(TERMIO) || defined(TERMIOS)
-# ifndef TAB3
-# ifdef OXTABS
-# define TAB3 OXTABS
-# else
-# define TAB3 0
-# endif
-# endif
-#endif
-#include <curses.h>
-#include <termcap.h>
-#include "screen.h"
-#include "boolean.h"
-
-extern char *myname;
-
-
-int overstrike;
-int screen_length;
-int screen_width;
-char ch_erase;
-char ch_kill;
-char smart_terminal;
-char PC;
-char *tgetstr();
-char *tgoto();
-char termcap_buf[1024];
-char string_buffer[1024];
-char home[15];
-char lower_left[15];
-char *clear_line;
-char *clear_screen;
-char *clear_to_end;
-char *cursor_motion;
-char *start_standout;
-char *end_standout;
-char *terminal_init;
-char *terminal_end;
-
-#ifdef SGTTY
-static struct sgttyb old_settings;
-static struct sgttyb new_settings;
-#endif
-#ifdef TERMIO
-static struct termio old_settings;
-static struct termio new_settings;
-#endif
-#ifdef TERMIOS
-static struct termios old_settings;
-static struct termios new_settings;
-#endif
-static char is_a_terminal = No;
-#ifdef TOStop
-static int old_lword;
-static int new_lword;
-#endif
-
-#define STDIN 0
-#define STDOUT 1
-#define STDERR 2
-
-void
-init_termcap(interactive)
-
-int interactive;
-
-{
- char *bufptr;
- char *PCptr;
- char *term_name;
- char *getenv();
- int status;
-
- /* set defaults in case we aren't smart */
- screen_width = MAX_COLS;
- screen_length = 0;
-
- if (!interactive)
- {
- /* pretend we have a dumb terminal */
- smart_terminal = No;
- return;
- }
-
- /* assume we have a smart terminal until proven otherwise */
- smart_terminal = Yes;
-
- /* get the terminal name */
- term_name = getenv("TERM");
-
- /* if there is no TERM, assume it's a dumb terminal */
- /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
- if (term_name == NULL)
- {
- smart_terminal = No;
- return;
- }
-
- /* now get the termcap entry */
- if ((status = tgetent(termcap_buf, term_name)) != 1)
- {
- if (status == -1)
- {
- fprintf(stderr, "%s: can't open termcap file\n", myname);
- }
- else
- {
- fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
- myname, term_name);
- }
-
- /* pretend it's dumb and proceed */
- smart_terminal = No;
- return;
- }
-
- /* "hardcopy" immediately indicates a very stupid terminal */
- if (tgetflag("hc"))
- {
- smart_terminal = No;
- return;
- }
-
- /* set up common terminal capabilities */
- if ((screen_length = tgetnum("li")) <= 0)
- {
- screen_length = smart_terminal = 0;
- return;
- }
-
- /* screen_width is a little different */
- if ((screen_width = tgetnum("co")) == -1)
- {
- screen_width = 79;
- }
- else
- {
- screen_width -= 1;
- }
-
- /* terminals that overstrike need special attention */
- overstrike = tgetflag("os");
-
- /* initialize the pointer into the termcap string buffer */
- bufptr = string_buffer;
-
- /* get "ce", clear to end */
- if (!overstrike)
- {
- clear_line = tgetstr("ce", &bufptr);
- }
-
- /* get necessary capabilities */
- if ((clear_screen = tgetstr("cl", &bufptr)) == NULL ||
- (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
- {
- smart_terminal = No;
- return;
- }
-
- /* get some more sophisticated stuff -- these are optional */
- clear_to_end = tgetstr("cd", &bufptr);
- terminal_init = tgetstr("ti", &bufptr);
- terminal_end = tgetstr("te", &bufptr);
- start_standout = tgetstr("so", &bufptr);
- end_standout = tgetstr("se", &bufptr);
-
- /* pad character */
- PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
-
- /* set convenience strings */
- (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof(home) - 1);
- home[sizeof(home) - 1] = '\0';
- /* (lower_left is set in get_screensize) */
-
- /* get the actual screen size with an ioctl, if needed */
- /* This may change screen_width and screen_length, and it always
- sets lower_left. */
- get_screensize();
-
- /* if stdout is not a terminal, pretend we are a dumb terminal */
-#ifdef SGTTY
- if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
- {
- smart_terminal = No;
- }
-#endif
-#ifdef TERMIO
- if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
- {
- smart_terminal = No;
- }
-#endif
-#ifdef TERMIOS
- if (tcgetattr(STDOUT, &old_settings) == -1)
- {
- smart_terminal = No;
- }
-#endif
-}
-
-void
-init_screen()
-
-{
- /* get the old settings for safe keeping */
-#ifdef SGTTY
- if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
- {
- /* copy the settings so we can modify them */
- new_settings = old_settings;
-
- /* turn on CBREAK and turn off character echo and tab expansion */
- new_settings.sg_flags |= CBREAK;
- new_settings.sg_flags &= ~(ECHO|XTABS);
- (void) ioctl(STDOUT, TIOCSETP, &new_settings);
-
- /* remember the erase and kill characters */
- ch_erase = old_settings.sg_erase;
- ch_kill = old_settings.sg_kill;
-
-#ifdef TOStop
- /* get the local mode word */
- (void) ioctl(STDOUT, TIOCLGET, &old_lword);
-
- /* modify it */
- new_lword = old_lword | LTOSTOP;
- (void) ioctl(STDOUT, TIOCLSET, &new_lword);
-#endif
- /* remember that it really is a terminal */
- is_a_terminal = Yes;
-
- /* send the termcap initialization string */
- putcap(terminal_init);
- }
-#endif
-#ifdef TERMIO
- if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
- {
- /* copy the settings so we can modify them */
- new_settings = old_settings;
-
- /* turn off ICANON, character echo and tab expansion */
- new_settings.c_lflag &= ~(ICANON|ECHO);
- new_settings.c_oflag &= ~(TAB3);
- new_settings.c_cc[VMIN] = 1;
- new_settings.c_cc[VTIME] = 0;
- (void) ioctl(STDOUT, TCSETA, &new_settings);
-
- /* remember the erase and kill characters */
- ch_erase = old_settings.c_cc[VERASE];
- ch_kill = old_settings.c_cc[VKILL];
-
- /* remember that it really is a terminal */
- is_a_terminal = Yes;
-
- /* send the termcap initialization string */
- putcap(terminal_init);
- }
-#endif
-#ifdef TERMIOS
- if (tcgetattr(STDOUT, &old_settings) != -1)
- {
- /* copy the settings so we can modify them */
- new_settings = old_settings;
-
- /* turn off ICANON, character echo and tab expansion */
- new_settings.c_lflag &= ~(ICANON|ECHO);
- new_settings.c_oflag &= ~(TAB3);
- new_settings.c_cc[VMIN] = 1;
- new_settings.c_cc[VTIME] = 0;
- (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
-
- /* remember the erase and kill characters */
- ch_erase = old_settings.c_cc[VERASE];
- ch_kill = old_settings.c_cc[VKILL];
-
- /* remember that it really is a terminal */
- is_a_terminal = Yes;
-
- /* send the termcap initialization string */
- putcap(terminal_init);
- }
-#endif
-
- if (!is_a_terminal)
- {
- /* not a terminal at all---consider it dumb */
- smart_terminal = No;
- }
-}
-
-void
-end_screen()
-
-{
- /* move to the lower left, clear the line and send "te" */
- if (smart_terminal)
- {
- putcap(lower_left);
- putcap(clear_line);
- fflush(stdout);
- putcap(terminal_end);
- }
-
- /* if we have settings to reset, then do so */
- if (is_a_terminal)
- {
-#ifdef SGTTY
- (void) ioctl(STDOUT, TIOCSETP, &old_settings);
-#ifdef TOStop
- (void) ioctl(STDOUT, TIOCLSET, &old_lword);
-#endif
-#endif
-#ifdef TERMIO
- (void) ioctl(STDOUT, TCSETA, &old_settings);
-#endif
-#ifdef TERMIOS
- (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
-#endif
- }
-}
-
-void
-reinit_screen()
-
-{
- /* install our settings if it is a terminal */
- if (is_a_terminal)
- {
-#ifdef SGTTY
- (void) ioctl(STDOUT, TIOCSETP, &new_settings);
-#ifdef TOStop
- (void) ioctl(STDOUT, TIOCLSET, &new_lword);
-#endif
-#endif
-#ifdef TERMIO
- (void) ioctl(STDOUT, TCSETA, &new_settings);
-#endif
-#ifdef TERMIOS
- (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
-#endif
- }
-
- /* send init string */
- if (smart_terminal)
- {
- putcap(terminal_init);
- }
-}
-
-void
-get_screensize()
-
-{
-
-#ifdef TIOCGWINSZ
-
- struct winsize ws;
-
- if (ioctl (1, TIOCGWINSZ, &ws) != -1)
- {
- if (ws.ws_row != 0)
- {
- screen_length = ws.ws_row;
- }
- if (ws.ws_col != 0)
- {
- screen_width = ws.ws_col - 1;
- }
- }
-
-#else
-#ifdef TIOCGSIZE
-
- struct ttysize ts;
-
- if (ioctl (1, TIOCGSIZE, &ts) != -1)
- {
- if (ts.ts_lines != 0)
- {
- screen_length = ts.ts_lines;
- }
- if (ts.ts_cols != 0)
- {
- screen_width = ts.ts_cols - 1;
- }
- }
-
-#endif /* TIOCGSIZE */
-#endif /* TIOCGWINSZ */
-
- (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
- sizeof(lower_left) - 1);
- lower_left[sizeof(lower_left) - 1] = '\0';
-}
-
-void
-top_standout(char *msg)
-{
- if (smart_terminal)
- {
- putcap(start_standout);
- fputs(msg, stdout);
- putcap(end_standout);
- }
- else
- {
- fputs(msg, stdout);
- }
-}
-
-void
-top_clear()
-{
- if (smart_terminal)
- {
- putcap(clear_screen);
- }
-}
-
-int
-clear_eol(int len)
-{
- if (smart_terminal && !overstrike && len > 0)
- {
- if (clear_line)
- {
- putcap(clear_line);
- return(0);
- }
- else
- {
- while (len-- > 0)
- {
- putchar(' ');
- }
- return(1);
- }
- }
- return(-1);
-}
-
-void
-go_home()
-
-{
- if (smart_terminal)
- {
- putcap(home);
- }
-}
-
-/* This has to be defined as a subroutine for tputs (instead of a macro) */
-
-int
-putstdout(int ch)
-{
- return putchar(ch);
-}
Index: head/contrib/top/sigconv.awk
===================================================================
--- head/contrib/top/sigconv.awk
+++ head/contrib/top/sigconv.awk
@@ -1,55 +0,0 @@
-# $FreeBSD$
-
-BEGIN {
- nsig = 0;
- j = 0;
- print "/* This file was automatically generated */"
- print "/* by the awk script \"sigconv.awk\". */\n"
- print "struct sigdesc {"
- print " char *name;"
- print " int number;"
- print "};\n"
- print "struct sigdesc sigdesc[] = {"
- }
-
-/^#define[ \t][ \t]*SIG[A-Z]+[0-9]*[ \t]/ {
-
- j = sprintf("%d", $3);
- str = $2;
-
- if (nsig < j)
- nsig = j;
-
- siglist[j] = sprintf("{ \"%s\",\t%2d },", \
- substr(str, 4), j);
- }
-/^#[ \t]*define[ \t][ \t]*SIG[A-Z]+[0-9]*[ \t]/ {
-
- j = sprintf("%d", $4);
- str = $3;
-
- if (nsig < j)
- nsig = j;
-
- siglist[j] = sprintf("{ \"%s\",\t%2d },", \
- substr(str, 4), j);
- }
-/^#[ \t]*define[ \t][ \t]*_SIG[A-Z]+[0-9]*[ \t]/ {
-
- j = sprintf("%d", $4);
- str = $3;
-
- if (nsig < j)
- nsig = j;
-
- siglist[j] = sprintf("{ \"%s\",\t%2d },", \
- substr(str, 5), j);
- }
-
-END {
- for (n = 1; n <= nsig; n++)
- if (siglist[n] != "")
- printf(" %s\n", siglist[n]);
-
- printf(" { NULL,\t 0 }\n};\n");
- }
Index: head/contrib/top/top.h
===================================================================
--- head/contrib/top/top.h
+++ head/contrib/top/top.h
@@ -1,54 +0,0 @@
-/*
- * $FreeBSD$
- */
-/*
- * Top - a top users display for Berkeley Unix
- *
- * General (global) definitions
- */
-
-#ifndef TOP_H
-#define TOP_H
-
-/* Current major version number */
-#define VERSION 3
-
-/* Number of lines of header information on the standard screen */
-extern int Header_lines; /* 7 */
-
-/* Maximum number of columns allowed for display */
-#define MAX_COLS 512
-
-/* Log base 2 of 1024 is 10 (2^10 == 1024) */
-#define LOG1024 10
-
-char *itoa();
-char *itoa7();
-
-char *version_string();
-
-/* Special atoi routine returns either a non-negative number or one of: */
-#define Infinity -1
-#define Invalid -2
-
-/* maximum number we can have */
-#define Largest 0x7fffffff
-
-/*
- * The entire display is based on these next numbers being defined as is.
- */
-
-#define NUM_AVERAGES 3
-
-enum displaymodes { DISP_CPU = 0, DISP_IO, DISP_MAX };
-
-/*
- * Format modifiers
- */
-#define FMT_SHOWARGS 0x00000001
-
-extern enum displaymodes displaymode;
-
-extern int pcpu_stats;
-
-#endif /* TOP_H */
Index: head/contrib/top/top.c
===================================================================
--- head/contrib/top/top.c
+++ head/contrib/top/top.c
@@ -1,1318 +0,0 @@
-char *copyright =
- "Copyright (c) 1984 through 1996, William LeFebvre";
-
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University
- * Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory
- * Copyright (c) 1996, William LeFebvre, Group sys Consulting
- *
- * $FreeBSD$
- */
-
-/*
- * See the file "Changes" for information on version-to-version changes.
- */
-
-/*
- * This file contains "main" and other high-level routines.
- */
-
-/*
- * The following preprocessor variables, when defined, are used to
- * distinguish between different Unix implementations:
- *
- * SIGHOLD - use SVR4 sighold function when defined
- * SIGRELSE - use SVR4 sigrelse function when defined
- * FD_SET - macros FD_SET and FD_ZERO are used when defined
- */
-
-#include "os.h"
-
-#include <sys/jail.h>
-#include <sys/time.h>
-
-#include <ctype.h>
-#include <curses.h>
-#include <errno.h>
-#include <jail.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <unistd.h>
-
-/* includes specific to top */
-#include "commands.h"
-#include "display.h" /* interface to display package */
-#include "screen.h" /* interface to screen package */
-#include "top.h"
-#include "top.local.h"
-#include "boolean.h"
-#include "machine.h"
-#include "utils.h"
-#include "username.h"
-
-/* Size of the stdio buffer given to stdout */
-#define Buffersize 2048
-
-/* The buffer that stdio will use */
-char stdoutbuf[Buffersize];
-
-/* build Signal masks */
-#define Smask(s) (1 << ((s) - 1))
-
-/* for getopt: */
-extern int optind;
-extern char *optarg;
-
-/* imported from screen.c */
-extern int overstrike;
-
-static int fmt_flags = 0;
-int pcpu_stats = No;
-
-/* signal handling routines */
-sigret_t leave();
-sigret_t tstop();
-#ifdef SIGWINCH
-sigret_t top_winch(int);
-#endif
-
-volatile sig_atomic_t leaveflag;
-volatile sig_atomic_t tstopflag;
-volatile sig_atomic_t winchflag;
-
-/* internal routines */
-void quit();
-
-/* values which need to be accessed by signal handlers */
-static int max_topn; /* maximum displayable processes */
-
-/* miscellaneous things */
-struct process_select ps;
-char *myname = "top";
-jmp_buf jmp_int;
-
-/* routines that don't return int */
-
-char *username();
-char *ctime();
-char *kill_procs();
-char *renice_procs();
-
-#ifdef ORDER
-extern int (*compares[])();
-#else
-extern int proc_compare();
-extern int io_compare();
-#endif
-time_t time();
-
-caddr_t get_process_info(struct system_info *si, struct process_select *sel,
- int (*compare)(const void *, const void *));
-
-/* different routines for displaying the user's identification */
-/* (values assigned to get_userid) */
-char *username();
-char *itoa7();
-
-/* pointers to display routines */
-void (*d_loadave)(int mpid, double *avenrun) = i_loadave;
-void (*d_procstates)(int total, int *brkdn) = i_procstates;
-void (*d_cpustates)(int *states) = i_cpustates;
-void (*d_memory)(int *stats) = i_memory;
-void (*d_arc)(int *stats) = i_arc;
-void (*d_carc)(int *stats) = i_carc;
-void (*d_swap)(int *stats) = i_swap;
-void (*d_message)(void) = i_message;
-void (*d_header)(char *text) = i_header;
-void (*d_process)(int line, char *thisline) = i_process;
-
-void reset_display(void);
-
-static void
-reset_uids()
-{
- for (size_t i = 0; i < TOP_MAX_UIDS; ++i)
- ps.uid[i] = -1;
-}
-
-static int
-add_uid(int uid)
-{
- size_t i = 0;
-
- /* Add the uid if there's room */
- for (; i < TOP_MAX_UIDS; ++i)
- {
- if (ps.uid[i] == -1 || ps.uid[i] == uid)
- {
- ps.uid[i] = uid;
- break;
- }
- }
-
- return (i == TOP_MAX_UIDS);
-}
-
-static void
-rem_uid(int uid)
-{
- size_t i = 0;
- size_t where = TOP_MAX_UIDS;
-
- /* Look for the user to remove - no problem if it's not there */
- for (; i < TOP_MAX_UIDS; ++i)
- {
- if (ps.uid[i] == -1)
- break;
- if (ps.uid[i] == uid)
- where = i;
- }
-
- /* Make sure we don't leave a hole in the middle */
- if (where != TOP_MAX_UIDS)
- {
- ps.uid[where] = ps.uid[i-1];
- ps.uid[i-1] = -1;
- }
-}
-
-static int
-handle_user(char *buf, size_t buflen)
-{
- int rc = 0;
- int uid = -1;
- char *buf2 = buf;
-
- new_message(MT_standout, "Username to show (+ for all): ");
- if (readline(buf, buflen, No) <= 0)
- {
- clear_message();
- return rc;
- }
-
- if (buf[0] == '+' || buf[0] == '-')
- {
- if (buf[1] == '\0')
- {
- reset_uids();
- goto end;
- }
- else
- ++buf2;
- }
-
- if ((uid = userid(buf2)) == -1)
- {
- new_message(MT_standout, " %s: unknown user", buf2);
- rc = 1;
- goto end;
- }
-
- if (buf2 == buf)
- {
- reset_uids();
- ps.uid[0] = uid;
- goto end;
- }
-
- if (buf[0] == '+')
- {
- if (add_uid(uid))
- {
- new_message(MT_standout, " too many users, reset with '+'");
- rc = 1;
- goto end;
- }
- }
- else
- rem_uid(uid);
-
-end:
- putchar('\r');
- return rc;
-}
-
-int
-main(argc, argv)
-
-int argc;
-char *argv[];
-
-{
- register int i;
- register int active_procs;
- register int change;
-
- struct system_info system_info;
- struct statics statics;
- caddr_t processes;
-
- static char tempbuf1[50];
- static char tempbuf2[50];
- int old_sigmask; /* only used for BSD-style signals */
- int topn = Default_TOPN;
- int delay = Default_DELAY;
- int displays = 0; /* indicates unspecified */
- int sel_ret = 0;
- time_t curr_time;
- char *(*get_userid)() = username;
- char *uname_field = "USERNAME";
- char *header_text;
- char *env_top;
- char **preset_argv;
- int preset_argc = 0;
- char **av;
- int ac;
- char dostates = No;
- char do_unames = Yes;
- char interactive = Maybe;
- char warnings = 0;
-#if Default_TOPN == Infinity
- char topn_specified = No;
-#endif
- char ch;
- char *iptr;
- char no_command = 1;
- struct timeval timeout;
-#ifdef ORDER
- char *order_name = NULL;
- int order_index = 0;
-#endif
-#ifndef FD_SET
- /* FD_SET and friends are not present: fake it */
- typedef int fd_set;
-#define FD_ZERO(x) (*(x) = 0)
-#define FD_SET(f, x) (*(x) = 1<<f)
-#endif
- fd_set readfds;
-
-#ifdef ORDER
- static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
-#else
- static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJw";
-#endif
-/* these defines enumerate the "strchr"s of the commands in command_chars */
-#define CMD_redraw 0
-#define CMD_update 1
-#define CMD_quit 2
-#define CMD_help1 3
-#define CMD_help2 4
-#define CMD_OSLIMIT 4 /* terminals with OS can only handle commands */
-#define CMD_errors 5 /* less than or equal to CMD_OSLIMIT */
-#define CMD_number1 6
-#define CMD_number2 7
-#define CMD_delay 8
-#define CMD_displays 9
-#define CMD_kill 10
-#define CMD_renice 11
-#define CMD_idletog 12
-#define CMD_idletog2 13
-#define CMD_user 14
-#define CMD_selftog 15
-#define CMD_thrtog 16
-#define CMD_viewtog 17
-#define CMD_viewsys 18
-#define CMD_wcputog 19
-#define CMD_showargs 20
-#define CMD_jidtog 21
-#define CMD_kidletog 22
-#define CMD_pcputog 23
-#define CMD_jail 24
-#define CMD_swaptog 25
-#ifdef ORDER
-#define CMD_order 26
-#endif
-
- /* set the buffer for stdout */
-#ifdef DEBUG
- extern FILE *debug;
- debug = fopen("debug.run", "w");
- setbuffer(stdout, NULL, 0);
-#else
- setbuffer(stdout, stdoutbuf, Buffersize);
-#endif
-
- /* get our name */
- if (argc > 0)
- {
- if ((myname = strrchr(argv[0], '/')) == 0)
- {
- myname = argv[0];
- }
- else
- {
- myname++;
- }
- }
-
- /* initialize some selection options */
- ps.idle = Yes;
- ps.self = -1;
- ps.system = No;
- reset_uids();
- ps.thread = No;
- ps.wcpu = 1;
- ps.jid = -1;
- ps.jail = No;
- ps.swap = No;
- ps.kidle = Yes;
- ps.command = NULL;
-
- /* get preset options from the environment */
- if ((env_top = getenv("TOP")) != NULL)
- {
- av = preset_argv = argparse(env_top, &preset_argc);
- ac = preset_argc;
-
- /* set the dummy argument to an explanatory message, in case
- getopt encounters a bad argument */
- preset_argv[0] = "while processing environment";
- }
-
- /* process options */
- do {
- /* if we're done doing the presets, then process the real arguments */
- if (preset_argc == 0)
- {
- ac = argc;
- av = argv;
-
- /* this should keep getopt happy... */
- optind = 1;
- }
-
- while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
- {
- switch(i)
- {
- case 'v': /* show version number */
- fprintf(stderr, "%s: version %s\n",
- myname, version_string());
- exit(1);
- break;
-
- case 'u': /* toggle uid/username display */
- do_unames = !do_unames;
- break;
-
- case 'U': /* display only username's processes */
- if ((ps.uid[0] = userid(optarg)) == -1)
- {
- fprintf(stderr, "%s: unknown user\n", optarg);
- exit(1);
- }
- break;
-
- case 'S': /* show system processes */
- ps.system = !ps.system;
- break;
-
- case 'I': /* show idle processes */
- ps.idle = !ps.idle;
- break;
-
- case 'i': /* go interactive regardless */
- interactive = Yes;
- break;
-
- case 'n': /* batch, or non-interactive */
- case 'b':
- interactive = No;
- break;
-
- case 'a':
- fmt_flags ^= FMT_SHOWARGS;
- break;
-
- case 'd': /* number of displays to show */
- if ((i = atoiwi(optarg)) == Invalid || i == 0)
- {
- fprintf(stderr,
- "%s: warning: display count should be positive -- option ignored\n",
- myname);
- warnings++;
- }
- else
- {
- displays = i;
- }
- break;
-
- case 's':
- if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
- {
- fprintf(stderr,
- "%s: warning: seconds delay should be positive -- using default\n",
- myname);
- delay = Default_DELAY;
- warnings++;
- }
- break;
-
- case 'q': /* be quick about it */
- /* only allow this if user is really root */
- if (getuid() == 0)
- {
- /* be very un-nice! */
- (void) nice(-20);
- }
- else
- {
- fprintf(stderr,
- "%s: warning: `-q' option can only be used by root\n",
- myname);
- warnings++;
- }
- break;
-
- case 'm': /* select display mode */
- if (strcmp(optarg, "io") == 0) {
- displaymode = DISP_IO;
- } else if (strcmp(optarg, "cpu") == 0) {
- displaymode = DISP_CPU;
- } else {
- fprintf(stderr,
- "%s: warning: `-m' option can only take args "
- "'io' or 'cpu'\n",
- myname);
- exit(1);
- }
- break;
-
- case 'o': /* select sort order */
-#ifdef ORDER
- order_name = optarg;
-#else
- fprintf(stderr,
- "%s: this platform does not support arbitrary ordering. Sorry.\n",
- myname);
- warnings++;
-#endif
- break;
-
- case 't':
- ps.self = (ps.self == -1) ? getpid() : -1;
- break;
-
- case 'C':
- ps.wcpu = !ps.wcpu;
- break;
-
- case 'H':
- ps.thread = !ps.thread;
- break;
-
- case 'j':
- ps.jail = !ps.jail;
- break;
-
- case 'J': /* display only jail's processes */
- if ((ps.jid = jail_getid(optarg)) == -1)
- {
- fprintf(stderr, "%s: unknown jail\n", optarg);
- exit(1);
- }
- ps.jail = 1;
- break;
-
- case 'P':
- pcpu_stats = !pcpu_stats;
- break;
-
- case 'w':
- ps.swap = 1;
- break;
-
- case 'z':
- ps.kidle = !ps.kidle;
- break;
-
- default:
- fprintf(stderr,
-"Top version %s\n"
-"Usage: %s [-abCHIijnPqStuvwz] [-d count] [-m io | cpu] [-o field] [-s time]\n"
-" [-J jail] [-U username] [number]\n",
- version_string(), myname);
- exit(1);
- }
- }
-
- /* get count of top processes to display (if any) */
- if (optind < ac)
- {
- if ((topn = atoiwi(av[optind])) == Invalid)
- {
- fprintf(stderr,
- "%s: warning: process display count should be non-negative -- using default\n",
- myname);
- warnings++;
- }
-#if Default_TOPN == Infinity
- else
- {
- topn_specified = Yes;
- }
-#endif
- }
-
- /* tricky: remember old value of preset_argc & set preset_argc = 0 */
- i = preset_argc;
- preset_argc = 0;
-
- /* repeat only if we really did the preset arguments */
- } while (i != 0);
-
- /* set constants for username/uid display correctly */
- if (!do_unames)
- {
- uname_field = " UID ";
- get_userid = itoa7;
- }
-
- /* initialize the kernel memory interface */
- if (machine_init(&statics, do_unames) == -1)
- {
- exit(1);
- }
-
-#ifdef ORDER
- /* determine sorting order index, if necessary */
- if (order_name != NULL)
- {
- if ((order_index = string_index(order_name, statics.order_names)) == -1)
- {
- char **pp;
-
- fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
- myname, order_name);
- fprintf(stderr, "\tTry one of these:");
- pp = statics.order_names;
- while (*pp != NULL)
- {
- fprintf(stderr, " %s", *pp++);
- }
- fputc('\n', stderr);
- exit(1);
- }
- }
-#endif
-
-#ifdef no_initialization_needed
- /* initialize the hashing stuff */
- if (do_unames)
- {
- init_hash();
- }
-#endif
-
- /* initialize termcap */
- init_termcap(interactive);
-
- /* get the string to use for the process area header */
- header_text = format_header(uname_field);
-
- /* initialize display interface */
- if ((max_topn = display_init(&statics)) == -1)
- {
- fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);
- exit(4);
- }
-
- /* print warning if user requested more processes than we can display */
- if (topn > max_topn)
- {
- fprintf(stderr,
- "%s: warning: this terminal can only display %d processes.\n",
- myname, max_topn);
- warnings++;
- }
-
- /* adjust for topn == Infinity */
- if (topn == Infinity)
- {
- /*
- * For smart terminals, infinity really means everything that can
- * be displayed, or Largest.
- * On dumb terminals, infinity means every process in the system!
- * We only really want to do that if it was explicitly specified.
- * This is always the case when "Default_TOPN != Infinity". But if
- * topn wasn't explicitly specified and we are on a dumb terminal
- * and the default is Infinity, then (and only then) we use
- * "Nominal_TOPN" instead.
- */
-#if Default_TOPN == Infinity
- topn = smart_terminal ? Largest :
- (topn_specified ? Largest : Nominal_TOPN);
-#else
- topn = Largest;
-#endif
- }
-
- /* set header display accordingly */
- display_header(topn > 0);
-
- /* determine interactive state */
- if (interactive == Maybe)
- {
- interactive = smart_terminal;
- }
-
- /* if # of displays not specified, fill it in */
- if (displays == 0)
- {
- displays = smart_terminal ? Infinity : 1;
- }
-
- /* hold interrupt signals while setting up the screen and the handlers */
-#ifdef SIGHOLD
- sighold(SIGINT);
- sighold(SIGQUIT);
- sighold(SIGTSTP);
-#else
- old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));
-#endif
- init_screen();
- (void) signal(SIGINT, leave);
- (void) signal(SIGQUIT, leave);
- (void) signal(SIGTSTP, tstop);
-#ifdef SIGWINCH
- (void) signal(SIGWINCH, top_winch);
-#endif
-#ifdef SIGRELSE
- sigrelse(SIGINT);
- sigrelse(SIGQUIT);
- sigrelse(SIGTSTP);
-#else
- (void) sigsetmask(old_sigmask);
-#endif
- if (warnings)
- {
- fputs("....", stderr);
- fflush(stderr); /* why must I do this? */
- sleep((unsigned)(3 * warnings));
- fputc('\n', stderr);
- }
-
-restart:
-
- /*
- * main loop -- repeat while display count is positive or while it
- * indicates infinity (by being -1)
- */
-
- while ((displays == -1) || (displays-- > 0))
- {
- int (*compare)();
-
-
- /* get the current stats */
- get_system_info(&system_info);
-
-#ifdef ORDER
- compare = compares[order_index];
-#else
- if (displaymode == DISP_CPU)
- compare = proc_compare;
- else
- compare = io_compare;
-#endif
-
- /* get the current set of processes */
- processes =
- get_process_info(&system_info, &ps, compare);
-
- /* display the load averages */
- (*d_loadave)(system_info.last_pid,
- system_info.load_avg);
-
- /* display the current time */
- /* this method of getting the time SHOULD be fairly portable */
- time(&curr_time);
- i_uptime(&system_info.boottime, &curr_time);
- i_timeofday(&curr_time);
-
- /* display process state breakdown */
- (*d_procstates)(system_info.p_total,
- system_info.procstates);
-
- /* display the cpu state percentage breakdown */
- if (dostates) /* but not the first time */
- {
- (*d_cpustates)(system_info.cpustates);
- }
- else
- {
- /* we'll do it next time */
- if (smart_terminal)
- {
- z_cpustates();
- }
- else
- {
- putchar('\n');
- }
- dostates = Yes;
- }
-
- /* display memory stats */
- (*d_memory)(system_info.memory);
- (*d_arc)(system_info.arc);
- (*d_carc)(system_info.carc);
-
- /* display swap stats */
- (*d_swap)(system_info.swap);
-
- /* handle message area */
- (*d_message)();
-
- /* update the header area */
- (*d_header)(header_text);
-
- if (topn > 0)
- {
- /* determine number of processes to actually display */
- /* this number will be the smallest of: active processes,
- number user requested, number current screen accomodates */
- active_procs = system_info.P_ACTIVE;
- if (active_procs > topn)
- {
- active_procs = topn;
- }
- if (active_procs > max_topn)
- {
- active_procs = max_topn;
- }
-
- /* now show the top "n" processes. */
- for (i = 0; i < active_procs; i++)
- {
- (*d_process)(i, format_next_process(processes, get_userid,
- fmt_flags));
- }
- }
- else
- {
- i = 0;
- }
-
- /* do end-screen processing */
- u_endscreen(i);
-
- /* now, flush the output buffer */
- if (fflush(stdout) != 0)
- {
- new_message(MT_standout, " Write error on stdout");
- putchar('\r');
- quit(1);
- /*NOTREACHED*/
- }
-
- /* only do the rest if we have more displays to show */
- if (displays)
- {
- /* switch out for new display on smart terminals */
- if (smart_terminal)
- {
- if (overstrike)
- {
- reset_display();
- }
- else
- {
- d_loadave = u_loadave;
- d_procstates = u_procstates;
- d_cpustates = u_cpustates;
- d_memory = u_memory;
- d_arc = u_arc;
- d_carc = u_carc;
- d_swap = u_swap;
- d_message = u_message;
- d_header = u_header;
- d_process = u_process;
- }
- }
-
- no_command = Yes;
- if (!interactive)
- {
- sleep(delay);
- if (leaveflag) {
- end_screen();
- exit(0);
- }
- }
- else while (no_command)
- {
- /* assume valid command unless told otherwise */
- no_command = No;
-
- /* set up arguments for select with timeout */
- FD_ZERO(&readfds);
- FD_SET(0, &readfds); /* for standard input */
- timeout.tv_sec = delay;
- timeout.tv_usec = 0;
-
- if (leaveflag) {
- end_screen();
- exit(0);
- }
-
- if (tstopflag) {
- /* move to the lower left */
- end_screen();
- fflush(stdout);
-
- /* default the signal handler action */
- (void) signal(SIGTSTP, SIG_DFL);
-
- /* unblock the signal and send ourselves one */
-#ifdef SIGRELSE
- sigrelse(SIGTSTP);
-#else
- (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
-#endif
- (void) kill(0, SIGTSTP);
-
- /* reset the signal handler */
- (void) signal(SIGTSTP, tstop);
-
- /* reinit screen */
- reinit_screen();
- reset_display();
- tstopflag = 0;
- goto restart;
- }
-
- if (winchflag) {
- /* reascertain the screen dimensions */
- get_screensize();
-
- /* tell display to resize */
- max_topn = display_resize();
-
- /* reset the signal handler */
- (void) signal(SIGWINCH, top_winch);
-
- reset_display();
- winchflag = 0;
- goto restart;
- }
-
- /* wait for either input or the end of the delay period */
- sel_ret = select(2, &readfds, NULL, NULL, &timeout);
- if (sel_ret < 0 && errno != EINTR)
- quit(0);
- if (sel_ret > 0)
- {
- int newval;
- char *errmsg;
-
- /* something to read -- clear the message area first */
- clear_message();
-
- /* now read it and convert to command strchr */
- /* (use "change" as a temporary to hold strchr) */
- if (read(0, &ch, 1) != 1)
- {
- /* read error: either 0 or -1 */
- new_message(MT_standout, " Read error on stdin");
- putchar('\r');
- quit(1);
- /*NOTREACHED*/
- }
- if ((iptr = strchr(command_chars, ch)) == NULL)
- {
- if (ch != '\r' && ch != '\n')
- {
- /* illegal command */
- new_message(MT_standout, " Command not understood");
- }
- putchar('\r');
- no_command = Yes;
- }
- else
- {
- change = iptr - command_chars;
- if (overstrike && change > CMD_OSLIMIT)
- {
- /* error */
- new_message(MT_standout,
- " Command cannot be handled by this terminal");
- putchar('\r');
- no_command = Yes;
- }
- else switch(change)
- {
- case CMD_redraw: /* redraw screen */
- reset_display();
- break;
-
- case CMD_update: /* merely update display */
- /* is the load average high? */
- if (system_info.load_avg[0] > LoadMax)
- {
- /* yes, go home for visual feedback */
- go_home();
- fflush(stdout);
- }
- break;
-
- case CMD_quit: /* quit */
- quit(0);
- /*NOTREACHED*/
- break;
-
- case CMD_help1: /* help */
- case CMD_help2:
- reset_display();
- top_clear();
- show_help();
- top_standout("Hit any key to continue: ");
- fflush(stdout);
- (void) read(0, &ch, 1);
- break;
-
- case CMD_errors: /* show errors */
- if (error_count() == 0)
- {
- new_message(MT_standout,
- " Currently no errors to report.");
- putchar('\r');
- no_command = Yes;
- }
- else
- {
- reset_display();
- top_clear();
- show_errors();
- top_standout("Hit any key to continue: ");
- fflush(stdout);
- (void) read(0, &ch, 1);
- }
- break;
-
- case CMD_number1: /* new number */
- case CMD_number2:
- new_message(MT_standout,
- "Number of processes to show: ");
- newval = readline(tempbuf1, 8, Yes);
- if (newval > -1)
- {
- if (newval > max_topn)
- {
- new_message(MT_standout | MT_delayed,
- " This terminal can only display %d processes.",
- max_topn);
- putchar('\r');
- }
-
- if (newval == 0)
- {
- /* inhibit the header */
- display_header(No);
- }
- else if (newval > topn && topn == 0)
- {
- /* redraw the header */
- display_header(Yes);
- d_header = i_header;
- }
- topn = newval;
- }
- break;
-
- case CMD_delay: /* new seconds delay */
- new_message(MT_standout, "Seconds to delay: ");
- if ((i = readline(tempbuf1, 8, Yes)) > -1)
- {
- if ((delay = i) == 0 && getuid() != 0)
- {
- delay = 1;
- }
- }
- clear_message();
- break;
-
- case CMD_displays: /* change display count */
- new_message(MT_standout,
- "Displays to show (currently %s): ",
- displays == -1 ? "infinite" :
- itoa(displays));
- if ((i = readline(tempbuf1, 10, Yes)) > 0)
- {
- displays = i;
- }
- else if (i == 0)
- {
- quit(0);
- }
- clear_message();
- break;
-
- case CMD_kill: /* kill program */
- new_message(0, "kill ");
- if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
- {
- if ((errmsg = kill_procs(tempbuf2)) != NULL)
- {
- new_message(MT_standout, "%s", errmsg);
- putchar('\r');
- no_command = Yes;
- }
- }
- else
- {
- clear_message();
- }
- break;
-
- case CMD_renice: /* renice program */
- new_message(0, "renice ");
- if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
- {
- if ((errmsg = renice_procs(tempbuf2)) != NULL)
- {
- new_message(MT_standout, "%s", errmsg);
- putchar('\r');
- no_command = Yes;
- }
- }
- else
- {
- clear_message();
- }
- break;
-
- case CMD_idletog:
- case CMD_idletog2:
- ps.idle = !ps.idle;
- new_message(MT_standout | MT_delayed,
- " %sisplaying idle processes.",
- ps.idle ? "D" : "Not d");
- putchar('\r');
- break;
-
- case CMD_selftog:
- ps.self = (ps.self == -1) ? getpid() : -1;
- new_message(MT_standout | MT_delayed,
- " %sisplaying self.",
- (ps.self == -1) ? "D" : "Not d");
- putchar('\r');
- break;
-
- case CMD_user:
- if (handle_user(tempbuf2, sizeof(tempbuf2)))
- no_command = Yes;
- break;
-
- case CMD_thrtog:
- ps.thread = !ps.thread;
- new_message(MT_standout | MT_delayed,
- " Displaying threads %s",
- ps.thread ? "separately" : "as a count");
- header_text = format_header(uname_field);
- reset_display();
- putchar('\r');
- break;
- case CMD_wcputog:
- ps.wcpu = !ps.wcpu;
- new_message(MT_standout | MT_delayed,
- " Displaying %s CPU",
- ps.wcpu ? "weighted" : "raw");
- header_text = format_header(uname_field);
- reset_display();
- putchar('\r');
- break;
- case CMD_viewtog:
- if (++displaymode == DISP_MAX)
- displaymode = 0;
- header_text = format_header(uname_field);
- display_header(Yes);
- d_header = i_header;
- reset_display();
- break;
- case CMD_viewsys:
- ps.system = !ps.system;
- break;
- case CMD_showargs:
- fmt_flags ^= FMT_SHOWARGS;
- break;
-#ifdef ORDER
- case CMD_order:
- new_message(MT_standout,
- "Order to sort: ");
- if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
- {
- if ((i = string_index(tempbuf2, statics.order_names)) == -1)
- {
- new_message(MT_standout,
- " %s: unrecognized sorting order", tempbuf2);
- no_command = Yes;
- }
- else
- {
- order_index = i;
- }
- putchar('\r');
- }
- else
- {
- clear_message();
- }
- break;
-#endif
- case CMD_jidtog:
- ps.jail = !ps.jail;
- new_message(MT_standout | MT_delayed,
- " %sisplaying jail ID.",
- ps.jail ? "D" : "Not d");
- header_text = format_header(uname_field);
- reset_display();
- putchar('\r');
- break;
-
- case CMD_jail:
- new_message(MT_standout,
- "Jail to show (+ for all): ");
- if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
- {
- if (tempbuf2[0] == '+' &&
- tempbuf2[1] == '\0')
- {
- ps.jid = -1;
- }
- else if ((i = jail_getid(tempbuf2)) == -1)
- {
- new_message(MT_standout,
- " %s: unknown jail", tempbuf2);
- no_command = Yes;
- }
- else
- {
- ps.jid = i;
- }
- if (ps.jail == 0) {
- ps.jail = 1;
- new_message(MT_standout |
- MT_delayed, " Displaying jail "
- "ID.");
- header_text =
- format_header(uname_field);
- reset_display();
- }
- putchar('\r');
- }
- else
- {
- clear_message();
- }
- break;
-
- case CMD_kidletog:
- ps.kidle = !ps.kidle;
- new_message(MT_standout | MT_delayed,
- " %sisplaying system idle process.",
- ps.kidle ? "D" : "Not d");
- putchar('\r');
- break;
- case CMD_pcputog:
- pcpu_stats = !pcpu_stats;
- new_message(MT_standout | MT_delayed,
- " Displaying %sCPU statistics.",
- pcpu_stats ? "per-" : "global ");
- toggle_pcpustats();
- max_topn = display_updatecpus(&statics);
- reset_display();
- putchar('\r');
- break;
- case CMD_swaptog:
- ps.swap = !ps.swap;
- new_message(MT_standout | MT_delayed,
- " %sisplaying per-process swap usage.",
- ps.swap ? "D" : "Not d");
- header_text = format_header(uname_field);
- reset_display();
- putchar('\r');
- break;
- default:
- new_message(MT_standout, " BAD CASE IN SWITCH!");
- putchar('\r');
- }
- }
-
- /* flush out stuff that may have been written */
- fflush(stdout);
- }
- }
- }
- }
-
-#ifdef DEBUG
- fclose(debug);
-#endif
- quit(0);
- /*NOTREACHED*/
-}
-
-/*
- * reset_display() - reset all the display routine pointers so that entire
- * screen will get redrawn.
- */
-
-void
-reset_display()
-
-{
- d_loadave = i_loadave;
- d_procstates = i_procstates;
- d_cpustates = i_cpustates;
- d_memory = i_memory;
- d_arc = i_arc;
- d_carc = i_carc;
- d_swap = i_swap;
- d_message = i_message;
- d_header = i_header;
- d_process = i_process;
-}
-
-/*
- * signal handlers
- */
-
-sigret_t leave() /* exit under normal conditions -- INT handler */
-
-{
- leaveflag = 1;
-}
-
-sigret_t tstop(i) /* SIGTSTP handler */
-
-int i;
-
-{
- tstopflag = 1;
-}
-
-#ifdef SIGWINCH
-sigret_t top_winch(int i) /* SIGWINCH handler */
-{
- winchflag = 1;
-}
-#endif
-
-void quit(status) /* exit under duress */
-
-int status;
-
-{
- end_screen();
- exit(status);
- /*NOTREACHED*/
-}
Index: head/contrib/top/top.local.hs
===================================================================
--- head/contrib/top/top.local.hs
+++ head/contrib/top/top.local.hs
@@ -1,68 +0,0 @@
-/*
- * Top - a top users display for Berkeley Unix
- *
- * Definitions for things that might vary between installations.
- */
-
-/*
- * The space command forces an immediate update. Sometimes, on loaded
- * systems, this update will take a significant period of time (because all
- * the output is buffered). So, if the short-term load average is above
- * "LoadMax", then top will put the cursor home immediately after the space
- * is pressed before the next update is attempted. This serves as a visual
- * acknowledgement of the command. On Suns, "LoadMax" will get multiplied by
- * "FSCALE" before being compared to avenrun[0]. Therefore, "LoadMax"
- * should always be specified as a floating point number.
- */
-#ifndef LoadMax
-#define LoadMax %LoadMax%
-#endif
-
-/*
- * "Table_size" defines the size of the hash tables used to map uid to
- * username. The number of users in /etc/passwd CANNOT be greater than
- * this number. If the error message "table overflow: too many users"
- * is printed by top, then "Table_size" needs to be increased. Things will
- * work best if the number is a prime number that is about twice the number
- * of lines in /etc/passwd.
- */
-#ifndef Table_size
-#define Table_size %TableSize%
-#endif
-
-/*
- * "Nominal_TOPN" is used as the default TOPN when Default_TOPN is Infinity
- * and the output is a dumb terminal. If we didn't do this, then
- * installations who use a default TOPN of Infinity will get every
- * process in the system when running top on a dumb terminal (or redirected
- * to a file). Note that Nominal_TOPN is a default: it can still be
- * overridden on the command line, even with the value "infinity".
- */
-#ifndef Nominal_TOPN
-#define Nominal_TOPN %NominalTopn%
-#endif
-
-#ifndef Default_TOPN
-#define Default_TOPN %topn%
-#endif
-
-#ifndef Default_DELAY
-#define Default_DELAY %delay%
-#endif
-
-/*
- * If the local system's getpwnam interface uses random access to retrieve
- * a record (i.e.: 4.3 systems, Sun "yellow pages"), then defining
- * RANDOM_PW will take advantage of that fact. If RANDOM_PW is defined,
- * then getpwnam is used and the result is cached. If not, then getpwent
- * is used to read and cache the password entries sequentially until the
- * desired one is found.
- *
- * We initially set RANDOM_PW to something which is controllable by the
- * Configure script. Then if its value is 0, we undef it.
- */
-
-#define RANDOM_PW %random%
-#if RANDOM_PW == 0
-#undef RANDOM_PW
-#endif
Index: head/contrib/top/top.xs
===================================================================
--- head/contrib/top/top.xs
+++ head/contrib/top/top.xs
@@ -1,459 +0,0 @@
-.\" NOTE: changes to the manual page for "top" should be made in the
-.\" file "top.X" and NOT in the file "top.1".
-.\" $FreeBSD$
-.nr N %topn%
-.nr D %delay%
-.TH TOP 1 Local
-.UC 4
-.SH NAME
-top \- display and update information about the top cpu processes
-.SH SYNOPSIS
-.B top
-[
-.B \-abCHIijnPqStuvwz
-] [
-.BI \-d count
-] [
-.BI \-m io | cpu
-] [
-.BI \-o field
-] [
-.BI \-s time
-] [
-.BI \-J jail
-] [
-.BI \-U username
-] [
-.I number
-]
-.SH DESCRIPTION
-.\" This defines appropriate quote strings for nroff and troff
-.ds lq \&"
-.ds rq \&"
-.if t .ds lq ``
-.if t .ds rq ''
-.\" Just in case these number registers aren't set yet...
-.if \nN==0 .nr N 10
-.if \nD==0 .nr D 2
-.I Top
-displays the top
-.if !\nN==-1 \nN
-processes on the system and periodically updates this information.
-.if \nN==-1 \
-\{\
-If standard output is an intelligent terminal (see below) then
-as many processes as will fit on the terminal screen are displayed
-by default. Otherwise, a good number of them are shown (around 20).
-.\}
-Raw cpu percentage is used to rank the processes. If
-.I number
-is given, then the top
-.I number
-processes will be displayed instead of the default.
-.PP
-.I Top
-makes a distinction between terminals that support advanced capabilities
-and those that do not. This
-distinction affects the choice of defaults for certain options. In the
-remainder of this document, an \*(lqintelligent\*(rq terminal is one that
-supports cursor addressing, clear screen, and clear to end of line.
-Conversely, a \*(lqdumb\*(rq terminal is one that does not support such
-features. If the output of
-.I top
-is redirected to a file, it acts as if it were being run on a dumb
-terminal.
-.SH OPTIONS
-.TP
-.B \-C
-Toggle CPU display mode.
-By default top displays the weighted CPU percentage in the WCPU column
-(this is the same value that
-.IR ps (1)
-displays as CPU).
-Each time
-.B \-C
-flag is passed it toggles between \*(lqraw cpu\*(rq mode
-and \*(lqweighted cpu\*(rq mode, showing the \*(lqCPU\*(rq or
-the \*(lqWCPU\*(rq column respectively.
-.TP
-.B \-S
-Show system processes in the display. Normally, system processes such as
-the pager and the swapper are not shown. This option makes them visible.
-.TP
-.B \-a
-Display command names derived from the argv[] vector, rather than real
-executable name. It's useful when you want to watch applications, that
-puts their status information there. If the real name differs from argv[0],
-it will be displayed in parenthesis.
-.TP
-.B \-b
-Use \*(lqbatch\*(rq mode. In this mode, all input from the terminal is
-ignored. Interrupt characters (such as ^C and ^\e) still have an effect.
-This is the default on a dumb terminal, or when the output is not a terminal.
-.TP
-.B \-H
-Display each thread for a multithreaded process individually.
-By default a single summary line is displayed for each process.
-.TP
-.B \-i
-Use \*(lqinteractive\*(rq mode. In this mode, any input is immediately
-read for processing. See the section on \*(lqInteractive Mode\*(rq
-for an explanation of
-which keys perform what functions. After the command is processed, the
-screen will immediately be updated, even if the command was not
-understood. This mode is the default when standard output is an
-intelligent terminal.
-.TP
-.B \-I
-Do not display idle processes.
-By default, top displays both active and idle processes.
-.TP
-.B \-j
-Display the
-.IR jail (8)
-ID.
-.TP
-.B \-t
-Do not display the
-.I top
-process.
-.TP
-.BI \-m display
-Display either 'cpu' or 'io' statistics. Default is 'cpu'.
-.TP
-.B \-n
-Use \*(lqnon-interactive\*(rq mode. This is identical to \*(lqbatch\*(rq
-mode.
-.TP
-.B \-P
-Display per-cpu CPU usage statistics.
-.TP
-.B \-q
-Renice
-.I top
-to -20 so that it will run faster. This can be used when the system is
-being very sluggish to improve the possibility of discovering the problem.
-This option can only be used by root.
-.TP
-.B \-u
-Do not take the time to map uid numbers to usernames. Normally,
-.I top
-will read as much of the file \*(lq/etc/passwd\*(rq as is necessary to map
-all the user id numbers it encounters into login names. This option
-disables all that, while possibly decreasing execution time. The uid
-numbers are displayed instead of the names.
-.TP
-.B \-v
-Write version number information to stderr then exit immediately.
-No other processing takes place when this option is used. To see current
-revision information while top is running, use the help command \*(lq?\*(rq.
-.TP
-.B \-w
-Display approximate swap usage for each process.
-.TP
-.B \-z
-Do not display the system idle process.
-.TP
-.BI \-d count
-Show only
-.I count
-displays, then exit. A display is considered to be one update of the
-screen. This option allows the user to select the number of displays he
-wants to see before
-.I top
-automatically exits. For intelligent terminals, no upper limit
-is set. The default is 1 for dumb terminals.
-.TP
-.BI \-s time
-Set the delay between screen updates to
-.I time
-seconds. The default delay between updates is \nD seconds.
-.TP
-.BI \-o field
-Sort the process display area on the specified field. The field name
-is the name of the column as seen in the output, but in lower case:
-\*(lqcpu\*(lq, \*(rqsize\*(lq, \*(rqres\*(lq, \*(rqtime\*(lq,
-\*(rqpri\*(lq, \*(rqthreads\*(lq, \*(lqtotal\*(lq, \*(rqread\*(lq,
-\*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
-\*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
-.TP
-.BI \-J jail
-Show only those processes owned by
-.IR jail .
-This may be either the
-.B jid
-or
-.B name
-of the jail.
-Use
-.B 0
-to limit to host processes.
-Using this option implies the
-.B \-j
-flag.
-.PP
-.BI \-U username
-Show only those processes owned by
-.IR username .
-This option currently only accepts usernames and will not understand
-uid numbers.
-.PP
-Both
-.I count
-and
-.I number
-fields can be specified as \*(lqinfinite\*(rq, indicating that they can
-stretch as far as possible. This is accomplished by using any proper
-prefix of the keywords
-\*(lqinfinity\*(rq,
-\*(lqmaximum\*(rq,
-or
-\*(lqall\*(rq.
-The default for
-.I count
-on an intelligent terminal is, in fact,
-.BI infinity .
-.PP
-The environment variable
-.B TOP
-is examined for options before the command line is scanned. This enables
-a user to set his or her own defaults. The number of processes to display
-can also be specified in the environment variable
-.BR TOP .
-The options
-.BR \-a ,
-.BR \-C ,
-.BR \-H ,
-.BR \-I ,
-.BR \-j ,
-.BR \-P ,
-.BR \-S ,
-.BR \-t ,
-.BR \-u ,
-.BR \-w ,
-and
-.B \-z
-are actually toggles. A second specification of any of these options
-will negate the first. Thus a user who has the environment variable
-.B TOP
-set to \*(lq\-I\*(rq may use the command \*(lqtop \-I\*(rq to see idle processes.
-.SH "INTERACTIVE MODE"
-When
-.I top
-is running in \*(lqinteractive mode\*(rq, it reads commands from the
-terminal and acts upon them accordingly. In this mode, the terminal is
-put in \*(lqCBREAK\*(rq, so that a character will be
-processed as soon as it is typed. Almost always, a key will be
-pressed when
-.I top
-is between displays; that is, while it is waiting for
-.I time
-seconds to elapse. If this is the case, the command will be
-processed and the display will be updated immediately thereafter
-(reflecting any changes that the command may have specified). This
-happens even if the command was incorrect. If a key is pressed while
-.I top
-is in the middle of updating the display, it will finish the update and
-then process the command. Some commands require additional information,
-and the user will be prompted accordingly. While typing this information
-in, the user's erase and kill keys (as set up by the command
-.IR stty )
-are recognized, and a newline terminates the input.
-.PP
-These commands are currently recognized (^L refers to control-L):
-.TP
-.B ^L
-Redraw the screen.
-.IP "\fBh\fP\ or\ \fB?\fP"
-Display a summary of the commands (help screen). Version information
-is included in this display.
-.TP
-.B q
-Quit
-.IR top.
-.TP
-.B d
-Change the number of displays to show (prompt for new number).
-Remember that the next display counts as one, so typing
-.B d1
-will make
-.I top
-show one final display and then immediately exit.
-.TP
-.B m
-Toggle the display between 'cpu' and 'io' modes.
-.TP
-.B n or #
-Change the number of processes to display (prompt for new number).
-.TP
-.B s
-Change the number of seconds to delay between displays
-(prompt for new number).
-.TP
-.B S
-Toggle the display of system processes.
-.TP
-.B a
-Toggle the display of process titles.
-.TP
-.B k
-Send a signal (\*(lqkill\*(rq by default) to a list of processes. This
-acts similarly to the command
-.IR kill (1)).
-.TP
-.B r
-Change the priority (the \*(lqnice\*(rq) of a list of processes.
-This acts similarly to the command
-.IR renice (8)).
-.TP
-.B u
-Display only processes owned by a specific set of usernames (prompt for
-username). If the username specified is simply \*(lq+\*(rq or \*(lq-\*(rq,
-then processes belonging to all users will be displayed. Usernames can be added
-to and removed from the set by prepending them with \*(lq+\*(rq and
-\*(lq-\*(rq, respectively.
-.TP
-.B o
-Change the order in which the display is sorted. This command is not
-available on all systems. The sort key names vary from system to system
-but usually include: \*(lqcpu\*(rq, \*(lqres\*(rq, \*(lqsize\*(rq,
-\*(lqtime\*(rq. The default is cpu.
-.TP
-.B e
-Display a list of system errors (if any) generated by the last
-.BR k ill
-or
-.BR r enice
-command.
-.TP
-.B H
-Toggle the display of threads.
-.TP
-.B i
-(or
-.BR I )
-Toggle the display of idle processes.
-.TP
-.B j
-Toggle the display of
-.IR jail (8)
-ID.
-.TP
-.B J
-Display only processes owned by a specific jail (prompt for jail).
-If the jail specified is simply \*(lq+\*(rq, then processes belonging
-to all jails and the host will be displayed.
-This will also enable the display of JID.
-.TP
-.B P
-Toggle the display of per-CPU statistics.
-.TP
-.B t
-Toggle the display of the
-.I top
-process.
-.TP
-.B w
-Toggle the display of swap usage.
-.TP
-.B z
-Toggle the display of the system idle process.
-.SH "THE DISPLAY"
-The actual display varies depending on the specific variant of Unix
-that the machine is running. This description may not exactly match
-what is seen by top running on this particular machine. Differences
-are listed at the end of this manual entry.
-.PP
-The top few lines of the display show general information
-about the state of the system, including
-the last process id assigned to a process (on most systems),
-the three load averages,
-the current time,
-the number of existing processes,
-the number of processes in each state
-(sleeping, running, starting, zombies, and stopped),
-and a percentage of time spent in each of the processor states
-(user, nice, system, and idle).
-It also includes information about physical and virtual memory allocation.
-.PP
-The remainder of the screen displays information about individual
-processes. This display is similar in spirit to
-.IR ps (1)
-but it is not exactly the same. PID is the process id,
-JID, when displayed, is the
-.IR jail (8)
-ID corresponding to the process,
-USERNAME is the name of the process's owner (if
-.B \-u
-is specified, a UID column will be substituted for USERNAME),
-PRI is the current priority of the process,
-NICE is the nice amount (in the range \-20 to 20),
-SIZE is the total size of the process (text, data, and stack),
-RES is the current amount of resident memory,
-SWAP is the approximate amount of swap, if enabled
-(SIZE, RES and SWAP are given in kilobytes),
-STATE is the current state (one of \*(lqSTART\*(rq, \*(lqRUN\*(rq
-(shown as \*(lqCPUn\*(rq on SMP systems), \*(lqSLEEP\*(rq, \*(lqSTOP\*(rq,
-\*(lqZOMB\*(rq, \*(lqWAIT\*(rq, \*(lqLOCK\*(rq or the event on which the
-process waits),
-C is the processor number on which the process is executing
-(visible only on SMP systems),
-TIME is the number of system and user cpu seconds that the process has used,
-WCPU, when displayed, is the weighted cpu percentage (this is the same
-value that
-.IR ps (1)
-displays as CPU),
-CPU is the raw percentage and is the field that is sorted to determine
-the order of the processes, and
-COMMAND is the name of the command that the process is currently running
-(if the process is swapped out, this column is marked \*(lq<swapped>\*(rq).
-.SH NOTES
-If a process is in the \*(lqSLEEP\*(rq or \*(lqLOCK\*(rq state,
-the state column will report the name of the event or lock on which the
-process is waiting.
-Lock names are prefixed with an asterisk \*(lq*\*(rq while sleep events
-are not.
-.SH AUTHOR
-William LeFebvre, EECS Department, Northwestern University
-.SH ENVIRONMENT
-.DT
-TOP user-configurable defaults for options.
-.SH FILES
-.DT
-/dev/kmem kernel memory
-.br
-/dev/mem physical memory
-.br
-/etc/passwd used to map uid numbers to user names
-.br
-/boot/kernel/kernel system image
-.SH BUGS
-Don't shoot me, but the default for
-.B \-I
-has changed once again. So many people were confused by the fact that
-.I top
-wasn't showing them all the processes that I have decided to make the
-default behavior show idle processes, just like it did in version 2.
-But to appease folks who can't stand that behavior, I have added the
-ability to set \*(lqdefault\*(rq options in the environment variable
-.B TOP
-(see the OPTIONS section). Those who want the behavior that version
-3.0 had need only set the environment variable
-.B TOP
-to \*(lq\-I\*(rq.
-.PP
-The command name for swapped processes should be tracked down, but this
-would make the program run slower.
-.PP
-As with
-.IR ps (1),
-things can change while
-.I top
-is collecting information for an update. The picture it gives is only a
-close approximation to reality.
-.SH "SEE ALSO"
-kill(1),
-ps(1),
-stty(1),
-mem(4),
-renice(8)
Index: head/contrib/top/username.h
===================================================================
--- head/contrib/top/username.h
+++ head/contrib/top/username.h
@@ -1,23 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- * Copyright (c) 2016, Randy Westlund
- *
- * $FreeBSD$
- */
-#ifndef USERNAME_H
-#define USERNAME_H
-
-int enter_user(int uid, char *name, int wecare);
-int get_user(int uid);
-void init_hash(void);
-char *username(int uid);
-int userid(char *username);
-
-#endif /* USERNAME_H */
Index: head/contrib/top/username.c
===================================================================
--- head/contrib/top/username.c
+++ head/contrib/top/username.c
@@ -1,195 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- *
- * $FreeBSD$
- */
-
-/*
- * Username translation code for top.
- *
- * These routines handle uid to username mapping.
- * They use a hashing table scheme to reduce reading overhead.
- * For the time being, these are very straightforward hashing routines.
- * Maybe someday I'll put in something better. But with the advent of
- * "random access" password files, it might not be worth the effort.
- *
- * Changes to these have been provided by John Gilmore (gnu@toad.com).
- *
- * The hash has been simplified in this release, to avoid the
- * table overflow problems of previous releases. If the value
- * at the initial hash location is not right, it is replaced
- * by the right value. Collisions will cause us to call getpw*
- * but hey, this is a cache, not the Library of Congress.
- * This makes the table size independent of the passwd file size.
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "top.local.h"
-#include "utils.h"
-#include "username.h"
-
-struct hash_el {
- int uid;
- char name[MAXLOGNAME];
-};
-
-#define is_empty_hash(x) (hash_table[x].name[0] == 0)
-
-/* simple minded hashing function */
-/* Uid "nobody" is -2 results in hashit(-2) = -2 which is out of bounds for
- the hash_table. Applied abs() function to fix. 2/16/96 tpugh
-*/
-#define hashit(i) (abs(i) % Table_size)
-
-/* K&R requires that statically declared tables be initialized to zero. */
-/* We depend on that for hash_table and YOUR compiler had BETTER do it! */
-struct hash_el hash_table[Table_size];
-
-
-void
-init_hash()
-
-{
- /*
- * There used to be some steps we had to take to initialize things.
- * We don't need to do that anymore, but we will leave this stub in
- * just in case future changes require initialization steps.
- */
-}
-
-char *username(uid)
-
-int uid;
-
-{
- register int hashindex;
-
- hashindex = hashit(uid);
- if (is_empty_hash(hashindex) || (hash_table[hashindex].uid != uid))
- {
- /* not here or not right -- get it out of passwd */
- hashindex = get_user(uid);
- }
- return(hash_table[hashindex].name);
-}
-
-int userid(username)
-
-char *username;
-
-{
- struct passwd *pwd;
-
- /* Eventually we want this to enter everything in the hash table,
- but for now we just do it simply and remember just the result.
- */
-
- if ((pwd = getpwnam(username)) == NULL)
- {
- return(-1);
- }
-
- /* enter the result in the hash table */
- enter_user(pwd->pw_uid, username, 1);
-
- /* return our result */
- return(pwd->pw_uid);
-}
-
-int enter_user(uid, name, wecare)
-
-int uid;
-char *name;
-int wecare; /* 1 = enter it always, 0 = nice to have */
-
-{
- register int hashindex;
-
-#ifdef DEBUG
- fprintf(stderr, "enter_hash(%d, %s, %d)\n", uid, name, wecare);
-#endif
-
- hashindex = hashit(uid);
-
- if (!is_empty_hash(hashindex))
- {
- if (!wecare)
- return 0; /* Don't clobber a slot for trash */
- if (hash_table[hashindex].uid == uid)
- return(hashindex); /* Fortuitous find */
- }
-
- /* empty or wrong slot -- fill it with new value */
- hash_table[hashindex].uid = uid;
- (void) strncpy(hash_table[hashindex].name, name, MAXLOGNAME - 1);
- return(hashindex);
-}
-
-/*
- * Get a userid->name mapping from the system.
- * If the passwd database is hashed (#define RANDOM_PW), we
- * just handle this uid. Otherwise we scan the passwd file
- * and cache any entries we pass over while looking.
- */
-
-int get_user(uid)
-
-int uid;
-
-{
- struct passwd *pwd;
-
-#ifdef RANDOM_PW
- /* no performance penalty for using getpwuid makes it easy */
- if ((pwd = getpwuid(uid)) != NULL)
- {
- return(enter_user(pwd->pw_uid, pwd->pw_name, 1));
- }
-#else
-
- int from_start = 0;
-
- /*
- * If we just called getpwuid each time, things would be very slow
- * since that just iterates through the passwd file each time. So,
- * we walk through the file instead (using getpwent) and cache each
- * entry as we go. Once the right record is found, we cache it and
- * return immediately. The next time we come in, getpwent will get
- * the next record. In theory, we never have to read the passwd file
- * a second time (because we cache everything we read). But in
- * practice, the cache may not be large enough, so if we don't find
- * it the first time we have to scan the file a second time. This
- * is not very efficient, but it will do for now.
- */
-
- while (from_start++ < 2)
- {
- while ((pwd = getpwent()) != NULL)
- {
- if (pwd->pw_uid == uid)
- {
- return(enter_user(pwd->pw_uid, pwd->pw_name, 1));
- }
- (void) enter_user(pwd->pw_uid, pwd->pw_name, 0);
- }
- /* try again */
- setpwent();
- }
-#endif
- /* if we can't find the name at all, then use the uid as the name */
- return(enter_user(uid, itoa7(uid), 1));
-}
Index: head/contrib/top/utils.h
===================================================================
--- head/contrib/top/utils.h
+++ head/contrib/top/utils.h
@@ -1,26 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- */
-
-/* prototypes for functions found in utils.c */
-
-int atoiwi();
-char *itoa();
-char *itoa7();
-int digits();
-char *strecpy();
-char **argparse();
-long percentages();
-char *errmsg();
-char *format_time();
-char *format_k();
-char *format_k2(unsigned long long);
-int string_index(char *string, char **array);
-
Index: head/contrib/top/utils.c
===================================================================
--- head/contrib/top/utils.c
+++ head/contrib/top/utils.c
@@ -1,508 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- *
- * $FreeBSD$
- */
-
-/*
- * This file contains various handy utilities used by top.
- */
-
-#include "top.h"
-#include "os.h"
-
-int atoiwi(str)
-
-char *str;
-
-{
- register int len;
-
- len = strlen(str);
- if (len != 0)
- {
- if (strncmp(str, "infinity", len) == 0 ||
- strncmp(str, "all", len) == 0 ||
- strncmp(str, "maximum", len) == 0)
- {
- return(Infinity);
- }
- else if (str[0] == '-')
- {
- return(Invalid);
- }
- else
- {
- return(atoi(str));
- }
- }
- return(0);
-}
-
-/*
- * itoa - convert integer (decimal) to ascii string for positive numbers
- * only (we don't bother with negative numbers since we know we
- * don't use them).
- */
-
- /*
- * How do we know that 16 will suffice?
- * Because the biggest number that we will
- * ever convert will be 2^32-1, which is 10
- * digits.
- */
-_Static_assert(sizeof(int) <= 4, "buffer too small for this sized int");
-
-char *itoa(val)
-
-register int val;
-
-{
- register char *ptr;
- static char buffer[16]; /* result is built here */
- /* 16 is sufficient since the largest number
- we will ever convert will be 2^32-1,
- which is 10 digits. */
-
- ptr = buffer + sizeof(buffer);
- *--ptr = '\0';
- if (val == 0)
- {
- *--ptr = '0';
- }
- else while (val != 0)
- {
- *--ptr = (val % 10) + '0';
- val /= 10;
- }
- return(ptr);
-}
-
-/*
- * itoa7(val) - like itoa, except the number is right justified in a 7
- * character field. This code is a duplication of itoa instead of
- * a front end to a more general routine for efficiency.
- */
-
-char *itoa7(val)
-
-register int val;
-
-{
- register char *ptr;
- static char buffer[16]; /* result is built here */
- /* 16 is sufficient since the largest number
- we will ever convert will be 2^32-1,
- which is 10 digits. */
-
- ptr = buffer + sizeof(buffer);
- *--ptr = '\0';
- if (val == 0)
- {
- *--ptr = '0';
- }
- else while (val != 0)
- {
- *--ptr = (val % 10) + '0';
- val /= 10;
- }
- while (ptr > buffer + sizeof(buffer) - 7)
- {
- *--ptr = ' ';
- }
- return(ptr);
-}
-
-/*
- * digits(val) - return number of decimal digits in val. Only works for
- * positive numbers. If val <= 0 then digits(val) == 0.
- */
-
-int digits(val)
-
-int val;
-
-{
- register int cnt = 0;
-
- while (val > 0)
- {
- cnt++;
- val /= 10;
- }
- return(cnt);
-}
-
-/*
- * strecpy(to, from) - copy string "from" into "to" and return a pointer
- * to the END of the string "to".
- */
-
-char *strecpy(to, from)
-
-register char *to;
-register char *from;
-
-{
- while ((*to++ = *from++) != '\0');
- return(--to);
-}
-
-/*
- * string_index(string, array) - find string in array and return index
- */
-
-int string_index(string, array)
-
-char *string;
-char **array;
-
-{
- register int i = 0;
-
- while (*array != NULL)
- {
- if (strcmp(string, *array) == 0)
- {
- return(i);
- }
- array++;
- i++;
- }
- return(-1);
-}
-
-/*
- * argparse(line, cntp) - parse arguments in string "line", separating them
- * out into an argv-like array, and setting *cntp to the number of
- * arguments encountered. This is a simple parser that doesn't understand
- * squat about quotes.
- */
-
-char **argparse(line, cntp)
-
-char *line;
-int *cntp;
-
-{
- register char *from;
- register char *to;
- register int cnt;
- register int ch;
- int length;
- int lastch;
- register char **argv;
- char **argarray;
- char *args;
-
- /* unfortunately, the only real way to do this is to go thru the
- input string twice. */
-
- /* step thru the string counting the white space sections */
- from = line;
- lastch = cnt = length = 0;
- while ((ch = *from++) != '\0')
- {
- length++;
- if (ch == ' ' && lastch != ' ')
- {
- cnt++;
- }
- lastch = ch;
- }
-
- /* add three to the count: one for the initial "dummy" argument,
- one for the last argument and one for NULL */
- cnt += 3;
-
- /* allocate a char * array to hold the pointers */
- argarray = (char **)malloc(cnt * sizeof(char *));
-
- /* allocate another array to hold the strings themselves */
- args = (char *)malloc(length+2);
-
- /* initialization for main loop */
- from = line;
- to = args;
- argv = argarray;
- lastch = '\0';
-
- /* create a dummy argument to keep getopt happy */
- *argv++ = to;
- *to++ = '\0';
- cnt = 2;
-
- /* now build argv while copying characters */
- *argv++ = to;
- while ((ch = *from++) != '\0')
- {
- if (ch != ' ')
- {
- if (lastch == ' ')
- {
- *to++ = '\0';
- *argv++ = to;
- cnt++;
- }
- *to++ = ch;
- }
- lastch = ch;
- }
- *to++ = '\0';
-
- /* set cntp and return the allocated array */
- *cntp = cnt;
- return(argarray);
-}
-
-/*
- * percentages(cnt, out, new, old, diffs) - calculate percentage change
- * between array "old" and "new", putting the percentages i "out".
- * "cnt" is size of each array and "diffs" is used for scratch space.
- * The array "old" is updated on each call.
- * The routine assumes modulo arithmetic. This function is especially
- * useful on BSD mchines for calculating cpu state percentages.
- */
-
-long percentages(cnt, out, new, old, diffs)
-
-int cnt;
-int *out;
-register long *new;
-register long *old;
-long *diffs;
-
-{
- register int i;
- register long change;
- register long total_change;
- register long *dp;
- long half_total;
-
- /* initialization */
- total_change = 0;
- dp = diffs;
-
- /* calculate changes for each state and the overall change */
- for (i = 0; i < cnt; i++)
- {
- if ((change = *new - *old) < 0)
- {
- /* this only happens when the counter wraps */
- change = (int)
- ((unsigned long)*new-(unsigned long)*old);
- }
- total_change += (*dp++ = change);
- *old++ = *new++;
- }
-
- /* avoid divide by zero potential */
- if (total_change == 0)
- {
- total_change = 1;
- }
-
- /* calculate percentages based on overall change, rounding up */
- half_total = total_change / 2l;
-
- /* Do not divide by 0. Causes Floating point exception */
- if(total_change) {
- for (i = 0; i < cnt; i++)
- {
- *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
- }
- }
-
- /* return the total in case the caller wants to use it */
- return(total_change);
-}
-
-/*
- * errmsg(errnum) - return an error message string appropriate to the
- * error number "errnum". This is a substitute for the System V
- * function "strerror". There appears to be no reliable way to
- * determine if "strerror" exists at compile time, so I make do
- * by providing something of similar functionality. For those
- * systems that have strerror and NOT errlist, define
- * -DHAVE_STRERROR in the module file and this function will
- * use strerror.
- */
-
-/* externs referenced by errmsg */
-
-#ifndef HAVE_STRERROR
-#ifndef SYS_ERRLIST_DECLARED
-#define SYS_ERRLIST_DECLARED
-extern char *sys_errlist[];
-#endif
-
-extern int sys_nerr;
-#endif
-
-char *errmsg(errnum)
-
-int errnum;
-
-{
-#ifdef HAVE_STRERROR
- char *msg = strerror(errnum);
- if (msg != NULL)
- {
- return msg;
- }
-#else
- if (errnum > 0 && errnum < sys_nerr)
- {
- return((char *)sys_errlist[errnum]);
- }
-#endif
- return("No error");
-}
-
-/* format_time(seconds) - format number of seconds into a suitable
- * display that will fit within 6 characters. Note that this
- * routine builds its string in a static area. If it needs
- * to be called more than once without overwriting previous data,
- * then we will need to adopt a technique similar to the
- * one used for format_k.
- */
-
-/* Explanation:
- We want to keep the output within 6 characters. For low values we use
- the format mm:ss. For values that exceed 999:59, we switch to a format
- that displays hours and fractions: hhh.tH. For values that exceed
- 999.9, we use hhhh.t and drop the "H" designator. For values that
- exceed 9999.9, we use "???".
- */
-
-char *format_time(seconds)
-
-long seconds;
-
-{
- register int value;
- register int digit;
- register char *ptr;
- static char result[10];
-
- /* sanity protection */
- if (seconds < 0 || seconds > (99999l * 360l))
- {
- strcpy(result, " ???");
- }
- else if (seconds >= (1000l * 60l))
- {
- /* alternate (slow) method displaying hours and tenths */
- sprintf(result, "%5.1fH", (double)seconds / (double)(60l * 60l));
-
- /* It is possible that the sprintf took more than 6 characters.
- If so, then the "H" appears as result[6]. If not, then there
- is a \0 in result[6]. Either way, it is safe to step on.
- */
- result[6] = '\0';
- }
- else
- {
- /* standard method produces MMM:SS */
- /* we avoid printf as must as possible to make this quick */
- sprintf(result, "%3ld:%02ld",
- (long)(seconds / 60), (long)(seconds % 60));
- }
- return(result);
-}
-
-/*
- * format_k(amt) - format a kilobyte memory value, returning a string
- * suitable for display. Returns a pointer to a static
- * area that changes each call. "amt" is converted to a
- * string with a trailing "K". If "amt" is 10000 or greater,
- * then it is formatted as megabytes (rounded) with a
- * trailing "M".
- */
-
-/*
- * Compromise time. We need to return a string, but we don't want the
- * caller to have to worry about freeing a dynamically allocated string.
- * Unfortunately, we can't just return a pointer to a static area as one
- * of the common uses of this function is in a large call to sprintf where
- * it might get invoked several times. Our compromise is to maintain an
- * array of strings and cycle thru them with each invocation. We make the
- * array large enough to handle the above mentioned case. The constant
- * NUM_STRINGS defines the number of strings in this array: we can tolerate
- * up to NUM_STRINGS calls before we start overwriting old information.
- * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer
- * to convert the modulo operation into something quicker. What a hack!
- */
-
-#define NUM_STRINGS 8
-
-char *format_k(amt)
-
-int amt;
-
-{
- static char retarray[NUM_STRINGS][16];
- static int index = 0;
- register char *p;
- register char *ret;
- register char tag = 'K';
-
- p = ret = retarray[index];
- index = (index + 1) % NUM_STRINGS;
-
- if (amt >= 10000)
- {
- amt = (amt + 512) / 1024;
- tag = 'M';
- if (amt >= 10000)
- {
- amt = (amt + 512) / 1024;
- tag = 'G';
- }
- }
-
- p = strecpy(p, itoa(amt));
- *p++ = tag;
- *p = '\0';
-
- return(ret);
-}
-
-char *format_k2(amt)
-
-unsigned long long amt;
-
-{
- static char retarray[NUM_STRINGS][16];
- static int index = 0;
- register char *p;
- register char *ret;
- register char tag = 'K';
-
- p = ret = retarray[index];
- index = (index + 1) % NUM_STRINGS;
-
- if (amt >= 100000)
- {
- amt = (amt + 512) / 1024;
- tag = 'M';
- if (amt >= 100000)
- {
- amt = (amt + 512) / 1024;
- tag = 'G';
- }
- }
-
- p = strecpy(p, itoa((int)amt));
- *p++ = tag;
- *p = '\0';
-
- return(ret);
-}
Index: head/contrib/top/version.c
===================================================================
--- head/contrib/top/version.c
+++ head/contrib/top/version.c
@@ -1,28 +0,0 @@
-/*
- * Top users/processes display for Unix
- * Version 3
- *
- * This program may be freely redistributed,
- * but this entire comment MUST remain intact.
- *
- * Copyright (c) 1984, 1989, William LeFebvre, Rice University
- * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include "top.h"
-#include "patchlevel.h"
-
-static char version[16];
-
-char *version_string()
-
-{
- sprintf(version, "%d.%d", VERSION, PATCHLEVEL);
-#ifdef BETA
- strcat(version, BETA);
-#endif
- return(version);
-}
Index: head/usr.bin/top/Makefile
===================================================================
--- head/usr.bin/top/Makefile
+++ head/usr.bin/top/Makefile
@@ -1,36 +1,21 @@
# $FreeBSD$
-TOPDIR= ${SRCTOP}/contrib/top
-.PATH: ${TOPDIR}
-
PROG= top
SRCS= commands.c display.c machine.c screen.c top.c \
- username.c utils.c version.c
+ username.c utils.c version.c
SRCS+= sigdesc.h top.local.h
-CFLAGS+= -DHAVE_GETOPT -DHAVE_STRERROR -DORDER
-CFLAGS+= -I${.CURDIR} -I${TOPDIR} -I.
+CFLAGS+= -DHAVE_GETOPT -DHAVE_STRERROR -DORDER -I ${.OBJDIR}
+MAN= top.1
WARNS?= 0
-#
-# The table size should be a prime number approximately twice as
-# large as the number of lines in /etc/passwd. The default number
-# is 20011; use /etc/make.conf to override this.
-#
-.if defined(TOP_TABLE_SIZE)
-CFLAGS+= -D"Table_size=${TOP_TABLE_SIZE}"
-.endif
-
LIBADD= ncursesw m kvm jail
CLEANFILES= sigdesc.h
-SIGCONV_AWK= ${SRCTOP}/contrib/top/sigconv.awk
-STAGED_INCLUDE_DIR?= ${DESTDIR}/usr/include
-SIGNAL_H= ${STAGED_INCLUDE_DIR}/sys/signal.h
-sigdesc.h: ${SIGCONV_AWK} ${SIGNAL_H}
- awk -f ${SIGCONV_AWK} < ${SIGNAL_H} > ${.TARGET}
+SIGNAL_H= ${SRCTOP}/sys/sys/signal.h
+sigdesc.h: sigconv.awk ${SIGNAL_H}
+ awk -f ${SRCTOP}/usr.bin/top/sigconv.awk < ${SIGNAL_H} > ${.TARGET}
-CLEANFILES+= top.local.h top.x
.SUFFIXES: .xs .x .hs .h
.xs.x .hs.h:
@${ECHO} Making ${.TARGET} from ${.IMPSRC}
@@ -41,9 +26,5 @@
-e's,%delay%,2,g' \
-e's,%random%,1,g' \
${.IMPSRC} > ${.TARGET}
-
-CLEANFILES+= top.1
-top.1: top.x top.local.1
- cat ${.ALLSRC} > ${.TARGET}
.include <bsd.prog.mk>
Index: head/usr.bin/top/boolean.h
===================================================================
--- head/usr.bin/top/boolean.h
+++ head/usr.bin/top/boolean.h
@@ -0,0 +1,5 @@
+/* My favorite names for boolean values */
+#define No 0
+#define Yes 1
+#define Maybe 2 /* tri-state boolean, actually */
+
Index: head/usr.bin/top/commands.h
===================================================================
--- head/usr.bin/top/commands.h
+++ head/usr.bin/top/commands.h
@@ -0,0 +1,21 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ * Copyright (c) 2016, Randy Westlund
+ *
+ * $FreeBSD$
+ */
+#ifndef COMMANDS_H
+#define COMMANDS_H
+
+void show_errors(void);
+int error_count(void);
+void show_help(void);
+
+#endif /* COMMANDS_H */
Index: head/usr.bin/top/commands.c
===================================================================
--- head/usr.bin/top/commands.c
+++ head/usr.bin/top/commands.c
@@ -0,0 +1,542 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This file contains the routines that implement some of the interactive
+ * mode commands. Note that some of the commands are implemented in-line
+ * in "main". This is necessary because they change the global state of
+ * "top" (i.e.: changing the number of processes to display).
+ */
+
+#include "os.h"
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "commands.h"
+#include "sigdesc.h" /* generated automatically */
+#include "top.h"
+#include "boolean.h"
+#include "utils.h"
+#include "machine.h"
+
+extern int errno;
+
+extern char *copyright;
+
+/* imported from screen.c */
+extern int overstrike;
+
+int err_compar();
+char *err_string();
+static int str_adderr(char *str, int len, int err);
+static int str_addarg(char *str, int len, char *arg, int first);
+
+/*
+ * show_help() - display the help screen; invoked in response to
+ * either 'h' or '?'.
+ */
+
+void
+show_help()
+
+{
+ printf("Top version %s, %s\n", version_string(), copyright);
+ fputs("\n\n\
+A top users display for Unix\n\
+\n\
+These single-character commands are available:\n\
+\n\
+^L - redraw screen\n\
+q - quit\n\
+h or ? - help; show this text\n", stdout);
+
+ /* not all commands are availalbe with overstrike terminals */
+ if (overstrike)
+ {
+ fputs("\n\
+Other commands are also available, but this terminal is not\n\
+sophisticated enough to handle those commands gracefully.\n\n", stdout);
+ }
+ else
+ {
+ fputs("\
+C - toggle the displaying of weighted CPU percentage\n\
+d - change number of displays to show\n\
+e - list errors generated by last \"kill\" or \"renice\" command\n\
+H - toggle the displaying of threads\n\
+i or I - toggle the displaying of idle processes\n\
+j - toggle the displaying of jail ID\n\
+J - display processes for only one jail (+ selects all jails)\n\
+k - kill processes; send a signal to a list of processes\n\
+m - toggle the display between 'cpu' and 'io' modes\n\
+n or # - change number of processes to display\n", stdout);
+#ifdef ORDER
+ if (displaymode == DISP_CPU)
+ fputs("\
+o - specify sort order (pri, size, res, cpu, time, threads, jid, pid)\n",
+ stdout);
+ else
+ fputs("\
+o - specify sort order (vcsw, ivcsw, read, write, fault, total, jid, pid)\n",
+ stdout);
+#endif
+ fputs("\
+P - toggle the displaying of per-CPU statistics\n\
+r - renice a process\n\
+s - change number of seconds to delay between updates\n\
+S - toggle the displaying of system processes\n\
+a - toggle the displaying of process titles\n\
+t - toggle the display of this process\n\
+u - display processes for only one user (+ selects all users)\n\
+w - toggle the display of swap use for each process\n\
+z - toggle the displaying of the system idle process\n\
+\n\
+\n", stdout);
+ }
+}
+
+/*
+ * Utility routines that help with some of the commands.
+ */
+
+char *next_field(str)
+
+register char *str;
+
+{
+ if ((str = strchr(str, ' ')) == NULL)
+ {
+ return(NULL);
+ }
+ *str = '\0';
+ while (*++str == ' ') /* loop */;
+
+ /* if there is nothing left of the string, return NULL */
+ /* This fix is dedicated to Greg Earle */
+ return(*str == '\0' ? NULL : str);
+}
+
+int
+scanint(str, intp)
+
+char *str;
+int *intp;
+
+{
+ register int val = 0;
+ register char ch;
+
+ /* if there is nothing left of the string, flag it as an error */
+ /* This fix is dedicated to Greg Earle */
+ if (*str == '\0')
+ {
+ return(-1);
+ }
+
+ while ((ch = *str++) != '\0')
+ {
+ if (isdigit(ch))
+ {
+ val = val * 10 + (ch - '0');
+ }
+ else if (isspace(ch))
+ {
+ break;
+ }
+ else
+ {
+ return(-1);
+ }
+ }
+ *intp = val;
+ return(0);
+}
+
+/*
+ * Some of the commands make system calls that could generate errors.
+ * These errors are collected up in an array of structures for later
+ * contemplation and display. Such routines return a string containing an
+ * error message, or NULL if no errors occurred. The next few routines are
+ * for manipulating and displaying these errors. We need an upper limit on
+ * the number of errors, so we arbitrarily choose 20.
+ */
+
+#define ERRMAX 20
+
+struct errs /* structure for a system-call error */
+{
+ int errnum; /* value of errno (that is, the actual error) */
+ char *arg; /* argument that caused the error */
+};
+
+static struct errs errs[ERRMAX];
+static int errcnt;
+static char *err_toomany = " too many errors occurred";
+static char *err_listem =
+ " Many errors occurred. Press `e' to display the list of errors.";
+
+/* These macros get used to reset and log the errors */
+#define ERR_RESET errcnt = 0
+#define ERROR(p, e) if (errcnt >= ERRMAX) \
+ { \
+ return(err_toomany); \
+ } \
+ else \
+ { \
+ errs[errcnt].arg = (p); \
+ errs[errcnt++].errnum = (e); \
+ }
+
+/*
+ * err_string() - return an appropriate error string. This is what the
+ * command will return for displaying. If no errors were logged, then
+ * return NULL. The maximum length of the error string is defined by
+ * "STRMAX".
+ */
+
+#define STRMAX 80
+
+char *err_string()
+
+{
+ register struct errs *errp;
+ register int cnt = 0;
+ register int first = Yes;
+ register int currerr = -1;
+ int stringlen; /* characters still available in "string" */
+ static char string[STRMAX];
+
+ /* if there are no errors, return NULL */
+ if (errcnt == 0)
+ {
+ return(NULL);
+ }
+
+ /* sort the errors */
+ qsort((char *)errs, errcnt, sizeof(struct errs), err_compar);
+
+ /* need a space at the front of the error string */
+ string[0] = ' ';
+ string[1] = '\0';
+ stringlen = STRMAX - 2;
+
+ /* loop thru the sorted list, building an error string */
+ while (cnt < errcnt)
+ {
+ errp = &(errs[cnt++]);
+ if (errp->errnum != currerr)
+ {
+ if (currerr != -1)
+ {
+ if ((stringlen = str_adderr(string, stringlen, currerr)) < 2)
+ {
+ return(err_listem);
+ }
+ (void) strcat(string, "; "); /* we know there's more */
+ }
+ currerr = errp->errnum;
+ first = Yes;
+ }
+ if ((stringlen = str_addarg(string, stringlen, errp->arg, first)) ==0)
+ {
+ return(err_listem);
+ }
+ first = No;
+ }
+
+ /* add final message */
+ stringlen = str_adderr(string, stringlen, currerr);
+
+ /* return the error string */
+ return(stringlen == 0 ? err_listem : string);
+}
+
+/*
+ * str_adderr(str, len, err) - add an explanation of error "err" to
+ * the string "str".
+ */
+
+static int
+str_adderr(str, len, err)
+
+char *str;
+int len;
+int err;
+
+{
+ register char *msg;
+ register int msglen;
+
+ msg = err == 0 ? "Not a number" : errmsg(err);
+ msglen = strlen(msg) + 2;
+ if (len <= msglen)
+ {
+ return(0);
+ }
+ (void) strcat(str, ": ");
+ (void) strcat(str, msg);
+ return(len - msglen);
+}
+
+/*
+ * str_addarg(str, len, arg, first) - add the string argument "arg" to
+ * the string "str". This is the first in the group when "first"
+ * is set (indicating that a comma should NOT be added to the front).
+ */
+
+static int
+str_addarg(str, len, arg, first)
+
+char *str;
+int len;
+char *arg;
+int first;
+
+{
+ register int arglen;
+
+ arglen = strlen(arg);
+ if (!first)
+ {
+ arglen += 2;
+ }
+ if (len <= arglen)
+ {
+ return(0);
+ }
+ if (!first)
+ {
+ (void) strcat(str, ", ");
+ }
+ (void) strcat(str, arg);
+ return(len - arglen);
+}
+
+/*
+ * err_compar(p1, p2) - comparison routine used by "qsort"
+ * for sorting errors.
+ */
+
+int
+err_compar(p1, p2)
+
+register struct errs *p1, *p2;
+
+{
+ register int result;
+
+ if ((result = p1->errnum - p2->errnum) == 0)
+ {
+ return(strcmp(p1->arg, p2->arg));
+ }
+ return(result);
+}
+
+/*
+ * error_count() - return the number of errors currently logged.
+ */
+
+int
+error_count()
+
+{
+ return(errcnt);
+}
+
+/*
+ * show_errors() - display on stdout the current log of errors.
+ */
+
+void
+show_errors()
+
+{
+ register int cnt = 0;
+ register struct errs *errp = errs;
+
+ printf("%d error%s:\n\n", errcnt, errcnt == 1 ? "" : "s");
+ while (cnt++ < errcnt)
+ {
+ printf("%5s: %s\n", errp->arg,
+ errp->errnum == 0 ? "Not a number" : errmsg(errp->errnum));
+ errp++;
+ }
+}
+
+/*
+ * kill_procs(str) - send signals to processes, much like the "kill"
+ * command does; invoked in response to 'k'.
+ */
+
+char *kill_procs(str)
+
+char *str;
+
+{
+ register char *nptr;
+ int signum = SIGTERM; /* default */
+ int procnum;
+ struct sigdesc *sigp;
+ int uid;
+
+ /* reset error array */
+ ERR_RESET;
+
+ /* remember our uid */
+ uid = getuid();
+
+ /* skip over leading white space */
+ while (isspace(*str)) str++;
+
+ if (str[0] == '-')
+ {
+ /* explicit signal specified */
+ if ((nptr = next_field(str)) == NULL)
+ {
+ return(" kill: no processes specified");
+ }
+
+ if (isdigit(str[1]))
+ {
+ (void) scanint(str + 1, &signum);
+ if (signum <= 0 || signum >= NSIG)
+ {
+ return(" invalid signal number");
+ }
+ }
+ else
+ {
+ /* translate the name into a number */
+ for (sigp = sigdesc; sigp->name != NULL; sigp++)
+ {
+ if (strcmp(sigp->name, str + 1) == 0)
+ {
+ signum = sigp->number;
+ break;
+ }
+ }
+
+ /* was it ever found */
+ if (sigp->name == NULL)
+ {
+ return(" bad signal name");
+ }
+ }
+ /* put the new pointer in place */
+ str = nptr;
+ }
+
+ /* loop thru the string, killing processes */
+ do
+ {
+ if (scanint(str, &procnum) == -1)
+ {
+ ERROR(str, 0);
+ }
+ else
+ {
+ /* check process owner if we're not root */
+ if (uid && (uid != proc_owner(procnum)))
+ {
+ ERROR(str, EACCES);
+ }
+ /* go in for the kill */
+ else if (kill(procnum, signum) == -1)
+ {
+ /* chalk up an error */
+ ERROR(str, errno);
+ }
+ }
+ } while ((str = next_field(str)) != NULL);
+
+ /* return appropriate error string */
+ return(err_string());
+}
+
+/*
+ * renice_procs(str) - change the "nice" of processes, much like the
+ * "renice" command does; invoked in response to 'r'.
+ */
+
+char *renice_procs(str)
+
+char *str;
+
+{
+ register char negate;
+ int prio;
+ int procnum;
+ int uid;
+
+ ERR_RESET;
+ uid = getuid();
+
+ /* allow for negative priority values */
+ if ((negate = (*str == '-')) != 0)
+ {
+ /* move past the minus sign */
+ str++;
+ }
+
+ /* use procnum as a temporary holding place and get the number */
+ procnum = scanint(str, &prio);
+
+ /* negate if necessary */
+ if (negate)
+ {
+ prio = -prio;
+ }
+
+#if defined(PRIO_MIN) && defined(PRIO_MAX)
+ /* check for validity */
+ if (procnum == -1 || prio < PRIO_MIN || prio > PRIO_MAX)
+ {
+ return(" bad priority value");
+ }
+#endif
+
+ /* move to the first process number */
+ if ((str = next_field(str)) == NULL)
+ {
+ return(" no processes specified");
+ }
+
+ /* loop thru the process numbers, renicing each one */
+ do
+ {
+ if (scanint(str, &procnum) == -1)
+ {
+ ERROR(str, 0);
+ }
+
+ /* check process owner if we're not root */
+ else if (uid && (uid != proc_owner(procnum)))
+ {
+ ERROR(str, EACCES);
+ }
+ else if (setpriority(PRIO_PROCESS, procnum, prio) == -1)
+ {
+ ERROR(str, errno);
+ }
+ } while ((str = next_field(str)) != NULL);
+
+ /* return appropriate error string */
+ return(err_string());
+}
+
Index: head/usr.bin/top/display.h
===================================================================
--- head/usr.bin/top/display.h
+++ head/usr.bin/top/display.h
@@ -0,0 +1,43 @@
+/* constants needed for display.c */
+
+/* "type" argument for new_message function */
+
+#define MT_standout 1
+#define MT_delayed 2
+
+#include "machine.h"
+
+int display_updatecpus(struct statics *statics);
+void clear_message(void);
+int display_resize(void);
+void i_header(char *text);
+char *printable(char *string);
+char *cpustates_tag(void);
+void display_header(int t);
+int display_init(struct statics *statics);
+void i_arc(int *stats);
+void i_carc(int *stats);
+void i_cpustates(int *states);
+void i_loadave(int mpid, double *avenrun);
+void i_memory(int *stats);
+void i_message(void);
+void i_process(int line, char *thisline);
+void i_procstates(int total, int *brkdn);
+void i_swap(int *stats);
+void i_timeofday(time_t *tod);
+void i_uptime(struct timeval *bt, time_t *tod);
+void new_message();
+int readline(char *buffer, int size, int numeric);
+char *trim_header(char *text);
+void u_arc(int *stats);
+void u_carc(int *stats);
+void u_cpustates(int *states);
+void u_endscreen(int hi);
+void u_header(char *text);
+void u_loadave(int mpid, double *avenrun);
+void u_memory(int *stats);
+void u_message(void);
+void u_process(int line, char *newline);
+void u_procstates(int total, int *brkdn);
+void u_swap(int *stats);
+void z_cpustates(void);
Index: head/usr.bin/top/display.c
===================================================================
--- head/usr.bin/top/display.c
+++ head/usr.bin/top/display.c
@@ -0,0 +1,1455 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This file contains the routines that display information on the screen.
+ * Each section of the screen has two routines: one for initially writing
+ * all constant and dynamic text, and one for only updating the text that
+ * changes. The prefix "i_" is used on all the "initial" routines and the
+ * prefix "u_" is used for all the "updating" routines.
+ *
+ * ASSUMPTIONS:
+ * None of the "i_" routines use any of the termcap capabilities.
+ * In this way, those routines can be safely used on terminals that
+ * have minimal (or nonexistant) terminal capabilities.
+ *
+ * The routines are called in this order: *_loadave, i_timeofday,
+ * *_procstates, *_cpustates, *_memory, *_message, *_header,
+ * *_process, u_endscreen.
+ */
+
+#include "os.h"
+
+#include <sys/time.h>
+
+#include <curses.h>
+#include <ctype.h>
+#include <termcap.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "screen.h" /* interface to screen package */
+#include "layout.h" /* defines for screen position layout */
+#include "display.h"
+#include "top.h"
+#include "top.local.h"
+#include "boolean.h"
+#include "machine.h" /* we should eliminate this!!! */
+#include "utils.h"
+
+#ifdef DEBUG
+FILE *debug;
+#endif
+
+/* imported from screen.c */
+extern int overstrike;
+
+static int lmpid = 0;
+static int last_hi = 0; /* used in u_process and u_endscreen */
+static int lastline = 0;
+static int display_width = MAX_COLS;
+
+#define lineindex(l) ((l)*display_width)
+
+
+/* things initialized by display_init and used thruout */
+
+/* buffer of proc information lines for display updating */
+char *screenbuf = NULL;
+
+static char **procstate_names;
+static char **cpustate_names;
+static char **memory_names;
+static char **arc_names;
+static char **carc_names;
+static char **swap_names;
+
+static int num_procstates;
+static int num_cpustates;
+static int num_memory;
+static int num_swap;
+
+static int *lprocstates;
+static int *lcpustates;
+static int *lmemory;
+static int *lswap;
+
+static int num_cpus;
+static int *cpustate_columns;
+static int cpustate_total_length;
+static int cpustates_column;
+
+static enum { OFF, ON, ERASE } header_status = ON;
+
+static int string_count();
+static void summary_format();
+static void line_update();
+
+int x_lastpid = 10;
+int y_lastpid = 0;
+int x_loadave = 33;
+int x_loadave_nompid = 15;
+int y_loadave = 0;
+int x_procstate = 0;
+int y_procstate = 1;
+int x_brkdn = 15;
+int y_brkdn = 1;
+int x_mem = 5;
+int y_mem = 3;
+int x_arc = 5;
+int y_arc = 4;
+int x_carc = 5;
+int y_carc = 5;
+int x_swap = 6;
+int y_swap = 4;
+int y_message = 5;
+int x_header = 0;
+int y_header = 6;
+int x_idlecursor = 0;
+int y_idlecursor = 5;
+int y_procs = 7;
+
+int y_cpustates = 2;
+int Header_lines = 7;
+
+int display_resize()
+
+{
+ register int lines;
+
+ /* first, deallocate any previous buffer that may have been there */
+ if (screenbuf != NULL)
+ {
+ free(screenbuf);
+ }
+
+ /* calculate the current dimensions */
+ /* if operating in "dumb" mode, we only need one line */
+ lines = smart_terminal ? screen_length - Header_lines : 1;
+
+ if (lines < 0)
+ lines = 0;
+ /* we don't want more than MAX_COLS columns, since the machine-dependent
+ modules make static allocations based on MAX_COLS and we don't want
+ to run off the end of their buffers */
+ display_width = screen_width;
+ if (display_width >= MAX_COLS)
+ {
+ display_width = MAX_COLS - 1;
+ }
+
+ /* now, allocate space for the screen buffer */
+ screenbuf = (char *)malloc(lines * display_width);
+ if (screenbuf == (char *)NULL)
+ {
+ /* oops! */
+ return(-1);
+ }
+
+ /* return number of lines available */
+ /* for dumb terminals, pretend like we can show any amount */
+ return(smart_terminal ? lines : Largest);
+}
+
+int display_updatecpus(statics)
+
+struct statics *statics;
+
+{
+ register int *lp;
+ register int lines;
+ register int i;
+
+ /* call resize to do the dirty work */
+ lines = display_resize();
+ if (pcpu_stats)
+ num_cpus = statics->ncpus;
+ else
+ num_cpus = 1;
+ cpustates_column = 5; /* CPU: */
+ if (num_cpus != 1)
+ cpustates_column += 2; /* CPU 0: */
+ for (i = num_cpus; i > 9; i /= 10)
+ cpustates_column++;
+
+ /* fill the "last" array with all -1s, to insure correct updating */
+ lp = lcpustates;
+ i = num_cpustates * num_cpus;
+ while (--i >= 0)
+ {
+ *lp++ = -1;
+ }
+
+ return(lines);
+}
+
+int display_init(statics)
+
+struct statics *statics;
+
+{
+ register int lines;
+ register char **pp;
+ register int *ip;
+ register int i;
+
+ lines = display_updatecpus(statics);
+
+ /* only do the rest if we need to */
+ if (lines > -1)
+ {
+ /* save pointers and allocate space for names */
+ procstate_names = statics->procstate_names;
+ num_procstates = string_count(procstate_names);
+ lprocstates = (int *)malloc(num_procstates * sizeof(int));
+
+ cpustate_names = statics->cpustate_names;
+
+ swap_names = statics->swap_names;
+ num_swap = string_count(swap_names);
+ lswap = (int *)malloc(num_swap * sizeof(int));
+ num_cpustates = string_count(cpustate_names);
+ lcpustates = (int *)malloc(num_cpustates * sizeof(int) * statics->ncpus);
+ cpustate_columns = (int *)malloc(num_cpustates * sizeof(int));
+
+ memory_names = statics->memory_names;
+ num_memory = string_count(memory_names);
+ lmemory = (int *)malloc(num_memory * sizeof(int));
+
+ arc_names = statics->arc_names;
+ carc_names = statics->carc_names;
+
+ /* calculate starting columns where needed */
+ cpustate_total_length = 0;
+ pp = cpustate_names;
+ ip = cpustate_columns;
+ while (*pp != NULL)
+ {
+ *ip++ = cpustate_total_length;
+ if ((i = strlen(*pp++)) > 0)
+ {
+ cpustate_total_length += i + 8;
+ }
+ }
+ }
+
+ /* return number of lines available */
+ return(lines);
+}
+
+void
+i_loadave(mpid, avenrun)
+
+int mpid;
+double *avenrun;
+
+{
+ register int i;
+
+ /* i_loadave also clears the screen, since it is first */
+ top_clear();
+
+ /* mpid == -1 implies this system doesn't have an _mpid */
+ if (mpid != -1)
+ {
+ printf("last pid: %5d; ", mpid);
+ }
+
+ printf("load averages");
+
+ for (i = 0; i < 3; i++)
+ {
+ printf("%c %5.2f",
+ i == 0 ? ':' : ',',
+ avenrun[i]);
+ }
+ lmpid = mpid;
+}
+
+void
+u_loadave(mpid, avenrun)
+
+int mpid;
+double *avenrun;
+
+{
+ register int i;
+
+ if (mpid != -1)
+ {
+ /* change screen only when value has really changed */
+ if (mpid != lmpid)
+ {
+ Move_to(x_lastpid, y_lastpid);
+ printf("%5d", mpid);
+ lmpid = mpid;
+ }
+
+ /* i remembers x coordinate to move to */
+ i = x_loadave;
+ }
+ else
+ {
+ i = x_loadave_nompid;
+ }
+
+ /* move into position for load averages */
+ Move_to(i, y_loadave);
+
+ /* display new load averages */
+ /* we should optimize this and only display changes */
+ for (i = 0; i < 3; i++)
+ {
+ printf("%s%5.2f",
+ i == 0 ? "" : ", ",
+ avenrun[i]);
+ }
+}
+
+void
+i_timeofday(tod)
+
+time_t *tod;
+
+{
+ /*
+ * Display the current time.
+ * "ctime" always returns a string that looks like this:
+ *
+ * Sun Sep 16 01:03:52 1973
+ * 012345678901234567890123
+ * 1 2
+ *
+ * We want indices 11 thru 18 (length 8).
+ */
+
+ if (smart_terminal)
+ {
+ Move_to(screen_width - 8, 0);
+ }
+ else
+ {
+ fputs(" ", stdout);
+ }
+#ifdef DEBUG
+ {
+ char *foo;
+ foo = ctime(tod);
+ fputs(foo, stdout);
+ }
+#endif
+ printf("%-8.8s\n", &(ctime(tod)[11]));
+ lastline = 1;
+}
+
+static int ltotal = 0;
+static char procstates_buffer[MAX_COLS];
+
+/*
+ * *_procstates(total, brkdn, names) - print the process summary line
+ *
+ * Assumptions: cursor is at the beginning of the line on entry
+ * lastline is valid
+ */
+
+void
+i_procstates(total, brkdn)
+
+int total;
+int *brkdn;
+
+{
+ register int i;
+
+ /* write current number of processes and remember the value */
+ printf("%d processes:", total);
+ ltotal = total;
+
+ /* put out enough spaces to get to column 15 */
+ i = digits(total);
+ while (i++ < 4)
+ {
+ putchar(' ');
+ }
+
+ /* format and print the process state summary */
+ summary_format(procstates_buffer, brkdn, procstate_names);
+ fputs(procstates_buffer, stdout);
+
+ /* save the numbers for next time */
+ memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
+}
+
+void
+u_procstates(total, brkdn)
+
+int total;
+int *brkdn;
+
+{
+ static char new[MAX_COLS];
+ register int i;
+
+ /* update number of processes only if it has changed */
+ if (ltotal != total)
+ {
+ /* move and overwrite */
+#if (x_procstate == 0)
+ Move_to(x_procstate, y_procstate);
+#else
+ /* cursor is already there...no motion needed */
+ /* assert(lastline == 1); */
+#endif
+ printf("%d", total);
+
+ /* if number of digits differs, rewrite the label */
+ if (digits(total) != digits(ltotal))
+ {
+ fputs(" processes:", stdout);
+ /* put out enough spaces to get to column 15 */
+ i = digits(total);
+ while (i++ < 4)
+ {
+ putchar(' ');
+ }
+ /* cursor may end up right where we want it!!! */
+ }
+
+ /* save new total */
+ ltotal = total;
+ }
+
+ /* see if any of the state numbers has changed */
+ if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
+ {
+ /* format and update the line */
+ summary_format(new, brkdn, procstate_names);
+ line_update(procstates_buffer, new, x_brkdn, y_brkdn);
+ memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
+ }
+}
+
+#ifdef no_more
+/*
+ * *_cpustates(states, names) - print the cpu state percentages
+ *
+ * Assumptions: cursor is on the PREVIOUS line
+ */
+
+/* cpustates_tag() calculates the correct tag to use to label the line */
+
+char *cpustates_tag()
+
+{
+ register char *use;
+
+ static char *short_tag = "CPU: ";
+ static char *long_tag = "CPU states: ";
+
+ /* if length + strlen(long_tag) >= screen_width, then we have to
+ use the shorter tag (we subtract 2 to account for ": ") */
+ if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width)
+ {
+ use = short_tag;
+ }
+ else
+ {
+ use = long_tag;
+ }
+
+ /* set cpustates_column accordingly then return result */
+ cpustates_column = strlen(use);
+ return(use);
+}
+#endif
+
+void
+i_cpustates(states)
+
+int *states;
+
+{
+ register int i = 0;
+ register int value;
+ register char **names;
+ register char *thisname;
+ int cpu;
+
+for (cpu = 0; cpu < num_cpus; cpu++) {
+ names = cpustate_names;
+
+ /* print tag and bump lastline */
+ if (num_cpus == 1)
+ printf("\nCPU: ");
+ else {
+ value = printf("\nCPU %d: ", cpu);
+ while (value++ <= cpustates_column)
+ printf(" ");
+ }
+ lastline++;
+
+ /* now walk thru the names and print the line */
+ while ((thisname = *names++) != NULL)
+ {
+ if (*thisname != '\0')
+ {
+ /* retrieve the value and remember it */
+ value = *states++;
+
+ /* if percentage is >= 1000, print it as 100% */
+ printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
+ (i++ % num_cpustates) == 0 ? "" : ", ",
+ ((float)value)/10.,
+ thisname);
+ }
+ }
+}
+
+ /* copy over values into "last" array */
+ memcpy(lcpustates, states, num_cpustates * sizeof(int) * num_cpus);
+}
+
+void
+u_cpustates(states)
+
+int *states;
+
+{
+ register int value;
+ register char **names;
+ register char *thisname;
+ register int *lp;
+ register int *colp;
+ int cpu;
+
+for (cpu = 0; cpu < num_cpus; cpu++) {
+ names = cpustate_names;
+
+ Move_to(cpustates_column, y_cpustates + cpu);
+ lastline = y_cpustates + cpu;
+ lp = lcpustates + (cpu * num_cpustates);
+ colp = cpustate_columns;
+
+ /* we could be much more optimal about this */
+ while ((thisname = *names++) != NULL)
+ {
+ if (*thisname != '\0')
+ {
+ /* did the value change since last time? */
+ if (*lp != *states)
+ {
+ /* yes, move and change */
+ Move_to(cpustates_column + *colp, y_cpustates + cpu);
+ lastline = y_cpustates + cpu;
+
+ /* retrieve value and remember it */
+ value = *states;
+
+ /* if percentage is >= 1000, print it as 100% */
+ printf((value >= 1000 ? "%4.0f" : "%4.1f"),
+ ((double)value)/10.);
+
+ /* remember it for next time */
+ *lp = value;
+ }
+ }
+
+ /* increment and move on */
+ lp++;
+ states++;
+ colp++;
+ }
+}
+}
+
+void
+z_cpustates()
+
+{
+ register int i = 0;
+ register char **names;
+ register char *thisname;
+ register int *lp;
+ int cpu, value;
+
+for (cpu = 0; cpu < num_cpus; cpu++) {
+ names = cpustate_names;
+
+ /* show tag and bump lastline */
+ if (num_cpus == 1)
+ printf("\nCPU: ");
+ else {
+ value = printf("\nCPU %d: ", cpu);
+ while (value++ <= cpustates_column)
+ printf(" ");
+ }
+ lastline++;
+
+ while ((thisname = *names++) != NULL)
+ {
+ if (*thisname != '\0')
+ {
+ printf("%s %% %s", (i++ % num_cpustates) == 0 ? "" : ", ", thisname);
+ }
+ }
+}
+
+ /* fill the "last" array with all -1s, to insure correct updating */
+ lp = lcpustates;
+ i = num_cpustates * num_cpus;
+ while (--i >= 0)
+ {
+ *lp++ = -1;
+ }
+}
+
+/*
+ * *_memory(stats) - print "Memory: " followed by the memory summary string
+ *
+ * Assumptions: cursor is on "lastline"
+ * for i_memory ONLY: cursor is on the previous line
+ */
+
+char memory_buffer[MAX_COLS];
+
+void
+i_memory(stats)
+
+int *stats;
+
+{
+ fputs("\nMem: ", stdout);
+ lastline++;
+
+ /* format and print the memory summary */
+ summary_format(memory_buffer, stats, memory_names);
+ fputs(memory_buffer, stdout);
+}
+
+void
+u_memory(stats)
+
+int *stats;
+
+{
+ static char new[MAX_COLS];
+
+ /* format the new line */
+ summary_format(new, stats, memory_names);
+ line_update(memory_buffer, new, x_mem, y_mem);
+}
+
+/*
+ * *_arc(stats) - print "ARC: " followed by the ARC summary string
+ *
+ * Assumptions: cursor is on "lastline"
+ * for i_arc ONLY: cursor is on the previous line
+ */
+char arc_buffer[MAX_COLS];
+
+void
+i_arc(stats)
+
+int *stats;
+
+{
+ if (arc_names == NULL)
+ return;
+
+ fputs("\nARC: ", stdout);
+ lastline++;
+
+ /* format and print the memory summary */
+ summary_format(arc_buffer, stats, arc_names);
+ fputs(arc_buffer, stdout);
+}
+
+void
+u_arc(stats)
+
+int *stats;
+
+{
+ static char new[MAX_COLS];
+
+ if (arc_names == NULL)
+ return;
+
+ /* format the new line */
+ summary_format(new, stats, arc_names);
+ line_update(arc_buffer, new, x_arc, y_arc);
+}
+
+
+/*
+ * *_carc(stats) - print "Compressed ARC: " followed by the summary string
+ *
+ * Assumptions: cursor is on "lastline"
+ * for i_carc ONLY: cursor is on the previous line
+ */
+char carc_buffer[MAX_COLS];
+
+void
+i_carc(stats)
+
+int *stats;
+
+{
+ if (carc_names == NULL)
+ return;
+
+ fputs("\n ", stdout);
+ lastline++;
+
+ /* format and print the memory summary */
+ summary_format(carc_buffer, stats, carc_names);
+ fputs(carc_buffer, stdout);
+}
+
+void
+u_carc(stats)
+
+int *stats;
+
+{
+ static char new[MAX_COLS];
+
+ if (carc_names == NULL)
+ return;
+
+ /* format the new line */
+ summary_format(new, stats, carc_names);
+ line_update(carc_buffer, new, x_carc, y_carc);
+}
+
+/*
+ * *_swap(stats) - print "Swap: " followed by the swap summary string
+ *
+ * Assumptions: cursor is on "lastline"
+ * for i_swap ONLY: cursor is on the previous line
+ */
+
+char swap_buffer[MAX_COLS];
+
+void
+i_swap(stats)
+
+int *stats;
+
+{
+ fputs("\nSwap: ", stdout);
+ lastline++;
+
+ /* format and print the swap summary */
+ summary_format(swap_buffer, stats, swap_names);
+ fputs(swap_buffer, stdout);
+}
+
+void
+u_swap(stats)
+
+int *stats;
+
+{
+ static char new[MAX_COLS];
+
+ /* format the new line */
+ summary_format(new, stats, swap_names);
+ line_update(swap_buffer, new, x_swap, y_swap);
+}
+
+/*
+ * *_message() - print the next pending message line, or erase the one
+ * that is there.
+ *
+ * Note that u_message is (currently) the same as i_message.
+ *
+ * Assumptions: lastline is consistent
+ */
+
+/*
+ * i_message is funny because it gets its message asynchronously (with
+ * respect to screen updates).
+ */
+
+static char next_msg[MAX_COLS + 5];
+static int msglen = 0;
+/* Invariant: msglen is always the length of the message currently displayed
+ on the screen (even when next_msg doesn't contain that message). */
+
+void
+i_message()
+
+{
+ while (lastline < y_message)
+ {
+ fputc('\n', stdout);
+ lastline++;
+ }
+ if (next_msg[0] != '\0')
+ {
+ top_standout(next_msg);
+ msglen = strlen(next_msg);
+ next_msg[0] = '\0';
+ }
+ else if (msglen > 0)
+ {
+ (void) clear_eol(msglen);
+ msglen = 0;
+ }
+}
+
+void
+u_message()
+
+{
+ i_message();
+}
+
+static int header_length;
+
+/*
+ * Trim a header string to the current display width and return a newly
+ * allocated area with the trimmed header.
+ */
+
+char *
+trim_header(text)
+
+char *text;
+
+{
+ char *s;
+ int width;
+
+ s = NULL;
+ width = display_width;
+ header_length = strlen(text);
+ if (header_length >= width) {
+ s = malloc((width + 1) * sizeof(char));
+ if (s == NULL)
+ return (NULL);
+ strncpy(s, text, width);
+ s[width] = '\0';
+ }
+ return (s);
+}
+
+/*
+ * *_header(text) - print the header for the process area
+ *
+ * Assumptions: cursor is on the previous line and lastline is consistent
+ */
+
+void
+i_header(text)
+
+char *text;
+
+{
+ char *s;
+
+ s = trim_header(text);
+ if (s != NULL)
+ text = s;
+
+ if (header_status == ON)
+ {
+ putchar('\n');
+ fputs(text, stdout);
+ lastline++;
+ }
+ else if (header_status == ERASE)
+ {
+ header_status = OFF;
+ }
+ free(s);
+}
+
+/*ARGSUSED*/
+void
+u_header(text)
+
+char *text __unused; /* ignored */
+
+{
+
+ if (header_status == ERASE)
+ {
+ putchar('\n');
+ lastline++;
+ clear_eol(header_length);
+ header_status = OFF;
+ }
+}
+
+/*
+ * *_process(line, thisline) - print one process line
+ *
+ * Assumptions: lastline is consistent
+ */
+
+void
+i_process(line, thisline)
+
+int line;
+char *thisline;
+
+{
+ register char *p;
+ register char *base;
+
+ /* make sure we are on the correct line */
+ while (lastline < y_procs + line)
+ {
+ putchar('\n');
+ lastline++;
+ }
+
+ /* truncate the line to conform to our current screen width */
+ thisline[display_width] = '\0';
+
+ /* write the line out */
+ fputs(thisline, stdout);
+
+ /* copy it in to our buffer */
+ base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;
+ p = strecpy(base, thisline);
+
+ /* zero fill the rest of it */
+ memzero(p, display_width - (p - base));
+}
+
+void
+u_process(line, newline)
+
+int line;
+char *newline;
+
+{
+ register char *optr;
+ register int screen_line = line + Header_lines;
+ register char *bufferline;
+
+ /* remember a pointer to the current line in the screen buffer */
+ bufferline = &screenbuf[lineindex(line)];
+
+ /* truncate the line to conform to our current screen width */
+ newline[display_width] = '\0';
+
+ /* is line higher than we went on the last display? */
+ if (line >= last_hi)
+ {
+ /* yes, just ignore screenbuf and write it out directly */
+ /* get positioned on the correct line */
+ if (screen_line - lastline == 1)
+ {
+ putchar('\n');
+ lastline++;
+ }
+ else
+ {
+ Move_to(0, screen_line);
+ lastline = screen_line;
+ }
+
+ /* now write the line */
+ fputs(newline, stdout);
+
+ /* copy it in to the buffer */
+ optr = strecpy(bufferline, newline);
+
+ /* zero fill the rest of it */
+ memzero(optr, display_width - (optr - bufferline));
+ }
+ else
+ {
+ line_update(bufferline, newline, 0, line + Header_lines);
+ }
+}
+
+void
+u_endscreen(hi)
+
+int hi;
+
+{
+ register int screen_line = hi + Header_lines;
+ register int i;
+
+ if (smart_terminal)
+ {
+ if (hi < last_hi)
+ {
+ /* need to blank the remainder of the screen */
+ /* but only if there is any screen left below this line */
+ if (lastline + 1 < screen_length)
+ {
+ /* efficiently move to the end of currently displayed info */
+ if (screen_line - lastline < 5)
+ {
+ while (lastline < screen_line)
+ {
+ putchar('\n');
+ lastline++;
+ }
+ }
+ else
+ {
+ Move_to(0, screen_line);
+ lastline = screen_line;
+ }
+
+ if (clear_to_end)
+ {
+ /* we can do this the easy way */
+ putcap(clear_to_end);
+ }
+ else
+ {
+ /* use clear_eol on each line */
+ i = hi;
+ while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi)
+ {
+ putchar('\n');
+ }
+ }
+ }
+ }
+ last_hi = hi;
+
+ /* move the cursor to a pleasant place */
+ Move_to(x_idlecursor, y_idlecursor);
+ lastline = y_idlecursor;
+ }
+ else
+ {
+ /* separate this display from the next with some vertical room */
+ fputs("\n\n", stdout);
+ }
+}
+
+void
+display_header(t)
+
+int t;
+
+{
+ if (t)
+ {
+ header_status = ON;
+ }
+ else if (header_status == ON)
+ {
+ header_status = ERASE;
+ }
+}
+
+/*VARARGS2*/
+void
+new_message(type, msgfmt, a1, a2, a3)
+
+int type;
+char *msgfmt;
+caddr_t a1, a2, a3;
+
+{
+ register int i;
+
+ /* first, format the message */
+ (void) snprintf(next_msg, sizeof(next_msg), msgfmt, a1, a2, a3);
+
+ if (msglen > 0)
+ {
+ /* message there already -- can we clear it? */
+ if (!overstrike)
+ {
+ /* yes -- write it and clear to end */
+ i = strlen(next_msg);
+ if ((type & MT_delayed) == 0)
+ {
+ type & MT_standout ? top_standout(next_msg) :
+ fputs(next_msg, stdout);
+ (void) clear_eol(msglen - i);
+ msglen = i;
+ next_msg[0] = '\0';
+ }
+ }
+ }
+ else
+ {
+ if ((type & MT_delayed) == 0)
+ {
+ type & MT_standout ? top_standout(next_msg) : fputs(next_msg, stdout);
+ msglen = strlen(next_msg);
+ next_msg[0] = '\0';
+ }
+ }
+}
+
+void
+clear_message()
+
+{
+ if (clear_eol(msglen) == 1)
+ {
+ putchar('\r');
+ }
+}
+
+int
+readline(buffer, size, numeric)
+
+char *buffer;
+int size;
+int numeric;
+
+{
+ register char *ptr = buffer;
+ register char ch;
+ register char cnt = 0;
+ register char maxcnt = 0;
+
+ /* allow room for null terminator */
+ size -= 1;
+
+ /* read loop */
+ while ((fflush(stdout), read(0, ptr, 1) > 0))
+ {
+ /* newline means we are done */
+ if ((ch = *ptr) == '\n' || ch == '\r')
+ {
+ break;
+ }
+
+ /* handle special editing characters */
+ if (ch == ch_kill)
+ {
+ /* kill line -- account for overstriking */
+ if (overstrike)
+ {
+ msglen += maxcnt;
+ }
+
+ /* return null string */
+ *buffer = '\0';
+ putchar('\r');
+ return(-1);
+ }
+ else if (ch == ch_erase)
+ {
+ /* erase previous character */
+ if (cnt <= 0)
+ {
+ /* none to erase! */
+ putchar('\7');
+ }
+ else
+ {
+ fputs("\b \b", stdout);
+ ptr--;
+ cnt--;
+ }
+ }
+ /* check for character validity and buffer overflow */
+ else if (cnt == size || (numeric && !isdigit(ch)) ||
+ !isprint(ch))
+ {
+ /* not legal */
+ putchar('\7');
+ }
+ else
+ {
+ /* echo it and store it in the buffer */
+ putchar(ch);
+ ptr++;
+ cnt++;
+ if (cnt > maxcnt)
+ {
+ maxcnt = cnt;
+ }
+ }
+ }
+
+ /* all done -- null terminate the string */
+ *ptr = '\0';
+
+ /* account for the extra characters in the message area */
+ /* (if terminal overstrikes, remember the furthest they went) */
+ msglen += overstrike ? maxcnt : cnt;
+
+ /* return either inputted number or string length */
+ putchar('\r');
+ return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
+}
+
+/* internal support routines */
+
+static int string_count(pp)
+
+register char **pp;
+
+{
+ register int cnt;
+
+ cnt = 0;
+ while (*pp++ != NULL)
+ {
+ cnt++;
+ }
+ return(cnt);
+}
+
+static void summary_format(str, numbers, names)
+
+char *str;
+int *numbers;
+register char **names;
+
+{
+ register char *p;
+ register int num;
+ register char *thisname;
+ register int useM = No;
+ char rbuf[6];
+
+ /* format each number followed by its string */
+ p = str;
+ while ((thisname = *names++) != NULL)
+ {
+ /* get the number to format */
+ num = *numbers++;
+
+ /* display only non-zero numbers */
+ if (num > 0)
+ {
+ /* is this number in kilobytes? */
+ if (thisname[0] == 'K')
+ {
+ /* yes: format it as a memory value */
+ p = strecpy(p, format_k(num));
+
+ /* skip over the K, since it was included by format_k */
+ p = strecpy(p, thisname+1);
+ }
+ /* is this number a ratio? */
+ else if (thisname[0] == ':')
+ {
+ (void) snprintf(rbuf, sizeof(rbuf), "%.2f",
+ (float)*(numbers - 2) / (float)num);
+ p = strecpy(p, rbuf);
+ p = strecpy(p, thisname);
+ }
+ else
+ {
+ p = strecpy(p, itoa(num));
+ p = strecpy(p, thisname);
+ }
+ }
+
+ /* ignore negative numbers, but display corresponding string */
+ else if (num < 0)
+ {
+ p = strecpy(p, thisname);
+ }
+ }
+
+ /* if the last two characters in the string are ", ", delete them */
+ p -= 2;
+ if (p >= str && p[0] == ',' && p[1] == ' ')
+ {
+ *p = '\0';
+ }
+}
+
+static void line_update(old, new, start, line)
+
+register char *old;
+register char *new;
+int start;
+int line;
+
+{
+ register int ch;
+ register int diff;
+ register int newcol = start + 1;
+ register int lastcol = start;
+ char cursor_on_line = No;
+ char *current;
+
+ /* compare the two strings and only rewrite what has changed */
+ current = old;
+#ifdef DEBUG
+ fprintf(debug, "line_update, starting at %d\n", start);
+ fputs(old, debug);
+ fputc('\n', debug);
+ fputs(new, debug);
+ fputs("\n-\n", debug);
+#endif
+
+ /* start things off on the right foot */
+ /* this is to make sure the invariants get set up right */
+ if ((ch = *new++) != *old)
+ {
+ if (line - lastline == 1 && start == 0)
+ {
+ putchar('\n');
+ }
+ else
+ {
+ Move_to(start, line);
+ }
+ cursor_on_line = Yes;
+ putchar(ch);
+ *old = ch;
+ lastcol = 1;
+ }
+ old++;
+
+ /*
+ * main loop -- check each character. If the old and new aren't the
+ * same, then update the display. When the distance from the
+ * current cursor position to the new change is small enough,
+ * the characters that belong there are written to move the
+ * cursor over.
+ *
+ * Invariants:
+ * lastcol is the column where the cursor currently is sitting
+ * (always one beyond the end of the last mismatch).
+ */
+ do /* yes, a do...while */
+ {
+ if ((ch = *new++) != *old)
+ {
+ /* new character is different from old */
+ /* make sure the cursor is on top of this character */
+ diff = newcol - lastcol;
+ if (diff > 0)
+ {
+ /* some motion is required--figure out which is shorter */
+ if (diff < 6 && cursor_on_line)
+ {
+ /* overwrite old stuff--get it out of the old buffer */
+ printf("%.*s", diff, &current[lastcol-start]);
+ }
+ else
+ {
+ /* use cursor addressing */
+ Move_to(newcol, line);
+ cursor_on_line = Yes;
+ }
+ /* remember where the cursor is */
+ lastcol = newcol + 1;
+ }
+ else
+ {
+ /* already there, update position */
+ lastcol++;
+ }
+
+ /* write what we need to */
+ if (ch == '\0')
+ {
+ /* at the end--terminate with a clear-to-end-of-line */
+ (void) clear_eol(strlen(old));
+ }
+ else
+ {
+ /* write the new character */
+ putchar(ch);
+ }
+ /* put the new character in the screen buffer */
+ *old = ch;
+ }
+
+ /* update working column and screen buffer pointer */
+ newcol++;
+ old++;
+
+ } while (ch != '\0');
+
+ /* zero out the rest of the line buffer -- MUST BE DONE! */
+ diff = display_width - newcol;
+ if (diff > 0)
+ {
+ memzero(old, diff);
+ }
+
+ /* remember where the current line is */
+ if (cursor_on_line)
+ {
+ lastline = line;
+ }
+}
+
+/*
+ * printable(str) - make the string pointed to by "str" into one that is
+ * printable (i.e.: all ascii), by converting all non-printable
+ * characters into '?'. Replacements are done in place and a pointer
+ * to the original buffer is returned.
+ */
+
+char *printable(str)
+
+char *str;
+
+{
+ register char *ptr;
+ register char ch;
+
+ ptr = str;
+ while ((ch = *ptr) != '\0')
+ {
+ if (!isprint(ch))
+ {
+ *ptr = '?';
+ }
+ ptr++;
+ }
+ return(str);
+}
+
+void
+i_uptime(bt, tod)
+
+struct timeval* bt;
+time_t *tod;
+
+{
+ time_t uptime;
+ int days, hrs, mins, secs;
+
+ if (bt->tv_sec != -1) {
+ uptime = *tod - bt->tv_sec;
+ days = uptime / 86400;
+ uptime %= 86400;
+ hrs = uptime / 3600;
+ uptime %= 3600;
+ mins = uptime / 60;
+ secs = uptime % 60;
+
+ /*
+ * Display the uptime.
+ */
+
+ if (smart_terminal)
+ {
+ Move_to((screen_width - 24) - (days > 9 ? 1 : 0), 0);
+ }
+ else
+ {
+ fputs(" ", stdout);
+ }
+ printf(" up %d+%02d:%02d:%02d", days, hrs, mins, secs);
+ }
+}
Index: head/usr.bin/top/getopt.c
===================================================================
--- head/usr.bin/top/getopt.c
+++ head/usr.bin/top/getopt.c
@@ -0,0 +1,90 @@
+/*
+ * "getopt" routine customized for top.
+ */
+
+/*
+ * Many modern-day Unix implementations already have this function
+ * in libc. The standard "getopt" is perfectly sufficient for top's
+ * needs. If such a function exists in libc then you certainly don't
+ * need to compile this one in. To prevent this function from being
+ * compiled, define "HAVE_GETOPT". This is usually done in the "CFLAGS"
+ * line of the corresponding machine module.
+ */
+
+/*
+ * This empty declaration exists solely to placate overexhuberant C
+ * compilers that like to warn you about content-free files.
+ */
+static void __empty();
+
+#ifndef HAVE_GETOPT
+
+/*LINTLIBRARY*/
+
+#include "os.h"
+#ifndef NULL
+#define NULL 0
+#endif
+#ifndef EOF
+#define EOF (-1)
+#endif
+#define ERR(s, c) if(opterr){\
+ extern int write();\
+ char errbuf[2];\
+ errbuf[0] = c; errbuf[1] = '\n';\
+ (void) write(2, argv[0], strlen(argv[0]));\
+ (void) write(2, s, strlen(s));\
+ (void) write(2, errbuf, 2);}
+
+
+int opterr = 1;
+int optind = 1;
+int optopt;
+char *optarg;
+
+int
+getopt(argc, argv, opts)
+int argc;
+char **argv, *opts;
+{
+ static int sp = 1;
+ register int c;
+ register char *cp;
+
+ if(sp == 1)
+ if(optind >= argc ||
+ argv[optind][0] != '-' || argv[optind][1] == '\0')
+ return(EOF);
+ else if(strcmp(argv[optind], "--") == 0) {
+ optind++;
+ return(EOF);
+ }
+ optopt = c = argv[optind][sp];
+ if(c == ':' || (cp=strchr(opts, c)) == NULL) {
+ ERR(": unknown option, -", c);
+ if(argv[optind][++sp] == '\0') {
+ optind++;
+ sp = 1;
+ }
+ return('?');
+ }
+ if(*++cp == ':') {
+ if(argv[optind][sp+1] != '\0')
+ optarg = &argv[optind++][sp+1];
+ else if(++optind >= argc) {
+ ERR(": argument missing for -", c);
+ sp = 1;
+ return('?');
+ } else
+ optarg = argv[optind++];
+ sp = 1;
+ } else {
+ if(argv[optind][++sp] == '\0') {
+ sp = 1;
+ optind++;
+ }
+ optarg = NULL;
+ }
+ return(c);
+}
+#endif /* HAVE_GETOPT */
Index: head/usr.bin/top/layout.h
===================================================================
--- head/usr.bin/top/layout.h
+++ head/usr.bin/top/layout.h
@@ -0,0 +1,35 @@
+/*
+ * Top - a top users display for Berkeley Unix
+ *
+ * This file defines the locations on tne screen for various parts of the
+ * display. These definitions are used by the routines in "display.c" for
+ * cursor addressing.
+ *
+ * $FreeBSD$
+ */
+
+extern int x_lastpid; /* 10 */
+extern int y_lastpid; /* 0 */
+extern int x_loadave; /* 33 */
+extern int x_loadave_nompid; /* 15 */
+extern int y_loadave; /* 0 */
+extern int x_procstate; /* 0 */
+extern int y_procstate; /* 1 */
+extern int x_brkdn; /* 15 */
+extern int y_brkdn; /* 1 */
+extern int x_mem; /* 5 */
+extern int y_mem; /* 3 */
+extern int x_arc; /* 5 */
+extern int y_arc; /* 4 */
+extern int x_carc; /* 5 */
+extern int y_carc; /* 5 */
+extern int x_swap; /* 6 */
+extern int y_swap; /* 4 */
+extern int y_message; /* 5 */
+extern int x_header; /* 0 */
+extern int y_header; /* 6 */
+extern int x_idlecursor; /* 0 */
+extern int y_idlecursor; /* 5 */
+extern int y_procs; /* 7 */
+
+extern int y_cpustates; /* 2 */
Index: head/usr.bin/top/loadavg.h
===================================================================
--- head/usr.bin/top/loadavg.h
+++ head/usr.bin/top/loadavg.h
@@ -0,0 +1,57 @@
+/*
+ * Top - a top users display for Berkeley Unix
+ *
+ * Defines required to access load average figures.
+ *
+ * This include file sets up everything we need to access the load average
+ * values in the kernel in a machine independent way. First, it sets the
+ * typedef "load_avg" to be either double or long (depending on what is
+ * needed), then it defines these macros appropriately:
+ *
+ * loaddouble(la) - convert load_avg to double.
+ * intload(i) - convert integer to load_avg.
+ */
+
+/*
+ * We assume that if FSCALE is defined, then avenrun and ccpu are type long.
+ * If your machine is an exception (mips, perhaps?) then make adjustments
+ * here.
+ *
+ * Defined types: load_avg for load averages, pctcpu for cpu percentages.
+ */
+#if defined(__mips__) && !(defined(__NetBSD__) || defined(__FreeBSD__))
+# include <sys/fixpoint.h>
+# if defined(FBITS) && !defined(FSCALE)
+# define FSCALE (1 << FBITS) /* RISC/os on mips */
+# endif
+#endif
+
+#ifdef FSCALE
+# define FIXED_LOADAVG FSCALE
+# define FIXED_PCTCPU FSCALE
+#endif
+
+#ifdef ibm032
+# undef FIXED_LOADAVG
+# undef FIXED_PCTCPU
+# define FIXED_PCTCPU PCT_SCALE
+#endif
+
+
+#ifdef FIXED_PCTCPU
+ typedef long pctcpu;
+# define pctdouble(p) ((double)(p) / FIXED_PCTCPU)
+#else
+typedef double pctcpu;
+# define pctdouble(p) (p)
+#endif
+
+#ifdef FIXED_LOADAVG
+ typedef fixpt_t load_avg;
+# define loaddouble(la) ((double)(la) / FIXED_LOADAVG)
+# define intload(i) ((int)((i) * FIXED_LOADAVG))
+#else
+ typedef double load_avg;
+# define loaddouble(la) (la)
+# define intload(i) ((double)(i))
+#endif
Index: head/usr.bin/top/machine.h
===================================================================
--- head/usr.bin/top/machine.h
+++ head/usr.bin/top/machine.h
@@ -0,0 +1,96 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This file defines the interface between top and the machine-dependent
+ * module. It is NOT machine dependent and should not need to be changed
+ * for any specific machine.
+ */
+#ifndef MACHINE_H
+#define MACHINE_H
+
+#include "top.h"
+
+/*
+ * the statics struct is filled in by machine_init
+ */
+struct statics
+{
+ char **procstate_names;
+ char **cpustate_names;
+ char **memory_names;
+ char **arc_names;
+ char **carc_names;
+ char **swap_names;
+#ifdef ORDER
+ char **order_names;
+#endif
+ int ncpus;
+};
+
+/*
+ * the system_info struct is filled in by a machine dependent routine.
+ */
+
+#ifdef p_active /* uw7 define macro p_active */
+#define P_ACTIVE p_pactive
+#else
+#define P_ACTIVE p_active
+#endif
+
+struct system_info
+{
+ int last_pid;
+ double load_avg[NUM_AVERAGES];
+ int p_total;
+ int P_ACTIVE; /* number of procs considered "active" */
+ int *procstates;
+ int *cpustates;
+ int *memory;
+ int *arc;
+ int *carc;
+ int *swap;
+ struct timeval boottime;
+ int ncpus;
+};
+
+/* cpu_states is an array of percentages * 10. For example,
+ the (integer) value 105 is 10.5% (or .105).
+ */
+
+/*
+ * the process_select struct tells get_process_info what processes we
+ * are interested in seeing
+ */
+
+struct process_select
+{
+ int idle; /* show idle processes */
+ int self; /* show self */
+ int system; /* show system processes */
+ int thread; /* show threads */
+#define TOP_MAX_UIDS 8
+ int uid[TOP_MAX_UIDS]; /* only these uids (unless uid[0] == -1) */
+ int wcpu; /* show weighted cpu */
+ int jid; /* only this jid (unless jid == -1) */
+ int jail; /* show jail ID */
+ int swap; /* show swap usage */
+ int kidle; /* show per-CPU idle threads */
+ char *command; /* only this command (unless == NULL) */
+};
+
+/* routines defined by the machine dependent module */
+
+char *format_header(char *uname_field);
+char *format_next_process(caddr_t handle, char *(*get_userid)(int),
+ int flags);
+void toggle_pcpustats(void);
+void get_system_info(struct system_info *si);
+int machine_init(struct statics *statics, char do_unames);
+int proc_owner(int pid);
+
+/* non-int routines typically used by the machine dependent module */
+char *printable(char *string);
+
+#endif /* MACHINE_H */
Index: head/usr.bin/top/os.h
===================================================================
--- head/usr.bin/top/os.h
+++ head/usr.bin/top/os.h
@@ -0,0 +1,38 @@
+#include <sys/types.h>
+#include <sys/param.h> /* This defines BSD */
+#if defined(BSD) && !defined(BSD4_4) && !defined(__osf__)
+# include <stdio.h>
+# include <strings.h>
+# define strchr(a, b) index((a), (b))
+# define strrchr(a, b) rindex((a), (b))
+# define memcpy(a, b, c) bcopy((b), (a), (c))
+# define memzero(a, b) bzero((a), (b))
+# define memcmp(a, b, c) bcmp((a), (b), (c))
+#if defined(NeXT)
+ typedef void sigret_t;
+#else
+ typedef int sigret_t;
+#endif
+
+/* system routines that don't return int */
+char *getenv();
+caddr_t malloc();
+
+#else
+# include <stdio.h>
+# define setbuffer(f, b, s) setvbuf((f), (b), (b) ? _IOFBF : _IONBF, (s))
+# include <string.h>
+# include <memory.h>
+# include <stdlib.h>
+# define memzero(a, b) memset((a), 0, (b))
+ typedef void sigret_t;
+#endif
+
+/* some systems declare sys_errlist in stdio.h! */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#if !defined(__m68k__)
+# if !defined(__NetBSD132__)
+#define SYS_ERRLIST_DECLARED
+# endif /* __NetBSD132__ */
+#endif
+#endif
Index: head/usr.bin/top/patchlevel.h
===================================================================
--- head/usr.bin/top/patchlevel.h
+++ head/usr.bin/top/patchlevel.h
@@ -0,0 +1,2 @@
+#define PATCHLEVEL 5
+#define BETA "beta12"
Index: head/usr.bin/top/prime.c
===================================================================
--- head/usr.bin/top/prime.c
+++ head/usr.bin/top/prime.c
@@ -0,0 +1,41 @@
+/*
+ * Prime number generator. It prints on stdout the next prime number
+ * higher than the number specified as argv[1].
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+main(argc, argv)
+
+int argc;
+char *argv[];
+
+{
+ double i, j;
+ int f;
+
+ if (argc < 2)
+ {
+ exit(1);
+ }
+
+ i = atoi(argv[1]);
+ while (i++)
+ {
+ f=1;
+ for (j=2; j<i; j++)
+ {
+ if ((i/j)==floor(i/j))
+ {
+ f=0;
+ break;
+ }
+ }
+ if (f)
+ {
+ printf("%.0f\n", i);
+ exit(0);
+ }
+ }
+}
Index: head/usr.bin/top/screen.h
===================================================================
--- head/usr.bin/top/screen.h
+++ head/usr.bin/top/screen.h
@@ -0,0 +1,41 @@
+/*
+ * top - a top users display for Unix 4.2
+ *
+ * This file contains all the definitions necessary to use the hand-written
+ * screen package in "screen.c"
+ */
+
+#define TCputs(str) tputs(str, 1, putstdout)
+#define putcap(str) (void)((str) != NULL ? TCputs(str) : 0)
+#define Move_to(x, y) TCputs(tgoto(cursor_motion, x, y))
+
+/* declare return values for termcap functions */
+char *tgetstr();
+char *tgoto();
+
+extern char ch_erase; /* set to the user's erase character */
+extern char ch_kill; /* set to the user's kill character */
+extern char smart_terminal; /* set if the terminal has sufficient termcap
+ capabilities for normal operation */
+
+/* These are some termcap strings for use outside of "screen.c" */
+extern char *cursor_motion;
+extern char *clear_line;
+extern char *clear_to_end;
+
+/* rows and columns on the screen according to termcap */
+extern int screen_length;
+extern int screen_width;
+
+/* a function that puts a single character on stdout */
+int putstdout(int ch);
+int clear_eol(int len);
+void top_standout(char *msg);
+void top_clear(void);
+void go_home(void);
+void reinit_screen(void);
+void get_screensize(void);
+void init_termcap(int interactive);
+void end_screen(void);
+void init_screen(void);
+
Index: head/usr.bin/top/screen.c
===================================================================
--- head/usr.bin/top/screen.c
+++ head/usr.bin/top/screen.c
@@ -0,0 +1,498 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ *
+ * $FreeBSD$
+ */
+
+/* This file contains the routines that interface to termcap and stty/gtty.
+ *
+ * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
+ *
+ * I put in code to turn on the TOSTOP bit while top was running, but I
+ * didn't really like the results. If you desire it, turn on the
+ * preprocessor variable "TOStop". --wnl
+ */
+
+#include "os.h"
+#include "top.h"
+
+#include <sys/ioctl.h>
+#ifdef CBREAK
+# include <sgtty.h>
+# define SGTTY
+#else
+# ifdef TCGETA
+# define TERMIO
+# include <termio.h>
+# else
+# define TERMIOS
+# include <termios.h>
+# endif
+#endif
+#if defined(TERMIO) || defined(TERMIOS)
+# ifndef TAB3
+# ifdef OXTABS
+# define TAB3 OXTABS
+# else
+# define TAB3 0
+# endif
+# endif
+#endif
+#include <curses.h>
+#include <termcap.h>
+#include "screen.h"
+#include "boolean.h"
+
+extern char *myname;
+
+
+int overstrike;
+int screen_length;
+int screen_width;
+char ch_erase;
+char ch_kill;
+char smart_terminal;
+char PC;
+char *tgetstr();
+char *tgoto();
+char termcap_buf[1024];
+char string_buffer[1024];
+char home[15];
+char lower_left[15];
+char *clear_line;
+char *clear_screen;
+char *clear_to_end;
+char *cursor_motion;
+char *start_standout;
+char *end_standout;
+char *terminal_init;
+char *terminal_end;
+
+#ifdef SGTTY
+static struct sgttyb old_settings;
+static struct sgttyb new_settings;
+#endif
+#ifdef TERMIO
+static struct termio old_settings;
+static struct termio new_settings;
+#endif
+#ifdef TERMIOS
+static struct termios old_settings;
+static struct termios new_settings;
+#endif
+static char is_a_terminal = No;
+#ifdef TOStop
+static int old_lword;
+static int new_lword;
+#endif
+
+#define STDIN 0
+#define STDOUT 1
+#define STDERR 2
+
+void
+init_termcap(interactive)
+
+int interactive;
+
+{
+ char *bufptr;
+ char *PCptr;
+ char *term_name;
+ char *getenv();
+ int status;
+
+ /* set defaults in case we aren't smart */
+ screen_width = MAX_COLS;
+ screen_length = 0;
+
+ if (!interactive)
+ {
+ /* pretend we have a dumb terminal */
+ smart_terminal = No;
+ return;
+ }
+
+ /* assume we have a smart terminal until proven otherwise */
+ smart_terminal = Yes;
+
+ /* get the terminal name */
+ term_name = getenv("TERM");
+
+ /* if there is no TERM, assume it's a dumb terminal */
+ /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
+ if (term_name == NULL)
+ {
+ smart_terminal = No;
+ return;
+ }
+
+ /* now get the termcap entry */
+ if ((status = tgetent(termcap_buf, term_name)) != 1)
+ {
+ if (status == -1)
+ {
+ fprintf(stderr, "%s: can't open termcap file\n", myname);
+ }
+ else
+ {
+ fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
+ myname, term_name);
+ }
+
+ /* pretend it's dumb and proceed */
+ smart_terminal = No;
+ return;
+ }
+
+ /* "hardcopy" immediately indicates a very stupid terminal */
+ if (tgetflag("hc"))
+ {
+ smart_terminal = No;
+ return;
+ }
+
+ /* set up common terminal capabilities */
+ if ((screen_length = tgetnum("li")) <= 0)
+ {
+ screen_length = smart_terminal = 0;
+ return;
+ }
+
+ /* screen_width is a little different */
+ if ((screen_width = tgetnum("co")) == -1)
+ {
+ screen_width = 79;
+ }
+ else
+ {
+ screen_width -= 1;
+ }
+
+ /* terminals that overstrike need special attention */
+ overstrike = tgetflag("os");
+
+ /* initialize the pointer into the termcap string buffer */
+ bufptr = string_buffer;
+
+ /* get "ce", clear to end */
+ if (!overstrike)
+ {
+ clear_line = tgetstr("ce", &bufptr);
+ }
+
+ /* get necessary capabilities */
+ if ((clear_screen = tgetstr("cl", &bufptr)) == NULL ||
+ (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
+ {
+ smart_terminal = No;
+ return;
+ }
+
+ /* get some more sophisticated stuff -- these are optional */
+ clear_to_end = tgetstr("cd", &bufptr);
+ terminal_init = tgetstr("ti", &bufptr);
+ terminal_end = tgetstr("te", &bufptr);
+ start_standout = tgetstr("so", &bufptr);
+ end_standout = tgetstr("se", &bufptr);
+
+ /* pad character */
+ PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
+
+ /* set convenience strings */
+ (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof(home) - 1);
+ home[sizeof(home) - 1] = '\0';
+ /* (lower_left is set in get_screensize) */
+
+ /* get the actual screen size with an ioctl, if needed */
+ /* This may change screen_width and screen_length, and it always
+ sets lower_left. */
+ get_screensize();
+
+ /* if stdout is not a terminal, pretend we are a dumb terminal */
+#ifdef SGTTY
+ if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
+ {
+ smart_terminal = No;
+ }
+#endif
+#ifdef TERMIO
+ if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
+ {
+ smart_terminal = No;
+ }
+#endif
+#ifdef TERMIOS
+ if (tcgetattr(STDOUT, &old_settings) == -1)
+ {
+ smart_terminal = No;
+ }
+#endif
+}
+
+void
+init_screen()
+
+{
+ /* get the old settings for safe keeping */
+#ifdef SGTTY
+ if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
+ {
+ /* copy the settings so we can modify them */
+ new_settings = old_settings;
+
+ /* turn on CBREAK and turn off character echo and tab expansion */
+ new_settings.sg_flags |= CBREAK;
+ new_settings.sg_flags &= ~(ECHO|XTABS);
+ (void) ioctl(STDOUT, TIOCSETP, &new_settings);
+
+ /* remember the erase and kill characters */
+ ch_erase = old_settings.sg_erase;
+ ch_kill = old_settings.sg_kill;
+
+#ifdef TOStop
+ /* get the local mode word */
+ (void) ioctl(STDOUT, TIOCLGET, &old_lword);
+
+ /* modify it */
+ new_lword = old_lword | LTOSTOP;
+ (void) ioctl(STDOUT, TIOCLSET, &new_lword);
+#endif
+ /* remember that it really is a terminal */
+ is_a_terminal = Yes;
+
+ /* send the termcap initialization string */
+ putcap(terminal_init);
+ }
+#endif
+#ifdef TERMIO
+ if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
+ {
+ /* copy the settings so we can modify them */
+ new_settings = old_settings;
+
+ /* turn off ICANON, character echo and tab expansion */
+ new_settings.c_lflag &= ~(ICANON|ECHO);
+ new_settings.c_oflag &= ~(TAB3);
+ new_settings.c_cc[VMIN] = 1;
+ new_settings.c_cc[VTIME] = 0;
+ (void) ioctl(STDOUT, TCSETA, &new_settings);
+
+ /* remember the erase and kill characters */
+ ch_erase = old_settings.c_cc[VERASE];
+ ch_kill = old_settings.c_cc[VKILL];
+
+ /* remember that it really is a terminal */
+ is_a_terminal = Yes;
+
+ /* send the termcap initialization string */
+ putcap(terminal_init);
+ }
+#endif
+#ifdef TERMIOS
+ if (tcgetattr(STDOUT, &old_settings) != -1)
+ {
+ /* copy the settings so we can modify them */
+ new_settings = old_settings;
+
+ /* turn off ICANON, character echo and tab expansion */
+ new_settings.c_lflag &= ~(ICANON|ECHO);
+ new_settings.c_oflag &= ~(TAB3);
+ new_settings.c_cc[VMIN] = 1;
+ new_settings.c_cc[VTIME] = 0;
+ (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
+
+ /* remember the erase and kill characters */
+ ch_erase = old_settings.c_cc[VERASE];
+ ch_kill = old_settings.c_cc[VKILL];
+
+ /* remember that it really is a terminal */
+ is_a_terminal = Yes;
+
+ /* send the termcap initialization string */
+ putcap(terminal_init);
+ }
+#endif
+
+ if (!is_a_terminal)
+ {
+ /* not a terminal at all---consider it dumb */
+ smart_terminal = No;
+ }
+}
+
+void
+end_screen()
+
+{
+ /* move to the lower left, clear the line and send "te" */
+ if (smart_terminal)
+ {
+ putcap(lower_left);
+ putcap(clear_line);
+ fflush(stdout);
+ putcap(terminal_end);
+ }
+
+ /* if we have settings to reset, then do so */
+ if (is_a_terminal)
+ {
+#ifdef SGTTY
+ (void) ioctl(STDOUT, TIOCSETP, &old_settings);
+#ifdef TOStop
+ (void) ioctl(STDOUT, TIOCLSET, &old_lword);
+#endif
+#endif
+#ifdef TERMIO
+ (void) ioctl(STDOUT, TCSETA, &old_settings);
+#endif
+#ifdef TERMIOS
+ (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
+#endif
+ }
+}
+
+void
+reinit_screen()
+
+{
+ /* install our settings if it is a terminal */
+ if (is_a_terminal)
+ {
+#ifdef SGTTY
+ (void) ioctl(STDOUT, TIOCSETP, &new_settings);
+#ifdef TOStop
+ (void) ioctl(STDOUT, TIOCLSET, &new_lword);
+#endif
+#endif
+#ifdef TERMIO
+ (void) ioctl(STDOUT, TCSETA, &new_settings);
+#endif
+#ifdef TERMIOS
+ (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
+#endif
+ }
+
+ /* send init string */
+ if (smart_terminal)
+ {
+ putcap(terminal_init);
+ }
+}
+
+void
+get_screensize()
+
+{
+
+#ifdef TIOCGWINSZ
+
+ struct winsize ws;
+
+ if (ioctl (1, TIOCGWINSZ, &ws) != -1)
+ {
+ if (ws.ws_row != 0)
+ {
+ screen_length = ws.ws_row;
+ }
+ if (ws.ws_col != 0)
+ {
+ screen_width = ws.ws_col - 1;
+ }
+ }
+
+#else
+#ifdef TIOCGSIZE
+
+ struct ttysize ts;
+
+ if (ioctl (1, TIOCGSIZE, &ts) != -1)
+ {
+ if (ts.ts_lines != 0)
+ {
+ screen_length = ts.ts_lines;
+ }
+ if (ts.ts_cols != 0)
+ {
+ screen_width = ts.ts_cols - 1;
+ }
+ }
+
+#endif /* TIOCGSIZE */
+#endif /* TIOCGWINSZ */
+
+ (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
+ sizeof(lower_left) - 1);
+ lower_left[sizeof(lower_left) - 1] = '\0';
+}
+
+void
+top_standout(char *msg)
+{
+ if (smart_terminal)
+ {
+ putcap(start_standout);
+ fputs(msg, stdout);
+ putcap(end_standout);
+ }
+ else
+ {
+ fputs(msg, stdout);
+ }
+}
+
+void
+top_clear()
+{
+ if (smart_terminal)
+ {
+ putcap(clear_screen);
+ }
+}
+
+int
+clear_eol(int len)
+{
+ if (smart_terminal && !overstrike && len > 0)
+ {
+ if (clear_line)
+ {
+ putcap(clear_line);
+ return(0);
+ }
+ else
+ {
+ while (len-- > 0)
+ {
+ putchar(' ');
+ }
+ return(1);
+ }
+ }
+ return(-1);
+}
+
+void
+go_home()
+
+{
+ if (smart_terminal)
+ {
+ putcap(home);
+ }
+}
+
+/* This has to be defined as a subroutine for tputs (instead of a macro) */
+
+int
+putstdout(int ch)
+{
+ return putchar(ch);
+}
Index: head/usr.bin/top/sigconv.awk
===================================================================
--- head/usr.bin/top/sigconv.awk
+++ head/usr.bin/top/sigconv.awk
@@ -0,0 +1,55 @@
+# $FreeBSD$
+
+BEGIN {
+ nsig = 0;
+ j = 0;
+ print "/* This file was automatically generated */"
+ print "/* by the awk script \"sigconv.awk\". */\n"
+ print "struct sigdesc {"
+ print " char *name;"
+ print " int number;"
+ print "};\n"
+ print "struct sigdesc sigdesc[] = {"
+ }
+
+/^#define[ \t][ \t]*SIG[A-Z]+[0-9]*[ \t]/ {
+
+ j = sprintf("%d", $3);
+ str = $2;
+
+ if (nsig < j)
+ nsig = j;
+
+ siglist[j] = sprintf("{ \"%s\",\t%2d },", \
+ substr(str, 4), j);
+ }
+/^#[ \t]*define[ \t][ \t]*SIG[A-Z]+[0-9]*[ \t]/ {
+
+ j = sprintf("%d", $4);
+ str = $3;
+
+ if (nsig < j)
+ nsig = j;
+
+ siglist[j] = sprintf("{ \"%s\",\t%2d },", \
+ substr(str, 4), j);
+ }
+/^#[ \t]*define[ \t][ \t]*_SIG[A-Z]+[0-9]*[ \t]/ {
+
+ j = sprintf("%d", $4);
+ str = $3;
+
+ if (nsig < j)
+ nsig = j;
+
+ siglist[j] = sprintf("{ \"%s\",\t%2d },", \
+ substr(str, 5), j);
+ }
+
+END {
+ for (n = 1; n <= nsig; n++)
+ if (siglist[n] != "")
+ printf(" %s\n", siglist[n]);
+
+ printf(" { NULL,\t 0 }\n};\n");
+ }
Index: head/usr.bin/top/top.h
===================================================================
--- head/usr.bin/top/top.h
+++ head/usr.bin/top/top.h
@@ -0,0 +1,54 @@
+/*
+ * $FreeBSD$
+ */
+/*
+ * Top - a top users display for Berkeley Unix
+ *
+ * General (global) definitions
+ */
+
+#ifndef TOP_H
+#define TOP_H
+
+/* Current major version number */
+#define VERSION 3
+
+/* Number of lines of header information on the standard screen */
+extern int Header_lines; /* 7 */
+
+/* Maximum number of columns allowed for display */
+#define MAX_COLS 512
+
+/* Log base 2 of 1024 is 10 (2^10 == 1024) */
+#define LOG1024 10
+
+char *itoa();
+char *itoa7();
+
+char *version_string();
+
+/* Special atoi routine returns either a non-negative number or one of: */
+#define Infinity -1
+#define Invalid -2
+
+/* maximum number we can have */
+#define Largest 0x7fffffff
+
+/*
+ * The entire display is based on these next numbers being defined as is.
+ */
+
+#define NUM_AVERAGES 3
+
+enum displaymodes { DISP_CPU = 0, DISP_IO, DISP_MAX };
+
+/*
+ * Format modifiers
+ */
+#define FMT_SHOWARGS 0x00000001
+
+extern enum displaymodes displaymode;
+
+extern int pcpu_stats;
+
+#endif /* TOP_H */
Index: head/usr.bin/top/top.1
===================================================================
--- head/usr.bin/top/top.1
+++ head/usr.bin/top/top.1
@@ -0,0 +1,543 @@
+.\" NOTE: changes to the manual page for "top" should be made in the
+.\" file "top.X" and NOT in the file "top.1".
+.\" $FreeBSD$
+.nr N -1
+.nr D 2
+.TH TOP 1 Local
+.UC 4
+.SH NAME
+top \- display and update information about the top cpu processes
+.SH SYNOPSIS
+.B top
+[
+.B \-abCHIijnPqStuvwz
+] [
+.BI \-d count
+] [
+.BI \-m io | cpu
+] [
+.BI \-o field
+] [
+.BI \-s time
+] [
+.BI \-J jail
+] [
+.BI \-U username
+] [
+.I number
+]
+.SH DESCRIPTION
+.\" This defines appropriate quote strings for nroff and troff
+.ds lq \&"
+.ds rq \&"
+.if t .ds lq ``
+.if t .ds rq ''
+.\" Just in case these number registers aren't set yet...
+.if \nN==0 .nr N 10
+.if \nD==0 .nr D 2
+.I Top
+displays the top
+.if !\nN==-1 \nN
+processes on the system and periodically updates this information.
+.if \nN==-1 \
+\{\
+If standard output is an intelligent terminal (see below) then
+as many processes as will fit on the terminal screen are displayed
+by default. Otherwise, a good number of them are shown (around 20).
+.\}
+Raw cpu percentage is used to rank the processes. If
+.I number
+is given, then the top
+.I number
+processes will be displayed instead of the default.
+.PP
+.I Top
+makes a distinction between terminals that support advanced capabilities
+and those that do not. This
+distinction affects the choice of defaults for certain options. In the
+remainder of this document, an \*(lqintelligent\*(rq terminal is one that
+supports cursor addressing, clear screen, and clear to end of line.
+Conversely, a \*(lqdumb\*(rq terminal is one that does not support such
+features. If the output of
+.I top
+is redirected to a file, it acts as if it were being run on a dumb
+terminal.
+.SH OPTIONS
+.TP
+.B \-C
+Toggle CPU display mode.
+By default top displays the weighted CPU percentage in the WCPU column
+(this is the same value that
+.IR ps (1)
+displays as CPU).
+Each time
+.B \-C
+flag is passed it toggles between \*(lqraw cpu\*(rq mode
+and \*(lqweighted cpu\*(rq mode, showing the \*(lqCPU\*(rq or
+the \*(lqWCPU\*(rq column respectively.
+.TP
+.B \-S
+Show system processes in the display. Normally, system processes such as
+the pager and the swapper are not shown. This option makes them visible.
+.TP
+.B \-a
+Display command names derived from the argv[] vector, rather than real
+executable name. It's useful when you want to watch applications, that
+puts their status information there. If the real name differs from argv[0],
+it will be displayed in parenthesis.
+.TP
+.B \-b
+Use \*(lqbatch\*(rq mode. In this mode, all input from the terminal is
+ignored. Interrupt characters (such as ^C and ^\e) still have an effect.
+This is the default on a dumb terminal, or when the output is not a terminal.
+.TP
+.B \-H
+Display each thread for a multithreaded process individually.
+By default a single summary line is displayed for each process.
+.TP
+.B \-i
+Use \*(lqinteractive\*(rq mode. In this mode, any input is immediately
+read for processing. See the section on \*(lqInteractive Mode\*(rq
+for an explanation of
+which keys perform what functions. After the command is processed, the
+screen will immediately be updated, even if the command was not
+understood. This mode is the default when standard output is an
+intelligent terminal.
+.TP
+.B \-I
+Do not display idle processes.
+By default, top displays both active and idle processes.
+.TP
+.B \-j
+Display the
+.IR jail (8)
+ID.
+.TP
+.B \-t
+Do not display the
+.I top
+process.
+.TP
+.BI \-m display
+Display either 'cpu' or 'io' statistics. Default is 'cpu'.
+.TP
+.B \-n
+Use \*(lqnon-interactive\*(rq mode. This is identical to \*(lqbatch\*(rq
+mode.
+.TP
+.B \-P
+Display per-cpu CPU usage statistics.
+.TP
+.B \-q
+Renice
+.I top
+to -20 so that it will run faster. This can be used when the system is
+being very sluggish to improve the possibility of discovering the problem.
+This option can only be used by root.
+.TP
+.B \-u
+Do not take the time to map uid numbers to usernames. Normally,
+.I top
+will read as much of the file \*(lq/etc/passwd\*(rq as is necessary to map
+all the user id numbers it encounters into login names. This option
+disables all that, while possibly decreasing execution time. The uid
+numbers are displayed instead of the names.
+.TP
+.B \-v
+Write version number information to stderr then exit immediately.
+No other processing takes place when this option is used. To see current
+revision information while top is running, use the help command \*(lq?\*(rq.
+.TP
+.B \-w
+Display approximate swap usage for each process.
+.TP
+.B \-z
+Do not display the system idle process.
+.TP
+.BI \-d count
+Show only
+.I count
+displays, then exit. A display is considered to be one update of the
+screen. This option allows the user to select the number of displays he
+wants to see before
+.I top
+automatically exits. For intelligent terminals, no upper limit
+is set. The default is 1 for dumb terminals.
+.TP
+.BI \-s time
+Set the delay between screen updates to
+.I time
+seconds. The default delay between updates is \nD seconds.
+.TP
+.BI \-o field
+Sort the process display area on the specified field. The field name
+is the name of the column as seen in the output, but in lower case:
+\*(lqcpu\*(lq, \*(rqsize\*(lq, \*(rqres\*(lq, \*(rqtime\*(lq,
+\*(rqpri\*(lq, \*(rqthreads\*(lq, \*(lqtotal\*(lq, \*(rqread\*(lq,
+\*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
+\*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
+.TP
+.BI \-J jail
+Show only those processes owned by
+.IR jail .
+This may be either the
+.B jid
+or
+.B name
+of the jail.
+Use
+.B 0
+to limit to host processes.
+Using this option implies the
+.B \-j
+flag.
+.PP
+.BI \-U username
+Show only those processes owned by
+.IR username .
+This option currently only accepts usernames and will not understand
+uid numbers.
+.PP
+Both
+.I count
+and
+.I number
+fields can be specified as \*(lqinfinite\*(rq, indicating that they can
+stretch as far as possible. This is accomplished by using any proper
+prefix of the keywords
+\*(lqinfinity\*(rq,
+\*(lqmaximum\*(rq,
+or
+\*(lqall\*(rq.
+The default for
+.I count
+on an intelligent terminal is, in fact,
+.BI infinity .
+.PP
+The environment variable
+.B TOP
+is examined for options before the command line is scanned. This enables
+a user to set his or her own defaults. The number of processes to display
+can also be specified in the environment variable
+.BR TOP .
+The options
+.BR \-a ,
+.BR \-C ,
+.BR \-H ,
+.BR \-I ,
+.BR \-j ,
+.BR \-P ,
+.BR \-S ,
+.BR \-t ,
+.BR \-u ,
+.BR \-w ,
+and
+.B \-z
+are actually toggles. A second specification of any of these options
+will negate the first. Thus a user who has the environment variable
+.B TOP
+set to \*(lq\-I\*(rq may use the command \*(lqtop \-I\*(rq to see idle processes.
+.SH "INTERACTIVE MODE"
+When
+.I top
+is running in \*(lqinteractive mode\*(rq, it reads commands from the
+terminal and acts upon them accordingly. In this mode, the terminal is
+put in \*(lqCBREAK\*(rq, so that a character will be
+processed as soon as it is typed. Almost always, a key will be
+pressed when
+.I top
+is between displays; that is, while it is waiting for
+.I time
+seconds to elapse. If this is the case, the command will be
+processed and the display will be updated immediately thereafter
+(reflecting any changes that the command may have specified). This
+happens even if the command was incorrect. If a key is pressed while
+.I top
+is in the middle of updating the display, it will finish the update and
+then process the command. Some commands require additional information,
+and the user will be prompted accordingly. While typing this information
+in, the user's erase and kill keys (as set up by the command
+.IR stty )
+are recognized, and a newline terminates the input.
+.PP
+These commands are currently recognized (^L refers to control-L):
+.TP
+.B ^L
+Redraw the screen.
+.IP "\fBh\fP\ or\ \fB?\fP"
+Display a summary of the commands (help screen). Version information
+is included in this display.
+.TP
+.B q
+Quit
+.IR top.
+.TP
+.B d
+Change the number of displays to show (prompt for new number).
+Remember that the next display counts as one, so typing
+.B d1
+will make
+.I top
+show one final display and then immediately exit.
+.TP
+.B m
+Toggle the display between 'cpu' and 'io' modes.
+.TP
+.B n or #
+Change the number of processes to display (prompt for new number).
+.TP
+.B s
+Change the number of seconds to delay between displays
+(prompt for new number).
+.TP
+.B S
+Toggle the display of system processes.
+.TP
+.B a
+Toggle the display of process titles.
+.TP
+.B k
+Send a signal (\*(lqkill\*(rq by default) to a list of processes. This
+acts similarly to the command
+.IR kill (1)).
+.TP
+.B r
+Change the priority (the \*(lqnice\*(rq) of a list of processes.
+This acts similarly to the command
+.IR renice (8)).
+.TP
+.B u
+Display only processes owned by a specific set of usernames (prompt for
+username). If the username specified is simply \*(lq+\*(rq or \*(lq-\*(rq,
+then processes belonging to all users will be displayed. Usernames can be added
+to and removed from the set by prepending them with \*(lq+\*(rq and
+\*(lq-\*(rq, respectively.
+.TP
+.B o
+Change the order in which the display is sorted. This command is not
+available on all systems. The sort key names vary from system to system
+but usually include: \*(lqcpu\*(rq, \*(lqres\*(rq, \*(lqsize\*(rq,
+\*(lqtime\*(rq. The default is cpu.
+.TP
+.B e
+Display a list of system errors (if any) generated by the last
+.BR k ill
+or
+.BR r enice
+command.
+.TP
+.B H
+Toggle the display of threads.
+.TP
+.B i
+(or
+.BR I )
+Toggle the display of idle processes.
+.TP
+.B j
+Toggle the display of
+.IR jail (8)
+ID.
+.TP
+.B J
+Display only processes owned by a specific jail (prompt for jail).
+If the jail specified is simply \*(lq+\*(rq, then processes belonging
+to all jails and the host will be displayed.
+This will also enable the display of JID.
+.TP
+.B P
+Toggle the display of per-CPU statistics.
+.TP
+.B t
+Toggle the display of the
+.I top
+process.
+.TP
+.B w
+Toggle the display of swap usage.
+.TP
+.B z
+Toggle the display of the system idle process.
+.SH "THE DISPLAY"
+The actual display varies depending on the specific variant of Unix
+that the machine is running. This description may not exactly match
+what is seen by top running on this particular machine. Differences
+are listed at the end of this manual entry.
+.PP
+The top few lines of the display show general information
+about the state of the system, including
+the last process id assigned to a process (on most systems),
+the three load averages,
+the current time,
+the number of existing processes,
+the number of processes in each state
+(sleeping, running, starting, zombies, and stopped),
+and a percentage of time spent in each of the processor states
+(user, nice, system, and idle).
+It also includes information about physical and virtual memory allocation.
+.PP
+The remainder of the screen displays information about individual
+processes. This display is similar in spirit to
+.IR ps (1)
+but it is not exactly the same. PID is the process id,
+JID, when displayed, is the
+.IR jail (8)
+ID corresponding to the process,
+USERNAME is the name of the process's owner (if
+.B \-u
+is specified, a UID column will be substituted for USERNAME),
+PRI is the current priority of the process,
+NICE is the nice amount (in the range \-20 to 20),
+SIZE is the total size of the process (text, data, and stack),
+RES is the current amount of resident memory,
+SWAP is the approximate amount of swap, if enabled
+(SIZE, RES and SWAP are given in kilobytes),
+STATE is the current state (one of \*(lqSTART\*(rq, \*(lqRUN\*(rq
+(shown as \*(lqCPUn\*(rq on SMP systems), \*(lqSLEEP\*(rq, \*(lqSTOP\*(rq,
+\*(lqZOMB\*(rq, \*(lqWAIT\*(rq, \*(lqLOCK\*(rq or the event on which the
+process waits),
+C is the processor number on which the process is executing
+(visible only on SMP systems),
+TIME is the number of system and user cpu seconds that the process has used,
+WCPU, when displayed, is the weighted cpu percentage (this is the same
+value that
+.IR ps (1)
+displays as CPU),
+CPU is the raw percentage and is the field that is sorted to determine
+the order of the processes, and
+COMMAND is the name of the command that the process is currently running
+(if the process is swapped out, this column is marked \*(lq<swapped>\*(rq).
+.SH NOTES
+If a process is in the \*(lqSLEEP\*(rq or \*(lqLOCK\*(rq state,
+the state column will report the name of the event or lock on which the
+process is waiting.
+Lock names are prefixed with an asterisk \*(lq*\*(rq while sleep events
+are not.
+.SH AUTHOR
+William LeFebvre, EECS Department, Northwestern University
+.SH ENVIRONMENT
+.DT
+TOP user-configurable defaults for options.
+.SH FILES
+.DT
+/dev/kmem kernel memory
+.br
+/dev/mem physical memory
+.br
+/etc/passwd used to map uid numbers to user names
+.br
+/boot/kernel/kernel system image
+.SH BUGS
+Don't shoot me, but the default for
+.B \-I
+has changed once again. So many people were confused by the fact that
+.I top
+wasn't showing them all the processes that I have decided to make the
+default behavior show idle processes, just like it did in version 2.
+But to appease folks who can't stand that behavior, I have added the
+ability to set \*(lqdefault\*(rq options in the environment variable
+.B TOP
+(see the OPTIONS section). Those who want the behavior that version
+3.0 had need only set the environment variable
+.B TOP
+to \*(lq\-I\*(rq.
+.PP
+The command name for swapped processes should be tracked down, but this
+would make the program run slower.
+.PP
+As with
+.IR ps (1),
+things can change while
+.I top
+is collecting information for an update. The picture it gives is only a
+close approximation to reality.
+.SH "SEE ALSO"
+kill(1),
+ps(1),
+stty(1),
+mem(4),
+renice(8)
+.\" $FreeBSD$
+.SH "FreeBSD NOTES"
+
+.SH DESCRIPTION OF MEMORY
+Mem: 61M Active, 86M Inact, 368K Laundry, 22G Wired, 102G Free
+ARC: 15G Total, 9303M MFU, 6155M MRU, 1464K Anon, 98M Header, 35M Other
+ 15G Compressed, 27G Uncompressed, 1.75:1 Ratio, 174M Overhead
+Swap: 4096M Total, 532M Free, 13% Inuse, 80K In, 104K Out
+.TP
+.B K:
+Kilobyte
+.TP
+.B M:
+Megabyte
+.TP
+.B G:
+Gigabyte
+.TP
+.B %:
+1/100
+.SS Physical Memory Stats
+.TP
+.B Active:
+number of bytes active
+.TP
+.B Inact:
+number of clean bytes inactive
+.TP
+.B Laundry:
+number of dirty bytes queued for laundering
+.TP
+.B Wired:
+number of bytes wired down, including BIO-level cached file data pages
+.TP
+.B Buf:
+number of bytes used for BIO-level disk caching
+.TP
+.B Free:
+number of bytes free
+.SS ZFS ARC Stats
+These stats are only displayed when the ARC is in use.
+.TP
+.B Total:
+number of wired bytes used for the ZFS ARC
+.TP
+.B MRU:
+number of ARC bytes holding most recently used data
+.TP
+.B MFU:
+number of ARC bytes holding most frequently used data
+.TP
+.B Anon:
+number of ARC bytes holding in flight data
+.TP
+.B Header:
+number of ARC bytes holding headers
+.TP
+.B Other:
+miscellaneous ARC bytes
+.TP
+.B Compressed:
+bytes of memory used by ARC caches
+.TP
+.B Uncompressed:
+bytes of data stored in ARC caches before compression
+.TP
+.B Ratio:
+compression ratio of data cached in the ARC
+.SS Swap Stats
+.TP
+.B Total:
+total available swap usage
+.TP
+.B Free:
+total free swap usage
+.TP
+.B Inuse:
+swap usage
+.TP
+.B In:
+bytes paged in from swap devices (last interval)
+.TP
+.B Out:
+bytes paged out to swap devices (last interval)
Index: head/usr.bin/top/top.c
===================================================================
--- head/usr.bin/top/top.c
+++ head/usr.bin/top/top.c
@@ -0,0 +1,1318 @@
+char *copyright =
+ "Copyright (c) 1984 through 1996, William LeFebvre";
+
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989 - 1994, William LeFebvre, Northwestern University
+ * Copyright (c) 1994, 1995, William LeFebvre, Argonne National Laboratory
+ * Copyright (c) 1996, William LeFebvre, Group sys Consulting
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * See the file "Changes" for information on version-to-version changes.
+ */
+
+/*
+ * This file contains "main" and other high-level routines.
+ */
+
+/*
+ * The following preprocessor variables, when defined, are used to
+ * distinguish between different Unix implementations:
+ *
+ * SIGHOLD - use SVR4 sighold function when defined
+ * SIGRELSE - use SVR4 sigrelse function when defined
+ * FD_SET - macros FD_SET and FD_ZERO are used when defined
+ */
+
+#include "os.h"
+
+#include <sys/jail.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <curses.h>
+#include <errno.h>
+#include <jail.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <unistd.h>
+
+/* includes specific to top */
+#include "commands.h"
+#include "display.h" /* interface to display package */
+#include "screen.h" /* interface to screen package */
+#include "top.h"
+#include "top.local.h"
+#include "boolean.h"
+#include "machine.h"
+#include "utils.h"
+#include "username.h"
+
+/* Size of the stdio buffer given to stdout */
+#define Buffersize 2048
+
+/* The buffer that stdio will use */
+char stdoutbuf[Buffersize];
+
+/* build Signal masks */
+#define Smask(s) (1 << ((s) - 1))
+
+/* for getopt: */
+extern int optind;
+extern char *optarg;
+
+/* imported from screen.c */
+extern int overstrike;
+
+static int fmt_flags = 0;
+int pcpu_stats = No;
+
+/* signal handling routines */
+sigret_t leave();
+sigret_t tstop();
+#ifdef SIGWINCH
+sigret_t top_winch(int);
+#endif
+
+volatile sig_atomic_t leaveflag;
+volatile sig_atomic_t tstopflag;
+volatile sig_atomic_t winchflag;
+
+/* internal routines */
+void quit();
+
+/* values which need to be accessed by signal handlers */
+static int max_topn; /* maximum displayable processes */
+
+/* miscellaneous things */
+struct process_select ps;
+char *myname = "top";
+jmp_buf jmp_int;
+
+/* routines that don't return int */
+
+char *username();
+char *ctime();
+char *kill_procs();
+char *renice_procs();
+
+#ifdef ORDER
+extern int (*compares[])();
+#else
+extern int proc_compare();
+extern int io_compare();
+#endif
+time_t time();
+
+caddr_t get_process_info(struct system_info *si, struct process_select *sel,
+ int (*compare)(const void *, const void *));
+
+/* different routines for displaying the user's identification */
+/* (values assigned to get_userid) */
+char *username();
+char *itoa7();
+
+/* pointers to display routines */
+void (*d_loadave)(int mpid, double *avenrun) = i_loadave;
+void (*d_procstates)(int total, int *brkdn) = i_procstates;
+void (*d_cpustates)(int *states) = i_cpustates;
+void (*d_memory)(int *stats) = i_memory;
+void (*d_arc)(int *stats) = i_arc;
+void (*d_carc)(int *stats) = i_carc;
+void (*d_swap)(int *stats) = i_swap;
+void (*d_message)(void) = i_message;
+void (*d_header)(char *text) = i_header;
+void (*d_process)(int line, char *thisline) = i_process;
+
+void reset_display(void);
+
+static void
+reset_uids()
+{
+ for (size_t i = 0; i < TOP_MAX_UIDS; ++i)
+ ps.uid[i] = -1;
+}
+
+static int
+add_uid(int uid)
+{
+ size_t i = 0;
+
+ /* Add the uid if there's room */
+ for (; i < TOP_MAX_UIDS; ++i)
+ {
+ if (ps.uid[i] == -1 || ps.uid[i] == uid)
+ {
+ ps.uid[i] = uid;
+ break;
+ }
+ }
+
+ return (i == TOP_MAX_UIDS);
+}
+
+static void
+rem_uid(int uid)
+{
+ size_t i = 0;
+ size_t where = TOP_MAX_UIDS;
+
+ /* Look for the user to remove - no problem if it's not there */
+ for (; i < TOP_MAX_UIDS; ++i)
+ {
+ if (ps.uid[i] == -1)
+ break;
+ if (ps.uid[i] == uid)
+ where = i;
+ }
+
+ /* Make sure we don't leave a hole in the middle */
+ if (where != TOP_MAX_UIDS)
+ {
+ ps.uid[where] = ps.uid[i-1];
+ ps.uid[i-1] = -1;
+ }
+}
+
+static int
+handle_user(char *buf, size_t buflen)
+{
+ int rc = 0;
+ int uid = -1;
+ char *buf2 = buf;
+
+ new_message(MT_standout, "Username to show (+ for all): ");
+ if (readline(buf, buflen, No) <= 0)
+ {
+ clear_message();
+ return rc;
+ }
+
+ if (buf[0] == '+' || buf[0] == '-')
+ {
+ if (buf[1] == '\0')
+ {
+ reset_uids();
+ goto end;
+ }
+ else
+ ++buf2;
+ }
+
+ if ((uid = userid(buf2)) == -1)
+ {
+ new_message(MT_standout, " %s: unknown user", buf2);
+ rc = 1;
+ goto end;
+ }
+
+ if (buf2 == buf)
+ {
+ reset_uids();
+ ps.uid[0] = uid;
+ goto end;
+ }
+
+ if (buf[0] == '+')
+ {
+ if (add_uid(uid))
+ {
+ new_message(MT_standout, " too many users, reset with '+'");
+ rc = 1;
+ goto end;
+ }
+ }
+ else
+ rem_uid(uid);
+
+end:
+ putchar('\r');
+ return rc;
+}
+
+int
+main(argc, argv)
+
+int argc;
+char *argv[];
+
+{
+ register int i;
+ register int active_procs;
+ register int change;
+
+ struct system_info system_info;
+ struct statics statics;
+ caddr_t processes;
+
+ static char tempbuf1[50];
+ static char tempbuf2[50];
+ int old_sigmask; /* only used for BSD-style signals */
+ int topn = Default_TOPN;
+ int delay = Default_DELAY;
+ int displays = 0; /* indicates unspecified */
+ int sel_ret = 0;
+ time_t curr_time;
+ char *(*get_userid)() = username;
+ char *uname_field = "USERNAME";
+ char *header_text;
+ char *env_top;
+ char **preset_argv;
+ int preset_argc = 0;
+ char **av;
+ int ac;
+ char dostates = No;
+ char do_unames = Yes;
+ char interactive = Maybe;
+ char warnings = 0;
+#if Default_TOPN == Infinity
+ char topn_specified = No;
+#endif
+ char ch;
+ char *iptr;
+ char no_command = 1;
+ struct timeval timeout;
+#ifdef ORDER
+ char *order_name = NULL;
+ int order_index = 0;
+#endif
+#ifndef FD_SET
+ /* FD_SET and friends are not present: fake it */
+ typedef int fd_set;
+#define FD_ZERO(x) (*(x) = 0)
+#define FD_SET(f, x) (*(x) = 1<<f)
+#endif
+ fd_set readfds;
+
+#ifdef ORDER
+ static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
+#else
+ static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJw";
+#endif
+/* these defines enumerate the "strchr"s of the commands in command_chars */
+#define CMD_redraw 0
+#define CMD_update 1
+#define CMD_quit 2
+#define CMD_help1 3
+#define CMD_help2 4
+#define CMD_OSLIMIT 4 /* terminals with OS can only handle commands */
+#define CMD_errors 5 /* less than or equal to CMD_OSLIMIT */
+#define CMD_number1 6
+#define CMD_number2 7
+#define CMD_delay 8
+#define CMD_displays 9
+#define CMD_kill 10
+#define CMD_renice 11
+#define CMD_idletog 12
+#define CMD_idletog2 13
+#define CMD_user 14
+#define CMD_selftog 15
+#define CMD_thrtog 16
+#define CMD_viewtog 17
+#define CMD_viewsys 18
+#define CMD_wcputog 19
+#define CMD_showargs 20
+#define CMD_jidtog 21
+#define CMD_kidletog 22
+#define CMD_pcputog 23
+#define CMD_jail 24
+#define CMD_swaptog 25
+#ifdef ORDER
+#define CMD_order 26
+#endif
+
+ /* set the buffer for stdout */
+#ifdef DEBUG
+ extern FILE *debug;
+ debug = fopen("debug.run", "w");
+ setbuffer(stdout, NULL, 0);
+#else
+ setbuffer(stdout, stdoutbuf, Buffersize);
+#endif
+
+ /* get our name */
+ if (argc > 0)
+ {
+ if ((myname = strrchr(argv[0], '/')) == 0)
+ {
+ myname = argv[0];
+ }
+ else
+ {
+ myname++;
+ }
+ }
+
+ /* initialize some selection options */
+ ps.idle = Yes;
+ ps.self = -1;
+ ps.system = No;
+ reset_uids();
+ ps.thread = No;
+ ps.wcpu = 1;
+ ps.jid = -1;
+ ps.jail = No;
+ ps.swap = No;
+ ps.kidle = Yes;
+ ps.command = NULL;
+
+ /* get preset options from the environment */
+ if ((env_top = getenv("TOP")) != NULL)
+ {
+ av = preset_argv = argparse(env_top, &preset_argc);
+ ac = preset_argc;
+
+ /* set the dummy argument to an explanatory message, in case
+ getopt encounters a bad argument */
+ preset_argv[0] = "while processing environment";
+ }
+
+ /* process options */
+ do {
+ /* if we're done doing the presets, then process the real arguments */
+ if (preset_argc == 0)
+ {
+ ac = argc;
+ av = argv;
+
+ /* this should keep getopt happy... */
+ optind = 1;
+ }
+
+ while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
+ {
+ switch(i)
+ {
+ case 'v': /* show version number */
+ fprintf(stderr, "%s: version %s\n",
+ myname, version_string());
+ exit(1);
+ break;
+
+ case 'u': /* toggle uid/username display */
+ do_unames = !do_unames;
+ break;
+
+ case 'U': /* display only username's processes */
+ if ((ps.uid[0] = userid(optarg)) == -1)
+ {
+ fprintf(stderr, "%s: unknown user\n", optarg);
+ exit(1);
+ }
+ break;
+
+ case 'S': /* show system processes */
+ ps.system = !ps.system;
+ break;
+
+ case 'I': /* show idle processes */
+ ps.idle = !ps.idle;
+ break;
+
+ case 'i': /* go interactive regardless */
+ interactive = Yes;
+ break;
+
+ case 'n': /* batch, or non-interactive */
+ case 'b':
+ interactive = No;
+ break;
+
+ case 'a':
+ fmt_flags ^= FMT_SHOWARGS;
+ break;
+
+ case 'd': /* number of displays to show */
+ if ((i = atoiwi(optarg)) == Invalid || i == 0)
+ {
+ fprintf(stderr,
+ "%s: warning: display count should be positive -- option ignored\n",
+ myname);
+ warnings++;
+ }
+ else
+ {
+ displays = i;
+ }
+ break;
+
+ case 's':
+ if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
+ {
+ fprintf(stderr,
+ "%s: warning: seconds delay should be positive -- using default\n",
+ myname);
+ delay = Default_DELAY;
+ warnings++;
+ }
+ break;
+
+ case 'q': /* be quick about it */
+ /* only allow this if user is really root */
+ if (getuid() == 0)
+ {
+ /* be very un-nice! */
+ (void) nice(-20);
+ }
+ else
+ {
+ fprintf(stderr,
+ "%s: warning: `-q' option can only be used by root\n",
+ myname);
+ warnings++;
+ }
+ break;
+
+ case 'm': /* select display mode */
+ if (strcmp(optarg, "io") == 0) {
+ displaymode = DISP_IO;
+ } else if (strcmp(optarg, "cpu") == 0) {
+ displaymode = DISP_CPU;
+ } else {
+ fprintf(stderr,
+ "%s: warning: `-m' option can only take args "
+ "'io' or 'cpu'\n",
+ myname);
+ exit(1);
+ }
+ break;
+
+ case 'o': /* select sort order */
+#ifdef ORDER
+ order_name = optarg;
+#else
+ fprintf(stderr,
+ "%s: this platform does not support arbitrary ordering. Sorry.\n",
+ myname);
+ warnings++;
+#endif
+ break;
+
+ case 't':
+ ps.self = (ps.self == -1) ? getpid() : -1;
+ break;
+
+ case 'C':
+ ps.wcpu = !ps.wcpu;
+ break;
+
+ case 'H':
+ ps.thread = !ps.thread;
+ break;
+
+ case 'j':
+ ps.jail = !ps.jail;
+ break;
+
+ case 'J': /* display only jail's processes */
+ if ((ps.jid = jail_getid(optarg)) == -1)
+ {
+ fprintf(stderr, "%s: unknown jail\n", optarg);
+ exit(1);
+ }
+ ps.jail = 1;
+ break;
+
+ case 'P':
+ pcpu_stats = !pcpu_stats;
+ break;
+
+ case 'w':
+ ps.swap = 1;
+ break;
+
+ case 'z':
+ ps.kidle = !ps.kidle;
+ break;
+
+ default:
+ fprintf(stderr,
+"Top version %s\n"
+"Usage: %s [-abCHIijnPqStuvwz] [-d count] [-m io | cpu] [-o field] [-s time]\n"
+" [-J jail] [-U username] [number]\n",
+ version_string(), myname);
+ exit(1);
+ }
+ }
+
+ /* get count of top processes to display (if any) */
+ if (optind < ac)
+ {
+ if ((topn = atoiwi(av[optind])) == Invalid)
+ {
+ fprintf(stderr,
+ "%s: warning: process display count should be non-negative -- using default\n",
+ myname);
+ warnings++;
+ }
+#if Default_TOPN == Infinity
+ else
+ {
+ topn_specified = Yes;
+ }
+#endif
+ }
+
+ /* tricky: remember old value of preset_argc & set preset_argc = 0 */
+ i = preset_argc;
+ preset_argc = 0;
+
+ /* repeat only if we really did the preset arguments */
+ } while (i != 0);
+
+ /* set constants for username/uid display correctly */
+ if (!do_unames)
+ {
+ uname_field = " UID ";
+ get_userid = itoa7;
+ }
+
+ /* initialize the kernel memory interface */
+ if (machine_init(&statics, do_unames) == -1)
+ {
+ exit(1);
+ }
+
+#ifdef ORDER
+ /* determine sorting order index, if necessary */
+ if (order_name != NULL)
+ {
+ if ((order_index = string_index(order_name, statics.order_names)) == -1)
+ {
+ char **pp;
+
+ fprintf(stderr, "%s: '%s' is not a recognized sorting order.\n",
+ myname, order_name);
+ fprintf(stderr, "\tTry one of these:");
+ pp = statics.order_names;
+ while (*pp != NULL)
+ {
+ fprintf(stderr, " %s", *pp++);
+ }
+ fputc('\n', stderr);
+ exit(1);
+ }
+ }
+#endif
+
+#ifdef no_initialization_needed
+ /* initialize the hashing stuff */
+ if (do_unames)
+ {
+ init_hash();
+ }
+#endif
+
+ /* initialize termcap */
+ init_termcap(interactive);
+
+ /* get the string to use for the process area header */
+ header_text = format_header(uname_field);
+
+ /* initialize display interface */
+ if ((max_topn = display_init(&statics)) == -1)
+ {
+ fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);
+ exit(4);
+ }
+
+ /* print warning if user requested more processes than we can display */
+ if (topn > max_topn)
+ {
+ fprintf(stderr,
+ "%s: warning: this terminal can only display %d processes.\n",
+ myname, max_topn);
+ warnings++;
+ }
+
+ /* adjust for topn == Infinity */
+ if (topn == Infinity)
+ {
+ /*
+ * For smart terminals, infinity really means everything that can
+ * be displayed, or Largest.
+ * On dumb terminals, infinity means every process in the system!
+ * We only really want to do that if it was explicitly specified.
+ * This is always the case when "Default_TOPN != Infinity". But if
+ * topn wasn't explicitly specified and we are on a dumb terminal
+ * and the default is Infinity, then (and only then) we use
+ * "Nominal_TOPN" instead.
+ */
+#if Default_TOPN == Infinity
+ topn = smart_terminal ? Largest :
+ (topn_specified ? Largest : Nominal_TOPN);
+#else
+ topn = Largest;
+#endif
+ }
+
+ /* set header display accordingly */
+ display_header(topn > 0);
+
+ /* determine interactive state */
+ if (interactive == Maybe)
+ {
+ interactive = smart_terminal;
+ }
+
+ /* if # of displays not specified, fill it in */
+ if (displays == 0)
+ {
+ displays = smart_terminal ? Infinity : 1;
+ }
+
+ /* hold interrupt signals while setting up the screen and the handlers */
+#ifdef SIGHOLD
+ sighold(SIGINT);
+ sighold(SIGQUIT);
+ sighold(SIGTSTP);
+#else
+ old_sigmask = sigblock(Smask(SIGINT) | Smask(SIGQUIT) | Smask(SIGTSTP));
+#endif
+ init_screen();
+ (void) signal(SIGINT, leave);
+ (void) signal(SIGQUIT, leave);
+ (void) signal(SIGTSTP, tstop);
+#ifdef SIGWINCH
+ (void) signal(SIGWINCH, top_winch);
+#endif
+#ifdef SIGRELSE
+ sigrelse(SIGINT);
+ sigrelse(SIGQUIT);
+ sigrelse(SIGTSTP);
+#else
+ (void) sigsetmask(old_sigmask);
+#endif
+ if (warnings)
+ {
+ fputs("....", stderr);
+ fflush(stderr); /* why must I do this? */
+ sleep((unsigned)(3 * warnings));
+ fputc('\n', stderr);
+ }
+
+restart:
+
+ /*
+ * main loop -- repeat while display count is positive or while it
+ * indicates infinity (by being -1)
+ */
+
+ while ((displays == -1) || (displays-- > 0))
+ {
+ int (*compare)();
+
+
+ /* get the current stats */
+ get_system_info(&system_info);
+
+#ifdef ORDER
+ compare = compares[order_index];
+#else
+ if (displaymode == DISP_CPU)
+ compare = proc_compare;
+ else
+ compare = io_compare;
+#endif
+
+ /* get the current set of processes */
+ processes =
+ get_process_info(&system_info, &ps, compare);
+
+ /* display the load averages */
+ (*d_loadave)(system_info.last_pid,
+ system_info.load_avg);
+
+ /* display the current time */
+ /* this method of getting the time SHOULD be fairly portable */
+ time(&curr_time);
+ i_uptime(&system_info.boottime, &curr_time);
+ i_timeofday(&curr_time);
+
+ /* display process state breakdown */
+ (*d_procstates)(system_info.p_total,
+ system_info.procstates);
+
+ /* display the cpu state percentage breakdown */
+ if (dostates) /* but not the first time */
+ {
+ (*d_cpustates)(system_info.cpustates);
+ }
+ else
+ {
+ /* we'll do it next time */
+ if (smart_terminal)
+ {
+ z_cpustates();
+ }
+ else
+ {
+ putchar('\n');
+ }
+ dostates = Yes;
+ }
+
+ /* display memory stats */
+ (*d_memory)(system_info.memory);
+ (*d_arc)(system_info.arc);
+ (*d_carc)(system_info.carc);
+
+ /* display swap stats */
+ (*d_swap)(system_info.swap);
+
+ /* handle message area */
+ (*d_message)();
+
+ /* update the header area */
+ (*d_header)(header_text);
+
+ if (topn > 0)
+ {
+ /* determine number of processes to actually display */
+ /* this number will be the smallest of: active processes,
+ number user requested, number current screen accomodates */
+ active_procs = system_info.P_ACTIVE;
+ if (active_procs > topn)
+ {
+ active_procs = topn;
+ }
+ if (active_procs > max_topn)
+ {
+ active_procs = max_topn;
+ }
+
+ /* now show the top "n" processes. */
+ for (i = 0; i < active_procs; i++)
+ {
+ (*d_process)(i, format_next_process(processes, get_userid,
+ fmt_flags));
+ }
+ }
+ else
+ {
+ i = 0;
+ }
+
+ /* do end-screen processing */
+ u_endscreen(i);
+
+ /* now, flush the output buffer */
+ if (fflush(stdout) != 0)
+ {
+ new_message(MT_standout, " Write error on stdout");
+ putchar('\r');
+ quit(1);
+ /*NOTREACHED*/
+ }
+
+ /* only do the rest if we have more displays to show */
+ if (displays)
+ {
+ /* switch out for new display on smart terminals */
+ if (smart_terminal)
+ {
+ if (overstrike)
+ {
+ reset_display();
+ }
+ else
+ {
+ d_loadave = u_loadave;
+ d_procstates = u_procstates;
+ d_cpustates = u_cpustates;
+ d_memory = u_memory;
+ d_arc = u_arc;
+ d_carc = u_carc;
+ d_swap = u_swap;
+ d_message = u_message;
+ d_header = u_header;
+ d_process = u_process;
+ }
+ }
+
+ no_command = Yes;
+ if (!interactive)
+ {
+ sleep(delay);
+ if (leaveflag) {
+ end_screen();
+ exit(0);
+ }
+ }
+ else while (no_command)
+ {
+ /* assume valid command unless told otherwise */
+ no_command = No;
+
+ /* set up arguments for select with timeout */
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds); /* for standard input */
+ timeout.tv_sec = delay;
+ timeout.tv_usec = 0;
+
+ if (leaveflag) {
+ end_screen();
+ exit(0);
+ }
+
+ if (tstopflag) {
+ /* move to the lower left */
+ end_screen();
+ fflush(stdout);
+
+ /* default the signal handler action */
+ (void) signal(SIGTSTP, SIG_DFL);
+
+ /* unblock the signal and send ourselves one */
+#ifdef SIGRELSE
+ sigrelse(SIGTSTP);
+#else
+ (void) sigsetmask(sigblock(0) & ~(1 << (SIGTSTP - 1)));
+#endif
+ (void) kill(0, SIGTSTP);
+
+ /* reset the signal handler */
+ (void) signal(SIGTSTP, tstop);
+
+ /* reinit screen */
+ reinit_screen();
+ reset_display();
+ tstopflag = 0;
+ goto restart;
+ }
+
+ if (winchflag) {
+ /* reascertain the screen dimensions */
+ get_screensize();
+
+ /* tell display to resize */
+ max_topn = display_resize();
+
+ /* reset the signal handler */
+ (void) signal(SIGWINCH, top_winch);
+
+ reset_display();
+ winchflag = 0;
+ goto restart;
+ }
+
+ /* wait for either input or the end of the delay period */
+ sel_ret = select(2, &readfds, NULL, NULL, &timeout);
+ if (sel_ret < 0 && errno != EINTR)
+ quit(0);
+ if (sel_ret > 0)
+ {
+ int newval;
+ char *errmsg;
+
+ /* something to read -- clear the message area first */
+ clear_message();
+
+ /* now read it and convert to command strchr */
+ /* (use "change" as a temporary to hold strchr) */
+ if (read(0, &ch, 1) != 1)
+ {
+ /* read error: either 0 or -1 */
+ new_message(MT_standout, " Read error on stdin");
+ putchar('\r');
+ quit(1);
+ /*NOTREACHED*/
+ }
+ if ((iptr = strchr(command_chars, ch)) == NULL)
+ {
+ if (ch != '\r' && ch != '\n')
+ {
+ /* illegal command */
+ new_message(MT_standout, " Command not understood");
+ }
+ putchar('\r');
+ no_command = Yes;
+ }
+ else
+ {
+ change = iptr - command_chars;
+ if (overstrike && change > CMD_OSLIMIT)
+ {
+ /* error */
+ new_message(MT_standout,
+ " Command cannot be handled by this terminal");
+ putchar('\r');
+ no_command = Yes;
+ }
+ else switch(change)
+ {
+ case CMD_redraw: /* redraw screen */
+ reset_display();
+ break;
+
+ case CMD_update: /* merely update display */
+ /* is the load average high? */
+ if (system_info.load_avg[0] > LoadMax)
+ {
+ /* yes, go home for visual feedback */
+ go_home();
+ fflush(stdout);
+ }
+ break;
+
+ case CMD_quit: /* quit */
+ quit(0);
+ /*NOTREACHED*/
+ break;
+
+ case CMD_help1: /* help */
+ case CMD_help2:
+ reset_display();
+ top_clear();
+ show_help();
+ top_standout("Hit any key to continue: ");
+ fflush(stdout);
+ (void) read(0, &ch, 1);
+ break;
+
+ case CMD_errors: /* show errors */
+ if (error_count() == 0)
+ {
+ new_message(MT_standout,
+ " Currently no errors to report.");
+ putchar('\r');
+ no_command = Yes;
+ }
+ else
+ {
+ reset_display();
+ top_clear();
+ show_errors();
+ top_standout("Hit any key to continue: ");
+ fflush(stdout);
+ (void) read(0, &ch, 1);
+ }
+ break;
+
+ case CMD_number1: /* new number */
+ case CMD_number2:
+ new_message(MT_standout,
+ "Number of processes to show: ");
+ newval = readline(tempbuf1, 8, Yes);
+ if (newval > -1)
+ {
+ if (newval > max_topn)
+ {
+ new_message(MT_standout | MT_delayed,
+ " This terminal can only display %d processes.",
+ max_topn);
+ putchar('\r');
+ }
+
+ if (newval == 0)
+ {
+ /* inhibit the header */
+ display_header(No);
+ }
+ else if (newval > topn && topn == 0)
+ {
+ /* redraw the header */
+ display_header(Yes);
+ d_header = i_header;
+ }
+ topn = newval;
+ }
+ break;
+
+ case CMD_delay: /* new seconds delay */
+ new_message(MT_standout, "Seconds to delay: ");
+ if ((i = readline(tempbuf1, 8, Yes)) > -1)
+ {
+ if ((delay = i) == 0 && getuid() != 0)
+ {
+ delay = 1;
+ }
+ }
+ clear_message();
+ break;
+
+ case CMD_displays: /* change display count */
+ new_message(MT_standout,
+ "Displays to show (currently %s): ",
+ displays == -1 ? "infinite" :
+ itoa(displays));
+ if ((i = readline(tempbuf1, 10, Yes)) > 0)
+ {
+ displays = i;
+ }
+ else if (i == 0)
+ {
+ quit(0);
+ }
+ clear_message();
+ break;
+
+ case CMD_kill: /* kill program */
+ new_message(0, "kill ");
+ if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
+ {
+ if ((errmsg = kill_procs(tempbuf2)) != NULL)
+ {
+ new_message(MT_standout, "%s", errmsg);
+ putchar('\r');
+ no_command = Yes;
+ }
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
+
+ case CMD_renice: /* renice program */
+ new_message(0, "renice ");
+ if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
+ {
+ if ((errmsg = renice_procs(tempbuf2)) != NULL)
+ {
+ new_message(MT_standout, "%s", errmsg);
+ putchar('\r');
+ no_command = Yes;
+ }
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
+
+ case CMD_idletog:
+ case CMD_idletog2:
+ ps.idle = !ps.idle;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying idle processes.",
+ ps.idle ? "D" : "Not d");
+ putchar('\r');
+ break;
+
+ case CMD_selftog:
+ ps.self = (ps.self == -1) ? getpid() : -1;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying self.",
+ (ps.self == -1) ? "D" : "Not d");
+ putchar('\r');
+ break;
+
+ case CMD_user:
+ if (handle_user(tempbuf2, sizeof(tempbuf2)))
+ no_command = Yes;
+ break;
+
+ case CMD_thrtog:
+ ps.thread = !ps.thread;
+ new_message(MT_standout | MT_delayed,
+ " Displaying threads %s",
+ ps.thread ? "separately" : "as a count");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+ case CMD_wcputog:
+ ps.wcpu = !ps.wcpu;
+ new_message(MT_standout | MT_delayed,
+ " Displaying %s CPU",
+ ps.wcpu ? "weighted" : "raw");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+ case CMD_viewtog:
+ if (++displaymode == DISP_MAX)
+ displaymode = 0;
+ header_text = format_header(uname_field);
+ display_header(Yes);
+ d_header = i_header;
+ reset_display();
+ break;
+ case CMD_viewsys:
+ ps.system = !ps.system;
+ break;
+ case CMD_showargs:
+ fmt_flags ^= FMT_SHOWARGS;
+ break;
+#ifdef ORDER
+ case CMD_order:
+ new_message(MT_standout,
+ "Order to sort: ");
+ if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
+ {
+ if ((i = string_index(tempbuf2, statics.order_names)) == -1)
+ {
+ new_message(MT_standout,
+ " %s: unrecognized sorting order", tempbuf2);
+ no_command = Yes;
+ }
+ else
+ {
+ order_index = i;
+ }
+ putchar('\r');
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
+#endif
+ case CMD_jidtog:
+ ps.jail = !ps.jail;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying jail ID.",
+ ps.jail ? "D" : "Not d");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+
+ case CMD_jail:
+ new_message(MT_standout,
+ "Jail to show (+ for all): ");
+ if (readline(tempbuf2, sizeof(tempbuf2), No) > 0)
+ {
+ if (tempbuf2[0] == '+' &&
+ tempbuf2[1] == '\0')
+ {
+ ps.jid = -1;
+ }
+ else if ((i = jail_getid(tempbuf2)) == -1)
+ {
+ new_message(MT_standout,
+ " %s: unknown jail", tempbuf2);
+ no_command = Yes;
+ }
+ else
+ {
+ ps.jid = i;
+ }
+ if (ps.jail == 0) {
+ ps.jail = 1;
+ new_message(MT_standout |
+ MT_delayed, " Displaying jail "
+ "ID.");
+ header_text =
+ format_header(uname_field);
+ reset_display();
+ }
+ putchar('\r');
+ }
+ else
+ {
+ clear_message();
+ }
+ break;
+
+ case CMD_kidletog:
+ ps.kidle = !ps.kidle;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying system idle process.",
+ ps.kidle ? "D" : "Not d");
+ putchar('\r');
+ break;
+ case CMD_pcputog:
+ pcpu_stats = !pcpu_stats;
+ new_message(MT_standout | MT_delayed,
+ " Displaying %sCPU statistics.",
+ pcpu_stats ? "per-" : "global ");
+ toggle_pcpustats();
+ max_topn = display_updatecpus(&statics);
+ reset_display();
+ putchar('\r');
+ break;
+ case CMD_swaptog:
+ ps.swap = !ps.swap;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying per-process swap usage.",
+ ps.swap ? "D" : "Not d");
+ header_text = format_header(uname_field);
+ reset_display();
+ putchar('\r');
+ break;
+ default:
+ new_message(MT_standout, " BAD CASE IN SWITCH!");
+ putchar('\r');
+ }
+ }
+
+ /* flush out stuff that may have been written */
+ fflush(stdout);
+ }
+ }
+ }
+ }
+
+#ifdef DEBUG
+ fclose(debug);
+#endif
+ quit(0);
+ /*NOTREACHED*/
+}
+
+/*
+ * reset_display() - reset all the display routine pointers so that entire
+ * screen will get redrawn.
+ */
+
+void
+reset_display()
+
+{
+ d_loadave = i_loadave;
+ d_procstates = i_procstates;
+ d_cpustates = i_cpustates;
+ d_memory = i_memory;
+ d_arc = i_arc;
+ d_carc = i_carc;
+ d_swap = i_swap;
+ d_message = i_message;
+ d_header = i_header;
+ d_process = i_process;
+}
+
+/*
+ * signal handlers
+ */
+
+sigret_t leave() /* exit under normal conditions -- INT handler */
+
+{
+ leaveflag = 1;
+}
+
+sigret_t tstop(i) /* SIGTSTP handler */
+
+int i;
+
+{
+ tstopflag = 1;
+}
+
+#ifdef SIGWINCH
+sigret_t top_winch(int i) /* SIGWINCH handler */
+{
+ winchflag = 1;
+}
+#endif
+
+void quit(status) /* exit under duress */
+
+int status;
+
+{
+ end_screen();
+ exit(status);
+ /*NOTREACHED*/
+}
Index: head/usr.bin/top/top.local.hs
===================================================================
--- head/usr.bin/top/top.local.hs
+++ head/usr.bin/top/top.local.hs
@@ -0,0 +1,68 @@
+/*
+ * Top - a top users display for Berkeley Unix
+ *
+ * Definitions for things that might vary between installations.
+ */
+
+/*
+ * The space command forces an immediate update. Sometimes, on loaded
+ * systems, this update will take a significant period of time (because all
+ * the output is buffered). So, if the short-term load average is above
+ * "LoadMax", then top will put the cursor home immediately after the space
+ * is pressed before the next update is attempted. This serves as a visual
+ * acknowledgement of the command. On Suns, "LoadMax" will get multiplied by
+ * "FSCALE" before being compared to avenrun[0]. Therefore, "LoadMax"
+ * should always be specified as a floating point number.
+ */
+#ifndef LoadMax
+#define LoadMax %LoadMax%
+#endif
+
+/*
+ * "Table_size" defines the size of the hash tables used to map uid to
+ * username. The number of users in /etc/passwd CANNOT be greater than
+ * this number. If the error message "table overflow: too many users"
+ * is printed by top, then "Table_size" needs to be increased. Things will
+ * work best if the number is a prime number that is about twice the number
+ * of lines in /etc/passwd.
+ */
+#ifndef Table_size
+#define Table_size %TableSize%
+#endif
+
+/*
+ * "Nominal_TOPN" is used as the default TOPN when Default_TOPN is Infinity
+ * and the output is a dumb terminal. If we didn't do this, then
+ * installations who use a default TOPN of Infinity will get every
+ * process in the system when running top on a dumb terminal (or redirected
+ * to a file). Note that Nominal_TOPN is a default: it can still be
+ * overridden on the command line, even with the value "infinity".
+ */
+#ifndef Nominal_TOPN
+#define Nominal_TOPN %NominalTopn%
+#endif
+
+#ifndef Default_TOPN
+#define Default_TOPN %topn%
+#endif
+
+#ifndef Default_DELAY
+#define Default_DELAY %delay%
+#endif
+
+/*
+ * If the local system's getpwnam interface uses random access to retrieve
+ * a record (i.e.: 4.3 systems, Sun "yellow pages"), then defining
+ * RANDOM_PW will take advantage of that fact. If RANDOM_PW is defined,
+ * then getpwnam is used and the result is cached. If not, then getpwent
+ * is used to read and cache the password entries sequentially until the
+ * desired one is found.
+ *
+ * We initially set RANDOM_PW to something which is controllable by the
+ * Configure script. Then if its value is 0, we undef it.
+ */
+
+#define RANDOM_PW %random%
+#if RANDOM_PW == 0
+#undef RANDOM_PW
+#endif
Index: head/usr.bin/top/top.local.1
===================================================================
--- head/usr.bin/top/top.local.1
+++ head/usr.bin/top/top.local.1
@@ -1,84 +0,0 @@
-.\" $FreeBSD$
-.SH "FreeBSD NOTES"
-
-.SH DESCRIPTION OF MEMORY
-Mem: 61M Active, 86M Inact, 368K Laundry, 22G Wired, 102G Free
-ARC: 15G Total, 9303M MFU, 6155M MRU, 1464K Anon, 98M Header, 35M Other
- 15G Compressed, 27G Uncompressed, 1.75:1 Ratio, 174M Overhead
-Swap: 4096M Total, 532M Free, 13% Inuse, 80K In, 104K Out
-.TP
-.B K:
-Kilobyte
-.TP
-.B M:
-Megabyte
-.TP
-.B G:
-Gigabyte
-.TP
-.B %:
-1/100
-.SS Physical Memory Stats
-.TP
-.B Active:
-number of bytes active
-.TP
-.B Inact:
-number of clean bytes inactive
-.TP
-.B Laundry:
-number of dirty bytes queued for laundering
-.TP
-.B Wired:
-number of bytes wired down, including BIO-level cached file data pages
-.TP
-.B Buf:
-number of bytes used for BIO-level disk caching
-.TP
-.B Free:
-number of bytes free
-.SS ZFS ARC Stats
-These stats are only displayed when the ARC is in use.
-.TP
-.B Total:
-number of wired bytes used for the ZFS ARC
-.TP
-.B MRU:
-number of ARC bytes holding most recently used data
-.TP
-.B MFU:
-number of ARC bytes holding most frequently used data
-.TP
-.B Anon:
-number of ARC bytes holding in flight data
-.TP
-.B Header:
-number of ARC bytes holding headers
-.TP
-.B Other:
-miscellaneous ARC bytes
-.TP
-.B Compressed:
-bytes of memory used by ARC caches
-.TP
-.B Uncompressed:
-bytes of data stored in ARC caches before compression
-.TP
-.B Ratio:
-compression ratio of data cached in the ARC
-.SS Swap Stats
-.TP
-.B Total:
-total available swap usage
-.TP
-.B Free:
-total free swap usage
-.TP
-.B Inuse:
-swap usage
-.TP
-.B In:
-bytes paged in from swap devices (last interval)
-.TP
-.B Out:
-bytes paged out to swap devices (last interval)
Index: head/usr.bin/top/top.xs
===================================================================
--- head/usr.bin/top/top.xs
+++ head/usr.bin/top/top.xs
@@ -0,0 +1,459 @@
+.\" NOTE: changes to the manual page for "top" should be made in the
+.\" file "top.X" and NOT in the file "top.1".
+.\" $FreeBSD$
+.nr N %topn%
+.nr D %delay%
+.TH TOP 1 Local
+.UC 4
+.SH NAME
+top \- display and update information about the top cpu processes
+.SH SYNOPSIS
+.B top
+[
+.B \-abCHIijnPqStuvwz
+] [
+.BI \-d count
+] [
+.BI \-m io | cpu
+] [
+.BI \-o field
+] [
+.BI \-s time
+] [
+.BI \-J jail
+] [
+.BI \-U username
+] [
+.I number
+]
+.SH DESCRIPTION
+.\" This defines appropriate quote strings for nroff and troff
+.ds lq \&"
+.ds rq \&"
+.if t .ds lq ``
+.if t .ds rq ''
+.\" Just in case these number registers aren't set yet...
+.if \nN==0 .nr N 10
+.if \nD==0 .nr D 2
+.I Top
+displays the top
+.if !\nN==-1 \nN
+processes on the system and periodically updates this information.
+.if \nN==-1 \
+\{\
+If standard output is an intelligent terminal (see below) then
+as many processes as will fit on the terminal screen are displayed
+by default. Otherwise, a good number of them are shown (around 20).
+.\}
+Raw cpu percentage is used to rank the processes. If
+.I number
+is given, then the top
+.I number
+processes will be displayed instead of the default.
+.PP
+.I Top
+makes a distinction between terminals that support advanced capabilities
+and those that do not. This
+distinction affects the choice of defaults for certain options. In the
+remainder of this document, an \*(lqintelligent\*(rq terminal is one that
+supports cursor addressing, clear screen, and clear to end of line.
+Conversely, a \*(lqdumb\*(rq terminal is one that does not support such
+features. If the output of
+.I top
+is redirected to a file, it acts as if it were being run on a dumb
+terminal.
+.SH OPTIONS
+.TP
+.B \-C
+Toggle CPU display mode.
+By default top displays the weighted CPU percentage in the WCPU column
+(this is the same value that
+.IR ps (1)
+displays as CPU).
+Each time
+.B \-C
+flag is passed it toggles between \*(lqraw cpu\*(rq mode
+and \*(lqweighted cpu\*(rq mode, showing the \*(lqCPU\*(rq or
+the \*(lqWCPU\*(rq column respectively.
+.TP
+.B \-S
+Show system processes in the display. Normally, system processes such as
+the pager and the swapper are not shown. This option makes them visible.
+.TP
+.B \-a
+Display command names derived from the argv[] vector, rather than real
+executable name. It's useful when you want to watch applications, that
+puts their status information there. If the real name differs from argv[0],
+it will be displayed in parenthesis.
+.TP
+.B \-b
+Use \*(lqbatch\*(rq mode. In this mode, all input from the terminal is
+ignored. Interrupt characters (such as ^C and ^\e) still have an effect.
+This is the default on a dumb terminal, or when the output is not a terminal.
+.TP
+.B \-H
+Display each thread for a multithreaded process individually.
+By default a single summary line is displayed for each process.
+.TP
+.B \-i
+Use \*(lqinteractive\*(rq mode. In this mode, any input is immediately
+read for processing. See the section on \*(lqInteractive Mode\*(rq
+for an explanation of
+which keys perform what functions. After the command is processed, the
+screen will immediately be updated, even if the command was not
+understood. This mode is the default when standard output is an
+intelligent terminal.
+.TP
+.B \-I
+Do not display idle processes.
+By default, top displays both active and idle processes.
+.TP
+.B \-j
+Display the
+.IR jail (8)
+ID.
+.TP
+.B \-t
+Do not display the
+.I top
+process.
+.TP
+.BI \-m display
+Display either 'cpu' or 'io' statistics. Default is 'cpu'.
+.TP
+.B \-n
+Use \*(lqnon-interactive\*(rq mode. This is identical to \*(lqbatch\*(rq
+mode.
+.TP
+.B \-P
+Display per-cpu CPU usage statistics.
+.TP
+.B \-q
+Renice
+.I top
+to -20 so that it will run faster. This can be used when the system is
+being very sluggish to improve the possibility of discovering the problem.
+This option can only be used by root.
+.TP
+.B \-u
+Do not take the time to map uid numbers to usernames. Normally,
+.I top
+will read as much of the file \*(lq/etc/passwd\*(rq as is necessary to map
+all the user id numbers it encounters into login names. This option
+disables all that, while possibly decreasing execution time. The uid
+numbers are displayed instead of the names.
+.TP
+.B \-v
+Write version number information to stderr then exit immediately.
+No other processing takes place when this option is used. To see current
+revision information while top is running, use the help command \*(lq?\*(rq.
+.TP
+.B \-w
+Display approximate swap usage for each process.
+.TP
+.B \-z
+Do not display the system idle process.
+.TP
+.BI \-d count
+Show only
+.I count
+displays, then exit. A display is considered to be one update of the
+screen. This option allows the user to select the number of displays he
+wants to see before
+.I top
+automatically exits. For intelligent terminals, no upper limit
+is set. The default is 1 for dumb terminals.
+.TP
+.BI \-s time
+Set the delay between screen updates to
+.I time
+seconds. The default delay between updates is \nD seconds.
+.TP
+.BI \-o field
+Sort the process display area on the specified field. The field name
+is the name of the column as seen in the output, but in lower case:
+\*(lqcpu\*(lq, \*(rqsize\*(lq, \*(rqres\*(lq, \*(rqtime\*(lq,
+\*(rqpri\*(lq, \*(rqthreads\*(lq, \*(lqtotal\*(lq, \*(rqread\*(lq,
+\*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
+\*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
+.TP
+.BI \-J jail
+Show only those processes owned by
+.IR jail .
+This may be either the
+.B jid
+or
+.B name
+of the jail.
+Use
+.B 0
+to limit to host processes.
+Using this option implies the
+.B \-j
+flag.
+.PP
+.BI \-U username
+Show only those processes owned by
+.IR username .
+This option currently only accepts usernames and will not understand
+uid numbers.
+.PP
+Both
+.I count
+and
+.I number
+fields can be specified as \*(lqinfinite\*(rq, indicating that they can
+stretch as far as possible. This is accomplished by using any proper
+prefix of the keywords
+\*(lqinfinity\*(rq,
+\*(lqmaximum\*(rq,
+or
+\*(lqall\*(rq.
+The default for
+.I count
+on an intelligent terminal is, in fact,
+.BI infinity .
+.PP
+The environment variable
+.B TOP
+is examined for options before the command line is scanned. This enables
+a user to set his or her own defaults. The number of processes to display
+can also be specified in the environment variable
+.BR TOP .
+The options
+.BR \-a ,
+.BR \-C ,
+.BR \-H ,
+.BR \-I ,
+.BR \-j ,
+.BR \-P ,
+.BR \-S ,
+.BR \-t ,
+.BR \-u ,
+.BR \-w ,
+and
+.B \-z
+are actually toggles. A second specification of any of these options
+will negate the first. Thus a user who has the environment variable
+.B TOP
+set to \*(lq\-I\*(rq may use the command \*(lqtop \-I\*(rq to see idle processes.
+.SH "INTERACTIVE MODE"
+When
+.I top
+is running in \*(lqinteractive mode\*(rq, it reads commands from the
+terminal and acts upon them accordingly. In this mode, the terminal is
+put in \*(lqCBREAK\*(rq, so that a character will be
+processed as soon as it is typed. Almost always, a key will be
+pressed when
+.I top
+is between displays; that is, while it is waiting for
+.I time
+seconds to elapse. If this is the case, the command will be
+processed and the display will be updated immediately thereafter
+(reflecting any changes that the command may have specified). This
+happens even if the command was incorrect. If a key is pressed while
+.I top
+is in the middle of updating the display, it will finish the update and
+then process the command. Some commands require additional information,
+and the user will be prompted accordingly. While typing this information
+in, the user's erase and kill keys (as set up by the command
+.IR stty )
+are recognized, and a newline terminates the input.
+.PP
+These commands are currently recognized (^L refers to control-L):
+.TP
+.B ^L
+Redraw the screen.
+.IP "\fBh\fP\ or\ \fB?\fP"
+Display a summary of the commands (help screen). Version information
+is included in this display.
+.TP
+.B q
+Quit
+.IR top.
+.TP
+.B d
+Change the number of displays to show (prompt for new number).
+Remember that the next display counts as one, so typing
+.B d1
+will make
+.I top
+show one final display and then immediately exit.
+.TP
+.B m
+Toggle the display between 'cpu' and 'io' modes.
+.TP
+.B n or #
+Change the number of processes to display (prompt for new number).
+.TP
+.B s
+Change the number of seconds to delay between displays
+(prompt for new number).
+.TP
+.B S
+Toggle the display of system processes.
+.TP
+.B a
+Toggle the display of process titles.
+.TP
+.B k
+Send a signal (\*(lqkill\*(rq by default) to a list of processes. This
+acts similarly to the command
+.IR kill (1)).
+.TP
+.B r
+Change the priority (the \*(lqnice\*(rq) of a list of processes.
+This acts similarly to the command
+.IR renice (8)).
+.TP
+.B u
+Display only processes owned by a specific set of usernames (prompt for
+username). If the username specified is simply \*(lq+\*(rq or \*(lq-\*(rq,
+then processes belonging to all users will be displayed. Usernames can be added
+to and removed from the set by prepending them with \*(lq+\*(rq and
+\*(lq-\*(rq, respectively.
+.TP
+.B o
+Change the order in which the display is sorted. This command is not
+available on all systems. The sort key names vary from system to system
+but usually include: \*(lqcpu\*(rq, \*(lqres\*(rq, \*(lqsize\*(rq,
+\*(lqtime\*(rq. The default is cpu.
+.TP
+.B e
+Display a list of system errors (if any) generated by the last
+.BR k ill
+or
+.BR r enice
+command.
+.TP
+.B H
+Toggle the display of threads.
+.TP
+.B i
+(or
+.BR I )
+Toggle the display of idle processes.
+.TP
+.B j
+Toggle the display of
+.IR jail (8)
+ID.
+.TP
+.B J
+Display only processes owned by a specific jail (prompt for jail).
+If the jail specified is simply \*(lq+\*(rq, then processes belonging
+to all jails and the host will be displayed.
+This will also enable the display of JID.
+.TP
+.B P
+Toggle the display of per-CPU statistics.
+.TP
+.B t
+Toggle the display of the
+.I top
+process.
+.TP
+.B w
+Toggle the display of swap usage.
+.TP
+.B z
+Toggle the display of the system idle process.
+.SH "THE DISPLAY"
+The actual display varies depending on the specific variant of Unix
+that the machine is running. This description may not exactly match
+what is seen by top running on this particular machine. Differences
+are listed at the end of this manual entry.
+.PP
+The top few lines of the display show general information
+about the state of the system, including
+the last process id assigned to a process (on most systems),
+the three load averages,
+the current time,
+the number of existing processes,
+the number of processes in each state
+(sleeping, running, starting, zombies, and stopped),
+and a percentage of time spent in each of the processor states
+(user, nice, system, and idle).
+It also includes information about physical and virtual memory allocation.
+.PP
+The remainder of the screen displays information about individual
+processes. This display is similar in spirit to
+.IR ps (1)
+but it is not exactly the same. PID is the process id,
+JID, when displayed, is the
+.IR jail (8)
+ID corresponding to the process,
+USERNAME is the name of the process's owner (if
+.B \-u
+is specified, a UID column will be substituted for USERNAME),
+PRI is the current priority of the process,
+NICE is the nice amount (in the range \-20 to 20),
+SIZE is the total size of the process (text, data, and stack),
+RES is the current amount of resident memory,
+SWAP is the approximate amount of swap, if enabled
+(SIZE, RES and SWAP are given in kilobytes),
+STATE is the current state (one of \*(lqSTART\*(rq, \*(lqRUN\*(rq
+(shown as \*(lqCPUn\*(rq on SMP systems), \*(lqSLEEP\*(rq, \*(lqSTOP\*(rq,
+\*(lqZOMB\*(rq, \*(lqWAIT\*(rq, \*(lqLOCK\*(rq or the event on which the
+process waits),
+C is the processor number on which the process is executing
+(visible only on SMP systems),
+TIME is the number of system and user cpu seconds that the process has used,
+WCPU, when displayed, is the weighted cpu percentage (this is the same
+value that
+.IR ps (1)
+displays as CPU),
+CPU is the raw percentage and is the field that is sorted to determine
+the order of the processes, and
+COMMAND is the name of the command that the process is currently running
+(if the process is swapped out, this column is marked \*(lq<swapped>\*(rq).
+.SH NOTES
+If a process is in the \*(lqSLEEP\*(rq or \*(lqLOCK\*(rq state,
+the state column will report the name of the event or lock on which the
+process is waiting.
+Lock names are prefixed with an asterisk \*(lq*\*(rq while sleep events
+are not.
+.SH AUTHOR
+William LeFebvre, EECS Department, Northwestern University
+.SH ENVIRONMENT
+.DT
+TOP user-configurable defaults for options.
+.SH FILES
+.DT
+/dev/kmem kernel memory
+.br
+/dev/mem physical memory
+.br
+/etc/passwd used to map uid numbers to user names
+.br
+/boot/kernel/kernel system image
+.SH BUGS
+Don't shoot me, but the default for
+.B \-I
+has changed once again. So many people were confused by the fact that
+.I top
+wasn't showing them all the processes that I have decided to make the
+default behavior show idle processes, just like it did in version 2.
+But to appease folks who can't stand that behavior, I have added the
+ability to set \*(lqdefault\*(rq options in the environment variable
+.B TOP
+(see the OPTIONS section). Those who want the behavior that version
+3.0 had need only set the environment variable
+.B TOP
+to \*(lq\-I\*(rq.
+.PP
+The command name for swapped processes should be tracked down, but this
+would make the program run slower.
+.PP
+As with
+.IR ps (1),
+things can change while
+.I top
+is collecting information for an update. The picture it gives is only a
+close approximation to reality.
+.SH "SEE ALSO"
+kill(1),
+ps(1),
+stty(1),
+mem(4),
+renice(8)
Index: head/usr.bin/top/username.h
===================================================================
--- head/usr.bin/top/username.h
+++ head/usr.bin/top/username.h
@@ -0,0 +1,23 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ * Copyright (c) 2016, Randy Westlund
+ *
+ * $FreeBSD$
+ */
+#ifndef USERNAME_H
+#define USERNAME_H
+
+int enter_user(int uid, char *name, int wecare);
+int get_user(int uid);
+void init_hash(void);
+char *username(int uid);
+int userid(char *username);
+
+#endif /* USERNAME_H */
Index: head/usr.bin/top/username.c
===================================================================
--- head/usr.bin/top/username.c
+++ head/usr.bin/top/username.c
@@ -0,0 +1,195 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Username translation code for top.
+ *
+ * These routines handle uid to username mapping.
+ * They use a hashing table scheme to reduce reading overhead.
+ * For the time being, these are very straightforward hashing routines.
+ * Maybe someday I'll put in something better. But with the advent of
+ * "random access" password files, it might not be worth the effort.
+ *
+ * Changes to these have been provided by John Gilmore (gnu@toad.com).
+ *
+ * The hash has been simplified in this release, to avoid the
+ * table overflow problems of previous releases. If the value
+ * at the initial hash location is not right, it is replaced
+ * by the right value. Collisions will cause us to call getpw*
+ * but hey, this is a cache, not the Library of Congress.
+ * This makes the table size independent of the passwd file size.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "top.local.h"
+#include "utils.h"
+#include "username.h"
+
+struct hash_el {
+ int uid;
+ char name[MAXLOGNAME];
+};
+
+#define is_empty_hash(x) (hash_table[x].name[0] == 0)
+
+/* simple minded hashing function */
+/* Uid "nobody" is -2 results in hashit(-2) = -2 which is out of bounds for
+ the hash_table. Applied abs() function to fix. 2/16/96 tpugh
+*/
+#define hashit(i) (abs(i) % Table_size)
+
+/* K&R requires that statically declared tables be initialized to zero. */
+/* We depend on that for hash_table and YOUR compiler had BETTER do it! */
+struct hash_el hash_table[Table_size];
+
+
+void
+init_hash()
+
+{
+ /*
+ * There used to be some steps we had to take to initialize things.
+ * We don't need to do that anymore, but we will leave this stub in
+ * just in case future changes require initialization steps.
+ */
+}
+
+char *username(uid)
+
+int uid;
+
+{
+ register int hashindex;
+
+ hashindex = hashit(uid);
+ if (is_empty_hash(hashindex) || (hash_table[hashindex].uid != uid))
+ {
+ /* not here or not right -- get it out of passwd */
+ hashindex = get_user(uid);
+ }
+ return(hash_table[hashindex].name);
+}
+
+int userid(username)
+
+char *username;
+
+{
+ struct passwd *pwd;
+
+ /* Eventually we want this to enter everything in the hash table,
+ but for now we just do it simply and remember just the result.
+ */
+
+ if ((pwd = getpwnam(username)) == NULL)
+ {
+ return(-1);
+ }
+
+ /* enter the result in the hash table */
+ enter_user(pwd->pw_uid, username, 1);
+
+ /* return our result */
+ return(pwd->pw_uid);
+}
+
+int enter_user(uid, name, wecare)
+
+int uid;
+char *name;
+int wecare; /* 1 = enter it always, 0 = nice to have */
+
+{
+ register int hashindex;
+
+#ifdef DEBUG
+ fprintf(stderr, "enter_hash(%d, %s, %d)\n", uid, name, wecare);
+#endif
+
+ hashindex = hashit(uid);
+
+ if (!is_empty_hash(hashindex))
+ {
+ if (!wecare)
+ return 0; /* Don't clobber a slot for trash */
+ if (hash_table[hashindex].uid == uid)
+ return(hashindex); /* Fortuitous find */
+ }
+
+ /* empty or wrong slot -- fill it with new value */
+ hash_table[hashindex].uid = uid;
+ (void) strncpy(hash_table[hashindex].name, name, MAXLOGNAME - 1);
+ return(hashindex);
+}
+
+/*
+ * Get a userid->name mapping from the system.
+ * If the passwd database is hashed (#define RANDOM_PW), we
+ * just handle this uid. Otherwise we scan the passwd file
+ * and cache any entries we pass over while looking.
+ */
+
+int get_user(uid)
+
+int uid;
+
+{
+ struct passwd *pwd;
+
+#ifdef RANDOM_PW
+ /* no performance penalty for using getpwuid makes it easy */
+ if ((pwd = getpwuid(uid)) != NULL)
+ {
+ return(enter_user(pwd->pw_uid, pwd->pw_name, 1));
+ }
+#else
+
+ int from_start = 0;
+
+ /*
+ * If we just called getpwuid each time, things would be very slow
+ * since that just iterates through the passwd file each time. So,
+ * we walk through the file instead (using getpwent) and cache each
+ * entry as we go. Once the right record is found, we cache it and
+ * return immediately. The next time we come in, getpwent will get
+ * the next record. In theory, we never have to read the passwd file
+ * a second time (because we cache everything we read). But in
+ * practice, the cache may not be large enough, so if we don't find
+ * it the first time we have to scan the file a second time. This
+ * is not very efficient, but it will do for now.
+ */
+
+ while (from_start++ < 2)
+ {
+ while ((pwd = getpwent()) != NULL)
+ {
+ if (pwd->pw_uid == uid)
+ {
+ return(enter_user(pwd->pw_uid, pwd->pw_name, 1));
+ }
+ (void) enter_user(pwd->pw_uid, pwd->pw_name, 0);
+ }
+ /* try again */
+ setpwent();
+ }
+#endif
+ /* if we can't find the name at all, then use the uid as the name */
+ return(enter_user(uid, itoa7(uid), 1));
+}
Index: head/usr.bin/top/utils.h
===================================================================
--- head/usr.bin/top/utils.h
+++ head/usr.bin/top/utils.h
@@ -0,0 +1,26 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+/* prototypes for functions found in utils.c */
+
+int atoiwi();
+char *itoa();
+char *itoa7();
+int digits();
+char *strecpy();
+char **argparse();
+long percentages();
+char *errmsg();
+char *format_time();
+char *format_k();
+char *format_k2(unsigned long long);
+int string_index(char *string, char **array);
+
Index: head/usr.bin/top/utils.c
===================================================================
--- head/usr.bin/top/utils.c
+++ head/usr.bin/top/utils.c
@@ -0,0 +1,508 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This file contains various handy utilities used by top.
+ */
+
+#include "top.h"
+#include "os.h"
+
+int atoiwi(str)
+
+char *str;
+
+{
+ register int len;
+
+ len = strlen(str);
+ if (len != 0)
+ {
+ if (strncmp(str, "infinity", len) == 0 ||
+ strncmp(str, "all", len) == 0 ||
+ strncmp(str, "maximum", len) == 0)
+ {
+ return(Infinity);
+ }
+ else if (str[0] == '-')
+ {
+ return(Invalid);
+ }
+ else
+ {
+ return(atoi(str));
+ }
+ }
+ return(0);
+}
+
+/*
+ * itoa - convert integer (decimal) to ascii string for positive numbers
+ * only (we don't bother with negative numbers since we know we
+ * don't use them).
+ */
+
+ /*
+ * How do we know that 16 will suffice?
+ * Because the biggest number that we will
+ * ever convert will be 2^32-1, which is 10
+ * digits.
+ */
+_Static_assert(sizeof(int) <= 4, "buffer too small for this sized int");
+
+char *itoa(val)
+
+register int val;
+
+{
+ register char *ptr;
+ static char buffer[16]; /* result is built here */
+ /* 16 is sufficient since the largest number
+ we will ever convert will be 2^32-1,
+ which is 10 digits. */
+
+ ptr = buffer + sizeof(buffer);
+ *--ptr = '\0';
+ if (val == 0)
+ {
+ *--ptr = '0';
+ }
+ else while (val != 0)
+ {
+ *--ptr = (val % 10) + '0';
+ val /= 10;
+ }
+ return(ptr);
+}
+
+/*
+ * itoa7(val) - like itoa, except the number is right justified in a 7
+ * character field. This code is a duplication of itoa instead of
+ * a front end to a more general routine for efficiency.
+ */
+
+char *itoa7(val)
+
+register int val;
+
+{
+ register char *ptr;
+ static char buffer[16]; /* result is built here */
+ /* 16 is sufficient since the largest number
+ we will ever convert will be 2^32-1,
+ which is 10 digits. */
+
+ ptr = buffer + sizeof(buffer);
+ *--ptr = '\0';
+ if (val == 0)
+ {
+ *--ptr = '0';
+ }
+ else while (val != 0)
+ {
+ *--ptr = (val % 10) + '0';
+ val /= 10;
+ }
+ while (ptr > buffer + sizeof(buffer) - 7)
+ {
+ *--ptr = ' ';
+ }
+ return(ptr);
+}
+
+/*
+ * digits(val) - return number of decimal digits in val. Only works for
+ * positive numbers. If val <= 0 then digits(val) == 0.
+ */
+
+int digits(val)
+
+int val;
+
+{
+ register int cnt = 0;
+
+ while (val > 0)
+ {
+ cnt++;
+ val /= 10;
+ }
+ return(cnt);
+}
+
+/*
+ * strecpy(to, from) - copy string "from" into "to" and return a pointer
+ * to the END of the string "to".
+ */
+
+char *strecpy(to, from)
+
+register char *to;
+register char *from;
+
+{
+ while ((*to++ = *from++) != '\0');
+ return(--to);
+}
+
+/*
+ * string_index(string, array) - find string in array and return index
+ */
+
+int string_index(string, array)
+
+char *string;
+char **array;
+
+{
+ register int i = 0;
+
+ while (*array != NULL)
+ {
+ if (strcmp(string, *array) == 0)
+ {
+ return(i);
+ }
+ array++;
+ i++;
+ }
+ return(-1);
+}
+
+/*
+ * argparse(line, cntp) - parse arguments in string "line", separating them
+ * out into an argv-like array, and setting *cntp to the number of
+ * arguments encountered. This is a simple parser that doesn't understand
+ * squat about quotes.
+ */
+
+char **argparse(line, cntp)
+
+char *line;
+int *cntp;
+
+{
+ register char *from;
+ register char *to;
+ register int cnt;
+ register int ch;
+ int length;
+ int lastch;
+ register char **argv;
+ char **argarray;
+ char *args;
+
+ /* unfortunately, the only real way to do this is to go thru the
+ input string twice. */
+
+ /* step thru the string counting the white space sections */
+ from = line;
+ lastch = cnt = length = 0;
+ while ((ch = *from++) != '\0')
+ {
+ length++;
+ if (ch == ' ' && lastch != ' ')
+ {
+ cnt++;
+ }
+ lastch = ch;
+ }
+
+ /* add three to the count: one for the initial "dummy" argument,
+ one for the last argument and one for NULL */
+ cnt += 3;
+
+ /* allocate a char * array to hold the pointers */
+ argarray = (char **)malloc(cnt * sizeof(char *));
+
+ /* allocate another array to hold the strings themselves */
+ args = (char *)malloc(length+2);
+
+ /* initialization for main loop */
+ from = line;
+ to = args;
+ argv = argarray;
+ lastch = '\0';
+
+ /* create a dummy argument to keep getopt happy */
+ *argv++ = to;
+ *to++ = '\0';
+ cnt = 2;
+
+ /* now build argv while copying characters */
+ *argv++ = to;
+ while ((ch = *from++) != '\0')
+ {
+ if (ch != ' ')
+ {
+ if (lastch == ' ')
+ {
+ *to++ = '\0';
+ *argv++ = to;
+ cnt++;
+ }
+ *to++ = ch;
+ }
+ lastch = ch;
+ }
+ *to++ = '\0';
+
+ /* set cntp and return the allocated array */
+ *cntp = cnt;
+ return(argarray);
+}
+
+/*
+ * percentages(cnt, out, new, old, diffs) - calculate percentage change
+ * between array "old" and "new", putting the percentages i "out".
+ * "cnt" is size of each array and "diffs" is used for scratch space.
+ * The array "old" is updated on each call.
+ * The routine assumes modulo arithmetic. This function is especially
+ * useful on BSD mchines for calculating cpu state percentages.
+ */
+
+long percentages(cnt, out, new, old, diffs)
+
+int cnt;
+int *out;
+register long *new;
+register long *old;
+long *diffs;
+
+{
+ register int i;
+ register long change;
+ register long total_change;
+ register long *dp;
+ long half_total;
+
+ /* initialization */
+ total_change = 0;
+ dp = diffs;
+
+ /* calculate changes for each state and the overall change */
+ for (i = 0; i < cnt; i++)
+ {
+ if ((change = *new - *old) < 0)
+ {
+ /* this only happens when the counter wraps */
+ change = (int)
+ ((unsigned long)*new-(unsigned long)*old);
+ }
+ total_change += (*dp++ = change);
+ *old++ = *new++;
+ }
+
+ /* avoid divide by zero potential */
+ if (total_change == 0)
+ {
+ total_change = 1;
+ }
+
+ /* calculate percentages based on overall change, rounding up */
+ half_total = total_change / 2l;
+
+ /* Do not divide by 0. Causes Floating point exception */
+ if(total_change) {
+ for (i = 0; i < cnt; i++)
+ {
+ *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
+ }
+ }
+
+ /* return the total in case the caller wants to use it */
+ return(total_change);
+}
+
+/*
+ * errmsg(errnum) - return an error message string appropriate to the
+ * error number "errnum". This is a substitute for the System V
+ * function "strerror". There appears to be no reliable way to
+ * determine if "strerror" exists at compile time, so I make do
+ * by providing something of similar functionality. For those
+ * systems that have strerror and NOT errlist, define
+ * -DHAVE_STRERROR in the module file and this function will
+ * use strerror.
+ */
+
+/* externs referenced by errmsg */
+
+#ifndef HAVE_STRERROR
+#ifndef SYS_ERRLIST_DECLARED
+#define SYS_ERRLIST_DECLARED
+extern char *sys_errlist[];
+#endif
+
+extern int sys_nerr;
+#endif
+
+char *errmsg(errnum)
+
+int errnum;
+
+{
+#ifdef HAVE_STRERROR
+ char *msg = strerror(errnum);
+ if (msg != NULL)
+ {
+ return msg;
+ }
+#else
+ if (errnum > 0 && errnum < sys_nerr)
+ {
+ return((char *)sys_errlist[errnum]);
+ }
+#endif
+ return("No error");
+}
+
+/* format_time(seconds) - format number of seconds into a suitable
+ * display that will fit within 6 characters. Note that this
+ * routine builds its string in a static area. If it needs
+ * to be called more than once without overwriting previous data,
+ * then we will need to adopt a technique similar to the
+ * one used for format_k.
+ */
+
+/* Explanation:
+ We want to keep the output within 6 characters. For low values we use
+ the format mm:ss. For values that exceed 999:59, we switch to a format
+ that displays hours and fractions: hhh.tH. For values that exceed
+ 999.9, we use hhhh.t and drop the "H" designator. For values that
+ exceed 9999.9, we use "???".
+ */
+
+char *format_time(seconds)
+
+long seconds;
+
+{
+ register int value;
+ register int digit;
+ register char *ptr;
+ static char result[10];
+
+ /* sanity protection */
+ if (seconds < 0 || seconds > (99999l * 360l))
+ {
+ strcpy(result, " ???");
+ }
+ else if (seconds >= (1000l * 60l))
+ {
+ /* alternate (slow) method displaying hours and tenths */
+ sprintf(result, "%5.1fH", (double)seconds / (double)(60l * 60l));
+
+ /* It is possible that the sprintf took more than 6 characters.
+ If so, then the "H" appears as result[6]. If not, then there
+ is a \0 in result[6]. Either way, it is safe to step on.
+ */
+ result[6] = '\0';
+ }
+ else
+ {
+ /* standard method produces MMM:SS */
+ /* we avoid printf as must as possible to make this quick */
+ sprintf(result, "%3ld:%02ld",
+ (long)(seconds / 60), (long)(seconds % 60));
+ }
+ return(result);
+}
+
+/*
+ * format_k(amt) - format a kilobyte memory value, returning a string
+ * suitable for display. Returns a pointer to a static
+ * area that changes each call. "amt" is converted to a
+ * string with a trailing "K". If "amt" is 10000 or greater,
+ * then it is formatted as megabytes (rounded) with a
+ * trailing "M".
+ */
+
+/*
+ * Compromise time. We need to return a string, but we don't want the
+ * caller to have to worry about freeing a dynamically allocated string.
+ * Unfortunately, we can't just return a pointer to a static area as one
+ * of the common uses of this function is in a large call to sprintf where
+ * it might get invoked several times. Our compromise is to maintain an
+ * array of strings and cycle thru them with each invocation. We make the
+ * array large enough to handle the above mentioned case. The constant
+ * NUM_STRINGS defines the number of strings in this array: we can tolerate
+ * up to NUM_STRINGS calls before we start overwriting old information.
+ * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer
+ * to convert the modulo operation into something quicker. What a hack!
+ */
+
+#define NUM_STRINGS 8
+
+char *format_k(amt)
+
+int amt;
+
+{
+ static char retarray[NUM_STRINGS][16];
+ static int index = 0;
+ register char *p;
+ register char *ret;
+ register char tag = 'K';
+
+ p = ret = retarray[index];
+ index = (index + 1) % NUM_STRINGS;
+
+ if (amt >= 10000)
+ {
+ amt = (amt + 512) / 1024;
+ tag = 'M';
+ if (amt >= 10000)
+ {
+ amt = (amt + 512) / 1024;
+ tag = 'G';
+ }
+ }
+
+ p = strecpy(p, itoa(amt));
+ *p++ = tag;
+ *p = '\0';
+
+ return(ret);
+}
+
+char *format_k2(amt)
+
+unsigned long long amt;
+
+{
+ static char retarray[NUM_STRINGS][16];
+ static int index = 0;
+ register char *p;
+ register char *ret;
+ register char tag = 'K';
+
+ p = ret = retarray[index];
+ index = (index + 1) % NUM_STRINGS;
+
+ if (amt >= 100000)
+ {
+ amt = (amt + 512) / 1024;
+ tag = 'M';
+ if (amt >= 100000)
+ {
+ amt = (amt + 512) / 1024;
+ tag = 'G';
+ }
+ }
+
+ p = strecpy(p, itoa((int)amt));
+ *p++ = tag;
+ *p = '\0';
+
+ return(ret);
+}
Index: head/usr.bin/top/version.c
===================================================================
--- head/usr.bin/top/version.c
+++ head/usr.bin/top/version.c
@@ -0,0 +1,28 @@
+/*
+ * Top users/processes display for Unix
+ * Version 3
+ *
+ * This program may be freely redistributed,
+ * but this entire comment MUST remain intact.
+ *
+ * Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "top.h"
+#include "patchlevel.h"
+
+static char version[16];
+
+char *version_string()
+
+{
+ sprintf(version, "%d.%d", VERSION, PATCHLEVEL);
+#ifdef BETA
+ strcat(version, BETA);
+#endif
+ return(version);
+}

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 17, 11:10 PM (10 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29857676
Default Alt Text
D15387.id42750.diff (384 KB)

Event Timeline