Rename top(1) to mtop(1), import NetBSD top(1)

Due to differences in (mainly) measuring and accumulating CPU times,
the two top programs end up serving different purposes: the NetBSD
top is a system administration tool, while the MINIX3 top (now mtop)
is a performance debugging tool.  Therefore, we keep both.

The newly imported BSD top has a few MINIX3-specific changes.  CPU
statistics separate system time from kernel time, rather than kernel
time from time spent on handling interrupts.  Memory statistics show
numbers that are currently relevant for MINIX3.  Swap statistics are
disabled entirely.  All of these changes effectively bring it closer
to how mtop already worked as well.

Change-Id: I9611917cb03e164ddf012c5def6da0e7fede826d
This commit is contained in:
David van Moolenbroek
2015-11-08 11:29:53 +00:00
committed by Lionel Sambuc
parent 97189037b1
commit b89261ba01
91 changed files with 46927 additions and 3 deletions

View File

@@ -406,6 +406,7 @@
./usr/bin/more minix-base
./usr/bin/msgc minix-base
./usr/bin/mt minix-base
./usr/bin/mtop minix-base
./usr/bin/nbperf minix-base
./usr/bin/netpgp minix-base crypto
./usr/bin/netpgpkeys minix-base crypto

View File

@@ -367,6 +367,7 @@
./usr/man/man1/tic.1 minix-man
./usr/man/man1/time.1 minix-man
./usr/man/man1/tmux.1 minix-man
./usr/man/man1/top.1 minix-man
./usr/man/man1/touch.1 minix-man
./usr/man/man1/tput.1 minix-man
./usr/man/man1/tr.1 minix-man

View File

@@ -6,7 +6,7 @@
SUBDIR= byacc \
fetch file flex less \
libarchive libevent mdocml \
tmux
tmux top
.if (${MKATF} != "no")
SUBDIR+= atf

5
external/bsd/top/Makefile vendored Normal file
View File

@@ -0,0 +1,5 @@
# $NetBSD: Makefile,v 1.2 2008/07/17 10:46:56 lukem Exp $
SUBDIR= bin
.include <bsd.subdir.mk>

41
external/bsd/top/bin/Makefile vendored Normal file
View File

@@ -0,0 +1,41 @@
# $NetBSD: Makefile,v 1.9 2013/03/21 21:43:22 christos Exp $
.include <bsd.own.mk>
PROG= top
BINDIR= /usr/bin
TOPDIR=${.CURDIR}/../dist
.PATH: ${TOPDIR} ${TOPDIR}/machine
WARNS= 4
CWARNFLAGS+= -Wno-missing-noreturn
CPPFLAGS+=-I${.CURDIR} -I${TOPDIR} -I.
SRCS= color.c commands.c display.c hash.c screen.c \
top.c username.c utils.c version.c m_netbsd.c
DPSRCS+=sigdesc.h config.h
LDADD+= -lterminfo -lm -lkvm -lutil
DPADD+= ${LIBTERMINFO} ${LIBM} ${LIBKVM} ${LIBUTIL}
sigdesc.h: ${TOPDIR}/sigconv.awk ${DESTDIR}/usr/include/sys/signal.h
${_MKTARGET_CREATE}
${TOOL_AWK} -f ${TOPDIR}/sigconv.awk \
${DESTDIR}/usr/include/sys/signal.h > ${.TARGET}
CLEANFILES+= sigdesc.h top.1 config.h
top.1: top.1.in
${TOOL_SED} -e s/@DEFAULT_TOPN@/-1/ \
-e s/@DEFAULT_DELAY@/5/ \
-e s/@HAVE_GETOPT_LONG@/1/ \
-e s/@ENABLE_KILL@/1/ \
-e s/@MAN_SUPPLEMENT@// < $? > $@
commands.c: sigdesc.h
config.h: config.h.in
${TOOL_SED} -e s/@MACHINE@/${MACHINE}/ < $? > $@
COPTS.display.c = -Wno-format-nonliteral
.include <bsd.prog.mk>

257
external/bsd/top/bin/config.h.in vendored Normal file
View File

@@ -0,0 +1,257 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Support for debugging output */
/* #undef DEBUG */
/* Default delay */
#define DEFAULT_DELAY 5
/* Default number of processes to display */
#define DEFAULT_TOPN -1
/* Enable color */
#define ENABLE_COLOR 1
/* Enable dual architecture */
/* #undef ENABLE_DUALARCH */
/* Enable kill and renice */
#define ENABLE_KILL 1
/* Supports C99 style variadic macros */
#define HAVE_C99_VARIADIC_MACROS 1
/* Define to 1 if you have the <curses.h> header file. */
#define HAVE_CURSES_H 1
/* Define to 1 if you have the declaration of `sys_errlist', and to 0 if you
don't. */
#define HAVE_DECL_SYS_ERRLIST 0
/* Define to 1 if you have the declaration of `sys_signame', and to 0 if you
don't. */
#define HAVE_DECL_SYS_SIGNAME 1
/* Define to 1 if you have the declaration of `tgetent', and to 0 if you
don't. */
#define HAVE_DECL_TGETENT 1
/* Define to 1 if you have the declaration of `tgetflag', and to 0 if you
don't. */
#define HAVE_DECL_TGETFLAG 1
/* Define to 1 if you have the declaration of `tgetnum', and to 0 if you
don't. */
#define HAVE_DECL_TGETNUM 1
/* Define to 1 if you have the declaration of `tgetstr', and to 0 if you
don't. */
#define HAVE_DECL_TGETSTR 1
/* Define to 1 if you have the declaration of `tgoto', and to 0 if you don't.
*/
#define HAVE_DECL_TGOTO 1
/* Define to 1 if you have the declaration of `tputs', and to 0 if you don't.
*/
#define HAVE_DECL_TPUTS 1
/* Platform module */
#define HAVE_FORMAT_PROCESS_HEADER 1
/* Define to 1 if you have the `getopt' function. */
#define HAVE_GETOPT 1
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
/* Define to 1 if you have the `getopt_long' function. */
#define HAVE_GETOPT_LONG 1
/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1
/* Supports gnu style variadic macros */
#define HAVE_GNU_VARIADIC_MACROS 1
/* Define to 1 if the system has the type `id_t'. */
#define HAVE_ID_T 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `elf' library (-lelf). */
/* #undef HAVE_LIBELF */
/* Define to 1 if you have the `kstat' library (-lkstat). */
/* #undef HAVE_LIBKSTAT */
/* Define to 1 if you have the `kvm' library (-lkvm). */
#define HAVE_LIBKVM 1
/* Define to 1 if you have the `m' library (-lm). */
#define HAVE_LIBM 1
/* Define to 1 if you have the `mach' library (-lmach). */
/* #undef HAVE_LIBMACH */
/* Define to 1 if you have the `mas' library (-lmas). */
/* #undef HAVE_LIBMAS */
/* Define to 1 if you have the `perfstat' library (-lperfstat). */
/* #undef HAVE_LIBPERFSTAT */
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if the system has the type `lwpid_t'. */
#define HAVE_LWPID_T 1
/* Define to 1 if you have the <math.h> header file. */
#define HAVE_MATH_H 1
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if the system has the type `pid_t'. */
#define HAVE_PID_T 1
/* Define to 1 if you have the `setbuffer' function. */
#define HAVE_SETBUFFER 1
/* Define to 1 if you have the `setpriority' function. */
#define HAVE_SETPRIORITY 1
/* Define to 1 if you have the `setvbuf' function. */
#define HAVE_SETVBUF 1
/* Define to 1 if you have the `sigaction' function. */
#define HAVE_SIGACTION 1
/* Define to 1 if you have the `sighold' function. */
#define HAVE_SIGHOLD 1
/* Define to 1 if you have the `sigprocmask' function. */
#define HAVE_SIGPROCMASK 1
/* Define to 1 if you have the `sigrelse' function. */
#define HAVE_SIGRELSE 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `sysconf' function. */
#define HAVE_SYSCONF 1
/* Define to 1 if you have the <sysexits.h> header file. */
#define HAVE_SYSEXITS_H 1
/* Define to 1 if you have the <sys/resource.h> header file. */
#define HAVE_SYS_RESOURCE_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/utsname.h> header file. */
#define HAVE_SYS_UTSNAME_H 1
/* Define to 1 if you have the <termcap.h> header file. */
#define HAVE_TERMCAP_H 1
/* Define to 1 if you have the <term.h> header file. */
/* #undef HAVE_TERM_H */
/* Define to 1 if the system has the type `time_t'. */
#define HAVE_TIME_T 1
/* Define to 1 if the system has the type `uid_t'. */
#define HAVE_UID_T 1
/* Define to 1 if you have the `uname' function. */
#define HAVE_UNAME 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Platform module */
#define MODULE "netbsd"
/* Default number of processes to display on non-terminals when topn is all */
#define NOMINAL_TOPN 40
/* Define the major OS revision number. */
#define OSMAJOR 4
/* Define the OS revision. */
#define OSREV 49962
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME "top"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "top 3.8beta1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "top"
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.8beta1"
/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define TIME_WITH_SYS_TIME 1
/* Define as the type for the argument to the putc function of tputs ('int' or
'char') */
#define TPUTS_PUTC_ARGTYPE int
/* Define the system hardware platform */
#define UNAME_HARDWARE "@MACHINE@"
/* Include code that utilizes extensions */
/* #undef WITH_EXT */

949
external/bsd/top/dist/Changes vendored Normal file
View File

@@ -0,0 +1,949 @@
Tue May 6 2008 - wnl (3.8beta1)
Main code: fixed bugs in screen_cleareol and in display code. Fixed
bug in i_swap when all data is 0. Added ^W patch (from thaquis).
Fixed bug in xdprintf. Added command line options for the "t" and
"m" commands.
SunOS 5 changes: Support for showing individual threads. Redid
allocation of prpsinfo structures. Added a pidthr hash that uses
both pid and thread id for a key. Changed format_process_header
and format_next_process to use a table-driven method for generating
the columns. Status files from /proc (psinfo and lpsinfo) are now
cached to avoid repeatedly reopening them. Column showing number of
LWPs is now called "NLWP" and column showing lwpid is "LWP".
FreeBSD changes: Runtime check to ensure binary is running on
the same machine type it was compiled for. Lots of cleanup and
changed nearly everything to use sysctl rather than kvm, and
inability to open kvm is no longer fatal. Improved thread reporting:
disabled for 7.x and lower. Added lwpid hash for proper tracking
of threads. Changed format_process_header and format_next_process
to use a table-driven method for generating the columns.
Dec Alpha: configure uses compile-time options to properly trap
and handle exceptions from the Alpha FPU (from Brian Maly).
Tue Feb 26 2008 - wnl (3.7)
Prepare for version 3.7 release.
Fri Feb 1 2008 - wnl (3.7beta4)
Using the $ notation in printf formats for freebsd apparently was
causing problems on 64-bit systems. All such usage has been
removed and the process line is formatted piecemeal.
Thu Dec 27 2007 - wnl (3.7beta3)
Improved function comments in display.c for message_error functions.
Changed some of the error messages in top.c to be more succint.
Fri Dec 7 2007 - wnl (3.7beta3)
Changes to freebsd port: moved some functions up front to
eliminate forward references. Use sysctl to get all vm stats
information, as some of this isn't updated in the struct
vmmeter under FreeBSD 7.0. Added routines to support large-scale
sysctl access.
Wed Nov 28 2007 - wnl (3.7beta3)
Changes to documentation: FAQ, README, man page.
Tue Nov 27 2007 - wnl (3.7beta3)
For freebsd, added page faults, pageins, pageouts, and pages
freed to the kernel display line. These numbers reflect the
values presented in vmstat. For sunos5, added page faults,
pageins and pageouts to the kernel display line.
Fri Nov 2 2007 - wnl (3.7beta3)
Added copyright notices to the top of every source and include file.
Added copyright information to the man page.
Removed a few outdated things from the manifest.
Minor changes to sigconv.awk.
Sat Oct 27 2007 - wnl (3.7beta3)
Added check for sys_signame at configure time and if it is
present then it is used in commands.c to translate signal names
in to numbers.
Added alternate snprintf and vsnprintf functions from apache (in
ap_snprintf.c). Added configure magic to define and compile them in
where needed. Added check to configure for variadic macros.
Preprocessor defintion of dprintf (in utils.h) now depends on
support for variadic macros. Cleaned up m_linux code.
Wed Oct 3 2007 - wnl (3.7beta3)
Lots of changes, thanks to Mark Wong. Most changes were to
clean the code up so that it would compile cleanly with -Wall
(all warnings). Changed function names in screen.c so that
they all start with "screen_". Isolated all interaction with
termcap to screen.c by adding a real function for cursor
addressing (in the past it was just a macro). Only screen.c
now needs to worry about defining templates for the termcap
functions. Added configure and preprocessor magic to ensure
that all the termcap functions used in the code are defined
with templates. Changed names of some other functions and
global variables to avoid name conflicts with functions in
curses and other well established libraries. Changed dprintf
macro to use variadic arguments so that the preprocessor can
gobble up the entire call when compiling without debugging
(this will have to be made more portable). All include files
are surrounded by #ifndef statements to accomodate multiple
inclusions. Platform module is now compiled with
-fno-strict-aliasing as some of the modules do type punning
that can confuse the optimizer.
Wed Sep 26 2007 - wnl (3.7beta3)
For freebsd, priority is no longer normalized by PZERO. This
contradicts the behavior used by ps when it displays priority.
But normalizing by PZERO has become a bit of an anachronism
and it actually obscures the meaning of the priority without
adding any real value.
Wed Sep 19 2007 - wnl (3.7beta3)
Many changes to improve the display of threads. Changed
process summary line to use the word "threads" when showing
individual threads. Added the system command to toggle the
display of system processes. Fixed bug in hash.c remove_pos.
For freebsd: count threads correctly when they are being
displayed, nice column is more closely in line with ps
(nothing fancy for real time processes), add two more process
states that didn't exist in older releases of freebsd (wait
and lock).
For linux: Threads done right. Now track individual threads
of multi-threaded processes separately so that we always know
their %cpu. Switch to format_process_header so that we can
change the column headings and remove the THR column when
displaying individual threads. Switched process (and thread)
tracking over to use generic hash table functions included
with the new version of top. Process states and total now
include threads when they are being shown. Added "SHR" column
to show the amount of shared memory per process. Improved
calculation of elapsed time and percent cpu to avoid
overflows. Remove weighted cpu calculations entirely as it is
an anachronism.
For Solaris: Moved check for libelf to accomodate older systems.
Sun Sep 9 2007 - wnl (3.7beta2)
Documentation changes. Fixes to sunos5 port. Added display of
thread count and selection by command name to linux port. Removed
the use of inline functions from hash.c as that doesn't appear to
be very portable.
Wed Sep 5 2007 - wnl (3.7beta1)
Fixed freebsd and linux configuration bugs. Added configuration
options for tweaking program defaults. Rewrote top level code
(top.c) from scratch, including command handling so that adding
new commands is much easier. Changed message-line handling to
ensure that the message is displayed for at least 5 seconds
regardless of the update frequency. Added a "miniupdate" that
occurs one second after the initial screen on systems that don't
already delay the first screen. The mini-update shows cpu state
percentages. Added ability to select output by command name on
some systems. Fixed color toggling via the "C" command. Added
long options via getopt_long to complement the existing single
character options. Added the freebsd "m" command to chose
alternate display modes. On freebsd this gives a process i/o
display. Added the freebsd "H" command to select the display of
individual threads. Added "-a" option ("all") to set number of
displays and number of processes to infinity (equivalent to
"-d all all"). Added dual architecture compilation for Solaris
to generate both a 32-bit and a 64-bit binary. This is on by
default when compiling on a 64-bit system and can be explicitly
set via "configure --enable-dualarch". Added uniform hashing
functions that use bucket hash for uint, pid, and string. Changed
username.c and the sunos and freebsd modules to use these functions.
Added the "kernel" information line to the display to show
statistics on what the kernel is doing (context switches, forks,
traps, etc.). This requires explicit support by the platform
module, currently only freebsd, linux, and sunos.
Wed Apr 18 2007 - wnl (3.6.1)
Fixed a few bugs in sigconv.awk that were causing incorrect
results on FreeBSD. Changed configure.ac to fix a few linux
problems: signal include file and /proc/1/stat.
Fri Apr 13 2007 - wnl (3.6.1)
Removed the use of VPATH for compiling the system module and used
an explicit dependency in the Makefile instead. VPATH is now set
to just srcdir to ensure that top will compile correctly when
configured from a different directory. On systems without VPATH
support, top will still configure and compile, but only
from within the source directory. This fixes bug 1699526.
Fri Feb 2 2007 - wnl (3.6.1)
Revised the way that configure figures out owner, group, and mode.
For systems that don't use the kernel, it tries to match install
settings to allow access to stuff in /proc. More importantly, if
mode is 755 then neither owner nor group are set. This fixes bug
1631136. Added patch from haanjdj@xs4all.nl to fix an occasional
core dump in m_decosf1.c. This checks return code from task_threads.
Made sure all get_system_info functions are declared void. Fixed
string termination bug. Cleaned up documetation for sunos5.
Tue Aug 8 2006 - wnl (3.6.1)
For Solaris, changed the tag "swap" to "total swap" to clarify
what is beign displayed. Note that the calculations are still the
same: the display is just showing total rather than total - free.
Thu Apr 27 2006 - wnl (3.6)
Added patches for linux-style sort shortcuts and for Unixware
support in configure (patch 1474427). Fixed sunos5 to do slow start
and to ensure cpucount is set (patch 1477386). Added pagination
routines to display.c and modified show_help to use it, since the
help screen is now longer than 24 lines. Applied patch for unixware
support that adds check for mas library (patch #1474423). Solaris
cpu percent now reflects a percentage of the entire server, rather
than a single cpu (bug 1478138).
Mon Mar 27 2006 - wnl (3.6)
The production release of version 3.6. Fixed a minor scaling
bug in the decosf1 module. Support for MacOS X is officially
withdrawn although the macosx module is still part of the
distribution. Hopefully this is a temporary situation.
Documentation updated.
Wed Feb 15 2006 - wnl (3.6beta5)
Minor changes to eliminate warnings from the Sun Studio compiler.
These were mostly sloppy argument declarations. I also added
message.h to provide an interface file for just the message
related functions of display.c.
Mon Dec 26 2005 - wnl (3.6beta4)
Added new netbsd module, courtesy of Simon Burge.
Fixed a few bugs in SVR4 module and added its use to
configure.ac, thanks to Sanchet Dighe. Also ensured that the
novpath Makefile was in the distribution.
Fixed portability problem in display.c
Mon Oct 24 2005 - wnl (3.6beta3)
Set up a color tagging mechanism in color.c to allow for the
dynamic creation of tag names to contol color highlighting.
These names are partially derived from the tags used to label
memory and swap information on the screen, thus are driven by
the machine module itself. Added -T option to list color
highlighting information. Help screen now includes the actual
list of sort order names. Incorporated some minor fixes to
the main code from the Freebsd source tree. Fixed bug #1324582.
Freebsd 5: removed WCPU column and added THR column. Display
for freebsd 4 and earlier unchanged since they don't track
threads in the kernel. Added LICENSE file to distribution.
Wed Oct 12 2005 - wnl (3.6beta2)
Major overhaul to display.c. All lines of the display are
directly tracked and controlled via display_write and its
companion display_fmt. Added support for complete control
of ANSI color on the screen: this will be used in the future
to allow for full use of color everywhere on the screen.
Signal handling code now uses sigaction on all systems that
support it. Restored the freebsd module and did away with
freebsd4, and upgraded freebsd module to support 5.x.
Fix bug #1306099 (wio(wait) timer ignored on OSF1).
Fri Sep 23 2005 - wnl (3.6beta1)
Fixed bugs #1266341 (compilation errors with gcc 4.x),
#1156464 (cpu% field for sunos), #1156243 (compilation
errors on AIX). Applied patches #1217855 (Solaris 10
xarch flag). Overhaul of sunos5 module, making code more
efficient and easier to follow. Got rid of need for MEMTYPE
type in utils.h. Changed all memory statistics data in the
module specification from an int to a long to better support
64-bit systems with lots of memory. Moved all unused modules
out of the distribution (I will add them back in as needed).
Moved freebsd module to freebsd4 as it won't work with 5.x
(a new module will be necessary). Added support to configure
for makes that don't understand VPATH. Updated documentation:
man page, FAQ, README, INSTALL.
Mon Jan 24 2005 - wnl (3.6alpha10)
Updated aix43 module with ANSI function declarations and fixed
declaration of get_system_info. Configure now uses irixsgi
module for irix6* systems. Updates to the following modules:
irixsgi, sunos5. Fixed null pointer bug in color.c. Removed
some useless code and definitions in display.c
Sun Nov 28 2004 - wnl (3.6alpha9)
Replace AIX 5 module with alternate (bug 1056565).
Fixed vulnerability in use of snprintf.
Fri Oct 22 2004 - wnl (3.6alpha8)
Support for linux 2.6, added more stuff to memory and swap lines.
Updated linuxthr module, which is only useful on 2.4 and earlier.
Added some color support back in (feature request 930588), but
still need to add it back to the per-process display. Added
OSF 5 support (untested).
Fixed bug 1017951 (invalid process count argument not caught)
Tue Apr 20 2004 - wnl (3.6alpha7)
Added 64 bit support for AIX.
Thu Apr 15 2004 - wnl (3.6alpha6)
Included fixes for decosf1 pid size and updated module. Also
added osf1 to list of recognized operating systems in configure.ac.
Tue Mar 30 2004 - wnl (3.6alpha5)
Minor bug fixes and some code rearrangement. Changes to install
rule. Added several more platforms including: aix 4.2 thru 5,
MacOS 10, Dec OSF, HPUX 7 thru 11. Fixed the core dumping bug
in linux. Code cleanup, including sigdesc.h (by changing
sigconv.awk). Startup error messages are displayed on the
first screen rather than beforehand (no more pause). Cleaned
up interrupt handling to avoid a race condition. Eliminated
top.local.h. REMOVED Configure!!!
Mon Mar 22 2004 - wnl (3.6alpha1)
Now using gnu autoconf. Eliminated the need for CFLAGS and LIBS
tags in the module source files. Autoconf tries to figure all
that out now. Machine module interface now uses flags to determine
if module supports sorting, selective display of idle processes,
viewing full commands. Added display of uptime for modules that
support it. Added display of full command lines for modules that
support it. 3.5 modules must be changed a bit to work for 3.6:
ORDER is no longer defined, and the module must fill in the
appropriate fields in struct statics to get the extra features.
Added a extenstion interface to allow for putting extra stuff
on the screen -- this is still half baked and not documented.
Mon Feb 23 2004 - wnl (3.5)
Turned rc1 in to version 3.5. Only changes were to the FAQ.
Mon Feb 2 2004 - wnl (3.5rc1)
Changed format_k (utils.c) to use MEMTYPE for its parameter.
On most systems this is a long, but if the module defines
USE_SIZE_T, this is set to be a size_t. The sunos5 module
now defines it, so that it will work correctly on 64-bit
machines. New "linuxthr" module for rolling up processes
that are really threads. Configure autodetects when running
on a 64-bit Solaris machine.
Tue Dec 16 2003 - wnl (3.5beta13)
Improved linux module. For Solaris, changed "THR" column
heading to "LWP" since that's what they really are.
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.

340
external/bsd/top/dist/FAQ vendored Normal file
View File

@@ -0,0 +1,340 @@
TOP
Version 3.8beta1
William LeFebvre
with much help from others
Frequently Asked Questions and their Answers
GENERAL
1. What is top?
Top provies the user with a regularly updated display showing
information about the system and its top cpu-using processes. Think
of it as a full-screen "ps" output that gets updated at regular
intervals.
2. Where do I get the latest version of top?
The official site for top is "ftp.unixtop.org" in the directory
"/pub/top". Top is also a SourceForge project, and the most recent
releases are available on any of the SourceForge mirrors. The
SourceForge project page is at
http://sourceforge.net/projects/unixtop.
3. Is there a web page for top?
Yes. Point your browser at http://www.unixtop.org. 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 other neat stuff.
4. Is there a mailing list or on-line bulletin board for top?
There is a mailing list used for general announcements regarding top,
including new releases. This mailing list is available to sourceforge
members and can be accessed from the unixtop sourceforge project
page. Visit SourceForge and search for the project "unixtop", then
click on "mailing lists". There are also on-line forums available
through SourceForge where members can post questions and comments.
5. What about Year 2000 compliance?
Top did 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.
6. Will there be another major release of top? Will there be a top
version 4?
I have some great ideas for the next major release of top, and I very
much want to make those ideas a reality. What I don't have much of
these days is free time. But I will keep poking at it and I hope to
have top version 4.0 ready by the fall of 2006.
7. Does top really support multi-processor systems?
On platforms that support multiple processors, top is able to detect
and correctly summarize the information about those processors. What
top does not do is break down the cpu states summary (the third line
of the display) by cpu. Instead it collects the cpu state information
from all processors and combines them in to a single line. Some
vendors include a modified version of top that presents this
information for each cpu. Top 3.7 may have this functionality but it
is not present in the standard top 3.6 release.
8. Is top under CVS control? Can I access the sources via SourceForge
CVS or Subversion?
I maintain top using subversion, not CVS. Although I utilize my own
private subversion repository, it is regularly mirrored in to the
SourceForge Subversion repository. You can access the SourceForge
repository here: https://svn.unixtop.org/unixtop/top-3.
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 "install" 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. Also note
that newer versions of top can use columns beyond 79, and understand
window resizes. So you can always make your window wider.
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.6 to Solaris
2.7) 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 a different compiler.
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.
FREEBSD PROBLEMS
15. This version of top does not show individual threads with the "t" or
"H" commands. Instead it says "command not available." Why?
Previous versions of top attempted to support the display of
individual threads under FreeBSD through the use of the "t" command.
However, the FreeBSD kernel does not supply sufficient or correct
information on the individual threads within a process. So the data
that was being displayed was incorrect and misleading. Therefore, top
version 3.8 disables the use of this command to prevent the display
of incorrect information. FreeBSD 8.0 will correctly report
per-thread information and top version 3.8 supports the use of the
"t" command for version 8.0.
16. The "f" command (to display full command lines for the processes)
does not work and instead says "command not available". Why?
The current version of top is able to use sysctl to retrieve almost
all of the information it needs without having to open /dev/kmem. The
one piece of information not available via sysctl is the full command
line of each argument. If you run top as a regular user and it cannot
open /dev/kmem (in other words, it is not installed set-gid to the
kmem group) then it will disable the "f" command. Make sure the top
binary is installed with a group ownership of "kmem" and with the
set-gid bit on if you want the "f" command to work properly.
MACOSX PROBLEMS
17. I tried to configure top on my Mac OSX system and I got an error
claiming "macosx not supported". What up?
Since I don't have full time root access to a Mac OSX system I cannot
provide effective support for the platform. MacOSX uses Mach, and it
is very difficult to extract accurate system and process information
from the system. It takes a lot of trial and error, along with root
access. I have included the most up-to-date version of the macosx
module in the distribution, but I do not claim that it works. If you
want to try to use it, you can configure with "./configure
--with-module=macosx".
SUNOS PROBLEMS
18. I tried compiling top under SunOS version 4.1.x and it got compile
time errors or run 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.
SOLARIS PROBLEMS
NOTE: the most common source of problems with top under Solaris is
the result of compiling it with the wrong front end. Make sure that
/usr/ucb is not on your path before attempting to compile top under
Solaris.
19. Is there somewhere I can get a pre-compiled package?
Yes. Although I don't provide pre-compiled binaries, you can get a
Sun-style package from www.sunfreeware.com.
20. Under Solaris 2, when I type "make", the system says "language
optional software package not installed." What's going on?
You tried to compile with /usr/ucb/cc. Make sure /usr/ucb is not on
your path. Furthermore, you do not have a Sun compiler installed on
your system. You need a compiler to make top. Either Sun's C compiler
or the Gnu C compiler will work fine.
21. 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.
22. 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.
23. 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 22 for more details.
24. On my 64-bit system some processes show up with incorrect information
(such as zero memory).
If you are running a 64-bit system, then you need to make sure that
you are running the 64-bit top binary. Top's configure script
attempts to detect 64-bit systems, and will automatically generate
both 32-bit and 64-bit binaries on such systems. If you use or
install the 32-bit binary on a 64-bit system top will still run but
will not produce the correct results. This will also happen if you
configure your distribution on a 32-bit system then compile with that
configuration on a 64-bit system. You must configure and compile on
the same system. For Sparc systems the 32-bit binary will be created
in the subdirectory "sparcv7" and the 64-bit binary will be created
in the subdirectory "sparcv9". For Intel systems the directories will
be "i386" (32-bit) and "amd64" (64-bit). In all cases a copy of
/usr/lib/isaexec is made in the main directory and called "top". This
program will choose the correct binary to run from one of these
subdirectories. See isaexec(3c) for more details.
25. Can I install both 32-bit and 64-bit binaries on a central file
server and have machines which mount it automatically use the correct
one?
Yes. If you configure and compile on a 64-bit system, top's configure
script and makefile will automatically create both 32-bit and 64-bit
binaries. The "install" rule in the makefile will install these
binaries in subdirectories of /usr/local/bin appropriate to the
architecture (sparcv7/sparcv9 or i386/amd64) then create a copy of
/usr/lib/isaexec named "top" in /usr/local/bin to ensure that the
appropriate is run when a user types "top". If you make sure that you
configure and compile on a 64-bit system, then "make install" will do
the right thing.
26. This version of top show less available swap space than previous
versions. Why does it no longer match the output of the swap summary
produced with "swap -s"?
Starting with version 3.6 of top, the amount of swap space reported
by top has been changed to reflect only disk-based swap space. The
swap summary produced with "swap -s" also includes memory-based swap
space. This changed was made for several reasons. It makes the
display under Solaris more like those of other operating systems. The
display is more what users expect (except those used to previous
versions of top). Most importantly, "swap -s" gets its data via an
undocumented system interface. Now that top no longer displays that
data it can use publically documented and maintained system
interfaces to retrieve its data.
SVR4-DERIVED PROBLEMS
27. 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 displays process information for my own
processes). Yet when I run it as root, everything works fine. What's
wrong?
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.
SVR42 PROBLEMS
28. 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
29. 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 please use SourceForge to submit a support
request or a bug. Top is supported by the SourceForge project named
"unixtop". On SourceForge you will find defect tracking, a mailing
list, and on-line forums. You can also contact the author through
SourceForge.

54
external/bsd/top/dist/INSTALL vendored Normal file
View File

@@ -0,0 +1,54 @@
TOP
Version 3.8beta1
William LeFebvre
and a cast of many
INSTALLATION
Configuration and installation of top is easy. Top version 3.6
comes with a configure script generated by gnu autoconf. After
unpacking the tar file, simply run "./configure". The script will
automatically perform a series of checks on the system and determine
what settings are appropriate for the Makefile and certain include
files. Once configure completes, simply type "make install" and
top will be compiled and installed. By default, the installation
location is /usr/local/bin. You can change the destination location
with the --prefix option to configure.
In addition to the standard options, top's configure script supports
the following:
--with-module=name
Force the use of a particular module. Modules are located
in the subdirectory "machine". A module's name is derived
from the file's basename without the leading "m_".
--with-ext=name
Compile with the extension "name", found in the subdirectory
"ext". At the present time, there are no extensions in the
standard distribution.
--enable-debug
--disable-debug
Default off. Include debugging output in the compilation,
which can be seen with the -D switch.
--enable-color
--disable-color
Default on. Include code that allows for the use of color
in the output display. Use --disable-color if you do not
want this feature compiled in to the code. The configure
script also recognizes the spelling "colour".
--enable-kill
--disable-kill
Default on. Include code that allows for renicing and sending
signals to processes from within top (the 'kill' and 'renice'
commands). Use --disable-kill if you do not want this feature
compiled in to the code.

30
external/bsd/top/dist/LICENSE vendored Normal file
View File

@@ -0,0 +1,30 @@
Copyright (c) 1984 through 2008, William LeFebvre
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of William LeFebvre nor the names of other
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

92
external/bsd/top/dist/Makefile.in vendored Normal file
View File

@@ -0,0 +1,92 @@
# Makefile
#
# This makefile was generated by configure from a Makefile.in definition.
PROGRAM=top
INC=boolean.h color.h commands.h config.h display.h globalstate.h hash.h \
loadavg.h machine.h message.h os.h screen.h sigdesc.h top.h username.h \
utils.h version.h
SRC=color.c commands.c display.c hash.c screen.c top.c username.c utils.c version.c @SRC@
OBJ=color.o commands.o display.o hash.o screen.o top.o username.o utils.o version.o @OBJ@
MANPAGE=top.1
CLEAN_SRC=sigdesc.h
CLEAN_EXTRA=@CLEAN_EXTRA@
srcdir=@srcdir@
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
mandir=@mandir@
datarootdir=@datarootdir@
VPATH=@srcdir@
PACKAGE_NAME=@PACKAGE_NAME@
SIGNAL=@SIGNAL_H@
ARCHFLAG=@ARCHFLAG@
AWK=@AWK@
CC=@CC@
CFLAGS=$(DEFS) $(DEFAULT_INCLUDES) $(CFLAGSONLY) $(ARCHFLAG)
CFLAGSONLY=@CFLAGS@
CPPFLAGS=@CPPFLAGS@
DEBUG=
DEFS=@DEFS@ $(DEBUG)
ISAEXEC=@ISAEXEC@
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
MODULE_CFLAGS=@MODULE_CFLAGS@
INSTALL=@INSTALL@
INSTALL_PROGRAM=@INSTALL_PROGRAM@
INSTALL_DATA=@INSTALL_DATA@
INSTALL_OPTS_PROG=@INSTALL_OPTS_PROG@
INSTALL_OPTS_DATA=
DEFAULT_INCLUDES = -I. -I$(srcdir)
BINARY = $@
COMPILE = $(CC) $(CFLAGS) $(CPPFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $(BINARY)
@FIRST_RULE@
$(PROGRAM): $(OBJ)
$(LINK) $(OBJ) $(LIBS)
# explicit dependency for the module appropriate to this machine
m_@MODULE@.o: $(srcdir)/machine/m_@MODULE@.c
$(COMPILE) $(MODULE_CFLAGS) -o $@ -c $(srcdir)/machine/m_@MODULE@.c
sigdesc.h: $(srcdir)/sigconv.awk $(SIGNAL)
$(AWK) -f $(srcdir)/sigconv.awk $(SIGNAL) >sigdesc.h
@INSTALL_RULE@
install-man: $(MANPAGE)
mkdir -p $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(INSTALL_OPTS_DATA) \
$(MANPAGE) $(DESTDIR)$(mandir)/man1/$(MANPAGE)
clean:
-rm -f $(PROGRAM) $(OBJ) $(CLEAN_SRC) $(CLEAN_EXTRA)
distclean: clean
-rm -f Makefile config.status config.cache config.log config.h
configure: configure.ac
autoheader
autoconf
# Include file dependencies
color.o: os.h config.h message.h color.h
commands.o: os.h config.h sigdesc.h top.h machine.h globalstate.h \
boolean.h commands.h display.h utils.h version.h
display.o: os.h config.h top.h machine.h screen.h layout.h display.h \
boolean.h utils.h color.h
screen.o: os.h config.h top.h screen.h boolean.h
top.o: os.h config.h top.h machine.h globalstate.h commands.h display.h \
screen.h boolean.h username.h utils.h version.h color.h
username.o: os.h config.h top.h utils.h hash.h
utils.o: os.h config.h top.h utils.h
version.o: config.h top.h
m_@MODULE@.o: top.h machine.h utils.h loadavg.h

229
external/bsd/top/dist/Porting vendored Normal file
View File

@@ -0,0 +1,229 @@
Instructions for porting top to other architectures.
This is still a preliminary document. Suggestions for improvement are
most welcome.
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.
--------
Changes were made to the module interface between 3.5 and 3.6. Here are
the changes that need to be made to port a 3.5 module to 3.6:
The array that stores memory statistics and is passed back in the system
information structure as "memory" must now be an array of (signed) longs.
This was done to more easily accomodate systems that have gigabytes of
memory. Since the numbers are supposed to be kilobytes, a long can still
represent up to 2 terabytes. Look for "int memory_stats[X]" (where "X"
is some arbitrary number) and change it to "long memory_stats[X]". If
the module support reporting swap information on a separate line, then
its "swap_stats" array also needs to be an array of longs.
The argument to proc_owner should be an int, as in "int pid". When it is
used in proc_owner it should be cast as necessary. Many operating systems
will require it to be cast to a pid_t before being compared to the appropriate
element in the proc structure.
In the function format_next_process, the last argument in the main call
to sprintf is the string that contains the command for the process.
Make sure that this last argument is enclosed in a call to "printable".
For example: "printable(MPP(pp, p_comm))".
The third argument to "get_process_info" needs to be changed to an integer,
typically "int compare_index". The call to qsort in get_process_info may
be guarded by "if (compare != NULL)". If it is, remove the if statement.
The other changes to get_process_info depends on whether or not the module
supports multiple sort orders.
To support multiple keys:
Create an array int (*proc_compares[])() and assign to it the list of
comparison functions, NULL terminated. For example:
int (*proc_compares[])() = {
compare_cpu,
compare_size,
compare_res,
compare_time,
NULL };
In get_process_info there is a call to qsort which uses one of the
functions in proc_compares. It should be changed so that its fourth
argument is "proc_compares[compare_index]".
If the module contains the function "proc_compare", it should be removed.
There should also be a NULL-terminated array of strings which list the names
for the sort keys, for example:
char *ordernames[] =
{"cpu", "size", "res", "time", NULL};
To indicate that this module supports multiple sort keys, add the following
line in machine_init:
statics->order_names = ordernames;
If there is no support for multiple keys:
Leave statics->order_names alone and call the comparison function of
your choice in get_process_info, ignoring the third argument.

191
external/bsd/top/dist/README vendored Normal file
View File

@@ -0,0 +1,191 @@
TOP
Version 3.8beta1
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.
Starting with version 3.6, top includes a "configure" script generated
by Gnu's autoconf. This script MUST be run before attempting to
compile top. It will explore the system and generate approriate
contents for Makefile, config.h, and top.1.
On some systems, top requires read access to the memory files
"/dev/kmem" and "/dev/mem" as well as the system's kernel image. Most
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. On most systems with a /proc file system,
top will try to read everything it can from /proc, but may need extra
permissions to do so. The configure script will determine the
permissions needed by the top binary, and a "make install" as root
will get the binary installed correctly. Sometimes this requires that
the binary be installed with set-group-id privileges and, in rare
cases, set-user-id 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 SET-USER-ID
TO ROOT, YOU DO SO AT YOUR OWN RISK! I realize that some operating
systems will require top to run setuid root, and I will do everything
I can to make sure that top is a secure setuid program.
System support now takes the form of "modules". Adding support for a
different architecture requires only adding a module. These modules
are contained in the subdirectory "machine". The "configure" script
automatically determines which module is approproate. However, it may
not be able to determine what the correct module is. This can happen
either because it doesn't know about the system or there is no module
to support the system. In the former case, if you know which module
to use, you can force "configure" to choose a particular module with
the option "--with-module". For example, if you want to force the use
of the svr4 module (which appears as "machine/m_svr4.c") then use
"configure --with-module=svr4" to generate the correct Makefile. 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.
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.
COLOR
Version 3.6 incorporated the idea of using ANSI color sequences to
enhance information on the screen. By default, no color is used. But
you can configure the use of color through the environment variable
TOPCOLORS (or, for compatibility, TOPCOLOURS). The interface is
identical to the one first implemented by chris@spang.uk.eu.org, but
the implementation is entirely different. The option -C can be used
to diable the feature entirely.
Any information at the top of the screen can be enhanced with color.
However, due to implementation difficulties, the per-process area
cannot be color-enhanced. A complete description of color support can
be found in the man page. References for ANSI color codes can be
found all over the Internet, but if you want a handy reference, look
in color.h.
AVAILABILITY
Note that top is now a sourceforge project! Its project name is
"unixtop" and you can access its project page here:
http://sourceforge.net/projects/unixtop
On the project page you can find more information and access the
official bug and feature request trackers. If you find a bug,
want to request a feature, or need help, please submit a request
to the appropriate tracker on sourceforge. Thank you.
Subversion access is also provided by Sourceforge. If Subversion is
installed on your system you can check out the project with the
following command:
svn co https://svn.sourceforge.net/svnroot/unixtop unixtop
There is also a web site dedicated to the project, and it is here:
http://www.unixtop.org
The latest version of "top" is available as a download through
sourceforge. Start here to access the downloadable files:
http://sourceforge.net/project/showfiles.php?group_id=72892
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".
MacOS X
Since I don't have full time root access to a MacOS X system I cannot
provide effective support for the platform. MacOS X uses Mach, and it
is very difficult to extract accurate system and process information
from the system. It takes a lot of trial and error, along with root
access. I have included the most up-to-date version of the macosx module
in the distribution, but I do not claim that it works. If you want to
try to use it, you can configure with "./configure --with-module=macosx".
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.
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, Marc Cohen, David Cutter, Casper Dik,
Charles Hedrick, Andrew Herbert, Jeff Janvrin, Torsten Kasch,
Petri Kutvonen, William L. Jones, Tim Pugh, Steve Scherf,
Phillip Wu
(My apologies if I missed anyone.)
LICENSE
Top is distributed free of charge under the same terms as the BSD
license. For an official statement, please refer to the file "LICENSE"
which should be included with the source distribution.
AUTHOR
If you wish to contact me, please send a message to the sourceforge
username "wnl".
William LeFebvre
U.S. Mail address:
William LeFebvre
11585 Jones Bridge Road
Suite 420 PMB 139
Alpharetta, GA 30202

26
external/bsd/top/dist/Y2K vendored Normal file
View File

@@ -0,0 +1,26 @@
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 "LICENSE" for further
information.

1193
external/bsd/top/dist/ap_snprintf.c vendored Normal file

File diff suppressed because it is too large Load Diff

5
external/bsd/top/dist/boolean.h vendored Normal file
View File

@@ -0,0 +1,5 @@
/* My favorite names for boolean values */
#define No 0
#define Yes 1
#define Maybe 2 /* tri-state boolean, actually */

377
external/bsd/top/dist/color.c vendored Normal file
View File

@@ -0,0 +1,377 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top users/processes display for Unix
* Version 3
*/
/*
* This file handles color definitions and access for augmenting
* the output with ansi color sequences.
*
* The definition of a color setting is as follows, separated by
* colons:
*
* tag=minimum,maximum#code
*
* "tag" is the name of the value to display with color.
*
* "minimum" and "maximum" are positive integer values defining a range:
* when the value is within this range it will be shown with the
* specified color. A missing value indicates that no check should be
* made (i.e.: ",25" is n <= 25; "25,50" is 25 <= n <= 50; and "50,"
* is 50 <= n).
*
* "code" is the ansi sequence that defines the color to use with the
* escape sequence "[m". Semi-colons are allowed in this string to
* combine attributes.
*/
#include "os.h"
#include "display.h"
#include "message.h"
#include "color.h"
#include "utils.h"
typedef struct color_entry {
char *tag;
int min;
int max;
char color;
struct color_entry *next;
struct color_entry *tagnext;
} color_entry;
static color_entry *entries = NULL;
static color_entry **bytag = NULL;
static char **bytag_names = NULL;
static int totaltags = 0;
static int tagcnt = 0;
static int color_off = 0;
static char **color_ansi = NULL;
static int num_color_ansi = 0;
static int max_color_ansi = 0;
static int
color_slot(const char *str)
{
int i;
for (i = 0; i < num_color_ansi; i++)
{
if (strcmp(color_ansi[i], str) == 0)
{
return i;
}
}
/* need a new slot */
if (num_color_ansi >= max_color_ansi)
{
max_color_ansi += COLOR_ANSI_SLOTS;
color_ansi = erealloc(color_ansi, max_color_ansi * sizeof(char *));
}
color_ansi[num_color_ansi] = estrdup(str);
return num_color_ansi++;
}
/*
* int color_env_parse(char *env)
*
* Parse a color specification "env" (such as one found in the environment) and
* add them to the list of entries. Always returns 0. Should only be called
* once.
*/
int
color_env_parse(char *env)
{
char *p;
char *min;
char *max;
char *str;
int len;
color_entry *ce;
/* initialization */
color_ansi = emalloc(COLOR_ANSI_SLOTS * sizeof(char *));
max_color_ansi = COLOR_ANSI_SLOTS;
/* color slot 0 is always "0" */
color_slot("0");
if (env != NULL)
{
p = strtok(env, ":");
while (p != NULL)
{
if ((min = strchr(p, '=')) != NULL &&
(max = strchr(min, ',')) != NULL &&
(str = strchr(max, '#')) != NULL)
{
ce = emalloc(sizeof(color_entry));
len = min - p;
ce->tag = emalloc(len + 1);
strncpy(ce->tag, p, len);
ce->tag[len] = '\0';
ce->min = atoi(++min);
ce->max = atoi(++max);
ce->color = color_slot(++str);
ce->next = entries;
entries = ce;
}
else
{
if (min != NULL)
{
len = min - p;
}
else
{
len = strlen(p);
}
message_error(" %.*s: bad color entry", len, p);
}
p = strtok(NULL, ":");
}
}
return 0;
}
/*
* int color_tag(char *tag)
*
* Declare "tag" as a color tag. Return a tag index to use when testing
* a value against the tests for this tag. Should not be called before
* color_env_parse.
*/
int
color_tag(const char *tag)
{
color_entry *entryp;
color_entry *tp;
/* check for absurd arguments */
if (tag == NULL || *tag == '\0')
{
return -1;
}
dprintf("color_tag(%s)\n", tag);
/* initial allocation */
if (bytag == NULL)
{
totaltags = 10;
bytag = emalloc(totaltags * sizeof(color_entry *));
bytag_names = emalloc(totaltags * sizeof(char *));
}
/* if we dont have enough room then reallocate */
if (tagcnt >= totaltags)
{
totaltags *= 2;
bytag = erealloc(bytag, totaltags * sizeof(color_entry *));
bytag_names = erealloc(bytag_names, totaltags * sizeof(char *));
}
/* initialize scan */
entryp = entries;
tp = NULL;
/* look for tag in the list of entries */
while (entryp != NULL)
{
if (strcmp(entryp->tag, tag) == 0)
{
entryp->tagnext = tp;
tp = entryp;
}
entryp = entryp->next;
}
/* we track names in the array bytag */
bytag[tagcnt] = tp;
bytag_names[tagcnt] = estrdup(tag);
/* return this index number as a reference */
dprintf("color_tag: returns %d\n", tagcnt);
return (tagcnt++);
}
/*
* int color_test(int tagidx, int value)
*
* Test "value" against tests for tag "tagidx", a number previously returned
* by color_tag. Return the correct color number to use when highlighting.
* If there is no match, return 0 (color 0).
*/
int
color_test(int tagidx, int value)
{
color_entry *ce;
/* sanity check */
if (tagidx < 0 || tagidx >= tagcnt || color_off)
{
return 0;
}
ce = bytag[tagidx];
while (ce != NULL)
{
if ((!ce->min || ce->min <= value) &&
(!ce->max || ce->max >= value))
{
return ce->color;
}
ce = ce->tagnext;
}
return 0;
}
/*
* char *color_setstr(int color)
*
* Return ANSI string to set the terminal for color number "color".
*/
char *
color_setstr(int color)
{
static char v[32];
v[0] = '\0';
if (color >= 0 && color < num_color_ansi)
{
snprintf(v, sizeof(v), "\033[%sm", color_ansi[color]);
}
return v;
}
void
color_dump(FILE *f)
{
color_entry *ep;
int i;
int col;
int len;
fputs("These color tags are available:", f);
col = 81;
for (i = 0; i < tagcnt; i++)
{
len = strlen(bytag_names[i]) + 1;
if (len + col > 79)
{
fputs("\n ", f);
col = 2;
}
fprintf(f, " %s", bytag_names[i]);
col += len;
}
fputs("\n\nTop color settings:\n", f);
for (i = 0; i < tagcnt; i++)
{
ep = bytag[i];
while (ep != NULL)
{
fprintf(f, " %s (%d-", ep->tag, ep->min);
if (ep->max != 0)
{
fprintf(f, "%d", ep->max);
}
fprintf(f, "): ansi color %s, %sSample Text",
color_ansi[(int)ep->color],
color_setstr(ep->color));
fprintf(f, "%s\n", color_setstr(0));
ep = ep -> tagnext;
}
}
}
#ifdef notdef
void
color_debug(FILE *f)
{
color_entry *ep;
int i;
fprintf(f, "color debug dump\n");
ep = entries;
while (ep != NULL)
{
fprintf(f, "%s(%d,%d): slot %d, ansi %s, %sSample Text",
ep->tag, ep->min, ep->max, ep->color, color_ansi[(int)ep->color],
color_setstr(ep->color));
fprintf(f, "%s\n", color_setstr(0));
ep = ep -> next;
}
fprintf(f, "\ntags:");
for (i = 0; i < tagcnt; i++)
{
fprintf(f, " %s", bytag_names[i]);
}
fprintf(f, "\n");
}
#endif
int
color_activate(int i)
{
if (i == -1)
{
color_off = !color_off;
}
else
{
color_off = !i;
}
return color_off;
}

91
external/bsd/top/dist/color.h vendored Normal file
View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top - a top users display for Unix
*
* Definition of the color interface.
*/
#ifndef _COLOR_H_
#define _COLOR_H_
#define COLOR_ANSI_SLOTS 20
int color_env_parse(char *env);
int color_tag(const char *tag);
int color_test(int tagidx, int value);
char *color_setstr(int color);
void color_dump(FILE *f);
int color_activate(int i);
/*
* These color tag names are currently in use
* (or reserved for future use):
*
* cpu, size, res, time, 1min, 5min, 15min, host
*/
/*
* Valid ANSI values for colors are:
*
* 0 Reset all attributes
* 1 Bright
* 2 Dim
* 4 Underscore
* 5 Blink
* 7 Reverse
* 8 Hidden
*
* Foreground Colours
* 30 Black
* 31 Red
* 32 Green
* 33 Yellow
* 34 Blue
* 35 Magenta
* 36 Cyan
* 37 White
*
* Background Colours
* 40 Black
* 41 Red
* 42 Green
* 43 Yellow
* 44 Blue
* 45 Magenta
* 46 Cyan
* 47 White
*/
#endif /*_COLOR_H_ */

1070
external/bsd/top/dist/commands.c vendored Normal file

File diff suppressed because it is too large Load Diff

42
external/bsd/top/dist/commands.h vendored Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* call specifications for commands.c */
int command_process(globalstate *gstate, int cmd);
/* returns from command routines */
#define CMD_ERROR -1
#define CMD_OK 0
#define CMD_REFRESH 1
#define CMD_UNKNOWN 2
#define CMD_NA 3

10
external/bsd/top/dist/config.amd64.make vendored Normal file
View File

@@ -0,0 +1,10 @@
# Special rules for making 32-bit and 64-bit binaries on a sunos5 x86 box
all: i386/top amd64/top
-cp -f /usr/lib/isaexec top
i386/top: $(SRC) $(INC)
cd i386; $(MAKE) -f ../Makefile VPATH=.. srcdir=.. \
BINARY=./top ARCHFLAG= top
amd64/top: $(SRC) $(INC)
cd amd64; $(MAKE) -f ../Makefile VPATH=.. srcdir=.. BINARY=./top top

View File

@@ -0,0 +1,10 @@
# Install rule specific to i386/amd64 for sunos5
install: all install-man
mkdir -p $(DESTDIR)$(bindir)/i386
mkdir -p $(DESTDIR)$(bindir)/amd64
$(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \
i386/$(PROGRAM) $(DESTDIR)$(bindir)/i386/$(PROGRAM)
$(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \
amd64/$(PROGRAM) $(DESTDIR)$(bindir)/amd64/$(PROGRAM)
$(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \
$(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM)

View File

@@ -0,0 +1,5 @@
# Standard install rule
install: $(PROGRAM) install-man
mkdir -p $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \
$(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM)

1407
external/bsd/top/dist/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

256
external/bsd/top/dist/config.h.in vendored Normal file
View File

@@ -0,0 +1,256 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Support for debugging output */
#undef DEBUG
/* Default delay */
#undef DEFAULT_DELAY
/* Default number of processes to display */
#undef DEFAULT_TOPN
/* Enable color */
#undef ENABLE_COLOR
/* Enable dual architecture */
#undef ENABLE_DUALARCH
/* Enable kill and renice */
#undef ENABLE_KILL
/* Supports C99 style variadic macros */
#undef HAVE_C99_VARIADIC_MACROS
/* Define to 1 if you have the <curses.h> header file. */
#undef HAVE_CURSES_H
/* Define to 1 if you have the declaration of `sys_errlist', and to 0 if you
don't. */
#undef HAVE_DECL_SYS_ERRLIST
/* Define to 1 if you have the declaration of `sys_signame', and to 0 if you
don't. */
#undef HAVE_DECL_SYS_SIGNAME
/* Define to 1 if you have the declaration of `tgetent', and to 0 if you
don't. */
#undef HAVE_DECL_TGETENT
/* Define to 1 if you have the declaration of `tgetflag', and to 0 if you
don't. */
#undef HAVE_DECL_TGETFLAG
/* Define to 1 if you have the declaration of `tgetnum', and to 0 if you
don't. */
#undef HAVE_DECL_TGETNUM
/* Define to 1 if you have the declaration of `tgetstr', and to 0 if you
don't. */
#undef HAVE_DECL_TGETSTR
/* Define to 1 if you have the declaration of `tgoto', and to 0 if you don't.
*/
#undef HAVE_DECL_TGOTO
/* Define to 1 if you have the declaration of `tputs', and to 0 if you don't.
*/
#undef HAVE_DECL_TPUTS
/* Platform module */
#undef HAVE_FORMAT_PROCESS_HEADER
/* Define to 1 if you have the `getopt' function. */
#undef HAVE_GETOPT
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the `getopt_long' function. */
#undef HAVE_GETOPT_LONG
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Supports gnu style variadic macros */
#undef HAVE_GNU_VARIADIC_MACROS
/* Define to 1 if the system has the type `id_t'. */
#undef HAVE_ID_T
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `elf' library (-lelf). */
#undef HAVE_LIBELF
/* Define to 1 if you have the `kstat' library (-lkstat). */
#undef HAVE_LIBKSTAT
/* Define to 1 if you have the `kvm' library (-lkvm). */
#undef HAVE_LIBKVM
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the `mach' library (-lmach). */
#undef HAVE_LIBMACH
/* Define to 1 if you have the `mas' library (-lmas). */
#undef HAVE_LIBMAS
/* Define to 1 if you have the `perfstat' library (-lperfstat). */
#undef HAVE_LIBPERFSTAT
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if the system has the type `lwpid_t'. */
#undef HAVE_LWPID_T
/* Define to 1 if you have the <math.h> header file. */
#undef HAVE_MATH_H
/* Define to 1 if you have the `memcpy' function. */
#undef HAVE_MEMCPY
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if the system has the type `pid_t'. */
#undef HAVE_PID_T
/* Define to 1 if you have the `setbuffer' function. */
#undef HAVE_SETBUFFER
/* Define to 1 if you have the `setpriority' function. */
#undef HAVE_SETPRIORITY
/* Define to 1 if you have the `setvbuf' function. */
#undef HAVE_SETVBUF
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `sighold' function. */
#undef HAVE_SIGHOLD
/* Define to 1 if you have the `sigprocmask' function. */
#undef HAVE_SIGPROCMASK
/* Define to 1 if you have the `sigrelse' function. */
#undef HAVE_SIGRELSE
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `sysconf' function. */
#undef HAVE_SYSCONF
/* Define to 1 if you have the <sysexits.h> header file. */
#undef HAVE_SYSEXITS_H
/* Define to 1 if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_H
/* Define to 1 if you have the <termcap.h> header file. */
#undef HAVE_TERMCAP_H
/* Define to 1 if you have the <term.h> header file. */
#undef HAVE_TERM_H
/* Define to 1 if the system has the type `time_t'. */
#undef HAVE_TIME_T
/* Define to 1 if the system has the type `uid_t'. */
#undef HAVE_UID_T
/* Define to 1 if you have the `uname' function. */
#undef HAVE_UNAME
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Platform module */
#undef MODULE
/* Default number of processes to display on non-terminals when topn is all */
#undef NOMINAL_TOPN
/* Define the major OS revision number. */
#undef OSMAJOR
/* Define the OS revision. */
#undef OSREV
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define as the type for the argument to the putc function of tputs ('int' or
'char') */
#undef TPUTS_PUTC_ARGTYPE
/* Define the system hardware platform */
#undef UNAME_HARDWARE
/* Include code that utilizes extensions */
#undef WITH_EXT

View File

@@ -0,0 +1,10 @@
# Special rules for making 32-bit and 64-bit binaries on a sunos5 box
all: sparcv7/top sparcv9/top
-cp -f $(ISAEXEC) top
sparcv7/top: $(SRC) $(INC)
cd sparcv7; $(MAKE) -f ../Makefile VPATH=.. srcdir=.. \
BINARY=./top ARCHFLAG= top
sparcv9/top: $(SRC) $(INC)
cd sparcv9; $(MAKE) -f ../Makefile VPATH=.. srcdir=.. BINARY=./top top

View File

@@ -0,0 +1,10 @@
# Install rule specific to sparcv7/sparcv9 for sunos5
install: all install-man
mkdir -p $(DESTDIR)$(bindir)/sparcv7
mkdir -p $(DESTDIR)$(bindir)/sparcv9
$(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \
sparcv7/$(PROGRAM) $(DESTDIR)$(bindir)/sparcv7/$(PROGRAM)
$(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \
sparcv9/$(PROGRAM) $(DESTDIR)$(bindir)/sparcv9/$(PROGRAM)
$(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \
$(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM)

1504
external/bsd/top/dist/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

7969
external/bsd/top/dist/configure vendored Executable file

File diff suppressed because it is too large Load Diff

529
external/bsd/top/dist/configure.ac vendored Normal file
View File

@@ -0,0 +1,529 @@
# configure.ac
AC_INIT(top, 3.8beta1)
# AX_CHECK_VARIADIC_MACROS...
# -----
AC_DEFUN([AX_CHECK_VARIADIC_MACROS],
[AC_MSG_CHECKING([for variadic macros])
AC_COMPILE_IFELSE(AC_LANG_PROGRAM(
[#define a(x, ...) (x, __VA_ARGS__)], []),
[AS_VAR_SET(ax_cv_c99_variadic, yes)],
[AS_VAR_SET(ax_cv_c99_variadic, no)])
AC_COMPILE_IFELSE(AC_LANG_PROGRAM(
[#define a(x...) (x)], []),
[AS_VAR_SET(ax_cv_gnu_variadic, yes)],
[AS_VAR_SET(ax_cv_gnu_variadic, no)])
_result=""
if test "$ax_cv_c99_variadic" = "yes"; then
_result=" c99"
AC_DEFINE(HAVE_C99_VARIADIC_MACROS, 1, [Supports C99 style variadic macros])
fi
if test "$ax_cv_gnu_variadic" = "yes"; then
_result="$_result gnu"
AC_DEFINE(HAVE_GNU_VARIADIC_MACROS, 1, [Supports gnu style variadic macros])
fi
if test "x$_result" = x; then
_result="no"
fi
AC_MSG_RESULT($_result)
])
# AC_CHECK_CFLAG...
# -----
AC_DEFUN([AC_CHECK_CFLAG],
[AC_MSG_CHECKING([whether compiler accepts $1])
AS_VAR_PUSHDEF([ac_Flag], [ac_cv_cflag_$1])dnl
_savedcflags=$CFLAGS
_savedwerror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
CFLAGS=$CFLAGS" $1"
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [AS_VAR_SET(ac_Flag, yes)],
[AS_VAR_SET(ac_Flag, no)])
AC_MSG_RESULT([AS_VAR_GET(ac_Flag)])
CFLAGS=$_savedcflags
ac_c_werror_flag=$_savedwerror_flag
AS_IF([test AS_VAR_GET(ac_Flag) = yes], [$2], [$3])[]dnl
AS_VAR_POPDEF([ac_Flag])dnl
])# AC_CHECK_CFLAG
echo "Configuring $PACKAGE_STRING"
AC_CONFIG_HEADER([config.h])
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
# options processing
AC_ARG_WITH(module, AC_HELP_STRING([--with-module=NAME],
[use the platform module NAME]),
[if test ! -f machine/m_$withval.c;
then AC_MSG_ERROR([No such module $withval]); fi])
AC_ARG_WITH(ext, AC_HELP_STRING([--with-ext=EXT],
[use the extension EXT]),
[if test -f ext/$withval.c; then
AC_DEFINE(WITH_EXT, 1, [Include code that utilizes extensions])
SRC="$SRC ext/$withval.c"
OBJ="$OBJ $withval.o"
else
AC_MSG_ERROR([No such extension $withval])
fi])
DEFAULT_TOPN=30
AC_ARG_WITH(default-topn, AC_HELP_STRING([--with-default-topn=N],
[use N as the default for number of processes]),
[if test x"$with_default_topn" = xall; then
DEFAULT_TOPN="-1"
elif test x`echo $with_default_topn | tr -d '[0-9+-]'` = x; then
DEFAULT_TOPN=$with_default_topn
fi])
AC_DEFINE_UNQUOTED(DEFAULT_TOPN, $DEFAULT_TOPN, [Default number of processes to display])
AC_SUBST(DEFAULT_TOPN)
NOMINAL_TOPN=40
AC_ARG_WITH(nominal-topn, AC_HELP_STRING([--with-nominal-topn=N],
[use N as the default number of processes for non-terminals]),
[if test x"$with_nominal_topn" = xall; then
NOMINAL_TOPN="-1"
elif test x`echo $with_nominal_topn | tr -d '[0-9+-]'` = x; then
NOMINAL_TOPN=$with_nominal_topn
fi])
AC_DEFINE_UNQUOTED(NOMINAL_TOPN, $NOMINAL_TOPN, [Default number of processes to display on non-terminals when topn is all])
AC_SUBST(NOMINAL_TOPN)
DEFAULT_DELAY=5
AC_ARG_WITH(default-delay, AC_HELP_STRING([--with-default-delay=SEC],
[use a default delay of SEC seconds]),
[if test x`echo $with_default_delay | tr -d '[0-9+-]'` = x; then
DEFAULT_DELAY=$with_default_delay
fi])
AC_DEFINE_UNQUOTED(DEFAULT_DELAY, $DEFAULT_DELAY, [Default delay])
AC_SUBST(DEFAULT_DELAY)
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],
[enable support for debugging output]))
if test "x$enable_debug" = xyes; then
AC_DEFINE(DEBUG, 1, [Support for debugging output])
fi
ENABLE_KILL=0
AC_ARG_ENABLE(kill, AC_HELP_STRING([--disable-kill],
[disable kill and renice commands]))
if test x$enable_kill != xno; then
AC_DEFINE(ENABLE_KILL, 1, [Enable kill and renice])
ENABLE_KILL=1
fi
AC_SUBST(ENABLE_KILL)
AC_ARG_ENABLE(color, AC_HELP_STRING([--disable-color],
[disable the use of color]))
AC_ARG_ENABLE(colour, AC_HELP_STRING([--disable-colour],
[synonym for --disable-color]))
if test x$enable_color != xno -a x$enable_colour != xno; then
AC_DEFINE(ENABLE_COLOR, 1, [Enable color])
fi
AC_ARG_ENABLE(dualarch, AC_HELP_STRING([--enable-dualarch],
[enable or disable a dual architecture (32-bit and 64-bit) compile]))
# check for needed programs
AC_CHECK_PROGS(MAKE, make)
AC_PROG_CC
if test "$ac_cv_c_compiler_gnu" = "yes"; then
ax_cv_c_compiler_vendor="gnu"
else
AX_COMPILER_VENDOR
fi
AC_PROG_AWK
AC_PROG_INSTALL
AC_PATH_PROGS(ISAINFO, isainfo)
AC_PATH_PROGS(ISAEXEC, isaexec, , [$PATH:/usr/lib:/lib])
AC_PATH_PROGS(UNAME, uname)
AC_SUBST(ISAEXEC)
# system checks require uname
if test "$UNAME"; then
# we make the version number available as a C preprocessor definition
AC_MSG_CHECKING(OS revision number)
osrev=`$UNAME -r | tr -cd ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`
if test "$osrev" != "unknown" ; then
AC_DEFINE_UNQUOTED(OSREV, $osrev, [Define the OS revision.])
osmajor=`$UNAME -r | sed 's/^\([[0-9]]*\).*$/\1/'`
if test -n "$osmajor"; then
AC_DEFINE_UNQUOTED(OSMAJOR, $osmajor, [Define the major OS revision number.])
fi
else
AC_DEFINE(OSREV, "")
fi
AC_MSG_RESULT($osrev)
# we make the non-canonicalized hardware type available
AC_MSG_CHECKING(hardware platform)
UNAME_HARDWARE=`$UNAME -m`
if test "$UNAME_HARDWARE" != "unknown"; then
AC_DEFINE_UNQUOTED(UNAME_HARDWARE, "$UNAME_HARDWARE", [Define the system hardware platform])
fi
AC_MSG_RESULT($UNAME_HARDWARE)
fi
# checks for libraries
AC_CHECK_LIB(elf, elf32_getphdr)
AC_CHECK_LIB(kstat, kstat_open)
AC_CHECK_LIB(kvm, kvm_open)
# -lmld -lmach
AC_CHECK_LIB(mach, vm_statistics)
AC_SEARCH_LIBS(tgetent, termcap curses ncurses)
AC_CHECK_LIB(m, exp)
# check for libraries required by extension
extlibs=""
if test -n "$with_ext" -a -f "${srcdir}/ext/$with_ext.libs"; then
AC_MSG_CHECKING(for libraries needed by extensions)
for lib in `cat "${srcdir}/ext/$with_ext.libs"`
do
saveLIBS=$LIBS
LIBS="$LIBS -l$lib"
AC_TRY_LINK(, [exit(0);], [extlibs="$extlibs -l$lib"], )
LIBS=$saveLIBS
done
AC_MSG_RESULT($extlibs)
LIBS="$LIBS$extlibs"
fi
# checks for header files
AC_HEADER_STDC
AC_CHECK_HEADERS([curses.h getopt.h limits.h math.h stdarg.h sysexits.h termcap.h unistd.h sys/resource.h sys/time.h sys/utsname.h])
AC_CHECK_HEADERS([term.h],,,
[#if HAVE_CURSES_H
#include <curses.h>
#endif
])
AC_HEADER_TIME
AC_MSG_CHECKING(for a good signal.h)
SIGNAL_H="no"
for f in /usr/include/signal.h /usr/include/sys/signal.h /usr/include/sys/iso/signal_iso.h /usr/include/bits/signum.h; do
if grep SIGKILL $f >/dev/null 2>&1; then
SIGNAL_H=$f
break
fi
done
AC_MSG_RESULT($SIGNAL_H)
if test "$SIGNAL_H" = "no"; then
SIGNAL_H="/dev/null"
fi
AC_SUBST(SIGNAL_H)
# checks for typedefs, structures, and compiler characteristics.
AX_CHECK_VARIADIC_MACROS
AC_CHECK_DECLS([sys_errlist])
AC_CHECK_DECLS([sys_signame],,,
[#include <signal.h>
/* NetBSD declares sys_siglist in unistd.h. */
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
])
AC_CHECK_DECLS([tputs, tgoto, tgetent, tgetflag, tgetnum, tgetstr],,,
[#if HAVE_CURSES_H && HAVE_TERM_H
#include <curses.h>
#include <term.h>
#else
#if HAVE_TERMCAP_H
#include <termcap.h>
#else
#if HAVE_CURSES_H
#include <curses.h>
#endif
#endif
#endif
])
# The third argument to tputs is a putc-like function that takes an
# argument. On most systems that argument is an int, but on some it
# is a char. Determine which.
AC_MSG_CHECKING([argument type of tputs putc function])
_savedwerror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([#ifdef HAVE_TERMCAP_H
#include <termcap.h>
#endif
#ifdef HAVE_CURSES_H
#include <curses.h>
#endif
#ifdef HAVE_TERM_H
#include <term.h>
#endif
int f(char i) { }],
[tputs("a", 1, f);])],
[ac_cv_type_tputs_putc="char"],
[ac_cv_type_tputs_putc="int"])
AC_MSG_RESULT($ac_cv_type_tputs_putc)
AC_DEFINE_UNQUOTED(TPUTS_PUTC_ARGTYPE, $ac_cv_type_tputs_putc,
[Define as the type for the argument to the
putc function of tputs ('int' or 'char')])
ac_c_werror_flag=$_savedwerror_flag
# Determine presence of needed types
AC_TYPE_SIGNAL
AC_CHECK_TYPES([id_t, lwpid_t, pid_t, time_t, uid_t])
# Checks for library functions.
AC_CHECK_FUNCS([getopt getopt_long gettimeofday memcpy setbuffer setpriority setvbuf strcasecmp strchr strerror snprintf sighold sigrelse sigaction sigprocmask sysconf uname vsnprintf])
# this is needed in the man page
if test "x$ac_cv_func_getopt_long" = "xyes"; then
HAVE_GETOPT_LONG=1
else
HAVE_GETOPT_LONG=0
fi
AC_SUBST(HAVE_GETOPT_LONG)
# if we dont have snprintf/vsnprint then we need to compile the alternate
if test "x$ac_cv_func_snprintf" != "xyes" -o "x$ac_cv_func_vsnprintf" != "xyes"; then
SRC="$SRC ap_snprintf.c"
OBJ="$OBJ ap_snprintf.o"
fi
# determine correct user, group, and mode
# these can be overridden later if need be
AC_MSG_CHECKING(for correct ls options)
lslong="ls -l"
if test `$lslong -d . | wc -w` -lt 9; then
lslong="ls -lg"
fi
AC_MSG_RESULT($lslong)
# determine correct module
AC_MSG_CHECKING(for a platform module)
if test "$with_module"; then
MODULE=$with_module
else
case $target_os in
aix4.2*) MODULE=aix43;;
aix4.3*) MODULE=aix43;;
aix5*) MODULE=aix5;;
dec-osf*) MODULE=decosf1;;
osf1*) MODULE=decosf1;;
osf4*) MODULE=decosf1;;
osf5*) MODULE=decosf1;;
freebsd*) MODULE=freebsd; USE_KMEM=1; USE_FPH=1;;
hpux7*) MODULE=hpux7;;
hpux8*) MODULE=hpux8;;
hpux9*) MODULE=hpux9;;
hpux10*) MODULE=hpux10;;
hpux11*) MODULE=hpux10;;
irix5*) MODULE=irix5;;
irix6*) MODULE=irixsgi;;
linux*) MODULE=linux; USE_FPH=1; SET_MODE=755;;
netbsd*) MODULE=netbsd; SET_MODE=755;;
solaris2*) MODULE=sunos5; USE_FPH=1; SET_MODE=755;;
sunos4*) MODULE=sunos4;;
sysv4*) MODULE=svr4;;
sysv5*) MODULE=svr5;;
darwin*)
echo "macosx"
echo "The macosx module is untested. Use at your own risk."
echo "If you really want to use this module, please run configure as follows:"
echo " ./configure --with-module=macosx"
AC_MSG_ERROR([macosx module unsupported]);;
*) echo "none"
echo "Configure doesn't recognize this system and doesn't know"
echo "what module to assign to it. Help the cause and run the"
echo "following command to let the maintainers know about this"
echo "deficiency! Thanks. Just cut and paste the following:"
echo "uname -a | mail -s $target_os bill@lefebvre.org"
echo ""
AC_MSG_ERROR([System type $target_os unrecognized])
esac
fi
AC_MSG_RESULT($MODULE)
SRC="$SRC machine/m_$MODULE.c"
OBJ="$OBJ m_$MODULE.o"
CLEAN_EXTRA=""
AC_SUBST(SRC)
AC_SUBST(OBJ)
AC_SUBST(CLEAN_EXTRA)
AC_DEFINE_UNQUOTED(MODULE, "$MODULE", [Platform module])
FIRST_RULE=/dev/null
INSTALL_RULE=config.default.makeinstall
# extra things that need to be done for certain systems
# also handle setup for 64-bit detection
bits="default"
case $MODULE in
aix5)
AC_CHECK_LIB(perfstat, perfstat_cpu_total)
if test -f /usr/sbin/bootinfo; then
bits="`/usr/sbin/bootinfo -K`"
extra_flag="-q64"
fi
;;
svr5)
# -lmas
AC_CHECK_LIB(mas, mas_open)
;;
sunos5)
if test "$ISAINFO"; then
bits="`$ISAINFO -b`"
if test "$target_cpu" = "sparc"; then
extra_flag="-xarch=v9"
else
extra_flag="-xarch=amd64"
fi
fi
;;
esac
# USE_FPH means the module has format_process_header
if test -n "$USE_FPH"; then
AC_DEFINE(HAVE_FORMAT_PROCESS_HEADER, 1, [Platform module])
fi
# if we are 64-bit, try to turn on the appropriate flags
AC_MSG_CHECKING(address space size)
ARCHFLAG=""
if test "$bits" = "64"; then
AC_MSG_RESULT(64)
if test "$ax_cv_c_compiler_vendor" = "gnu"; then
extra_flag="-m64"
fi
# Make sure our compiler accepts the flag we want to use
AC_CHECK_CFLAG($extra_flag, [ARCHFLAG="$extra_flag"],
[enable_dualarch="no"])
else
AC_MSG_RESULT($bits)
fi
AC_SUBST(ARCHFLAG)
# Dual architecture handling: for now this is only enabled on Solaris.
# Config options can explicitly enable or disable dualarch. Otherwise,
# dualarch is only enabled when we are on a 64-bit system.
if test "$MODULE" = "sunos5"; then
AC_MSG_CHECKING(for dual architecture compilation)
if test "x$enable_dualarch" = x; then
# we must make the determination implicitly
if test "$bits" = "64"; then
enable_dualarch="yes"
else
enable_dualarch="no"
fi
fi
if test "x$enable_dualarch" = "xyes"; then
AC_MSG_RESULT(yes)
if test "$target_cpu" = "sparc"; then
FIRST_RULE="config.sparcv9.make"
INSTALL_RULE="config.sparcv9.makeinstall"
CLEAN_EXTRA="$CLEAN_EXTRA sparcv7/* sparcv9/*"
mkdir -p sparcv7 sparcv9
else
FIRST_RULE="config.amd64.make"
INSTALL_RULE="config.amd64.makeinstall"
CLEAN_EXTRA="$CLEAN_EXTRA i386/* amd64/*"
mkdir -p i386 amd64
fi
else
AC_MSG_RESULT(no)
fi
fi
if test x$enable_dualarch = xyes; then
AC_DEFINE(ENABLE_DUALARCH, 1, [Enable dual architecture])
fi
AC_SUBST_FILE(FIRST_RULE)
AC_SUBST_FILE(INSTALL_RULE)
AC_MSG_CHECKING(for installation settings)
# calculate appropriate settings
OWNER=""
GROUP=""
MODE=""
if test ! -n "$USE_KMEM" -a -d /proc; then
# make sure we are installed so that we can read /proc
rm -f conftest.txt
if test -r /proc/0/psinfo; then
# system uses solaris-style /proc
$lslong /proc/0/psinfo >conftest.txt
elif test -r /proc/1/stat; then
# linux-style /proc?
$lslong /proc/1/stat >conftest.txt
else
echo "-r--r--r-- 1 bin bin 32 Jan 1 12:00 /foo" >conftest.txt
fi
# set permissions so that we can read stuff in /proc
if grep '^.......r..' conftest.txt >/dev/null; then
# world readable
MODE=755
elif grep '^....r.....' conftest.txt >/dev/null; then
# group readable
MODE=2711
GROUP=`awk ' { print $4 }'`
else
# probably only readable by root
MODE=4711
OWNER=`awk ' { print $3 }'`
fi
elif test -c /dev/kmem; then
$lslong -L /dev/kmem >conftest.txt
if grep '^....r..r..' conftest.txt >/dev/null; then
MODE=755
elif grep '^....r..-..' conftest.txt >/dev/null; then
MODE=2755
GROUP=`$AWK ' { print $4 }' conftest.txt`
fi
else
MODE=755
fi
rm -f conftest.txt
# let module settings override what we calculated
OWNER=${SET_OWNER:-$OWNER}
GROUP=${SET_GROUP:-$GROUP}
MODE=${SET_MODE:-$MODE}
# set only those things that require it
result=""
INSTALL_OPTS_PROG=""
if test x$OWNER != x; then
result="${result}owner=$OWNER, "
INSTALL_OPTS_PROG="$INSTALL_OPTS_PROG -o $OWNER"
fi
if test x$GROUP != x; then
result="${result}group=$GROUP, "
INSTALL_OPTS_PROG="$INSTALL_OPTS_PROG -g $GROUP"
fi
result="${result}mode=$MODE"
INSTALL_OPTS_PROG="$INSTALL_OPTS_PROG -m $MODE"
AC_MSG_RESULT($result)
# add extra cflags if the compiler accepts them
AX_CFLAGS_WARN_ALL
MODULE_CFLAGS=""
if test "$ax_cv_c_compiler_vendor" = "gnu"; then
AX_CFLAGS_GCC_OPTION([-fno-strict-aliasing], [MODULE_CFLAGS])
if test "$target_cpu" = "alpha"; then
AX_CFLAGS_GCC_OPTION([-mfp-trap-mode=sui -mtrap-precision=i])
fi
fi
# Define man page supplement
MAN_SUPPLEMENT=machine/m_$MODULE.man
AC_SUBST_FILE(MAN_SUPPLEMENT)
# Extra things we want substituted
AC_SUBST(MODULE)
AC_SUBST(MODULE_CFLAGS)
AC_SUBST(INSTALL_OPTS_PROG)
# wrapup
AC_CONFIG_FILES(Makefile top.1)
AC_OUTPUT

2021
external/bsd/top/dist/display.c vendored Normal file

File diff suppressed because it is too large Load Diff

85
external/bsd/top/dist/display.h vendored Normal file
View File

@@ -0,0 +1,85 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* interface declaration for display.c */
#ifndef _DISPLAY_H
#define _DISPLAY_H
#include "globalstate.h"
void display_clear(void);
int display_resize(void);
int display_lines(void);
int display_setmulti(int m);
int display_columns(void);
int display_init(struct statics *statics, int percpuinfo);
void i_loadave(int mpid, double *avenrun);
void u_loadave(int mpid, double *avenrun);
void i_minibar(int (*formatter)(char *, int));
void u_minibar(int (*formatter)(char *, int));
void i_uptime(time_t *bt, time_t *tod);
void u_uptime(time_t *bt, time_t *tod);
void i_timeofday(time_t *tod);
void i_procstates(int total, int *brkdn, int threads);
void u_procstates(int total, int *brkdn, int threads);
void i_cpustates(int *states);
void u_cpustates(int *states);
void z_cpustates(void);
void i_kernel(int *stats);
void u_kernel(int *stats);
void i_memory(long *stats);
void u_memory(long *stats);
void i_swap(long *stats);
void u_swap(long *stats);
void i_message(struct timeval *now);
void u_message(struct timeval *now);
void i_header(char *text);
void u_header(char *text);
void i_process(int line, char *thisline);
void u_process(int, char *);
void i_endscreen(void);
void u_endscreen(void);
void display_header(int t);
void new_message(const char *msgfmt, ...);
void message_error(const char *msgfmt, ...);
void message_mark(void);
void message_clear(void);
void message_expire(void);
void message_prompt(const char *msgfmt, ...);
void message_prompt_plain(const char *msgfmt, ...);
int readline(char *buffer, int size, int numeric);
void display_pagerstart(void);
void display_pagerend(void);
void display_pager(const char *fmt, ...);
#endif

121
external/bsd/top/dist/getopt.c vendored Normal file
View File

@@ -0,0 +1,121 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* "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(int argc, char **argv, char *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 */

67
external/bsd/top/dist/globalstate.h vendored Normal file
View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The global state of top is described in this structure. It is passed
* to routines that may need to examine or alter it.
*/
#ifndef _GLOBALSTATE_H_
#define _GLOBALSTATE_H_
#include "machine.h"
typedef struct globalstate {
struct timeval now;
struct timeval refresh;
int fulldraw;
int topn;
int max_topn;
double delay;
int displays;
int order_index;
int show_cpustates;
int show_tags;
int show_usernames;
int use_color;
int smart_terminal;
int interactive;
int percpustates;
char *header_text;
char *order_name; /* only used before call to machine_init */
char *order_namelist;
char *(*get_userid)(int);
struct process_select pselect;
struct statics *statics;
} globalstate;
#endif /* _GLOBALSTATE_H_ */

1952
external/bsd/top/dist/hash.c vendored Normal file

File diff suppressed because it is too large Load Diff

155
external/bsd/top/dist/hash.h vendored Normal file
View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* hash.m4h */
/* Interface definition for hash.c */
/* The file hash.h is generated from hash.m4h via the preprocessor M4 */
#ifndef _HASH_H
#define _HASH_H
#include <sys/types.h>
typedef struct pidthr_t {
pid_t k_pid;
id_t k_thr;
} pidthr_t;
typedef struct llistitem {
void *datum;
struct llistitem *next;
} llistitem;
typedef struct llist {
llistitem *head;
unsigned int count;
} llist;
typedef struct bucket {
llist list;
} bucket_t;
typedef struct hash_table {
int num_buckets;
bucket_t *buckets;
} hash_table;
typedef struct hash_pos {
int num_buckets;
int curr;
bucket_t *hash_bucket;
llistitem *ll_item;
llistitem *ll_last;
} hash_pos;
hash_table *hash_create(int num);
void hash_sizeinfo(unsigned int *sizes, int max, hash_table *ht);
typedef struct hash_item_uint {
unsigned int key;
void *value;
} hash_item_uint;
void *hash_add_uint(hash_table *ht, unsigned int key, void *value);
void *hash_replace_uint(hash_table *ht, unsigned int key, void *value);
void *hash_lookup_uint(hash_table *ht, unsigned int key);
void *hash_remove_uint(hash_table *ht, unsigned int key);
hash_item_uint *hash_first_uint(hash_table *ht, hash_pos *pos);
hash_item_uint *hash_next_uint(hash_pos *pos);
void *hash_remove_pos_uint(hash_pos *pos);
typedef struct hash_item_pid {
pid_t key;
void *value;
} hash_item_pid;
void *hash_add_pid(hash_table *ht, pid_t key, void *value);
void *hash_replace_pid(hash_table *ht, pid_t key, void *value);
void *hash_lookup_pid(hash_table *ht, pid_t key);
void *hash_remove_pid(hash_table *ht, pid_t key);
hash_item_pid *hash_first_pid(hash_table *ht, hash_pos *pos);
hash_item_pid *hash_next_pid(hash_pos *pos);
void *hash_remove_pos_pid(hash_pos *pos);
typedef struct hash_item_string {
char * key;
void *value;
} hash_item_string;
void *hash_add_string(hash_table *ht, char * key, void *value);
void *hash_replace_string(hash_table *ht, char * key, void *value);
void *hash_lookup_string(hash_table *ht, char * key);
void *hash_remove_string(hash_table *ht, char * key);
hash_item_string *hash_first_string(hash_table *ht, hash_pos *pos);
hash_item_string *hash_next_string(hash_pos *pos);
void *hash_remove_pos_string(hash_pos *pos);
typedef struct hash_item_pidthr {
pidthr_t key;
void *value;
} hash_item_pidthr;
void *hash_add_pidthr(hash_table *ht, pidthr_t key, void *value);
void *hash_replace_pidthr(hash_table *ht, pidthr_t key, void *value);
void *hash_lookup_pidthr(hash_table *ht, pidthr_t key);
void *hash_remove_pidthr(hash_table *ht, pidthr_t key);
hash_item_pidthr *hash_first_pidthr(hash_table *ht, hash_pos *pos);
hash_item_pidthr *hash_next_pidthr(hash_pos *pos);
void *hash_remove_pos_pidthr(hash_pos *pos);
#if HAVE_LWPID_T
typedef struct hash_item_lwpid {
lwpid_t key;
void *value;
} hash_item_lwpid;
void *hash_add_lwpid(hash_table *ht, lwpid_t key, void *value);
void *hash_replace_lwpid(hash_table *ht, lwpid_t key, void *value);
void *hash_lookup_lwpid(hash_table *ht, lwpid_t key);
void *hash_remove_lwpid(hash_table *ht, lwpid_t key);
hash_item_lwpid *hash_first_lwpid(hash_table *ht, hash_pos *pos);
hash_item_lwpid *hash_next_lwpid(hash_pos *pos);
void *hash_remove_pos_lwpid(hash_pos *pos);
#endif
#endif

666
external/bsd/top/dist/hash.m4c vendored Executable file
View File

@@ -0,0 +1,666 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* hash.m4c */
/* The file hash.c is generated from hash.m4c via the preprocessor M4 */
/*
* Hash table functions: init, add, lookup, first, next, sizeinfo.
* This is a conventional "bucket hash". The key is hashed in to a number
* less than or equal to the number of buckets and the result is used
* to index in to the array of buckets. Each bucket is a linked list
* that contains all the key/value pairs which hashed to that index.
*/
#include "config.h"
#if STDC_HEADERS
#include <string.h>
#include <stdlib.h>
#define memzero(a, b) memset((a), 0, (b))
#else /* !STDC_HEADERS */
#ifdef HAVE_MEMCPY
#define memzero(a, b) memset((a), 0, (b))
#else
#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))
#endif /* HAVE_MEMCPY */
#ifdef HAVE_STRINGS_H
#include <strings.h>
#else
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#endif
void *malloc();
void free();
char *strdup();
#endif /* !STDC_HEADERS */
/* After all that there are still some systems that don't have NULL defined */
#ifndef NULL
#define NULL 0
#endif
#ifdef HAVE_MATH_H
#include <math.h>
#endif
#if !HAVE_PID_T
typedef long pid_t;
#endif
#if !HAVE_ID_T
typedef long id_t;
#endif
#include "hash.h"
dnl # The m4 code uses MALLOC, FREE, and STRDUP for dynamic allocation.
dnl # You can change what these get mapped to here:
define(`MALLOC', `malloc($1)')
define(`FREE', `free($1)')
define(`STRDUP', `strdup($1)')
static int
next_prime(int x)
{
double i, j;
int f;
i = x;
while (i++)
{
f=1;
for (j=2; j<i; j++)
{
if ((i/j)==floor(i/j))
{
f=0;
break;
}
}
if (f)
{
return (int)i;
}
}
return 1;
}
/* string hashes */
static int
string_hash(hash_table *ht, char *key)
{
unsigned long s = 0;
unsigned char ch;
int shifting = 24;
while ((ch = (unsigned char)*key++) != '\0')
{
if (shifting == 0)
{
s = s + ch;
shifting = 24;
}
else
{
s = s + (ch << shifting);
shifting -= 8;
}
}
return (s % ht->num_buckets);
}
void ll_init(llist *q)
{
q->head = NULL;
q->count = 0;
}
llistitem *ll_newitem(int size)
{
llistitem *qi;
qi = (llistitem *)MALLOC(sizeof(llistitem) + size);
qi->datum = ((void *)qi + sizeof(llistitem));
return qi;
}
void ll_freeitem(llistitem *li)
{
FREE(li);
}
void ll_add(llist *q, llistitem *new)
{
new->next = q->head;
q->head = new;
q->count++;
}
void ll_extract(llist *q, llistitem *qi, llistitem *last)
{
if (last == NULL)
{
q->head = qi->next;
}
else
{
last->next = qi->next;
}
qi->next = NULL;
q->count--;
}
#define LL_FIRST(q) ((q)->head)
llistitem *
ll_first(llist *q)
{
return q->head;
}
#define LL_NEXT(q, qi) ((qi) != NULL ? (qi)->next : NULL)
llistitem *
ll_next(llist *q, llistitem *qi)
{
return (qi != NULL ? qi->next : NULL);
}
#define LL_ISEMPTY(ll) ((ll)->count == 0)
int
ll_isempty(llist *ll)
{
return (ll->count == 0);
}
/*
* hash_table *hash_create(int num)
*
* Creates a hash table structure with at least "num" buckets.
*/
hash_table *
hash_create(int num)
{
hash_table *result;
bucket_t *b;
int bytes;
int i;
/* create the resultant structure */
result = (hash_table *)MALLOC(sizeof(hash_table));
/* adjust bucket count to be prime */
num = next_prime(num);
/* create the buckets */
bytes = sizeof(bucket_t) * num;
result->buckets = b = (bucket_t *)MALLOC(bytes);
result->num_buckets = num;
/* create each bucket as a linked list */
i = num;
while (--i >= 0)
{
ll_init(&(b->list));
b++;
}
return result;
}
/*
* unsigned int hash_count(hash_table *ht)
*
* Return total number of elements contained in hash table.
*/
unsigned int
hash_count(hash_table *ht)
{
register int i = 0;
register int cnt = 0;
register bucket_t *bucket;
bucket = ht->buckets;
while (i++ < ht->num_buckets)
{
cnt += bucket->list.count;
bucket++;
}
return cnt;
}
/*
* void hash_sizeinfo(unsigned int *sizes, int max, hash_table *ht)
*
* Fill in "sizes" with information about bucket lengths in hash
* table "max".
*/
void
hash_sizeinfo(unsigned int *sizes, int max, hash_table *ht)
{
register int i;
register int idx;
register bucket_t *bucket;
memzero(sizes, max * sizeof(unsigned int));
bucket = ht->buckets;
i = 0;
while (i++ < ht->num_buckets)
{
idx = bucket->list.count;
sizes[idx >= max ? max-1 : idx]++;
bucket++;
}
}
dnl # HASH_TABLE_TMPL(suffix, keytype, to_hash, to_cmp, to_alloc, to_free)
dnl #
dnl # This generates hash table functions suitable for keys
dnl # of type "keytype". The function names all end with "suffix".
dnl # "to_hash" is an expression that generates a hash index (this
dnl # expression can include key and ht). "to_cmp" is an expression
dnl # that compares "key" to "k1". "to_alloc" is an expression that
dnl # allocates space for "key", or empty if no allocation is needed.
dnl # "to_free" is an expression that frees "key", or empty if no
dnl # allocation is needed.
define(`HASH_TABLE_TMPL', `
/*
* void hash_add_$1(hash_table *ht, $2 key, void *value)
*
* Add an element to table "ht". The element is described by
* "key" and "value". Return NULL on success. If the key
* already exists in the table, then no action is taken and
* the data for the existing element is returned.
* Key type is $2
*/
void *
hash_add_$1(hash_table *ht, $2 key, void *value)
{
bucket_t *bucket;
hash_item_$1 *hi;
hash_item_$1 *h;
llist *ll;
llistitem *li;
llistitem *newli;
$2 k1;
/* allocate the space we will need */
newli = ll_newitem(sizeof(hash_item_$1));
hi = (hash_item_$1 *)newli->datum;
/* fill in the values */
hi->key = ifelse($5, , key, $5);
hi->value = value;
/* hash to the bucket */
bucket = &(ht->buckets[$3]);
/* walk the list to make sure we do not have a duplicate */
ll = &(bucket->list);
li = LL_FIRST(ll);
while (li != NULL)
{
h = (hash_item_$1 *)li->datum;
k1 = h->key;
if ($4)
{
/* found one */
break;
}
li = LL_NEXT(ll, li);
}
li = NULL;
/* is there already one there? */
if (li == NULL)
{
/* add the unique element to the buckets list */
ll_add(&(bucket->list), newli);
return NULL;
}
else
{
/* free the stuff we just allocated */
ll_freeitem(newli);
return ((hash_item_$1 *)(li->datum))->value;
}
}
/*
* void *hash_replace_$1(hash_table *ht, $2 key, void *value)
*
* Replace an existing value in the hash table with a new one and
* return the old value. If the key does not already exist in
* the hash table, add a new element and return NULL.
* Key type is $2
*/
void *
hash_replace_$1(hash_table *ht, $2 key, void *value)
{
bucket_t *bucket;
hash_item_$1 *hi;
llist *ll;
llistitem *li;
void *result = NULL;
$2 k1;
/* find the bucket */
bucket = &(ht->buckets[$3]);
/* walk the list until we find the existing item */
ll = &(bucket->list);
li = LL_FIRST(ll);
while (li != NULL)
{
hi = (hash_item_$1 *)li->datum;
k1 = hi->key;
if ($4)
{
/* found it: now replace the value with the new one */
result = hi->value;
hi->value = value;
break;
}
li = LL_NEXT(ll, li);
}
/* if the element wasnt found, add it */
if (result == NULL)
{
li = ll_newitem(sizeof(hash_item_$1));
hi = (hash_item_$1 *)li->datum;
hi->key = ifelse($5, , key, $5);
hi->value = value;
ll_add(&(bucket->list), li);
}
/* return the old value (so it can be freed) */
return result;
}
/*
* void *hash_lookup_$1(hash_table *ht, $2 key)
*
* Look up "key" in "ht" and return the associated value. If "key"
* is not found, return NULL. Key type is $2
*/
void *
hash_lookup_$1(hash_table *ht, $2 key)
{
bucket_t *bucket;
llist *ll;
llistitem *li;
hash_item_$1 *h;
void *result;
$2 k1;
result = NULL;
if ((bucket = &(ht->buckets[$3])) != NULL)
{
ll = &(bucket->list);
li = LL_FIRST(ll);
while (li != NULL)
{
h = (hash_item_$1 *)li->datum;
k1 = h->key;
if ($4)
{
result = h->value;
break;
}
li = LL_NEXT(ll, li);
}
}
return result;
}
/*
* void *hash_remove_$1(hash_table *ht, $2 key)
*
* Remove the element associated with "key" from the hash table
* "ht". Return the value or NULL if the key was not found.
*/
void *
hash_remove_$1(hash_table *ht, $2 key)
{
bucket_t *bucket;
llist *ll;
llistitem *li;
llistitem *lilast;
hash_item_$1 *hi;
void *result;
$2 k1;
result = NULL;
if ((bucket = &(ht->buckets[$3])) != NULL)
{
ll = &(bucket->list);
li = LL_FIRST(ll);
lilast = NULL;
while (li != NULL)
{
hi = (hash_item_$1 *)li->datum;
k1 = hi->key;
if ($4)
{
ll_extract(ll, li, lilast);
result = hi->value;
key = hi->key;
$6;
ll_freeitem(li);
break;
}
lilast = li;
li = LL_NEXT(ll, li);
}
}
return result;
}
/*
* hash_item_$1 *hash_first_$1(hash_table *ht, hash_pos *pos)
*
* First function to call when iterating through all items in the hash
* table. Returns the first item in "ht" and initializes "*pos" to track
* the current position.
*/
hash_item_$1 *
hash_first_$1(hash_table *ht, hash_pos *pos)
{
/* initialize pos for first item in first bucket */
pos->num_buckets = ht->num_buckets;
pos->hash_bucket = ht->buckets;
pos->curr = 0;
pos->ll_last = NULL;
/* find the first non-empty bucket */
while(pos->hash_bucket->list.count == 0)
{
pos->hash_bucket++;
if (++pos->curr >= pos->num_buckets)
{
return NULL;
}
}
/* set and return the first item */
pos->ll_item = LL_FIRST(&(pos->hash_bucket->list));
return (hash_item_$1 *)pos->ll_item->datum;
}
/*
* hash_item_$1 *hash_next_$1(hash_pos *pos)
*
* Return the next item in the hash table, using "pos" as a description
* of the present position in the hash table. "pos" also identifies the
* specific hash table. Return NULL if there are no more elements.
*/
hash_item_$1 *
hash_next_$1(hash_pos *pos)
{
llistitem *li;
/* move item to last and check for NULL */
if ((pos->ll_last = pos->ll_item) == NULL)
{
/* are we really at the end of the hash table? */
if (pos->curr >= pos->num_buckets)
{
/* yes: return NULL */
return NULL;
}
/* no: regrab first item in current bucket list (might be NULL) */
li = LL_FIRST(&(pos->hash_bucket->list));
}
else
{
/* get the next item in the llist */
li = LL_NEXT(&(pos->hash_bucket->list), pos->ll_item);
}
/* if its NULL we have to find another bucket */
while (li == NULL)
{
/* locate another bucket */
pos->ll_last = NULL;
/* move to the next one */
pos->hash_bucket++;
if (++pos->curr >= pos->num_buckets)
{
/* at the end of the hash table */
pos->ll_item = NULL;
return NULL;
}
/* get the first element (might be NULL) */
li = LL_FIRST(&(pos->hash_bucket->list));
}
/* li is the next element to dish out */
pos->ll_item = li;
return (hash_item_$1 *)li->datum;
}
/*
* void *hash_remove_pos_$1(hash_pos *pos)
*
* Remove the hash table entry pointed to by position marker "pos".
* The data from the entry is returned upon success, otherwise NULL.
*/
void *
hash_remove_pos_$1(hash_pos *pos)
{
llistitem *li;
void *ans;
hash_item_$1 *hi;
$2 key;
/* sanity checks */
if (pos == NULL || pos->ll_last == pos->ll_item)
{
return NULL;
}
/* at this point pos contains the item to remove (ll_item)
and its predecesor (ll_last) */
/* extract the item from the llist */
li = pos->ll_item;
ll_extract(&(pos->hash_bucket->list), li, pos->ll_last);
/* retain the data */
hi = (hash_item_$1 *)li->datum;
ans = hi->value;
/* free up the space */
key = hi->key;
$6;
ll_freeitem(li);
/* back up to previous item */
/* its okay for ll_item to be null: hash_next will detect it */
pos->ll_item = pos->ll_last;
return ans;
}
')
dnl # create hash talbe functions for unsigned int and for strings */
HASH_TABLE_TMPL(`uint', `unsigned int', `(key % ht->num_buckets)', `key == k1', ,)
HASH_TABLE_TMPL(`pid', `pid_t', `(key % ht->num_buckets)', `key == k1', ,)
HASH_TABLE_TMPL(`string', `char *', `string_hash(ht, key)', `strcmp(key, k1) == 0', `STRDUP(key)', `FREE(key)')
HASH_TABLE_TMPL(`pidthr', `pidthr_t', `((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)', `(key.k_pid == k1.k_pid && key.k_thr == k1.k_thr)', ,)
#if HAVE_LWPID_T
HASH_TABLE_TMPL(`lwpid', `lwpid_t', `(key % ht->num_buckets)', `key == k1', ,)
#endif

103
external/bsd/top/dist/hash.m4h vendored Executable file
View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* hash.m4h */
/* Interface definition for hash.c */
/* The file hash.h is generated from hash.m4h via the preprocessor M4 */
#ifndef _HASH_H
#define _HASH_H
#include <sys/types.h>
typedef struct pidthr_t {
pid_t k_pid;
id_t k_thr;
} pidthr_t;
typedef struct llistitem {
void *datum;
struct llistitem *next;
} llistitem;
typedef struct llist {
llistitem *head;
unsigned int count;
} llist;
typedef struct bucket {
llist list;
} bucket_t;
typedef struct hash_table {
int num_buckets;
bucket_t *buckets;
} hash_table;
typedef struct hash_pos {
int num_buckets;
int curr;
bucket_t *hash_bucket;
llistitem *ll_item;
llistitem *ll_last;
} hash_pos;
hash_table *hash_create(int num);
void hash_sizeinfo(unsigned int *sizes, int max, hash_table *ht);
define(`HASH_TYPE_TMPL', `
typedef struct hash_item_$1 {
$2 key;
void *value;
} hash_item_$1;
void *hash_add_$1(hash_table *ht, $2 key, void *value);
void *hash_replace_$1(hash_table *ht, $2 key, void *value);
void *hash_lookup_$1(hash_table *ht, $2 key);
void *hash_remove_$1(hash_table *ht, $2 key);
hash_item_$1 *hash_first_$1(hash_table *ht, hash_pos *pos);
hash_item_$1 *hash_next_$1(hash_pos *pos);
void *hash_remove_pos_$1(hash_pos *pos);
')
HASH_TYPE_TMPL(`uint', `unsigned int')
HASH_TYPE_TMPL(`pid', `pid_t')
HASH_TYPE_TMPL(`string', `char *')
HASH_TYPE_TMPL(`pidthr', `pidthr_t')
#if HAVE_LWPID_T
HASH_TYPE_TMPL(`lwpid', `lwpid_t')
#endif
#endif

251
external/bsd/top/dist/install-sh vendored Executable file
View File

@@ -0,0 +1,251 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
:
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
:
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
:
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
:
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
:
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
:
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

69
external/bsd/top/dist/layout.h vendored Normal file
View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top - a top users display for Unix
*
* This file defines the default locations on the screen for various parts
* of the display. These definitions are used by the routines in "display.c"
* for cursor addressing.
*/
#define X_LASTPID 10
#define Y_LASTPID 0
#define X_LASTPIDWIDTH 13
#define X_LOADAVE 27
#define Y_LOADAVE 0
#define X_LOADAVEWIDTH 7
#define X_MINIBAR 50
#define Y_MINIBAR 0
#define X_UPTIME 48
#define Y_UPTIME 0
#define X_PROCSTATE 15
#define Y_PROCSTATE 1
#define X_BRKDN 15
#define Y_BRKDN 1
#define X_CPUSTATES 0
#define Y_CPUSTATES 2
#define X_KERNEL 8
#define Y_KERNEL 3
#define X_MEM 8
#define Y_MEM 3
#define X_SWAP 6
#define Y_SWAP 4
#define Y_MESSAGE 4
#define X_HEADER 0
#define Y_HEADER 5
#define X_IDLECURSOR 0
#define Y_IDLECURSOR 4
#define Y_PROCS 6

89
external/bsd/top/dist/loadavg.h vendored Normal file
View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 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)
# include <sys/fixpoint.h>
# if defined(FBITS) && !defined(FSCALE)
# define FSCALE (1 << FBITS) /* 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 long 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

124
external/bsd/top/dist/machine.h vendored Normal file
View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 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. Fields marked as
* "optional" are not filled in by every module.
*/
struct statics
{
const char **procstate_names;
const char **cpustate_names;
const char **memory_names;
const char **swap_names; /* optional */
const char **order_names; /* optional */
const char **top_color_names; /* optional */
const char **kernel_names; /* optional */
time_t boottime; /* optional */
int modemax; /* optional */
int ncpu; /* optional */
struct {
unsigned int fullcmds : 1;
unsigned int idle : 1;
unsigned int warmup : 1;
unsigned int threads : 1;
} flags;
};
/*
* 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
{
pid_t last_pid;
double load_avg[NUM_AVERAGES];
int p_total;
int P_ACTIVE; /* number of procs considered "active" */
int *procstates;
int *cpustates;
int *kernel;
long *memory;
long *swap;
};
/* 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 system; /* show system processes */
int fullcmd; /* show full command */
int usernames; /* show usernames */
int uid; /* only this uid (unless uid == -1) */
char *command; /* only this command (unless == NULL) */
int mode; /* select display mode (0 is default) */
int threads; /* show threads separately */
pid_t pid; /* show only this pid (unless pid == -1) */
};
/* routines defined by the machine dependent module */
int machine_init(struct statics *);
void get_system_info(struct system_info *);
caddr_t get_process_info(struct system_info *, struct process_select *, int);
char *format_header(char *);
char *format_next_process(caddr_t, char *(*)(int));
int proc_owner(int);
#ifdef HAVE_FORMAT_PROCESS_HEADER
#endif /* _MACHINE_H_ */
char *format_process_header(struct process_select *sel, caddr_t handle, int count);
#endif

729
external/bsd/top/dist/machine/m_aix43.c vendored Normal file
View File

@@ -0,0 +1,729 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: PowerPC running AIX 4.2 or higher
*
* DESCRIPTION:
* This is the machine-dependent module for AIX 4.2 and higher
* It is currenlty only tested on PowerPC architectures.
*
* TERMCAP: -lcurses
*
* CFLAGS: -DORDER -DHAVE_GETOPT
*
* LIBS: -bD:0x18000000
*
* AUTHOR: Joep Vesseur <joep@fwi.uva.nl>
*
* PATCHES: Antoine Tabary <tabary@bruyeres.cea.fr>
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <nlist.h>
#include <sys/sysinfo.h>
#include <procinfo.h>
#include <sys/proc.h>
#include <sys/times.h>
#include <sys/param.h>
#include <pwd.h>
#include "top.h"
#include "machine.h"
#include "utils.h"
#define PROCRESS(p) (((p)->pi_trss + (p)->pi_drss)*4)
#define PROCSIZE(p) (((p)->pi_tsize/1024+(p)->pi_dvm)*4)
#define PROCTIME(pi) (pi->pi_ru.ru_utime.tv_sec + pi->pi_ru.ru_stime.tv_sec)
/*
* structure definition taken from 'monitor' by Jussi Maki (jmaki@hut.fi)
*/
struct vmker {
uint n0,n1,n2,n3,n4,n5,n6,n7,n8;
uint totalmem;
uint badmem; /* this is used in RS/6000 model 220 */
uint freemem;
uint n12;
uint numperm; /* this seems to keep other than text and data segment
usage; name taken from /usr/lpp/bos/samples/vmtune.c */
uint totalvmem,freevmem;
uint n15, n16, n17, n18, n19;
};
#define KMEM "/dev/kmem"
/* Indices in the nlist array */
#define X_AVENRUN 0
#define X_SYSINFO 1
#define X_VMKER 2
#define X_PROC 3
#define X_V 4
static struct nlist nlst[] = {
{ "avenrun", 0, 0, 0, 0, 0 }, /* 0 */
{ "sysinfo", 0, 0, 0, 0, 0 }, /* 1 */
{ "vmker", 0, 0, 0, 0, 0 }, /* 2 */
{ "proc", 0, 0, 0, 0, 0 }, /* 3 */
{ "v", 0, 0, 0, 0, 0 }, /* 4 */
{ NULL, 0, 0, 0, 0, 0 }
};
/* get_process_info returns handle. definition is here */
struct handle
{
struct procsinfo **next_proc;
int remaining;
};
/*
* 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 7
#define Proc_format \
"%6d %-8.8s %3d %4d %5d%c %4d%c %-5s %6s %5.2f%% %5.2f%% %.14s%s"
/* these are for detailing the process states */
int process_states[9];
char *procstatenames[] = {
" none, ", " sleeping, ", " state2, ", " runnable, ",
" idle, ", " zombie, ", " stopped, ", " running, ", " swapped, ",
NULL
};
/* these are for detailing the cpu states */
int cpu_states[4];
char *cpustatenames[] = {
"idle", "user", "kernel", "wait",
NULL
};
/* these are for detailing the memory statistics */
long memory_stats[4];
char *memorynames[] = {
"K Total, ", "K Free, ", "K Buffers", NULL
};
#define M_REAL 0
#define M_REALFREE 1
#define M_BUFFERS 2
long swap_stats[3];
char *swapnames[] = {
"K Total, ", "K Free", NULL
};
#define M_VIRTUAL 0
#define M_VIRTFREE 1
char *state_abbrev[] = {
"", "sleep", "", "", "sleep", "zomb", "stop", "run", "swap"
};
/* sorting orders. first is default */
char *ordernames[] = {
"cpu", "size", "res", "time", "pri", NULL
};
/* compare routines */
int compare_cpu(), compare_size(), compare_res(), compare_time(),
compare_prio();
int (*proc_compares[])() = {
compare_cpu,
compare_size,
compare_res,
compare_time,
compare_prio,
NULL
};
/* useful externals */
extern int errno;
extern char *sys_errlist[];
long lseek();
long time();
long percentages();
/* useful globals */
int kmem; /* file descriptor */
/* offsets in kernel */
static unsigned long avenrun_offset;
static unsigned long sysinfo_offset;
static unsigned long vmker_offset;
static unsigned long proc_offset;
static unsigned long v_offset;
/* used for calculating cpu state percentages */
static long cp_time[CPU_NTIMES];
static long cp_old[CPU_NTIMES];
static long cp_diff[CPU_NTIMES];
/* the runqueue length is a cumulative value. keep old value */
long old_runque;
/* process info */
struct var v_info; /* to determine nprocs */
int nprocs; /* maximum nr of procs in proctab */
int ncpus; /* nr of cpus installed */
int ptsize; /* size of process table in bytes */
struct proc *p_proc; /* a copy of the process table */
struct procsinfo *p_info; /* needed for vm and ru info */
struct procsinfo **pref; /* processes selected for display */
int pref_len; /* number of processes selected */
/* needed to calculate WCPU */
unsigned long curtime;
/*
* Initialize globals, get kernel offsets and stuff...
*/
machine_init(struct statics *statics)
{
time_t uptime, now;
struct tms tbuf;
if ((kmem = open(KMEM, O_RDONLY)) == -1) {
perror(KMEM);
return -1;
}
/* get kernel symbol offsets */
if (knlist(nlst, 5, sizeof(struct nlist)) != 0) {
perror("knlist");
return -1;
}
avenrun_offset = nlst[X_AVENRUN].n_value;
sysinfo_offset = nlst[X_SYSINFO].n_value;
vmker_offset = nlst[X_VMKER].n_value;
proc_offset = nlst[X_PROC].n_value;
v_offset = nlst[X_V].n_value;
getkval(v_offset, (caddr_t)&v_info, sizeof v_info, "v");
ncpus = v_info.v_ncpus; /* number of cpus */
nprocs = PROCMASK(PIDMAX);
if (nprocs > 1024) nprocs = 1024;
ptsize = nprocs * sizeof (struct proc);
p_proc = (struct proc *)malloc(ptsize);
p_info = (struct procsinfo *)malloc(nprocs * sizeof (struct procsinfo));
pref = (struct procsinfo **)malloc(nprocs * sizeof (struct procsinfo *));
if (!p_proc || !p_info || !pref) {
fprintf(stderr, "top: not enough memory\n");
return -1;
}
/* set boot time */
now = time(NULL);
uptime = times(&tbuf) / HZ;
statics->boottime = now - uptime;
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
statics->order_names = ordernames;
statics->swap_names = swapnames;
return(0);
}
char *format_header(char *uname_field)
{
register char *ptr;
ptr = header + UNAME_START;
while (*uname_field != '\0')
{
*ptr++ = *uname_field++;
}
return(header);
}
void
get_system_info(struct system_info *si)
{
int load_avg[3];
struct sysinfo s_info;
struct vmker m_info;
int i;
double total = 0;
/* get the load avarage array */
getkval(avenrun_offset, (caddr_t)load_avg, sizeof load_avg, "avenrun");
/* get the sysinfo structure */
getkval(sysinfo_offset, (caddr_t)&s_info, sizeof s_info, "sysinfo");
/* get vmker structure */
getkval(vmker_offset, (caddr_t)&m_info, sizeof m_info, "vmker");
/* convert load avarages to doubles */
for (i = 0; i < 3; i++)
si->load_avg[i] = (double)load_avg[i]/65536.0;
/* calculate cpu state in percentages */
for (i = 0; i < CPU_NTIMES; i++) {
cp_old[i] = cp_time[i];
cp_time[i] = s_info.cpu[i];
cp_diff[i] = cp_time[i] - cp_old[i];
total += cp_diff[i];
}
total = total/1000.0; /* top itself will correct this */
for (i = 0; i < CPU_NTIMES; i++) {
cpu_states[i] = cp_diff[i] / total;
}
/* calculate memory statistics, scale 4K pages to megabytes */
#define PAGE_TO_MB(a) ((a)*4/1024)
memory_stats[M_REAL] = PAGE_TO_MB(m_info.totalmem);
memory_stats[M_REALFREE] = PAGE_TO_MB(m_info.freemem);
memory_stats[M_BUFFERS] = PAGE_TO_MB(m_info.numperm);
swap_stats[M_VIRTUAL] = PAGE_TO_MB(m_info.totalvmem);
swap_stats[M_VIRTFREE] = PAGE_TO_MB(m_info.freevmem);
/* runnable processes */
process_states[0] = s_info.runque - old_runque;
old_runque = s_info.runque;
si->cpustates = cpu_states;
si->memory = memory_stats;
si->swap = swap_stats;
}
static struct handle handle;
caddr_t
get_process_info(struct system_info *si, struct process_select *sel, int compare_index)
{
int i, nproc;
int ptsize_util;
int active_procs = 0, total_procs = 0;
struct procsinfo *pp, **p_pref = pref;
unsigned long pctcpu;
pid_t procsindex = 0;
struct proc *p;
si->procstates = process_states;
curtime = time(0);
/* get the procsinfo structures of all running processes */
nproc = getprocs(p_info, sizeof (struct procsinfo), NULL, 0,
&procsindex, nprocs);
if (nproc < 0) {
perror("getprocs");
quit(1);
}
/* the swapper has no cmd-line attached */
strcpy(p_info[0].pi_comm, "swapper");
/* get proc table */
ptsize_util = (PROCMASK(p_info[nproc-1].pi_pid)+1) * sizeof(struct proc);
getkval(proc_offset, (caddr_t)p_proc, ptsize_util, "proc");
memset(process_states, 0, sizeof process_states);
/* build a list of pointers to processes to show. walk through the
* list of procsinfo structures instead of the proc table since the
* mapping of procsinfo -> proctable is easy, the other way around
* is cumbersome
*/
for (pp = p_info, i = 0; i < nproc; pp++, i++) {
p = &p_proc[PROCMASK(pp->pi_pid)];
/* AIX marks all runnable processes as ACTIVE. We want to know
which processes are sleeping, so check used cpu ticks and adjust
status field accordingly
*/
if (p->p_stat == SACTIVE && p->p_cpticks == 0)
p->p_stat = SIDL;
if (pp->pi_state && (sel->system || ((pp->pi_flags & SKPROC) == 0))) {
total_procs++;
process_states[p->p_stat]++;
if ( (pp->pi_state != SZOMB) &&
(sel->idle || p->p_cpticks != 0 || (p->p_stat == SACTIVE))
&& (sel->uid == -1 || pp->pi_uid == (uid_t)sel->uid)) {
*p_pref++ = pp;
active_procs++;
}
}
}
/* the pref array now holds pointers to the procsinfo structures in
* the p_info array that were selected for display
*/
/* sort if requested */
if (si->p_active)
qsort((char *)pref, active_procs, sizeof (struct procsinfo *),
proc_compares[compare_index]);
si->last_pid = -1; /* no way to figure out last used pid */
si->p_total = total_procs;
si->p_active = pref_len = active_procs;
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char fmt[MAX_COLS]; /* static area where result is built */
/* define what weighted cpu is. use definition of %CPU from 'man ps(1)' */
#define weighted_cpu(pp) (PROCTIME(pp) == 0 ? 0.0 : \
(((PROCTIME(pp)*100.0)/(curtime-pi->pi_start)/ncpus)))
#define double_pctcpu(p) ((double)p->p_pctcpu/(double)FLT_MODULO)
char *
format_next_process(caddr_t handle, char *(*get_userid)())
{
register struct handle *hp;
register struct procsinfo *pi;
register struct proc *p;
char *uname;
long cpu_time;
int proc_size, proc_ress;
char size_unit = 'K';
char ress_unit = 'K';
hp = (struct handle *)handle;
if (hp->remaining == 0) { /* safe guard */
fmt[0] = '\0';
return fmt;
}
pi = *(hp->next_proc++);
hp->remaining--;
p = &p_proc[PROCMASK(pi->pi_pid)];
cpu_time = PROCTIME(pi);
/* we disply sizes up to 10M in KiloBytes, beyond 10M in MegaBytes */
if ((proc_size = (pi->pi_tsize/1024+pi->pi_dvm)*4) > 10240) {
proc_size /= 1024;
size_unit = 'M';
}
if ((proc_ress = (pi->pi_trss + pi->pi_drss)*4) > 10240) {
proc_ress /= 1024;
ress_unit = 'M';
}
sprintf(fmt, Proc_format ,
pi->pi_pid, /* PID */
(*get_userid)(pi->pi_uid), /* login name */
getpriority(PRIO_PROCESS, pi->pi_pid),
EXTRACT_NICE(p), /* fixed or vari */
proc_size, /* size */
size_unit, /* K or M */
proc_ress, /* resident */
ress_unit, /* K or M */
state_abbrev[p->p_stat], /* process state */
format_time(cpu_time), /* time used */
weighted_cpu(pi), /* WCPU */
100.0 * double_pctcpu(p), /* CPU */
printable(pi->pi_comm), /* COMM */
(pi->pi_flags & SKPROC) == 0 ? "" : " (sys)" /* kernel process? */
);
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).
*
*/
int
getkval(unsigned long offset, caddr_t ptr, int size, char *refstr)
{
int upper_2gb = 0;
/* reads above 2Gb are done by seeking to offset%2Gb, and supplying
* 1 (opposed to 0) as fourth parameter to readx (see 'man kmem')
*/
if (offset > 1<<31) {
upper_2gb = 1;
offset &= 0x7fffffff;
}
if (lseek(kmem, offset, SEEK_SET) != offset) {
fprintf(stderr, "top: lseek failed\n");
quit(2);
}
if (readx(kmem, ptr, size, upper_2gb) != size) {
if (*refstr == '!')
return 0;
else {
fprintf(stderr, "top: kvm_read for %s: %s\n", refstr,
sys_errlist[errno]);
quit(2);
}
}
return 1 ;
}
/* comparison routine for qsort */
/*
* The following code is taken from the solaris module and adjusted
* for AIX -- JV .
*/
#define ORDERKEY_PCTCPU \
if (lresult = p2->p_pctcpu - p1->p_pctcpu, \
(result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
#define ORDERKEY_CPTICKS \
if ((result = PROCTIME(pi2) - PROCTIME(pi1)) == 0)
#define ORDERKEY_STATE \
if ((result = sorted_state[p2->p_stat] \
- sorted_state[p1->p_stat]) == 0)
/* Nice values directly reflect the process' priority, and are always >0 ;-) */
#define ORDERKEY_PRIO \
if ((result = EXTRACT_NICE(p1) - EXTRACT_NICE(p2)) == 0)
#define ORDERKEY_RSSIZE \
if ((result = PROCRESS(pi2) - PROCRESS(pi1)) == 0)
#define ORDERKEY_MEM \
if ((result = PROCSIZE(pi2) - PROCSIZE(pi1)) == 0)
static unsigned char sorted_state[] =
{
0, /* not used */
0,
0,
0,
3, /* sleep */
1, /* zombie */
4, /* stop */
6, /* run */
2, /* swap */
};
/* compare_cpu - the comparison function for sorting by cpu percentage */
int
compare_cpu(struct procsinfo **ppi1, struct procsinfo **ppi2)
{
register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2;
register struct proc *p1;
register struct proc *p2;
register int result;
register long lresult;
p1 = &p_proc[PROCMASK(pi1->pi_pid)];
p2 = &p_proc[PROCMASK(pi2->pi_pid)];
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_RSSIZE
ORDERKEY_MEM
;
return result;
}
/* compare_size - the comparison function for sorting by total memory usage */
int
compare_size(struct procsinfo **ppi1, struct procsinfo **ppi2)
{
register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2;
register struct proc *p1;
register struct proc *p2;
register int result;
register long lresult;
p1 = &p_proc[PROCMASK(pi1->pi_pid)];
p2 = &p_proc[PROCMASK(pi2->pi_pid)];
ORDERKEY_MEM
ORDERKEY_RSSIZE
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
;
return result;
}
/* compare_res - the comparison function for sorting by resident set size */
int
compare_res(struct procsinfo **ppi1, struct procsinfo **ppi2)
{
register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2;
register struct proc *p1;
register struct proc *p2;
register int result;
register long lresult;
p1 = &p_proc[PROCMASK(pi1->pi_pid)];
p2 = &p_proc[PROCMASK(pi2->pi_pid)];
ORDERKEY_RSSIZE
ORDERKEY_MEM
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
;
return result;
}
/* compare_time - the comparison function for sorting by total cpu time */
int
compare_time(struct procsinfo **ppi1, struct procsinfo **ppi2)
{
register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2;
register struct proc *p1;
register struct proc *p2;
register int result;
register long lresult;
p1 = &p_proc[PROCMASK(pi1->pi_pid)];
p2 = &p_proc[PROCMASK(pi2->pi_pid)];
ORDERKEY_CPTICKS
ORDERKEY_PCTCPU
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_MEM
ORDERKEY_RSSIZE
;
return result;
}
/* compare_prio - the comparison function for sorting by cpu percentage */
int
compare_prio(struct procsinfo **ppi1, struct procsinfo **ppi2)
{
register struct procsinfo *pi1 = *ppi1, *pi2 = *ppi2;
register struct proc *p1;
register struct proc *p2;
register int result;
register long lresult;
p1 = &p_proc[PROCMASK(pi1->pi_pid)];
p2 = &p_proc[PROCMASK(pi2->pi_pid)];
ORDERKEY_PRIO
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_RSSIZE
ORDERKEY_MEM
;
return result;
}
int
proc_owner(int pid)
{
int uid;
register struct procsinfo **prefp = pref;
register int cnt = pref_len;
while (--cnt >= 0) {
if ((*prefp)->pi_pid == pid)
return (*prefp)->pi_uid;
prefp++;
}
return(-1);
}

793
external/bsd/top/dist/machine/m_aix5.c vendored Normal file
View File

@@ -0,0 +1,793 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: PowerPC running AIX 5.1 or higher
*
* DESCRIPTION:
* This is the machine-dependent module for AIX 5.1 and higher (may work on
* older releases too). It is currently only tested on PowerPC
* architectures.
*
* TERMCAP: -lcurses
*
* CFLAGS: -DORDER -DHAVE_GETOPT -DHAVE_STRERROR -DMAXPROCS=10240
*
* LIBS: -lperfstat
*
* AUTHOR: Joep Vesseur <joep@fwi.uva.nl>
*
* PATCHES: Antoine Tabary <tabary@bruyeres.cea.fr>, Dan Nelson <dnelson@allantgroup.com>
*/
#define MAXPROCS 10240
#include "config.h"
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <nlist.h>
#include <procinfo.h>
#include <sys/types.h>
#include <sys/proc.h>
#include <sys/sysinfo.h>
#include <sys/sysconfig.h>
#include <pwd.h>
#include <errno.h>
#include <libperfstat.h>
#include "top.h"
#include "machine.h"
#include "utils.h"
#define PROCRESS(p) (((p)->pi_trss + (p)->pi_drss)*4)
#define PROCSIZE(p) (((p)->pi_tsize/1024+(p)->pi_dvm)*4)
#define PROCTIME(pi) (pi->pi_ru.ru_utime.tv_sec + pi->pi_ru.ru_stime.tv_sec)
#ifdef OLD
/*
* structure definition taken from 'monitor' by Jussi Maki (jmaki@hut.fi)
*/
struct vmker {
uint n0,n1,n2,n3,n4,n5,n6,n7,n8;
uint totalmem;
uint badmem; /* this is used in RS/6000 model 220 */
uint freemem;
uint n12;
uint numperm; /* this seems to keep other than text and data segment
usage; name taken from /usr/lpp/bos/samples/vmtune.c */
uint totalvmem,freevmem;
uint n15, n16, n17, n18, n19;
};
#define KMEM "/dev/kmem"
/* Indices in the nlist array */
#define X_AVENRUN 0
#define X_SYSINFO 1
#define X_VMKER 2
#define X_V 3
static struct nlist nlst[] = {
{ "avenrun", 0, 0, 0, 0, 0 }, /* 0 */
{ "sysinfo", 0, 0, 0, 0, 0 }, /* 1 */
{ "vmker", 0, 0, 0, 0, 0 }, /* 2 */
{ "v", 0, 0, 0, 0, 0 }, /* 3 */
{ NULL, 0, 0, 0, 0, 0 }
};
#endif
/* get_process_info returns handle. definition is here */
struct handle
{
struct procentry64 **next_proc;
int remaining;
};
/*
* 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 7
#define Proc_format \
"%6d %-8.8s %3d %4d %5d%c %4d%c %-5s %6s %5.2f%% %5.2f%% %.14s%s"
/* these are for detailing the process states */
int process_states[9];
char *procstatenames[] = {
" none, ", " sleeping, ", " state2, ", " runnable, ",
" idle, ", " zombie, ", " stopped, ", " running, ", " swapped, ",
NULL
};
/* these are for detailing the cpu states */
int cpu_states[CPU_NTIMES];
char *cpustatenames[] = {
"idle", "user", "kernel", "wait",
NULL
};
/* these are for detailing the memory statistics */
long memory_stats[7];
char *memorynames[] = {
"K total, ", "K buf, ", "K sys, ", "K free", NULL
};
#define M_REAL 0
#define M_BUFFERS 1
#define M_SYSTEM 2
#define M_REALFREE 3
long swap_stats[3];
char *swapnames[] = {
"K total, ", "K free", NULL
};
#define M_VIRTUAL 0
#define M_VIRTFREE 1
char *state_abbrev[] = {
NULL, NULL, NULL, NULL, "idle", "zomb", "stop", "run", "swap"
};
/* sorting orders. first is default */
char *ordernames[] = {
"cpu", "size", "res", "time", "pri", NULL
};
/* compare routines */
int compare_cpu(), compare_size(), compare_res(), compare_time(),
compare_prio();
int (*proc_compares[])() = {
compare_cpu,
compare_size,
compare_res,
compare_time,
compare_prio,
NULL
};
/* useful externals */
long percentages(int cnt, int *out, long *new, long *old, long *diffs);
char *format_time(long seconds);
#ifdef OLD
/* useful globals */
int kmem; /* file descriptor */
/* offsets in kernel */
static unsigned long avenrun_offset;
static unsigned long sysinfo_offset;
static unsigned long vmker_offset;
static unsigned long v_offset;
#endif
/* used for calculating cpu state percentages */
static long cp_time[CPU_NTIMES];
static long cp_old[CPU_NTIMES];
static long cp_diff[CPU_NTIMES];
/* the runqueue length is a cumulative value. keep old value */
long old_runque;
/* process info */
struct kernvars v_info; /* to determine nprocs */
int nprocs; /* maximum nr of procs in proctab */
int ncpus; /* nr of cpus installed */
struct procentry64 *p_info; /* needed for vm and ru info */
struct procentry64 **pref; /* processes selected for display */
struct timeval64 *cpu_proc, *old_cpu_proc; /* total cpu used by each process */
int pref_len; /* number of processes selected */
/* needed to calculate WCPU */
unsigned long curtime;
/* needed to calculate CPU */
struct timeval curtimeval;
struct timeval lasttimeval;
#ifdef OLD
int getkval(unsigned long offset, caddr_t ptr, int size, char *refstr);
#endif
void *xmalloc(long size)
{
void *p = malloc(size);
if (!p)
{
fprintf(stderr,"Could not allocate %ld bytes: %s\n", size, strerror(errno));
exit(1);
}
return p;
}
/*
* Initialize globals, get kernel offsets and stuff...
*/
int machine_init(statics)
struct statics *statics;
{
#ifdef OLD
if ((kmem = open(KMEM, O_RDONLY)) == -1) {
perror(KMEM);
return -1;
}
/* get kernel symbol offsets */
if (knlist(nlst, 4, sizeof(struct nlist)) != 0) {
perror("knlist");
return -1;
}
avenrun_offset = nlst[X_AVENRUN].n_value;
sysinfo_offset = nlst[X_SYSINFO].n_value;
vmker_offset = nlst[X_VMKER].n_value;
v_offset = nlst[X_V].n_value;
getkval(v_offset, (caddr_t)&v_info, sizeof v_info, "v");
#else
sysconfig(SYS_GETPARMS, &v_info, sizeof v_info);
#endif
ncpus = v_info.v_ncpus; /* number of cpus */
/* procentry64 is 4912 bytes, and PROCMASK(PIDMAX) is 262144. That'd
require 1.2gb for the p_info array, which is way overkill. Raise
MAXPROCS if you have more than 10240 active processes in the system.
*/
#if 0
nprocs = PROCMASK(PIDMAX);
#else
nprocs = MAXPROCS;
#endif
cpu_proc = (struct timeval64 *)xmalloc(PROCMASK(PIDMAX) * sizeof (struct timeval64));
old_cpu_proc = (struct timeval64 *)xmalloc(PROCMASK(PIDMAX) * sizeof (struct timeval64));
p_info = (struct procentry64 *)xmalloc(nprocs * sizeof (struct procentry64));
pref = (struct procentry64 **)xmalloc(nprocs * sizeof (struct procentry64 *));
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
statics->swap_names = swapnames;
statics->order_names = ordernames;
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);
}
void get_system_info(si)
struct system_info *si;
{
#ifdef OLD
long long load_avg[3];
struct sysinfo64 s_info;
struct vmker m_info;
#else
perfstat_memory_total_t m_info1;
perfstat_cpu_total_t s_info1;
#endif
int i;
int total = 0;
#ifdef OLD
/* get the load avarage array */
getkval(avenrun_offset, (caddr_t)load_avg, sizeof load_avg, "avenrun");
/* get the sysinfo structure */
getkval(sysinfo_offset, (caddr_t)&s_info, sizeof s_info, "sysinfo64");
/* get vmker structure */
getkval(vmker_offset, (caddr_t)&m_info, sizeof m_info, "vmker");
#else
/* cpu stats */
perfstat_cpu_total(NULL, &s_info1, sizeof s_info1, 1);
/* memory stats */
perfstat_memory_total(NULL, &m_info1, sizeof m_info1, 1);
#endif
#ifdef OLD
/* convert load avarages to doubles */
for (i = 0; i < 3; i++)
si->load_avg[i] = (double)load_avg[i]/65536.0;
/* calculate cpu state in percentages */
for (i = 0; i < CPU_NTIMES; i++) {
cp_old[i] = cp_time[i];
cp_time[i] = s_info.cpu[i];
cp_diff[i] = cp_time[i] - cp_old[i];
total += cp_diff[i];
}
#else
/* convert load avarages to doubles */
for (i = 0; i < 3; i++)
si->load_avg[i] = (double)s_info1.loadavg[i]/(1<<SBITS);
/* calculate cpu state in percentages */
for (i = 0; i < CPU_NTIMES; i++) {
cp_old[i] = cp_time[i];
cp_time[i] = ( i==CPU_IDLE?s_info1.idle:
i==CPU_USER?s_info1.user:
i==CPU_KERNEL?s_info1.sys:
i==CPU_WAIT?s_info1.wait:0);
cp_diff[i] = cp_time[i] - cp_old[i];
total += cp_diff[i];
}
#endif
for (i = 0; i < CPU_NTIMES; i++) {
cpu_states[i] = 1000 * cp_diff[i] / total;
}
/* calculate memory statistics, scale 4K pages */
#ifdef OLD
#define PAGE_TO_MB(a) ((a)*4/1024)
memory_stats[M_TOTAL] = PAGE_TO_MB(m_info.totalmem+m_info.totalvmem);
memory_stats[M_REAL] = PAGE_TO_MB(m_info.totalmem);
memory_stats[M_REALFREE] = PAGE_TO_MB(m_info.freemem);
memory_stats[M_BUFFERS] = PAGE_TO_MB(m_info.numperm);
swap_stats[M_VIRTUAL] = PAGE_TO_MB(m_info.totalvmem);
swap_stats[M_VIRTFREE] = PAGE_TO_MB(m_info.freevmem);
#else
#define PAGE_TO_KB(a) ((a)*4)
memory_stats[M_REAL] = PAGE_TO_KB(m_info1.real_total);
memory_stats[M_BUFFERS] = PAGE_TO_KB(m_info1.numperm);
#ifdef _AIXVERSION_520
memory_stats[M_SYSTEM] = PAGE_TO_KB(m_info1.real_system);
#endif
memory_stats[M_REALFREE] = PAGE_TO_KB(m_info1.real_free);
swap_stats[M_VIRTUAL] = PAGE_TO_KB(m_info1.pgsp_total);
swap_stats[M_VIRTFREE] = PAGE_TO_KB(m_info1.pgsp_free);
#endif
/* runnable processes */
#ifdef OLD
process_states[0] = s_info.runque - old_runque;
old_runque = s_info.runque;
#else
process_states[0] = s_info1.runque - old_runque;
old_runque = s_info1.runque;
#endif
si->cpustates = cpu_states;
si->memory = memory_stats;
si->swap = swap_stats;
}
static struct handle handle;
caddr_t get_process_info(si, sel, compare_index)
struct system_info *si;
struct process_select *sel;
int compare_index;
{
int i, nproc;
int active_procs = 0, total_procs = 0;
struct procentry64 *pp, **p_pref = pref;
struct timeval64 *cpu_proc_temp;
double timediff;
pid_t procsindex = 0;
si->procstates = process_states;
curtime = time(0);
lasttimeval = curtimeval;
gettimeofday(&curtimeval, NULL);
/* get the procentry64 structures of all running processes */
nproc = getprocs64(p_info, sizeof (struct procentry64), NULL, 0,
&procsindex, nprocs);
if (nproc < 0) {
perror("getprocs64");
quit(1);
}
/* the swapper has no cmd-line attached */
strcpy(p_info[0].pi_comm, "swapper");
if (lasttimeval.tv_sec)
{
timediff = (curtimeval.tv_sec - lasttimeval.tv_sec) +
1.0*(curtimeval.tv_usec - lasttimeval.tv_usec) / uS_PER_SECOND;
}
/* The pi_cpu value is wildly inaccurate. The maximum value is 120, but
when the scheduling timer fires, the field is zeroed for all
processes and ramps up over a short period of time. Instead of using
this weird number, manually calculate an accurate value from the
rusage data. Store this run's rusage in cpu_proc[pid], and subtract
from old_cpu_proc.
*/
for (pp = p_info, i = 0; i < nproc; pp++, i++) {
pid_t pid = PROCMASK(pp->pi_pid);
/* total system and user time into cpu_proc */
cpu_proc[pid] = pp->pi_ru.ru_utime;
cpu_proc[pid].tv_sec += pp->pi_ru.ru_stime.tv_sec;
cpu_proc[pid].tv_usec += pp->pi_ru.ru_stime.tv_usec;
if (cpu_proc[pid].tv_usec > NS_PER_SEC) {
cpu_proc[pid].tv_sec++;
cpu_proc[pid].tv_usec -= NS_PER_SEC;
}
/* If this process was around during the previous update, calculate
a true %CPU. If not, convert the kernel's cpu value from its
120-max value to a 10000-max one.
*/
if (old_cpu_proc[pid].tv_sec == 0 && old_cpu_proc[pid].tv_usec == 0)
pp->pi_cpu = pp->pi_cpu * 10000 / 120;
else
pp->pi_cpu = ((cpu_proc[pid].tv_sec - old_cpu_proc[pid].tv_sec) +
1.0*(cpu_proc[pid].tv_usec - old_cpu_proc[pid].tv_usec) / NS_PER_SEC) / timediff * 10000;
}
/* remember our current values as old_cpu_proc, and zero out cpu_proc
for the next update cycle */
memset(old_cpu_proc, 0, sizeof(struct timeval64) * nprocs);
cpu_proc_temp = cpu_proc;
cpu_proc = old_cpu_proc;
old_cpu_proc = cpu_proc_temp;
memset(process_states, 0, sizeof process_states);
/* build a list of pointers to processes to show. */
for (pp = p_info, i = 0; i < nproc; pp++, i++) {
/* AIX marks all runnable processes as ACTIVE. We want to know
which processes are sleeping, so check used cpu and adjust status
field accordingly
*/
if (pp->pi_state == SACTIVE && pp->pi_cpu == 0)
pp->pi_state = SIDL;
if (pp->pi_state && (sel->system || ((pp->pi_flags & SKPROC) == 0))) {
total_procs++;
process_states[pp->pi_state]++;
if ( (pp->pi_state != SZOMB) &&
(sel->idle || pp->pi_cpu != 0 || (pp->pi_state == SACTIVE))
&& (sel->uid == -1 || pp->pi_uid == (uid_t)sel->uid)) {
*p_pref++ = pp;
active_procs++;
}
}
}
/* the pref array now holds pointers to the procentry64 structures in
* the p_info array that were selected for display
*/
/* sort if requested */
if ( proc_compares[compare_index] != NULL)
qsort((char *)pref, active_procs, sizeof (struct procentry64 *),
proc_compares[compare_index]);
si->last_pid = -1; /* no way to figure out last used pid */
si->p_total = total_procs;
si->p_active = pref_len = active_procs;
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char fmt[128]; /* static area where result is built */
/* define what weighted cpu is. use definition of %CPU from 'man ps(1)' */
#define weighted_cpu(pp) (PROCTIME(pp) == 0 ? 0.0 : \
(((PROCTIME(pp)*100.0)/(curtime-pi->pi_start))))
char *format_next_process(handle, get_userid)
caddr_t handle;
char *(*get_userid)();
{
register struct handle *hp;
register struct procentry64 *pi;
long cpu_time;
int proc_size, proc_ress;
char size_unit = 'K';
char ress_unit = 'K';
hp = (struct handle *)handle;
if (hp->remaining == 0) { /* safe guard */
fmt[0] = '\0';
return fmt;
}
pi = *(hp->next_proc++);
hp->remaining--;
cpu_time = PROCTIME(pi);
/* we disply sizes up to 10M in KiloBytes, beyond 10M in MegaBytes */
if ((proc_size = (pi->pi_tsize/1024+pi->pi_dvm)*4) > 10240) {
proc_size /= 1024;
size_unit = 'M';
}
if ((proc_ress = (pi->pi_trss + pi->pi_drss)*4) > 10240) {
proc_ress /= 1024;
ress_unit = 'M';
}
sprintf(fmt, Proc_format ,
pi->pi_pid, /* PID */
(*get_userid)(pi->pi_uid), /* login name */
pi->pi_nice, /* fixed or vari */
getpriority(PRIO_PROCESS, pi->pi_pid),
proc_size, /* size */
size_unit, /* K or M */
proc_ress, /* resident */
ress_unit, /* K or M */
state_abbrev[pi->pi_state], /* process state */
format_time(cpu_time), /* time used */
weighted_cpu(pi), /* WCPU */
pi->pi_cpu / 100.0, /* CPU */
printable(pi->pi_comm), /* COMM */
(pi->pi_flags & SKPROC) == 0 ? "" : " (sys)" /* kernel process? */
);
return(fmt);
}
#ifdef OLD
/*
* 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).
*
*/
int getkval(offset, ptr, size, refstr)
unsigned long offset;
caddr_t ptr;
int size;
char *refstr;
{
int upper_2gb = 0;
/* reads above 2Gb are done by seeking to offset%2Gb, and supplying
* 1 (opposed to 0) as fourth parameter to readx (see 'man kmem')
*/
if (offset > 1<<31) {
upper_2gb = 1;
offset &= 0x7fffffff;
}
if (lseek(kmem, offset, SEEK_SET) != offset) {
fprintf(stderr, "top: lseek failed\n");
quit(2);
}
if (readx(kmem, ptr, size, upper_2gb) != size) {
if (*refstr == '!')
return 0;
else {
fprintf(stderr, "top: kvm_read for %s: %s\n", refstr,
sys_errlist[errno]);
quit(2);
}
}
return 1 ;
}
#endif
/* comparison routine for qsort */
/*
* The following code is taken from the solaris module and adjusted
* for AIX -- JV .
*/
#define ORDERKEY_PCTCPU \
if ((result = pi2->pi_cpu - pi1->pi_cpu) == 0)
#define ORDERKEY_CPTICKS \
if ((result = PROCTIME(pi2) - PROCTIME(pi1)) == 0)
#define ORDERKEY_STATE \
if ((result = sorted_state[pi2->pi_state] \
- sorted_state[pi1->pi_state]) == 0)
/* Nice values directly reflect the process' priority, and are always >0 ;-) */
#define ORDERKEY_PRIO \
if ((result = pi1->pi_nice - pi2->pi_nice) == 0)
#define ORDERKEY_RSSIZE \
if ((result = PROCRESS(pi2) - PROCRESS(pi1)) == 0)
#define ORDERKEY_MEM \
if ((result = PROCSIZE(pi2) - PROCSIZE(pi1)) == 0)
static unsigned char sorted_state[] =
{
0, /* not used */
0,
0,
0,
3, /* sleep */
1, /* zombie */
4, /* stop */
6, /* run */
2, /* swap */
};
/* compare_cpu - the comparison function for sorting by cpu percentage */
int
compare_cpu(ppi1, ppi2)
struct procentry64 **ppi1;
struct procentry64 **ppi2;
{
register struct procentry64 *pi1 = *ppi1, *pi2 = *ppi2;
register int result;
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_RSSIZE
ORDERKEY_MEM
;
return result;
}
/* compare_size - the comparison function for sorting by total memory usage */
int
compare_size(ppi1, ppi2)
struct procentry64 **ppi1;
struct procentry64 **ppi2;
{
register struct procentry64 *pi1 = *ppi1, *pi2 = *ppi2;
register int result;
ORDERKEY_MEM
ORDERKEY_RSSIZE
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
;
return result;
}
/* compare_res - the comparison function for sorting by resident set size */
int
compare_res(ppi1, ppi2)
struct procentry64 **ppi1;
struct procentry64 **ppi2;
{
register struct procentry64 *pi1 = *ppi1, *pi2 = *ppi2;
register int result;
ORDERKEY_RSSIZE
ORDERKEY_MEM
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
;
return result;
}
/* compare_time - the comparison function for sorting by total cpu time */
int
compare_time(ppi1, ppi2)
struct procentry64 **ppi1;
struct procentry64 **ppi2;
{
register struct procentry64 *pi1 = *ppi1, *pi2 = *ppi2;
register int result;
ORDERKEY_CPTICKS
ORDERKEY_PCTCPU
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_MEM
ORDERKEY_RSSIZE
;
return result;
}
/* compare_prio - the comparison function for sorting by cpu percentage */
int
compare_prio(ppi1, ppi2)
struct procentry64 **ppi1;
struct procentry64 **ppi2;
{
register struct procentry64 *pi1 = *ppi1, *pi2 = *ppi2;
register int result;
ORDERKEY_PRIO
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_RSSIZE
ORDERKEY_MEM
;
return result;
}
int proc_owner(pid)
int pid;
{
register struct procentry64 **prefp = pref;
register int cnt = pref_len;
while (--cnt >= 0) {
if ((*prefp)->pi_pid == pid)
return (*prefp)->pi_uid;
prefp++;
}
return(-1);
}

View File

@@ -0,0 +1,988 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: OSF/1, Digital Unix 4.0, Compaq Tru64 5.0
*
* DESCRIPTION:
* This is the machine-dependent module for DEC OSF/1 and its descendents
* It is known to work on OSF/1 1.2, 1.3, 2.0-T3, 3.0, Digital Unix V4.0,
* Digital Unix 5.0, and Tru64 5.0.
* WARNING: if you use optimization with the standard "cc" compiler that
* . comes with V3.0 the resulting executable may core dump. If
* . this happens, recompile without optimization.
*
* LIBS: -lmld -lmach
*
* CFLAGS: -DHAVE_GETOPT -DORDER
*
* AUTHOR: Anthony Baxter, <anthony@aaii.oz.au>
* Derived originally from m_ultrix, by David S. Comay <dsc@seismo.css.gov>,
* although by now there is hardly any of the code from m_ultrix left.
* Helped a lot by having the source for syd(1), by Claus Kalle, and
* from several people at DEC who helped with providing information on
* some of the less-documented bits of the kernel interface.
*
* Modified: 31-Oct-94, Pat Welch, tpw@physics.orst.edu
* changed _mpid to pidtab for compatibility with OSF/1 version 3.0
*
* Modified: 13-Dec-94, William LeFebvre, lefebvre@dis.anl.gov
* removed used of pidtab (that was bogus) and changed things to
* automatically detect the absence of _mpid in the nlist and
* recover gracefully---this appears to be the only difference
* with 3.0.
*
* Modified: 3-Mar-00, Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
* added support for sort ordering.
*/
/*
* Theory of operation:
*
* Use Mach calls to build up a structure that contains all the sorts
* of stuff normally found in a struct proc in a BSD system. Then
* everything else uses this structure. This has major performance wins,
* and also should work for future versions of the O/S.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <string.h>
#include <sys/user.h>
#include <stdio.h>
#include <nlist.h>
#include <math.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/dk.h>
#include <sys/vm.h>
#include <sys/file.h>
#include <sys/time.h>
/* #include <machine/pte.h> */
/* forward declarations, needed by <net/if.h> included from <sys/table.h> */
struct rtentry;
struct mbuf;
#include <sys/table.h>
#include <mach.h>
#include <mach/mach_types.h>
#include <mach/vm_statistics.h>
#include <sys/syscall.h> /* for SYS_setpriority, in setpriority(), below */
#include "top.h"
#include "machine.h"
#include "utils.h"
extern int errno, sys_nerr;
extern char *sys_errlist[];
#define strerror(e) (((e) >= 0 && (e) < sys_nerr) ? sys_errlist[(e)] : "Unknown error")
#define VMUNIX "/vmunix"
#define KMEM "/dev/kmem"
#define MEM "/dev/mem"
/* get_process_info passes back a handle. This is what it looks like: */
struct handle
{
struct osf1_top_proc **next_proc; /* points to next valid proc pointer */
int remaining; /* number of pointers remaining */
};
/* declarations for load_avg */
#include "loadavg.h"
/* definitions for indices in the nlist array */
#define X_MPID 0
static struct nlist nlst[] = {
{ "_mpid" }, /* 0 */
{ 0 }
};
/* Some versions of OSF/1 don't support reporting of the last PID.
This flag indicates whether or not we are reporting the last PID. */
static int do_last_pid = 1;
/*
* These definitions control the format of the per-process area
*/
static char header[] =
" PID X PRI NICE SIZE RES STATE TIME CPU COMMAND";
/* 01234567 -- field to fill in starts at header+7 */
#define UNAME_START 7
#define Proc_format \
"%6d %-8.8s %3d %4d %5s %5s %-5s %-6s %5.2f%% %s"
/* process state names for the "STATE" column of the display */
/* the extra nulls in the string "run" are for adding a slash and
* the processor number when needed. Although OSF/1 doesnt support
* multiple processors yet, (and this module _certainly_ doesnt
* support it, either, we may as well plan for the future. :-)
*/
char *state_abbrev[] =
{
"", "run\0\0\0", "WAIT", "sleep", "sleep", "stop", "halt", "???", "zomb"
};
static int kmem, mem;
/* values that we stash away in _init and use in later routines */
static double logcpu;
/* these are retrieved from the kernel in _init */
static unsigned long proc;
static int nproc;
static load_avg ccpu;
typedef long mtime_t;
/* these are offsets obtained via nlist and used in the get_ functions */
static unsigned long mpid_offset;
/* these are for detailing the process states */
int process_states[9];
char *procstatenames[] = {
"", " running, ", " waiting, ", " sleeping, ", " idle, ",
" stopped, ", " halted, ", "", " zombie",
NULL
};
/* these are for detailing the cpu states */
int cpu_states[5];
char *cpustatenames[] = {
"user", "nice", "system", "wio", "idle", NULL
};
long old_cpu_ticks[5];
/* these are for detailing the memory statistics */
long memory_stats[5];
char *memorynames[] = {
"K active, ", "K inactive, ", "K total, ", "K free", NULL
};
long swap_stats[3];
char *swapnames[] = {
"K in use, ", "K total", NULL
};
/* these are names given to allowed sorting orders -- first is default */
char *ordernames[] = {
"cpu", "size", "res", "time", NULL
};
/* forward definitions for comparison functions */
int compare_cpu();
int compare_size();
int compare_res();
int compare_time();
int (*proc_compares[])() = {
compare_cpu,
compare_size,
compare_res,
compare_time,
NULL
};
/* these are for getting the memory statistics */
static int pageshift; /* log base 2 of the pagesize */
/* define pagetok in terms of pageshift */
#define pagetok(size) ((size) << pageshift)
/* take a process, make it a mach task, and grab all the info out */
void do_threads_calculations();
/*
* Because I dont feel like repeatedly grunging through the kernel with
* Mach calls, and I also dont want the horrid performance hit this
* would give, I read the stuff I need out, and put in into my own
* structure, for later use.
*/
struct osf1_top_proc {
size_t p_mach_virt_size;
char p_mach_state;
int p_flag;
fixpt_t p_mach_pct_cpu; /* aka p_pctcpu */
int used_ticks;
size_t process_size;
pid_t p_pid;
uid_t p_ruid;
char p_pri;
char p_nice;
size_t p_rssize;
char u_comm[PI_COMLEN + 1];
} ;
/* these are for keeping track of the proc array */
static int bytes;
static int pref_len;
static struct osf1_top_proc *pbase;
static struct osf1_top_proc **pref;
/* useful externals */
extern int errno;
extern char *sys_errlist[];
long percentages();
machine_init(statics)
struct statics *statics;
{
register int i = 0;
register int pagesize;
struct tbl_sysinfo sibuf;
if ((kmem = open(KMEM, O_RDONLY)) == -1) {
perror(KMEM);
return(-1);
}
if ((mem = open(MEM, O_RDONLY)) == -1) {
perror(MEM);
return(-1);
}
/* get the list of symbols we want to access in the kernel */
if (nlist(VMUNIX, nlst) == -1)
{
perror("TOP(nlist)");
return (-1);
}
if (nlst[X_MPID].n_type == 0)
{
/* this kernel has no _mpid, so go without */
do_last_pid = 0;
}
else
{
/* stash away mpid pointer for later use */
mpid_offset = nlst[X_MPID].n_value;
}
/* get the symbol values out of kmem */
nproc = table(TBL_PROCINFO, 0, (struct tbl_procinfo *)NULL, INT_MAX, 0);
/* allocate space for proc structure array and array of pointers */
bytes = nproc * sizeof(struct osf1_top_proc);
pbase = (struct osf1_top_proc *)malloc(bytes);
pref = (struct osf1_top_proc **)malloc(nproc *
sizeof(struct osf1_top_proc *));
/* Just in case ... */
if (pbase == (struct osf1_top_proc *)NULL ||
pref == (struct osf1_top_proc **)NULL)
{
fprintf(stderr, "top: cannot allocate sufficient memory\n");
return(-1);
}
/* get the page size with "getpagesize" and calculate pageshift from it */
pagesize = getpagesize();
pageshift = 0;
while (pagesize > 1)
{
pageshift++;
pagesize >>= 1;
}
/* we only need the amount of log(2)1024 for our conversion */
pageshift -= LOG1024;
/* fill in the statics information */
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
statics->order_names = ordernames;
statics->swap_names = swapnames;
/* initialise this, for calculating cpu time */
if (table(TBL_SYSINFO,0,&sibuf,1,sizeof(struct tbl_sysinfo))<0) {
perror("TBL_SYSINFO");
return(-1);
}
old_cpu_ticks[0] = sibuf.si_user;
old_cpu_ticks[1] = sibuf.si_nice;
old_cpu_ticks[2] = sibuf.si_sys;
old_cpu_ticks[3] = sibuf.wait;
old_cpu_ticks[4] = sibuf.si_idle;
/* all done! */
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);
}
void get_system_info(si)
struct system_info *si;
{
struct tbl_loadavg labuf;
struct tbl_sysinfo sibuf;
struct tbl_swapinfo swbuf;
vm_statistics_data_t vmstats;
int swap_pages=0,swap_free=0,i;
long new_ticks[5],diff_ticks[5];
long delta_ticks;
if (do_last_pid)
{
/* last pid assigned */
(void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
"_mpid");
}
else
{
si->last_pid = -1;
}
/* get load averages */
if (table(TBL_LOADAVG,0,&labuf,1,sizeof(struct tbl_loadavg))<0) {
perror("TBL_LOADAVG");
return;
}
if (labuf.tl_lscale) /* scaled */
for(i=0;i<3;i++)
si->load_avg[i] = ((double)labuf.tl_avenrun.l[i] /
(double)labuf.tl_lscale );
else /* not scaled */
for(i=0;i<3;i++)
si->load_avg[i] = labuf.tl_avenrun.d[i];
/* array of cpu state counters */
if (table(TBL_SYSINFO,0,&sibuf,1,sizeof(struct tbl_sysinfo))<0) {
perror("TBL_SYSINFO");
return;
}
new_ticks[0] = sibuf.si_user ; new_ticks[1] = sibuf.si_nice;
new_ticks[2] = sibuf.si_sys ; new_ticks[3] = sibuf.wait;
new_ticks[4] = sibuf.si_idle;
delta_ticks=0;
for(i=0;i<5;i++) {
diff_ticks[i] = new_ticks[i] - old_cpu_ticks[i];
delta_ticks += diff_ticks[i];
old_cpu_ticks[i] = new_ticks[i];
}
si->cpustates = cpu_states;
if(delta_ticks)
for(i=0;i<5;i++)
si->cpustates[i] = (int)( ( (double)diff_ticks[i] /
(double)delta_ticks ) * 1000 );
/* memory information */
/* this is possibly bogus - we work out total # pages by */
/* adding up the free, active, inactive, wired down, and */
/* zero filled. Anyone who knows a better way, TELL ME! */
/* Change: dont use zero filled. */
(void) vm_statistics(task_self(),&vmstats);
/* thanks DEC for the table() command. No thanks at all for */
/* omitting the man page for it from OSF/1 1.2, and failing */
/* to document SWAPINFO in the 1.3 man page. Lets hear it for */
/* include files. */
i=0;
while(table(TBL_SWAPINFO,i,&swbuf,1,sizeof(struct tbl_swapinfo))>0) {
swap_pages += swbuf.size;
swap_free += swbuf.free;
i++;
}
memory_stats[0] = pagetok(vmstats.active_count);
memory_stats[1] = pagetok(vmstats.inactive_count);
memory_stats[2] = pagetok((vmstats.free_count + vmstats.active_count +
vmstats.inactive_count + vmstats.wire_count));
memory_stats[3] = pagetok(vmstats.free_count);
swap_stats[0] = pagetok(swap_pages - swap_free);
swap_stats[1] = pagetok(swap_pages);
si->memory = memory_stats;
si->swap = swap_stats;
}
static struct handle handle;
caddr_t get_process_info(si, sel, compare_index)
struct system_info *si;
struct process_select *sel;
int compare_index;
{
register int i;
register int total_procs;
register int active_procs;
register struct osf1_top_proc **prefp;
register struct osf1_top_proc *pp;
struct tbl_procinfo p_i[8];
int j,k,r;
/* these are copied out of sel for speed */
int show_idle;
int show_uid;
int show_command;
/* get a pointer to the states summary array */
si->procstates = process_states;
/* set up flags which define what we are going to select */
show_idle = sel->idle;
show_uid = sel->uid != -1;
show_command = sel->command != NULL;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
active_procs = 0;
memset((char *)process_states, 0, sizeof(process_states));
prefp = pref;
pp=pbase;
for (j=0; j<nproc; j += 8)
{
r = table(TBL_PROCINFO, j, (struct tbl_procinfo *)p_i, 8,
sizeof(struct tbl_procinfo));
for (k=0; k < r; k++ , pp++)
{
if(p_i[k].pi_pid == 0)
{
pp->p_pid = 0;
}
else
{
pp->p_pid = p_i[k].pi_pid;
pp->p_ruid = p_i[k].pi_ruid;
pp->p_flag = p_i[k].pi_flag;
pp->p_nice = getpriority(PRIO_PROCESS,p_i[k].pi_pid);
/* Load useful values into the proc structure */
do_threads_calculations(pp);
/*
* Place pointers to each valid proc structure in pref[].
* Process slots that are actually in use have a non-zero
* status field.
*/
#ifdef DEBUG
/*
* Emit debug info about all processes before selection.
*/
fprintf(stderr, "pid = %d ruid = %d comm = %s p_mach_state = %d p_stat = %d p_flag = 0x%x\n",
pp->p_pid, pp->p_ruid, p_i[k].pi_comm,
pp->p_mach_state, p_i[k].pi_status, pp->p_flag);
#endif
if (pp->p_mach_state != 0)
{
total_procs++;
process_states[pp->p_mach_state]++;
if ((pp->p_mach_state != 8) &&
(show_idle || (pp->p_mach_pct_cpu != 0) ||
(pp->p_mach_state == 1)) &&
(!show_uid || pp->p_ruid == (uid_t)sel->uid)) {
*prefp++ = pp;
active_procs++;
}
}
}
}
}
/* if requested, sort the "interesting" processes */
if (proc_compares[compare_index] != NULL)
{
qsort((char *)pref, active_procs, sizeof(struct osf1_top_proc *),
proc_compares[compare_index]);
}
/* remember active and total counts */
si->p_total = total_procs;
si->p_active = pref_len = active_procs;
/* pass back a handle */
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char fmt[MAX_COLS]; /* static area where result is built */
char *format_next_process(handle, get_userid)
caddr_t handle;
char *(*get_userid)();
{
register struct osf1_top_proc *pp;
register long cputime;
register double pct;
struct user u;
struct handle *hp;
/* find and remember the next proc structure */
hp = (struct handle *)handle;
pp = *(hp->next_proc++);
hp->remaining--;
/* get the process's user struct and set cputime */
if (table(TBL_UAREA,pp->p_pid,&u,1,sizeof(struct user))<0) {
/* whoops, it must have died between the read of the proc area
* and now. Oh well, lets just dump some meaningless thing out
* to keep the rest of the program happy
*/
sprintf(fmt,
Proc_format,
pp->p_pid,
(*get_userid)(pp->p_ruid),
0,
0,
"",
"",
"dead",
"",
0.0,
"<dead>");
return(fmt);
}
/* set u_comm for system processes */
if (u.u_comm[0] == '\0')
{
if (pp->p_pid == 0)
{
(void) strcpy(u.u_comm, "[idle]");
}
else if (pp->p_pid == 2)
{
(void) strcpy(u.u_comm, "[execpt.hndlr]");
}
}
/* Check if process is in core */
if (!(pp->p_flag & SLOAD)) {
/*
* Print swapped processes as <pname>
*/
char buf[sizeof(u.u_comm)];
(void) strncpy(buf, u.u_comm, sizeof(u.u_comm));
u.u_comm[0] = '<';
(void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2);
u.u_comm[sizeof(u.u_comm) - 2] = '\0';
(void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1);
u.u_comm[sizeof(u.u_comm) - 1] = '\0';
}
cputime = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec;
/* calculate the base for cpu percentages */
pct = pctdouble(pp->p_mach_pct_cpu);
/* format this entry */
sprintf(fmt,
Proc_format,
pp->p_pid,
(*get_userid)(pp->p_ruid),
pp->p_pri,
pp->p_nice,
format_k(pp->p_mach_virt_size/1024),
format_k(pp->p_rssize/1000),
state_abbrev[pp->p_mach_state],
format_time(cputime),
100.0 * ((double)pp->p_mach_pct_cpu / 10000.0),
printable(u.u_comm));
/* return the result */
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 (lseek(kmem, (long)offset, L_SET) == -1) {
if (*refstr == '!')
refstr++;
(void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
if (read(kmem, (char *) ptr, size) == -1) {
if (*refstr == '!')
return(0);
else {
(void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
}
return(1);
}
/* comparison routines for qsort */
/*
* There are currently four possible comparison routines. main selects
* one of these by indexing in to the array proc_compares.
*
* Possible keys are defined as macros below. Currently these keys are
* defined: percent cpu, cpu ticks, process state, resident set size,
* total virtual memory usage. The process states are ordered as follows
* (from least to most important): WAIT, zomb, ???, halt, idle, sleep,
* stop, run. The array declaration below maps a process state index into
* a number that reflects this ordering.
*/
/* First, the possible comparison keys. These are defined in such a way
that they can be merely listed in the source code to define the actual
desired ordering.
*/
#define ORDERKEY_PCTCPU if (lresult = p2->p_mach_pct_cpu - p1->p_mach_pct_cpu,\
(result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
#define ORDERKEY_CPTICKS if ((result = p2->used_ticks - p1->used_ticks) == 0)
#define ORDERKEY_STATE if ((result = sorted_state[p2->p_mach_state] - \
sorted_state[p1->p_mach_state]) == 0)
#define ORDERKEY_PRIO if ((result = p2->p_pri - p1->p_pri) == 0)
#define ORDERKEY_RSSIZE if ((result = p2->p_rssize - p1->p_rssize) == 0)
#define ORDERKEY_MEM if ((result = p2->p_mach_virt_size - p1->p_mach_virt_size) == 0)
/* Now the array that maps process state to a weight */
static unsigned char sorted_state[] =
{
0, /*""*/
8, /*"run"*/
1, /*"WAIT"*/
6, /*"sleep"*/
5, /*"idle"*/
7, /*"stop"*/
4, /*"halt"*/
3, /*"???"*/
2, /*"zomb"*/
};
/* compare_cpu - the comparison function for sorting by cpu percentage */
compare_cpu(pp1, pp2)
struct osf1_top_proc **pp1;
struct osf1_top_proc **pp2;
{
register struct osf1_top_proc *p1;
register struct osf1_top_proc *p2;
register long result;
register pctcpu lresult;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_RSSIZE
ORDERKEY_MEM
;
return(result);
}
/* compare_size - the comparison function for sorting by total memory usage */
compare_size(pp1, pp2)
struct osf1_top_proc **pp1;
struct osf1_top_proc **pp2;
{
register struct osf1_top_proc *p1;
register struct osf1_top_proc *p2;
register long result;
register pctcpu lresult;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
ORDERKEY_MEM
ORDERKEY_RSSIZE
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
;
return(result);
}
/* compare_res - the comparison function for sorting by resident set size */
compare_res(pp1, pp2)
struct osf1_top_proc **pp1;
struct osf1_top_proc **pp2;
{
register struct osf1_top_proc *p1;
register struct osf1_top_proc *p2;
register long result;
register pctcpu lresult;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
ORDERKEY_RSSIZE
ORDERKEY_MEM
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
;
return(result);
}
/* compare_time - the comparison function for sorting by total cpu time */
compare_time(pp1, pp2)
struct osf1_top_proc **pp1;
struct osf1_top_proc **pp2;
{
register struct osf1_top_proc *p1;
register struct osf1_top_proc *p2;
register long result;
register pctcpu lresult;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
ORDERKEY_CPTICKS
ORDERKEY_PCTCPU
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_RSSIZE
ORDERKEY_MEM
;
return(result);
}
/*
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
* the process does not exist.
* It is EXTREMLY IMPORTANT that this function work correctly.
* If top runs setuid root (as in SVR4), then this function
* is the only thing that stands in the way of a serious
* security problem. It validates requests for the "kill"
* and "renice" commands.
*/
int proc_owner(pid)
int pid;
{
register int cnt;
register struct osf1_top_proc **prefp;
register struct osf1_top_proc *pp;
prefp = pref;
cnt = pref_len;
while (--cnt >= 0)
{
if ((pp = *prefp++)->p_pid == (pid_t)pid)
{
return((int)pp->p_ruid);
}
}
return(-1);
}
/*
* We use the Mach interface, as well as the table(UAREA,,,) call to
* get some more information, then put it into unused fields in our
* copy of the proc structure, to make it faster and easier to get at
* later.
*/
void do_threads_calculations(thisproc)
struct osf1_top_proc *thisproc;
{
int j;
task_t thistask;
task_basic_info_data_t taskinfo;
unsigned int taskinfo_l;
thread_array_t threadarr;
unsigned int threadarr_l;
thread_basic_info_t threadinfo;
thread_basic_info_data_t threadinfodata;
unsigned int threadinfo_l;
int task_tot_cpu=0; /* total cpu usage of threads in a task */
struct user u;
thisproc->p_pri=0;
thisproc->p_rssize=0;
thisproc->p_mach_virt_size=0;
thisproc->p_mach_state=0;
thisproc->p_mach_pct_cpu=0;
if(task_by_unix_pid(task_self(), thisproc->p_pid, &thistask)
!= KERN_SUCCESS){
thisproc->p_mach_state=8; /* (zombie) */
} else {
taskinfo_l=TASK_BASIC_INFO_COUNT;
if(task_info(thistask, TASK_BASIC_INFO, (task_info_t) &taskinfo,
&taskinfo_l)
!= KERN_SUCCESS) {
thisproc->p_mach_state=8; /* (zombie) */
} else {
int minim_state=99,mcurp=1000,mbasp=1000,mslpt=999;
thisproc->p_rssize=taskinfo.resident_size;
thisproc->p_mach_virt_size=taskinfo.virtual_size;
if (task_threads(thistask, &threadarr, &threadarr_l) != KERN_SUCCESS)
return;
threadinfo= &threadinfodata;
for(j=0; j < threadarr_l; j++) {
threadinfo_l=THREAD_BASIC_INFO_COUNT;
if(thread_info(threadarr[j],THREAD_BASIC_INFO,
(thread_info_t) threadinfo, &threadinfo_l) == KERN_SUCCESS) {
task_tot_cpu += threadinfo->cpu_usage;
if(minim_state>threadinfo->run_state)
minim_state=threadinfo->run_state;
if(mcurp>threadinfo->cur_priority)
mcurp=threadinfo->cur_priority;
if(mbasp>threadinfo->base_priority)
mbasp=threadinfo->base_priority;
if(mslpt>threadinfo->sleep_time)
mslpt=threadinfo->sleep_time;
}
}
switch (minim_state) {
case TH_STATE_RUNNING:
thisproc->p_mach_state=1; break;
case TH_STATE_UNINTERRUPTIBLE:
thisproc->p_mach_state=2; break;
case TH_STATE_WAITING:
thisproc->p_mach_state=(threadinfo->sleep_time > 20) ? 4 : 3; break;
case TH_STATE_STOPPED:
thisproc->p_mach_state=5; break;
case TH_STATE_HALTED:
thisproc->p_mach_state=6; break;
default:
thisproc->p_mach_state=7; break;
}
thisproc->p_pri=mcurp;
thisproc->p_mach_pct_cpu=(fixpt_t)(task_tot_cpu*10);
vm_deallocate(task_self(),(vm_address_t)threadarr,threadarr_l);
}
}
if (table(TBL_UAREA,thisproc->p_pid,&u,1,sizeof(struct user))>=0) {
thisproc->used_ticks=(u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec);
thisproc->process_size=u.u_tsize + u.u_dsize + u.u_ssize;
}
}
/* The reason for this function is that the system call will let
* someone lower their own processes priority (because top is setuid :-(
* Yes, using syscall() is a hack, if you can come up with something
* better, then I'd be thrilled to hear it. I'm not holding my breath,
* though.
* Anthony.
*/
int setpriority(int dummy, int procnum, int niceval)
{
int uid, curprio;
uid=getuid();
if ( (curprio=getpriority(PRIO_PROCESS,procnum) ) == -1)
{
return(-1); /* errno goes back to renice_process() */
}
/* check for not-root - if so, dont allow users to decrease priority */
else if ( uid && (niceval<curprio) )
{
errno=EACCES;
return(-1);
}
return(syscall(SYS_setpriority,PRIO_PROCESS,procnum,niceval));
}

View File

@@ -0,0 +1,14 @@
.SH "DEC OSF/1 NOTES"
Original author was Anthony Baxter, <anthony@aaii.oz.au>.
Derived originally from m_ultrix, by David S. Comay <dsc@seismo.css.gov>,
although by now there is hardly any of the code from m_ultrix left.
Helped a lot by having the source for syd(1), by Claus Kalle, and
from several people at DEC who helped with providing information on
some of the less-documented bits of the kernel interface.
Patches from Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
Theory of operation:
Use Mach calls to build up a structure that contains all the sorts
of stuff normally found in a struct proc in a BSD system. Then
everything else uses this structure. This has major performance wins,
and also should work for future versions of the O/S.

1780
external/bsd/top/dist/machine/m_freebsd.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,134 @@
.SH "FreeBSD NOTES"
Priorities are shown the same as they exist in process data structures,
ranging from 0 to 255. Note that this is not the same as the ps(1)
\*(lqpri\*(rq column, which subtracts 84 from each number before displaying
it. Priority numbers fall in to priority classes as follows:
.TP 15
0 \- 63
Interrupt threads
.TP 15
64 \- 127
Top half kernel threads
.TP 15
128 \- 159
Realtime user threads
.TP 15
160 \- 223
Time sharing user threads
.TP 15
224 \- 255
Idle user threads
.SH "FreeBSD THREADS"
Starting with FreeBSD 8.0 the display of individual threads can be
toggled with the synonymous commands
.B t
and
.BR H.
Information about state, flags, CPU time and percent cpu are shown
for each individual thread. Other information is identical for all
threads in the same process.
.SH "FreeBSD ALTERNATE DISPLAY"
FreeBSD supports an alternate process display which shows i/o
information. Since this information is tracked per process and not
per thread, the per-thread display is not supported in this mode.
All fields calculate the number of operations observed since the
last update and are displayed as a per-second rate.
The fields in this display are as follows:
.TP
.B VCSW
Voluntary context switches
.TP
.B IVCSW
Involuntary context switches
.TP
.B READ
Number of blocks read
.TP
.B WRITE
Number of blocks written
.TP
.B FAULT
Number of page faults
.TP
.B TOTAL
Total number of i/o operations
.TP
.B PERCENT
Percentage of total i/o attributed to this process. If no i/o occured
then this field is 0 for all processes.
.SH "FreeBSD KERNEL SUMMARY"
All rates are shown per-second.
.TP
.B Ctx
Number of context switches.
.TP
.B Trap
Number of kernel traps.
.TP
.B Intr
Number of device interrupts.
.TP
.B Soft
Number of software interrupts.
.TP
.B Fork
Number of forks, vforks, and rforks.
.TP
.B Flt
Total number of page faults.
.TP
.B Pgin
Number of pages paged or swapped in to physical memory.
.TP
.B Pgout
Number of pages paged or swapped out from physical memory.
.TP
.B Fr
Total number of pages freed.
.SH "FreeBSD MEMORY SUMMARY"
Memory: 10M Act 1208K Inact 3220K Wired 132K Free 25% Swap, 2924Kin 2604Kout
.TP
.B K:
Kilobyte
.TP
.B M:
Megabyte
.TP
.B G:
Gigabyte
.TP
.B %:
1/100
.TP
.B Act:
number of pages active
.TP
.B Inact:
number of pages inactive
.TP
.B Wired:
number of pages wired down
.TP
.B Free:
number of pages free
.TP
.B Swap:
swap usage
.TP
.B Kin:
kilobytes swap pager pages paged in (last interval)
.TP
.B Kout:
kilobytes swap pager pages paged out (last interval)
.PP
See /usr/include/sys/vmmeter.h and /sys/vm/vm_meter.c.
.PP
Contributors: Christos Zoulas, Steven Wallace, Wolfram Schneider,
Monte Mitzelfelt.
.PP
This module was retrofitted from FreeBSD 4.6.2 sources.

701
external/bsd/top/dist/machine/m_hpux10.c vendored Normal file
View File

@@ -0,0 +1,701 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: any hp9000 running hpux version 10.x
*
* DESCRIPTION:
* This is the machine-dependent module for HPUX 10/11 that uses pstat.
* It has been tested on HP/UX 10.01, 10.20, and 11.00. It is presumed
* to work also on 10.10.
* Idle processes are marked by being either runnable or having a %CPU
* of at least 0.1%. This fraction is defined by CPU_IDLE_THRESH and
* can be adjusted at compile time.
*
* CFLAGS: -DHAVE_GETOPT
*
* LIBS:
*
* AUTHOR: John Haxby <john_haxby@hp.com>
* AUTHOR: adapted from Rich Holland <holland@synopsys.com>
* AUTHOR: adapted from Kevin Schmidt <kevin@mcl.ucsb.edu>
*/
#include "config.h"
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <signal.h>
#include <nlist.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/pstat.h>
#include <sys/dk.h>
#include <sys/stat.h>
#include <sys/dirent.h>
#include "top.h"
#include "machine.h"
#include "utils.h"
/*
* The idle threshold (CPU_IDLE_THRESH) is an extension to the normal
* idle process check. Basically, we regard a process as idle if it is
* both asleep and using less that CPU_IDLE_THRESH percent cpu time. I
* believe this makes the "i" option more useful, but if you don't, add
* "-DCPU_IDLE_THRESH=0.0" to the CFLAGS.
*/
#ifndef CPU_IDLE_THRESH
#define CPU_IDLE_THRESH 0.1
#endif
# define P_RSSIZE(p) (p)->pst_rssize
# define P_TSIZE(p) (p)->pst_tsize
# define P_DSIZE(p) (p)->pst_dsize
# define P_SSIZE(p) (p)->pst_ssize
#define VMUNIX "/stand/vmunix"
#define KMEM "/dev/kmem"
#define MEM "/dev/mem"
#ifdef DOSWAP
#define SWAP "/dev/dmem"
#endif
/* what we consider to be process size: */
#define PROCSIZE(pp) (P_TSIZE(pp) + P_DSIZE(pp) + P_SSIZE(pp))
/* definitions for indices in the nlist array */
#define X_MPID 0
static struct nlist nlst[] = {
{ "mpid" },
{ 0 }
};
/*
* These definitions control the format of the per-process area
*/
static char header[] =
" TTY PID X PRI NICE SIZE RES STATE TIME CPU COMMAND";
/* 0123456789.12345 -- field to fill in starts at header+6 */
#define UNAME_START 15
#define Proc_format \
"%8.8s %5d %-8.8s %4d %4d %5s %5s %-5s %6s %5.2f%% %s"
/* process state names for the "STATE" column of the display */
char *state_abbrev[] =
{
"", "sleep", "run", "stop", "zomb", "trans", "start"
};
/* values that we stash away in _init and use in later routines */
static int kmem;
static struct pst_status *pst;
/* these are retrieved from the OS in _init */
static int nproc;
static int ncpu = 0;
/* these are offsets obtained via nlist and used in the get_ functions */
static unsigned long mpid_offset;
/* these are for calculating cpu state percentages */
static long cp_time[PST_MAX_CPUSTATES];
static long cp_old[PST_MAX_CPUSTATES];
static long cp_diff[PST_MAX_CPUSTATES];
/* these are for detailing the process states */
int process_states[7];
char *procstatenames[] = {
"", " sleeping, ", " running, ", " stopped, ", " zombie, ",
" trans, ", " starting, ",
NULL
};
/* these are for detailing the cpu states */
int cpu_states[PST_MAX_CPUSTATES];
char *cpustatenames[] = {
/* roll "swait" into "block" and "ssys" into "sys" */
"usr", "nice", "sys", "idle", "", "block", "\0swait", "intr", "\0ssys",
NULL
};
/* these are for detailing the memory statistics */
long memory_stats[8];
char *memorynames[] = {
"Real: ", "K act, ", "K tot ", "Virtual: ", "K act, ",
"K tot, ", "K free", NULL
};
/* these are for getting the memory statistics */
static int pageshift; /* log base 2 of the pagesize */
/* define pagetok in terms of pageshift */
#define pagetok(size) ((size) << pageshift)
/* Mapping TTY major/minor numbers is done through this structure */
struct ttymap {
dev_t dev;
char name [9];
};
static struct ttymap *ttynames = NULL;
static int nttys = 0;
static get_tty_names ();
/* comparison routine for qsort */
/*
* 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 */
6, /* run */
4, /* stop */
2, /* zombie */
5, /* start */
1, /* other */
};
proc_compare(p1, p2)
struct pst_status *p1;
struct pst_status *p2;
{
int result;
float lresult;
/* compare percent cpu (pctcpu) */
if ((lresult = p2->pst_pctcpu - p1->pst_pctcpu) == 0)
{
/* use cpticks to break the tie */
if ((result = p2->pst_cpticks - p1->pst_cpticks) == 0)
{
/* use process state to break the tie */
if ((result = sorted_state[p2->pst_stat] -
sorted_state[p1->pst_stat]) == 0)
{
/* use priority to break the tie */
if ((result = p2->pst_pri - p1->pst_pri) == 0)
{
/* use resident set size (rssize) to break the tie */
if ((result = P_RSSIZE(p2) - P_RSSIZE(p1)) == 0)
{
/* use total memory to break the tie */
result = PROCSIZE(p2) - PROCSIZE(p1);
}
}
}
}
}
else
{
result = lresult < 0 ? -1 : 1;
}
return(result);
}
machine_init(statics)
struct statics *statics;
{
struct pst_static info;
int i = 0;
int pagesize;
/* If we can get mpid from the kernel, we'll use it, otherwise */
/* we'll guess from the most recently started proces */
if ((kmem = open (KMEM, O_RDONLY)) < 0 ||
(nlist (VMUNIX, nlst)) < 0 ||
(nlst[X_MPID].n_type) == 0)
mpid_offset = 0;
else
mpid_offset = nlst[X_MPID].n_value;
if (pstat_getstatic (&info, sizeof (info), 1, 0) < 0)
{
perror ("pstat_getstatic");
return -1;
}
/*
* Allocate space for the per-process structures (pst_status). To
* make life easier, simply allocate enough storage to hold all the
* process information at once. This won't normally be a problem
* since machines with lots of processes configured will also have
* lots of memory.
*/
nproc = info.max_proc;
pst = (struct pst_status *) malloc (nproc * sizeof (struct pst_status));
if (pst == NULL)
{
fprintf (stderr, "out of memory\n");
return -1;
}
/*
* Calculate pageshift -- the value needed to convert pages to Kbytes.
* This will usually be 2.
*/
pageshift = 0;
for (pagesize = info.page_size; pagesize > 1; pagesize >>= 1)
pageshift += 1;
pageshift -= LOG1024;
/* get tty name information */
i = 0;
get_tty_names ("/dev", &i);
/* fill in the statics information */
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
/* all done! */
return(0);
}
char *format_header(uname_field)
char *uname_field;
{
char *ptr = header + UNAME_START;
while (*uname_field != '\0')
*ptr++ = *uname_field++;
return header;
}
void
get_system_info(si)
struct system_info *si;
{
static struct pst_dynamic dynamic;
int i, n;
long total;
pstat_getdynamic (&dynamic, sizeof (dynamic), 1, 0);
ncpu = dynamic.psd_proc_cnt; /* need this later */
/* Load average */
si->load_avg[0] = dynamic.psd_avg_1_min;
si->load_avg[1] = dynamic.psd_avg_5_min;
si->load_avg[2] = dynamic.psd_avg_15_min;
/*
* CPU times
* to avoid space problems, we roll SWAIT (kernel semaphore block)
* into BLOCK (spin lock block) and SSYS (kernel process) into SYS
* (system time) Ideally, all screens would be wider :-)
*/
dynamic.psd_cpu_time [CP_BLOCK] += dynamic.psd_cpu_time [CP_SWAIT];
dynamic.psd_cpu_time [CP_SWAIT] = 0;
dynamic.psd_cpu_time [CP_SYS] += dynamic.psd_cpu_time [CP_SSYS];
dynamic.psd_cpu_time [CP_SSYS] = 0;
for (i = 0; i < PST_MAX_CPUSTATES; i++)
cp_time [i] = dynamic.psd_cpu_time [i];
percentages(PST_MAX_CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
si->cpustates = cpu_states;
/*
* VM statistics
*/
memory_stats[0] = -1;
memory_stats[1] = pagetok (dynamic.psd_arm);
memory_stats[2] = pagetok (dynamic.psd_rm);
memory_stats[3] = -1;
memory_stats[4] = pagetok (dynamic.psd_avm);
memory_stats[5] = pagetok (dynamic.psd_vm);
memory_stats[6] = pagetok (dynamic.psd_free);
si->memory = memory_stats;
/*
* If we can get mpid from the kernel, then we will do so now.
* Otherwise we'll guess at mpid from the most recently started
* process time. Note that this requires us to get the pst array
* now rather than in get_process_info(). We rely on
* get_system_info() being called before get_system_info() for this
* to work reliably.
*/
for (i = 0; i < nproc; i++)
pst[i].pst_pid = -1;
n = pstat_getproc (pst, sizeof (*pst), nproc, 0);
if (kmem >= 0 && mpid_offset > 0)
(void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid), "mpid");
else
{
static int last_start_time = 0;
int pid = 0;
for (i = 0; i < n; i++)
{
if (last_start_time <= pst[i].pst_start)
{
last_start_time = pst[i].pst_start;
if (pid <= pst[i].pst_pid)
pid = pst[i].pst_pid;
}
}
if (pid != 0)
si->last_pid = pid;
}
}
caddr_t get_process_info(si, sel, compare_index)
struct system_info *si;
struct process_select *sel;
int compare_index;
{
static int handle;
int i, active, total;
/*
* Eliminate unwanted processes
* and tot up all the wanted processes by state
*/
for (i = 0; i < sizeof (process_states)/sizeof (process_states[0]); i++)
process_states [i] = 0;
for (total = 0, active = 0, i = 0; pst[i].pst_pid >= 0; i++)
{
int state = pst[i].pst_stat;
process_states [state] += 1;
total += 1;
if (!sel->system && (pst[i].pst_flag & PS_SYS))
{
pst[i].pst_stat = -1;
continue;
}
/*
* If we are eliminating idle processes, then a process is regarded
* as idle if it is in a short term sleep and not using much
* CPU, or stopped, or simple dead.
*/
if (!sel->idle
&& (state == PS_SLEEP || state == PS_STOP || state == PS_ZOMBIE)
&& (state != PS_SLEEP && pst[i].pst_pctcpu < CPU_IDLE_THRESH/100.0))
pst[i].pst_stat = -1;
if (sel->uid > 0 && sel->uid != pst[i].pst_uid)
pst[i].pst_stat = -1;
if (sel->command != NULL &&
strncmp (sel->command, pst[i].pst_ucomm, strlen (pst[i].pst_ucomm)) != 0)
pst[i].pst_stat = -1;
if (pst[i].pst_stat >= 0)
active += 1;
}
si->procstates = process_states;
si->p_total = total;
si->p_active = active;
qsort ((char *)pst, i, sizeof(*pst), proc_compare);
/* handle is simply an index into the process structures */
handle = 0;
return (caddr_t) &handle;
}
/*
* Find the terminal name associated with a particular
* major/minor number pair
*/
static char *term_name (term)
struct psdev *term;
{
dev_t dev;
int i;
if (term->psd_major == -1 && term->psd_minor == -1)
return "?";
dev = makedev (term->psd_major, term->psd_minor);
for (i = 0; i < nttys && ttynames[i].name[0] != '\0'; i++)
{
if (dev == ttynames[i].dev)
return ttynames[i].name;
}
return "<unk>";
}
char *format_next_process(handle, get_userid)
caddr_t handle;
char *(*get_userid)();
{
static char fmt[MAX_COLS]; /* static area where result is built */
char run [sizeof ("runNN")];
int idx;
struct pst_status *proc;
char *state;
int size;
register long cputime;
register double pct;
int where;
struct handle *hp;
struct timeval time;
struct timezone timezone;
/* sanity check */
if (handle == NULL)
return "";
idx = *((int *) handle);
while (idx < nproc && pst[idx].pst_stat < 0)
idx += 1;
if (idx >= nproc || pst[idx].pst_stat < 0)
return "";
proc = &pst[idx];
*((int *) handle) = idx+1;
/* set ucomm for system processes, although we shouldn't need to */
if (proc->pst_ucomm[0] == '\0')
{
if (proc->pst_pid == 0)
strcpy (proc->pst_ucomm, "Swapper");
else if (proc->pst_pid == 2)
strcpy (proc->pst_ucomm, "Pager");
}
size = proc->pst_tsize + proc->pst_dsize + proc->pst_ssize;
if (ncpu > 1 && proc->pst_stat == PS_RUN)
{
sprintf (run, "run%02d", proc->pst_procnum);
state = run;
}
else if (proc->pst_stat == PS_SLEEP)
{
switch (proc->pst_pri+PTIMESHARE) {
case PSWP: state = "SWP"; break; /* also PMEM */
case PRIRWLOCK: state = "RWLOCK"; break;
case PRIBETA: state = "BETA"; break;
case PRIALPHA: state = "ALPHA"; break;
case PRISYNC: state = "SYNC"; break;
case PINOD: state = "INOD"; break;
case PRIBIO: state = "BIO"; break;
case PLLIO: state = "LLIO"; break; /* also PRIUBA */
case PZERO: state = "ZERO"; break;
case PPIPE: state = "pipe"; break;
case PVFS: state = "vfs"; break;
case PWAIT: state = "wait"; break;
case PLOCK: state = "lock"; break;
case PSLEP: state = "slep"; break;
case PUSER: state = "user"; break;
default:
if (proc->pst_pri < PZERO-PTIMESHARE)
state = "SLEEP";
else
state = "sleep";
}
}
else
state = state_abbrev [proc->pst_stat];
/* format this entry */
sprintf(fmt,
Proc_format,
term_name (&proc->pst_term),
proc->pst_pid,
(*get_userid)(proc->pst_uid),
proc->pst_pri,
proc->pst_nice - NZERO,
format_k(size),
format_k(proc->pst_rssize),
state,
format_time(proc->pst_utime + proc->pst_stime),
100.0 * proc->pst_pctcpu,
printable(proc->pst_ucomm));
/* return the result */
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 (lseek(kmem, (long)offset, SEEK_SET) == -1) {
if (*refstr == '!')
refstr++;
(void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
if (read(kmem, (char *) ptr, size) == -1) {
if (*refstr == '!')
return(0);
else {
(void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
}
return(1);
}
void (*signal(sig, func))()
int sig;
void (*func)();
{
struct sigaction act;
struct sigaction oact;
memset (&act, 0, sizeof (act));
act.sa_handler = func;
if (sigaction (sig, &act, &oact) < 0)
return BADSIG;
return oact.sa_handler;
}
/*
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
* the process does not exist.
* It is EXTREMLY IMPORTANT that this function work correctly.
* If top runs setuid root (as in SVR4), then this function
* is the only thing that stands in the way of a serious
* security problem. It validates requests for the "kill"
* and "renice" commands.
*/
int proc_owner(pid)
int pid;
{
int i;
for (i = 0; i < nproc; i++)
{
if (pst[i].pst_pid == pid)
return pst[i].pst_uid;
}
return -1;
}
static get_tty_names (dir, m)
char *dir;
int *m;
{
char name [MAXPATHLEN+1];
struct dirent **namelist;
int i, n;
if ((n = scandir (dir, &namelist, NULL, NULL)) < 0)
return;
if (ttynames == NULL)
{
nttys = n;
ttynames = malloc (n*sizeof (*ttynames));
}
else
{
nttys += n;
ttynames = realloc (ttynames, nttys*sizeof (*ttynames));
}
for (i = 0; i < n; i++)
{
struct stat statbuf;
char *str = namelist[i]->d_name;
if (*str == '.')
continue;
sprintf (name, "%s/%s", dir, str);
if (stat (name, &statbuf) < 0)
continue;
if (!isalpha (*str))
str = name + sizeof ("/dev");
if (S_ISCHR (statbuf.st_mode))
{
ttynames [*m].dev = statbuf.st_rdev;
strncpy (ttynames[*m].name, str, 8);
ttynames[*m].name[9] = '\0';
*m += 1;
}
else if (S_ISDIR (statbuf.st_mode))
get_tty_names (name, m);
}
if (*m < nttys)
ttynames[*m].name[0] = '\0';
free (namelist);
}

View File

@@ -0,0 +1,18 @@
.SH "HPUX 10 INFORMATION"
The process information layout has changed slightly since previous
versions. The CPU percentage column reports weighted cpu as
calculated directly by the kernel. The WCPU column is no longer
present in the output and a TTY column has been added to indicate
the name of the process's controlling terminal.
The definition of an
idle process has been relaxed to include those processes that have only
just gone to sleep.
This version of top does not display a per-cpu breakdown of processor
state. Perhaps a later version will add this sophistication across
all platforms.
The HP/UX 10 port has greatly benefitted from the diligent efforts
of the following individuals: John Haxby <john_haxby@hp.com>,
Rich Holland <holland@synopsys.com>, and <kevin@mcl.ucsb.edu>.

881
external/bsd/top/dist/machine/m_hpux7.c vendored Normal file
View File

@@ -0,0 +1,881 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: any hp9000 running hpux version 7 or earlier
*
* DESCRIPTION:
* This is the machine-dependent module for Hpux 6.5 and 7.0.
* This makes top work on the following systems:
* hp9000s300
* hp9000s700
* hp9000s800
*
* LIBS:
*
* AUTHOR: Christos Zoulas <christos@ee.cornell.edu>
*/
#include "config.h"
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <stdio.h>
#include <nlist.h>
#include <math.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/dk.h>
#include <sys/vm.h>
#include <sys/file.h>
#include <sys/time.h>
#include "top.h"
#include "machine.h"
#include "utils.h"
#define VMUNIX "/hp-ux"
#define KMEM "/dev/kmem"
#define MEM "/dev/mem"
#ifdef DOSWAP
#define SWAP "/dev/swap"
#endif
/* get_process_info passes back a handle. This is what it looks like: */
struct handle
{
struct proc **next_proc; /* points to next valid proc pointer */
int remaining; /* number of pointers remaining */
};
/* declarations for load_avg */
#include "loadavg.h"
/* define what weighted cpu is. */
#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
((pct) / (1.0 - exp((pp)->p_time * logcpu))))
/* what we consider to be process size: */
#define PROCSIZE(pp) ((pp)->p_tsize + (pp)->p_dsize + (pp)->p_ssize)
/* definitions for indices in the nlist array */
#define X_AVENRUN 0
#define X_CCPU 1
#define X_NPROC 2
#define X_PROC 3
#define X_TOTAL 4
#define X_CP_TIME 5
#ifdef hp9000s300
# define X_USRPTMAP 6
# define X_USRPT 7
#else
# define X_MPID 6
# define X_HZ 7
#endif
#ifdef hp9000s800
# define X_NPIDS 8
# define X_UBASE 9
#endif
static struct nlist nlst[] = {
{ "_avenrun" }, /* 0 */
{ "_ccpu" }, /* 1 */
{ "_nproc" }, /* 2 */
{ "_proc" }, /* 3 */
{ "_total" }, /* 4 */
{ "_cp_time" }, /* 5 */
#ifdef hp9000s300
{ "_Usrptmap" }, /* 6 */
{ "_usrpt" }, /* 7 */
#else
{ "_mpid" }, /* 6 */
{ "_hz" }, /* 7 */
#endif
#ifdef hp9000s800
{ "_npids" }, /* 8 */
{ "_ubase" }, /* 9 */
#endif
{ 0 }
};
/*
* 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 %5s %5s %-5s %6s %5.2f%% %5.2f%% %s"
/* process state names for the "STATE" column of the display */
/* the extra nulls in the string "run" are for adding a slash and
the processor number when needed */
char *state_abbrev[] =
{
"", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
};
static int kmem, mem;
#ifdef DOSWAP
static int swap;
#endif
/* values that we stash away in _init and use in later routines */
static double logcpu;
/* these are retrieved from the kernel in _init */
static unsigned long proc;
static int nproc;
static long hz;
static load_avg ccpu;
static int ncpu = 0;
/* these are offsets obtained via nlist and used in the get_ functions */
#ifndef hp9000s300
static unsigned long mpid_offset;
#endif
#ifdef hp9000s300
static struct pte *Usrptmap, *usrpt;
#endif
#ifdef hp9000s800
static int npids;
char *ubase;
#endif
static unsigned long avenrun_offset;
static unsigned long total_offset;
static unsigned long cp_time_offset;
/* these are for calculating cpu state percentages */
static long cp_time[CPUSTATES];
static long cp_old[CPUSTATES];
static long cp_diff[CPUSTATES];
/* these are for detailing the process states */
int process_states[7];
char *procstatenames[] = {
"", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
" zombie, ", " stopped, ",
NULL
};
/* these are for detailing the cpu states */
#ifdef hp9000s300
int cpu_states[9];
#endif
#ifdef hp9000s800
int cpu_states[5];
#endif
char *cpustatenames[] = {
#ifdef hp9000s300
"usr", "nice", "sys", "idle", "", "", "", "intr", "ker",
#endif
#ifdef hp9000s800
"user", "nice", "system", "idle", "wait",
#endif
NULL
};
/* these are for detailing the memory statistics */
long memory_stats[8];
char *memorynames[] = {
"Real: ", "K active, ", "K total ", "Virtual: ", "K active, ",
"K total, ", "K free", NULL
};
/* these are for keeping track of the proc array */
static int bytes;
static int pref_len;
static struct proc *pbase;
static struct proc **pref;
/* these are for getting the memory statistics */
static int pageshift; /* log base 2 of the pagesize */
/* define pagetok in terms of pageshift */
#define pagetok(size) ((size) << pageshift)
/* useful externals */
extern int errno;
extern char *sys_errlist[];
long lseek();
long time();
machine_init(statics)
struct statics *statics;
{
register int i = 0;
register int pagesize;
if ((kmem = open(KMEM, O_RDONLY)) == -1) {
perror(KMEM);
return(-1);
}
if ((mem = open(MEM, O_RDONLY)) == -1) {
perror(MEM);
return(-1);
}
#ifdef DOSWAP
if ((swap = open(SWAP, O_RDONLY)) == -1) {
perror(SWAP);
return(-1);
}
#endif
#ifdef hp9000s800
/* 800 names don't have leading underscores */
for (i = 0; nlst[i].n_name; nlst[i++].n_name++)
continue;
#endif
/* get the list of symbols we want to access in the kernel */
(void) nlist(VMUNIX, nlst);
if (nlst[0].n_type == 0)
{
fprintf(stderr, "top: nlist failed\n");
return(-1);
}
/* make sure they were all found */
if (i > 0 && check_nlist(nlst) > 0)
{
return(-1);
}
/* get the symbol values out of kmem */
(void) getkval(nlst[X_PROC].n_value, (int *)(&proc), sizeof(proc),
nlst[X_PROC].n_name);
(void) getkval(nlst[X_NPROC].n_value, &nproc, sizeof(nproc),
nlst[X_NPROC].n_name);
#ifndef hp9000s300
(void) getkval(nlst[X_HZ].n_value, (int *)(&hz), sizeof(hz),
nlst[X_HZ].n_name);
#else
hz = HZ;
#endif
(void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu),
nlst[X_CCPU].n_name);
#ifdef hp9000s800
(void) getkval(nlst[X_NPIDS].n_value, (int *)(&npids), sizeof(npids),
nlst[X_NPIDS].n_name);
#endif
/* stash away certain offsets for later use */
#ifdef hp9000s800
# ifndef UAREA
ubase = nlst[X_UBASE].n_value;
# else
ubase = UAREA;
# endif
#endif
#ifdef hp9000s300
Usrptmap = (struct pte *) nlst[X_USRPTMAP].n_value;
usrpt = (struct pte *) nlst[X_USRPT].n_value;
#endif
#ifndef hp9000s300
mpid_offset = nlst[X_MPID].n_value;
#endif
avenrun_offset = nlst[X_AVENRUN].n_value;
total_offset = nlst[X_TOTAL].n_value;
cp_time_offset = nlst[X_CP_TIME].n_value;
/* this is used in calculating WCPU -- calculate it ahead of time */
logcpu = log(loaddouble(ccpu));
/* allocate space for proc structure array and array of pointers */
bytes = nproc * sizeof(struct proc);
pbase = (struct proc *)malloc(bytes);
pref = (struct proc **)malloc(nproc * sizeof(struct proc *));
/* Just in case ... */
if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL)
{
fprintf(stderr, "top: can't allocate sufficient memory\n");
return(-1);
}
/* get the page size with "getpagesize" and calculate pageshift from it */
pagesize = getpagesize();
pageshift = 0;
while (pagesize > 1)
{
pageshift++;
pagesize >>= 1;
}
/* we only need the amount of log(2)1024 for our conversion */
pageshift -= LOG1024;
/* fill in the statics information */
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
/* all done! */
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);
}
void
get_system_info(si)
struct system_info *si;
{
load_avg avenrun[3];
long total;
/* get the cp_time array */
(void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
"_cp_time");
/* get load average array */
(void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
"_avenrun");
#ifndef hp9000s300
/* get mpid -- process id of last process */
(void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
"_mpid");
#else
si->last_pid = -1;
#endif
/* convert load averages to doubles */
{
register int i;
register double *infoloadp;
register load_avg *sysloadp;
infoloadp = si->load_avg;
sysloadp = avenrun;
for (i = 0; i < 3; i++)
{
*infoloadp++ = loaddouble(*sysloadp++);
}
}
/* convert cp_time counts to percentages */
total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
/* sum memory statistics */
{
struct vmtotal total;
/* get total -- systemwide main memory usage structure */
(void) getkval(total_offset, (int *)(&total), sizeof(total),
"_total");
/* convert memory stats to Kbytes */
memory_stats[0] = -1;
memory_stats[1] = pagetok(total.t_arm);
memory_stats[2] = pagetok(total.t_rm);
memory_stats[3] = -1;
memory_stats[4] = pagetok(total.t_avm);
memory_stats[5] = pagetok(total.t_vm);
memory_stats[6] = pagetok(total.t_free);
}
/* set arrays and strings */
si->cpustates = cpu_states;
si->memory = memory_stats;
}
static struct handle handle;
caddr_t get_process_info(si, sel, i)
struct system_info *si;
struct process_select *sel;
int i;
{
register int i;
register int total_procs;
register int active_procs;
register struct proc **prefp;
register struct proc *pp;
/* these are copied out of sel for speed */
int show_idle;
int show_system;
int show_uid;
int show_command;
/* read all the proc structures in one fell swoop */
(void) getkval(proc, (int *)pbase, bytes, "proc array");
/* get a pointer to the states summary array */
si->procstates = process_states;
/* set up flags which define what we are going to select */
show_idle = sel->idle;
show_system = sel->system;
show_uid = sel->uid != -1;
show_command = sel->command != NULL;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
active_procs = 0;
memset((char *)process_states, 0, sizeof(process_states));
prefp = pref;
for (pp = pbase, i = 0; i < nproc; pp++, i++)
{
/*
* Place pointers to each valid proc structure in pref[].
* Process slots that are actually in use have a non-zero
* status field. Processes with SSYS set are system
* processes---these get ignored unless show_sysprocs is set.
*/
if (pp->p_stat != 0 &&
(show_system || ((pp->p_flag & SSYS) == 0)))
{
total_procs++;
process_states[pp->p_stat]++;
if ((pp->p_stat != SZOMB) &&
(show_idle || (pp->p_pctcpu != 0) || (pp->p_stat == SRUN)) &&
(!show_uid || pp->p_uid == (uid_t)sel->uid))
{
*prefp++ = pp;
active_procs++;
}
}
}
/* if requested, sort the "interesting" processes */
if (compare != NULL)
{
qsort((char *)pref, active_procs, sizeof(struct proc *), proc_compare);
}
/* remember active and total counts */
si->p_total = total_procs;
si->p_active = pref_len = active_procs;
/* pass back a handle */
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char fmt[MAX_COLS]; /* static area where result is built */
char *format_next_process(handle, get_userid)
caddr_t handle;
char *(*get_userid)();
{
register struct proc *pp;
register long cputime;
register double pct;
int where;
struct user u;
struct handle *hp;
/* find and remember the next proc structure */
hp = (struct handle *)handle;
pp = *(hp->next_proc++);
hp->remaining--;
/* get the process's user struct and set cputime */
where = getu(pp, &u);
if (where == -1)
{
(void) strcpy(u.u_comm, "<swapped>");
cputime = 0;
}
else
{
/* set u_comm for system processes */
if (u.u_comm[0] == '\0')
{
if (pp->p_pid == 0)
{
(void) strcpy(u.u_comm, "Swapper");
}
else if (pp->p_pid == 2)
{
(void) strcpy(u.u_comm, "Pager");
}
}
if (where == 1) {
/*
* Print swapped processes as <pname>
*/
char buf[sizeof(u.u_comm)];
(void) strncpy(buf, u.u_comm, sizeof(u.u_comm));
u.u_comm[0] = '<';
(void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2);
u.u_comm[sizeof(u.u_comm) - 2] = '\0';
(void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1);
u.u_comm[sizeof(u.u_comm) - 1] = '\0';
}
cputime = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec;
}
/* calculate the base for cpu percentages */
pct = pctdouble(pp->p_pctcpu);
/* format this entry */
sprintf(fmt,
Proc_format,
pp->p_pid,
(*get_userid)(pp->p_uid),
pp->p_pri - PZERO,
pp->p_nice - NZERO,
format_k(pagetok(PROCSIZE(pp))),
format_k(pagetok(pp->p_rssize)),
state_abbrev[pp->p_stat],
format_time(cputime),
100.0 * weighted_cpu(pct, pp),
100.0 * pct,
printable(u.u_comm));
/* return the result */
return(fmt);
}
/*
* getu(p, u) - get the user structure for the process whose proc structure
* is pointed to by p. The user structure is put in the buffer pointed
* to by u. Return 0 if successful, -1 on failure (such as the process
* being swapped out).
*/
#define USERSIZE sizeof(struct user)
getu(p, u)
register struct proc *p;
struct user *u;
{
struct pte uptes[UPAGES];
register caddr_t upage;
register struct pte *pte;
register nbytes, n;
/*
* Check if the process is currently loaded or swapped out. The way we
* get the u area is totally different for the two cases. For this
* application, we just don't bother if the process is swapped out.
*/
if ((p->p_flag & SLOAD) == 0) {
#ifdef DOSWAP
if (lseek(swap, (long)dtob(p->p_swaddr), 0) == -1) {
perror("lseek(swap)");
return(-1);
}
if (read(swap, (char *) u, USERSIZE) != USERSIZE) {
perror("read(swap)");
return(-1);
}
return (1);
#else
return(-1);
#endif
}
/*
* Process is currently in memory, we hope!
*/
if (!getkval((unsigned long)p->p_addr, (int *)uptes, sizeof(uptes),
"!p->p_addr"))
{
#ifdef DEBUG
perror("getkval(uptes)");
#endif
/* we can't seem to get to it, so pretend it's swapped out */
return(-1);
}
upage = (caddr_t) u;
pte = uptes;
for (nbytes = USERSIZE; nbytes > 0; nbytes -= NBPG) {
(void) lseek(mem, (long)(pte++->pg_pfnum * NBPG), 0);
#ifdef DEBUG
perror("lseek(mem)");
#endif
n = MIN(nbytes, NBPG);
if (read(mem, upage, n) != n) {
#ifdef DEBUG
perror("read(mem)");
#endif
/* we can't seem to get to it, so pretend it's swapped out */
return(-1);
}
upage += n;
}
return(0);
}
/*
* check_nlist(nlst) - checks the nlist to see if any symbols were not
* found. For every symbol that was not found, a one-line
* message is printed to stderr. The routine returns the
* number of symbols NOT found.
*/
int check_nlist(nlst)
register struct nlist *nlst;
{
register int i;
/* check to see if we got ALL the symbols we requested */
/* this will write one line to stderr for every symbol not found */
i = 0;
while (nlst->n_name != NULL)
{
if (nlst->n_type == 0)
{
/* this one wasn't found */
fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
i = 1;
}
nlst++;
}
return(i);
}
/*
* 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 (lseek(kmem, (long)offset, L_SET) == -1) {
if (*refstr == '!')
refstr++;
(void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
if (read(kmem, (char *) ptr, size) == -1) {
if (*refstr == '!')
return(0);
else {
(void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
}
return(1);
}
/* comparison routine for qsort */
/*
* 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);
}
void (*signal(sig, func))()
int sig;
void (*func)();
{
struct sigvec osv, sv;
/*
* XXX: we should block the signal we are playing with,
* in case we get interrupted in here.
*/
if (sigvector(sig, NULL, &osv) == -1)
return BADSIG;
sv = osv;
sv.sv_handler = func;
#ifdef SV_BSDSIG
sv.sv_flags |= SV_BSDSIG;
#endif
if (sigvector(sig, &sv, NULL) == -1)
return BADSIG;
return osv.sv_handler;
}
int getpagesize() { return 1 << PGSHIFT; }
int setpriority(a, b, c) { errno = ENOSYS; return -1; }
/*
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
* the process does not exist.
* It is EXTREMLY IMPORTANT that this function work correctly.
* If top runs setuid root (as in SVR4), then this function
* is the only thing that stands in the way of a serious
* security problem. It validates requests for the "kill"
* and "renice" commands.
*/
int proc_owner(pid)
int pid;
{
register int cnt;
register struct proc **prefp;
register struct proc *pp;
prefp = pref;
cnt = pref_len;
while (--cnt >= 0)
{
if ((pp = *prefp++)->p_pid == (pid_t)pid)
{
return((int)pp->p_uid);
}
}
return(-1);
}

819
external/bsd/top/dist/machine/m_hpux8.c vendored Normal file
View File

@@ -0,0 +1,819 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: any hp9000 running hpux version 8 (may work with 9)
*
* DESCRIPTION:
* This is the machine-dependent module for HPUX 8 and is rumored to work
* for version 9 as well. This makes top work on (at least) the
* following systems:
* hp9000s300
* hp9000s700
* hp9000s800
*
* LIBS:
*
* AUTHOR: Christos Zoulas <christos@ee.cornell.edu>
*/
#include "config.h"
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <stdio.h>
#include <nlist.h>
#include <math.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/dk.h>
#include <sys/vm.h>
#include <sys/file.h>
#include <sys/time.h>
#ifndef hpux
# define P_RSSIZE(p) (p)->p_rssize
# define P_TSIZE(p) (p)->p_tsize
# define P_DSIZE(p) (p)->p_dsize
# define P_SSIZE(p) (p)->p_ssize
#else
# include <sys/pstat.h>
# define __PST2P(p, field) \
((p)->p_upreg ? ((struct pst_status *) (p)->p_upreg)->field : 0)
# define P_RSSIZE(p) __PST2P(p, pst_rssize)
# define P_TSIZE(p) __PST2P(p, pst_tsize)
# define P_DSIZE(p) __PST2P(p, pst_dsize)
# define P_SSIZE(p) __PST2P(p, pst_ssize)
#endif
#include "top.h"
#include "machine.h"
#include "utils.h"
#define VMUNIX "/hp-ux"
#define KMEM "/dev/kmem"
#define MEM "/dev/mem"
#ifdef DOSWAP
#define SWAP "/dev/dmem"
#endif
/* get_process_info passes back a handle. This is what it looks like: */
struct handle
{
struct proc **next_proc; /* points to next valid proc pointer */
int remaining; /* number of pointers remaining */
};
/* declarations for load_avg */
#include "loadavg.h"
/* define what weighted cpu is. */
#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
((pct) / (1.0 - exp((pp)->p_time * logcpu))))
/* what we consider to be process size: */
#define PROCSIZE(pp) (P_TSIZE(pp) + P_DSIZE(pp) + P_SSIZE(pp))
/* definitions for indices in the nlist array */
#define X_AVENRUN 0
#define X_CCPU 1
#define X_NPROC 2
#define X_PROC 3
#define X_TOTAL 4
#define X_CP_TIME 5
#define X_MPID 6
/*
* Steinar Haug from University of Trondheim, NORWAY pointed out that
* the HP 9000 system 800 doesn't have _hz defined in the kernel. He
* provided a patch to work around this. We've improved on this patch
* here and set the constant X_HZ only when _hz is available in the
* kernel. Code in this module that uses X_HZ is surrounded with
* appropriate ifdefs.
*/
#ifndef hp9000s300
#define X_HZ 7
#endif
static struct nlist nlst[] = {
{ "_avenrun" }, /* 0 */
{ "_ccpu" }, /* 1 */
{ "_nproc" }, /* 2 */
{ "_proc" }, /* 3 */
{ "_total" }, /* 4 */
{ "_cp_time" }, /* 5 */
{ "_mpid" }, /* 6 */
#ifdef X_HZ
{ "_hz" }, /* 7 */
#endif
{ 0 }
};
/*
* 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 %5s %5s %-5s %6s %5.2f%% %5.2f%% %s"
/* process state names for the "STATE" column of the display */
/* the extra nulls in the string "run" are for adding a slash and
the processor number when needed */
char *state_abbrev[] =
{
"", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
};
static int kmem;
/* values that we stash away in _init and use in later routines */
static double logcpu;
/* these are retrieved from the kernel in _init */
static unsigned long proc;
static int nproc;
static long hz;
static load_avg ccpu;
static int ncpu = 0;
/* these are offsets obtained via nlist and used in the get_ functions */
static unsigned long mpid_offset;
static unsigned long avenrun_offset;
static unsigned long total_offset;
static unsigned long cp_time_offset;
/* these are for calculating cpu state percentages */
static long cp_time[CPUSTATES];
static long cp_old[CPUSTATES];
static long cp_diff[CPUSTATES];
/* these are for detailing the process states */
int process_states[7];
char *procstatenames[] = {
"", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
" zombie, ", " stopped, ",
NULL
};
/* these are for detailing the cpu states */
int cpu_states[9];
char *cpustatenames[] = {
"usr", "nice", "sys", "idle", "", "", "", "intr", "ker",
NULL
};
/* these are for detailing the memory statistics */
long memory_stats[8];
char *memorynames[] = {
"Real: ", "K act, ", "K tot ", "Virtual: ", "K act, ",
"K tot, ", "K free", NULL
};
/* these are for keeping track of the proc array */
static int bytes;
static int pref_len;
static struct proc *pbase;
static struct proc **pref;
static struct pst_status *pst;
/* these are for getting the memory statistics */
static int pageshift; /* log base 2 of the pagesize */
/* define pagetok in terms of pageshift */
#define pagetok(size) ((size) << pageshift)
/* useful externals */
extern int errno;
extern char *sys_errlist[];
long lseek();
long time();
machine_init(statics)
struct statics *statics;
{
register int i = 0;
register int pagesize;
if ((kmem = open(KMEM, O_RDONLY)) == -1) {
perror(KMEM);
return(-1);
}
#ifdef hp9000s800
/* 800 names don't have leading underscores */
for (i = 0; nlst[i].n_name; nlst[i++].n_name++)
continue;
#endif
/* get the list of symbols we want to access in the kernel */
(void) nlist(VMUNIX, nlst);
if (nlst[0].n_type == 0)
{
fprintf(stderr, "top: nlist failed\n");
return(-1);
}
/* make sure they were all found */
if (check_nlist(nlst) > 0)
{
return(-1);
}
/* get the symbol values out of kmem */
(void) getkval(nlst[X_PROC].n_value, (int *)(&proc), sizeof(proc),
nlst[X_PROC].n_name);
(void) getkval(nlst[X_NPROC].n_value, &nproc, sizeof(nproc),
nlst[X_NPROC].n_name);
(void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu),
nlst[X_CCPU].n_name);
#ifdef X_HZ
(void) getkval(nlst[X_HZ].n_value, (int *)(&hz), sizeof(hz),
nlst[X_HZ].n_name);
#else
hz = HZ;
#endif
/* stash away certain offsets for later use */
mpid_offset = nlst[X_MPID].n_value;
avenrun_offset = nlst[X_AVENRUN].n_value;
total_offset = nlst[X_TOTAL].n_value;
cp_time_offset = nlst[X_CP_TIME].n_value;
/* this is used in calculating WCPU -- calculate it ahead of time */
logcpu = log(loaddouble(ccpu));
/* allocate space for proc structure array and array of pointers */
bytes = nproc * sizeof(struct proc);
pbase = (struct proc *)malloc(bytes);
pref = (struct proc **)malloc(nproc * sizeof(struct proc *));
pst = (struct pst_status *)malloc(nproc * sizeof(struct pst_status));
/* Just in case ... */
if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL)
{
fprintf(stderr, "top: can't allocate sufficient memory\n");
return(-1);
}
/* get the page size with "getpagesize" and calculate pageshift from it */
pagesize = getpagesize();
pageshift = 0;
while (pagesize > 1)
{
pageshift++;
pagesize >>= 1;
}
/* we only need the amount of log(2)1024 for our conversion */
pageshift -= LOG1024;
/* fill in the statics information */
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
/* all done! */
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);
}
void
get_system_info(si)
struct system_info *si;
{
load_avg avenrun[3];
long total;
/* get the cp_time array */
(void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
"_cp_time");
/* get load average array */
(void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
"_avenrun");
/* get mpid -- process id of last process */
(void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
"_mpid");
/* convert load averages to doubles */
{
register int i;
register double *infoloadp;
register load_avg *sysloadp;
infoloadp = si->load_avg;
sysloadp = avenrun;
for (i = 0; i < 3; i++)
{
*infoloadp++ = loaddouble(*sysloadp++);
}
}
/* convert cp_time counts to percentages */
total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
/* sum memory statistics */
{
struct vmtotal total;
/* get total -- systemwide main memory usage structure */
(void) getkval(total_offset, (int *)(&total), sizeof(total),
"_total");
/* convert memory stats to Kbytes */
memory_stats[0] = -1;
memory_stats[1] = pagetok(total.t_arm);
memory_stats[2] = pagetok(total.t_rm);
memory_stats[3] = -1;
memory_stats[4] = pagetok(total.t_avm);
memory_stats[5] = pagetok(total.t_vm);
memory_stats[6] = pagetok(total.t_free);
}
/* set arrays and strings */
si->cpustates = cpu_states;
si->memory = memory_stats;
}
static struct handle handle;
caddr_t get_process_info(si, sel, i)
struct system_info *si;
struct process_select *sel;
int i;
{
register int i;
register int total_procs;
register int active_procs;
register struct proc **prefp;
register struct proc *pp;
/* these are copied out of sel for speed */
int show_idle;
int show_system;
int show_uid;
int show_command;
/* read all the proc structures in one fell swoop */
(void) getkval(proc, (int *)pbase, bytes, "proc array");
for (i = 0; i < nproc; ++i) {
if (pstat(PSTAT_PROC, &pst[i], sizeof(pst[i]), 0, pbase[i].p_pid) != 1)
pbase[i].p_upreg = (preg_t *) 0;
else
pbase[i].p_upreg = (preg_t *) &pst[i];
pbase[i].p_nice = pst[i].pst_nice;
pbase[i].p_cpticks = pst[i].pst_cpticks;
}
/* get a pointer to the states summary array */
si->procstates = process_states;
/* set up flags which define what we are going to select */
show_idle = sel->idle;
show_system = sel->system;
show_uid = sel->uid != -1;
show_command = sel->command != NULL;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
active_procs = 0;
memset((char *)process_states, 0, sizeof(process_states));
prefp = pref;
for (pp = pbase, i = 0; i < nproc; pp++, i++)
{
/*
* Place pointers to each valid proc structure in pref[].
* Process slots that are actually in use have a non-zero
* status field. Processes with SSYS set are system
* processes---these get ignored unless show_sysprocs is set.
*/
if (pp->p_stat != 0 &&
(show_system || ((pp->p_flag & SSYS) == 0)))
{
total_procs++;
process_states[pp->p_stat]++;
if ((pp->p_stat != SZOMB) &&
(show_idle || (pp->p_pctcpu != 0) || (pp->p_stat == SRUN)) &&
(!show_uid || pp->p_uid == (uid_t)sel->uid))
{
*prefp++ = pp;
active_procs++;
}
}
}
/* if requested, sort the "interesting" processes */
if (compare != NULL)
{
qsort((char *)pref, active_procs, sizeof(struct proc *), proc_compare);
}
/* remember active and total counts */
si->p_total = total_procs;
si->p_active = pref_len = active_procs;
/* pass back a handle */
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char fmt[MAX_COLS]; /* static area where result is built */
char *format_next_process(handle, get_userid)
caddr_t handle;
char *(*get_userid)();
{
register struct proc *pp;
register long cputime;
register double pct;
int where;
struct user u;
struct handle *hp;
/* find and remember the next proc structure */
hp = (struct handle *)handle;
pp = *(hp->next_proc++);
hp->remaining--;
/* get the process's user struct and set cputime */
where = getu(pp, &u);
if (where == -1)
{
(void) strcpy(u.u_comm, "<swapped>");
cputime = 0;
}
else
{
/* set u_comm for system processes */
if (u.u_comm[0] == '\0')
{
if (pp->p_pid == 0)
{
(void) strcpy(u.u_comm, "Swapper");
}
else if (pp->p_pid == 2)
{
(void) strcpy(u.u_comm, "Pager");
}
}
if (where == 1) {
/*
* Print swapped processes as <pname>
*/
char buf[sizeof(u.u_comm)];
(void) strncpy(buf, u.u_comm, sizeof(u.u_comm));
u.u_comm[0] = '<';
(void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2);
u.u_comm[sizeof(u.u_comm) - 2] = '\0';
(void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1);
u.u_comm[sizeof(u.u_comm) - 1] = '\0';
}
cputime = __PST2P(pp, pst_cptickstotal) / hz;
}
/* calculate the base for cpu percentages */
pct = pctdouble(pp->p_pctcpu);
/* format this entry */
sprintf(fmt,
Proc_format,
pp->p_pid,
(*get_userid)(pp->p_uid),
pp->p_pri - PZERO,
pp->p_nice - NZERO,
format_k(pagetok(PROCSIZE(pp))),
format_k(pagetok(P_RSSIZE(pp))),
state_abbrev[pp->p_stat],
format_time(cputime),
100.0 * weighted_cpu(pct, pp),
100.0 * pct,
printable(u.u_comm));
/* return the result */
return(fmt);
}
/*
* getu(p, u) - get the user structure for the process whose proc structure
* is pointed to by p. The user structure is put in the buffer pointed
* to by u. Return 0 if successful, -1 on failure (such as the process
* being swapped out).
*/
getu(p, u)
register struct proc *p;
struct user *u;
{
struct pst_status *ps;
char *s, *c;
int i;
if ((ps = (struct pst_status *) p->p_upreg) == NULL)
return -1;
memset(u, 0, sizeof(struct user));
c = ps->pst_cmd;
ps->pst_cmd[PST_CLEN - 1] = '\0'; /* paranoia */
s = strtok(ps->pst_cmd, "\t \n");
if (c = strrchr(s, '/'))
c++;
else
c = s;
if (*c == '-')
c++;
i = 0;
for (; i < MAXCOMLEN; i++) {
if (*c == '\0' || *c == ' ' || *c == '/')
break;
u->u_comm[i] = *c++;
}
#ifndef DOSWAP
return ((p->p_flag & SLOAD) == 0 ? 1 : 0);
#endif
return(0);
}
/*
* check_nlist(nlst) - checks the nlist to see if any symbols were not
* found. For every symbol that was not found, a one-line
* message is printed to stderr. The routine returns the
* number of symbols NOT found.
*/
int check_nlist(nlst)
register struct nlist *nlst;
{
register int i;
/* check to see if we got ALL the symbols we requested */
/* this will write one line to stderr for every symbol not found */
i = 0;
while (nlst->n_name != NULL)
{
if (nlst->n_type == 0)
{
/* this one wasn't found */
fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
i = 1;
}
nlst++;
}
return(i);
}
/*
* 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 (lseek(kmem, (long)offset, L_SET) == -1) {
if (*refstr == '!')
refstr++;
(void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
if (read(kmem, (char *) ptr, size) == -1) {
if (*refstr == '!')
return(0);
else {
(void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
}
return(1);
}
/* comparison routine for qsort */
/*
* 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 = P_RSSIZE(p2) - P_RSSIZE(p1)) == 0)
{
/* use total memory to break the tie */
result = PROCSIZE(p2) - PROCSIZE(p1);
}
}
}
}
}
else
{
result = lresult < 0 ? -1 : 1;
}
return(result);
}
void (*signal(sig, func))()
int sig;
void (*func)();
{
struct sigvec osv, sv;
/*
* XXX: we should block the signal we are playing with,
* in case we get interrupted in here.
*/
if (sigvector(sig, NULL, &osv) == -1)
return BADSIG;
sv = osv;
sv.sv_handler = func;
#ifdef SV_BSDSIG
sv.sv_flags |= SV_BSDSIG;
#endif
if (sigvector(sig, &sv, NULL) == -1)
return BADSIG;
return osv.sv_handler;
}
int getpagesize() { return 1 << PGSHIFT; }
int setpriority(a, b, c) { errno = ENOSYS; return -1; }
/*
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
* the process does not exist.
* It is EXTREMLY IMPORTANT that this function work correctly.
* If top runs setuid root (as in SVR4), then this function
* is the only thing that stands in the way of a serious
* security problem. It validates requests for the "kill"
* and "renice" commands.
*/
int proc_owner(pid)
int pid;
{
register int cnt;
register struct proc **prefp;
register struct proc *pp;
prefp = pref;
cnt = pref_len;
while (--cnt >= 0)
{
if ((pp = *prefp++)->p_pid == (pid_t)pid)
{
return((int)pp->p_uid);
}
}
return(-1);
}

842
external/bsd/top/dist/machine/m_hpux9.c vendored Normal file
View File

@@ -0,0 +1,842 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: any hp9000 running hpux version 9
*
* DESCRIPTION:
* This is the machine-dependent module for HPUX 9.
* This makes top work on (at least) the following systems:
* hp9000s800
* hp9000s700
* This may make top work on the following, but we aren't sure:
* hp9000s300
*
* LIBS:
*
* CFLAGS: -DHAVE_GETOPT
*
* AUTHOR: Kevin Schmidt <kevin@mcl.ucsb.edu>
* adapted from Christos Zoulas <christos@ee.cornell.edu>
*/
#include "config.h"
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <stdio.h>
#include <nlist.h>
#include <math.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/dk.h>
#include <sys/vm.h>
#include <sys/file.h>
#include <sys/time.h>
#ifndef hpux
# define P_RSSIZE(p) (p)->p_rssize
# define P_TSIZE(p) (p)->p_tsize
# define P_DSIZE(p) (p)->p_dsize
# define P_SSIZE(p) (p)->p_ssize
#else
# include <sys/pstat.h>
# define __PST2P(p, field) \
((p)->p_upreg ? ((struct pst_status *) (p)->p_upreg)->field : 0)
# define P_RSSIZE(p) __PST2P(p, pst_rssize)
# define P_TSIZE(p) __PST2P(p, pst_tsize)
# define P_DSIZE(p) __PST2P(p, pst_dsize)
# define P_SSIZE(p) __PST2P(p, pst_ssize)
# ifdef __hp9000s700
# define p_percentcpu(p) ((p)->p_pctcpu)
# define p_time_exact(p) ((p)->p_time)
# else
/* The following 4 #defines are per HPUX-9.0's <sys/proc.h> */
# define PCT_NORM 9 /* log2(PCT_BASE) */
# define PCT_BASE (1<<PCT_NORM)
# define p_percentcpu(p) ((p)->p_fractioncpu/(float)(PCT_BASE*HZ))
# define p_time_exact(p) (time.tv_sec-((p)->p_swaptime))
# endif /* __hp9000s700 */
#endif /* hpux */
#include "top.h"
#include "machine.h"
#include "utils.h"
#define VMUNIX "/hp-ux"
#define KMEM "/dev/kmem"
#define MEM "/dev/mem"
#ifdef DOSWAP
#define SWAP "/dev/dmem"
#endif
/* get_process_info passes back a handle. This is what it looks like: */
struct handle
{
struct proc **next_proc; /* points to next valid proc pointer */
int remaining; /* number of pointers remaining */
};
/* declarations for load_avg */
#include "loadavg.h"
/* define what weighted cpu is. */
#define weighted_cpu(pct, pp) ((p_time_exact(pp)) == 0 ? 0.0 : \
((pct) / (1.0 - exp((p_time_exact(pp)) * logcpu))))
/* what we consider to be process size: */
#define PROCSIZE(pp) (P_TSIZE(pp) + P_DSIZE(pp) + P_SSIZE(pp))
/* definitions for indices in the nlist array */
#define X_AVENRUN 0
#define X_CCPU 1
#define X_NPROC 2
#define X_PROC 3
#define X_TOTAL 4
#define X_CP_TIME 5
#define X_MPID 6
/*
* Steinar Haug from University of Trondheim, NORWAY pointed out that
* the HP 9000 system 800 doesn't have _hz defined in the kernel. He
* provided a patch to work around this. We've improved on this patch
* here and set the constant X_HZ only when _hz is available in the
* kernel. Code in this module that uses X_HZ is surrounded with
* appropriate ifdefs.
*/
#ifndef hp9000s300
#define X_HZ 7
#endif
static struct nlist nlst[] = {
{ "_avenrun" }, /* 0 */
{ "_cexp" }, /* 1 */
{ "_nproc" }, /* 2 */
{ "_proc" }, /* 3 */
{ "_total" }, /* 4 */
{ "_cp_time" }, /* 5 */
{ "_mpid" }, /* 6 */
#ifdef X_HZ
{ "_hz" }, /* 7 */
#endif
{ 0 }
};
/*
* 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 %5s %5s %-5s %6s %5.2f%% %5.2f%% %s"
/* process state names for the "STATE" column of the display */
/* the extra nulls in the string "run" are for adding a slash and
the processor number when needed */
char *state_abbrev[] =
{
"", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
};
static int kmem;
/* values that we stash away in _init and use in later routines */
static double logcpu;
/* these are retrieved from the kernel in _init */
static unsigned long proc;
static int nproc;
static long hz;
static load_avg ccpu;
static int ncpu = 0;
/* these are offsets obtained via nlist and used in the get_ functions */
static unsigned long mpid_offset;
static unsigned long avenrun_offset;
static unsigned long total_offset;
static unsigned long cp_time_offset;
/* these are for calculating cpu state percentages */
static long cp_time[CPUSTATES];
static long cp_old[CPUSTATES];
static long cp_diff[CPUSTATES];
/* these are for detailing the process states */
int process_states[7];
char *procstatenames[] = {
"", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
" zombie, ", " stopped, ",
NULL
};
/* these are for detailing the cpu states */
int cpu_states[9];
char *cpustatenames[] = {
"usr", "nice", "sys", "idle", "", "", "", "intr", "ker",
NULL
};
/* these are for detailing the memory statistics */
long memory_stats[8];
char *memorynames[] = {
"Real: ", "K act, ", "K tot ", "Virtual: ", "K act, ",
"K tot, ", "K free", NULL
};
/* these are for keeping track of the proc array */
static int bytes;
static int pref_len;
static struct proc *pbase;
static struct proc **pref;
static struct pst_status *pst;
/* these are for getting the memory statistics */
static int pageshift; /* log base 2 of the pagesize */
/* define pagetok in terms of pageshift */
#define pagetok(size) ((size) << pageshift)
/* useful externals */
extern int errno;
extern char *sys_errlist[];
long lseek();
long time();
machine_init(statics)
struct statics *statics;
{
register int i = 0;
register int pagesize;
if ((kmem = open(KMEM, O_RDONLY)) == -1) {
perror(KMEM);
return(-1);
}
#ifdef hp9000s800
/* 800 names don't have leading underscores */
for (i = 0; nlst[i].n_name; nlst[i++].n_name++)
continue;
#endif
/* get the list of symbols we want to access in the kernel */
(void) nlist(VMUNIX, nlst);
if (nlst[0].n_type == 0)
{
fprintf(stderr, "top: nlist failed\n");
return(-1);
}
/* make sure they were all found */
if (check_nlist(nlst) > 0)
{
return(-1);
}
/* get the symbol values out of kmem */
(void) getkval(nlst[X_PROC].n_value, (int *)(&proc), sizeof(proc),
nlst[X_PROC].n_name);
(void) getkval(nlst[X_NPROC].n_value, &nproc, sizeof(nproc),
nlst[X_NPROC].n_name);
(void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu),
nlst[X_CCPU].n_name);
#ifdef X_HZ
(void) getkval(nlst[X_HZ].n_value, (int *)(&hz), sizeof(hz),
nlst[X_HZ].n_name);
#else
hz = HZ;
#endif
/* stash away certain offsets for later use */
mpid_offset = nlst[X_MPID].n_value;
avenrun_offset = nlst[X_AVENRUN].n_value;
total_offset = nlst[X_TOTAL].n_value;
cp_time_offset = nlst[X_CP_TIME].n_value;
/* this is used in calculating WCPU -- calculate it ahead of time */
logcpu = log(loaddouble(ccpu));
/* allocate space for proc structure array and array of pointers */
bytes = nproc * sizeof(struct proc);
pbase = (struct proc *)malloc(bytes);
pref = (struct proc **)malloc(nproc * sizeof(struct proc *));
pst = (struct pst_status *)malloc(nproc * sizeof(struct pst_status));
/* Just in case ... */
if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL)
{
fprintf(stderr, "top: can't allocate sufficient memory\n");
return(-1);
}
/* get the page size with "getpagesize" and calculate pageshift from it */
pagesize = getpagesize();
pageshift = 0;
while (pagesize > 1)
{
pageshift++;
pagesize >>= 1;
}
/* we only need the amount of log(2)1024 for our conversion */
pageshift -= LOG1024;
/* fill in the statics information */
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
/* all done! */
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);
}
void
get_system_info(si)
struct system_info *si;
{
load_avg avenrun[3];
long total;
/* get the cp_time array */
(void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
"_cp_time");
/* get load average array */
(void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
"_avenrun");
/* get mpid -- process id of last process */
(void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
"_mpid");
/* convert load averages to doubles */
{
register int i;
register double *infoloadp;
register load_avg *sysloadp;
infoloadp = si->load_avg;
sysloadp = avenrun;
for (i = 0; i < 3; i++)
{
*infoloadp++ = loaddouble(*sysloadp++);
}
}
/* convert cp_time counts to percentages */
total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
/* sum memory statistics */
{
struct vmtotal total;
/* get total -- systemwide main memory usage structure */
(void) getkval(total_offset, (int *)(&total), sizeof(total),
"_total");
/* convert memory stats to Kbytes */
memory_stats[0] = -1;
memory_stats[1] = pagetok(total.t_arm);
memory_stats[2] = pagetok(total.t_rm);
memory_stats[3] = -1;
memory_stats[4] = pagetok(total.t_avm);
memory_stats[5] = pagetok(total.t_vm);
memory_stats[6] = pagetok(total.t_free);
}
/* set arrays and strings */
si->cpustates = cpu_states;
si->memory = memory_stats;
}
static struct handle handle;
caddr_t get_process_info(si, sel, i)
struct system_info *si;
struct process_select *sel;
int i;
{
register int i;
register int total_procs;
register int active_procs;
register struct proc **prefp;
register struct proc *pp;
/* these are copied out of sel for speed */
int show_idle;
int show_system;
int show_uid;
int show_command;
/* read all the proc structures in one fell swoop */
(void) getkval(proc, (int *)pbase, bytes, "proc array");
for (i = 0; i < nproc; ++i) {
if (pstat(PSTAT_PROC, &pst[i], sizeof(pst[i]), 0, pbase[i].p_pid) != 1)
pbase[i].p_upreg = (preg_t *) 0;
else
pbase[i].p_upreg = (preg_t *) &pst[i];
pbase[i].p_nice = pst[i].pst_nice;
pbase[i].p_cpticks = pst[i].pst_cpticks;
}
/* get a pointer to the states summary array */
si->procstates = process_states;
/* set up flags which define what we are going to select */
show_idle = sel->idle;
show_system = sel->system;
show_uid = sel->uid != -1;
show_command = sel->command != NULL;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
active_procs = 0;
memset((char *)process_states, 0, sizeof(process_states));
prefp = pref;
for (pp = pbase, i = 0; i < nproc; pp++, i++)
{
/*
* Place pointers to each valid proc structure in pref[].
* Process slots that are actually in use have a non-zero
* status field. Processes with SSYS set are system
* processes---these get ignored unless show_sysprocs is set.
*/
if (pp->p_stat != 0 &&
(show_system || ((pp->p_flag & SSYS) == 0)))
{
total_procs++;
process_states[pp->p_stat]++;
/*
* idle processes can be selectively ignored: a process is
* considered idle when cpticks is zero AND it is not in the run
* state. Zombies are always ignored. We also skip over
* processes that have been excluded via a uid selection
*/
if ((pp->p_stat != SZOMB) &&
(show_idle || (pp->p_cpticks != 0) || (pp->p_stat == SRUN)) &&
(!show_uid || pp->p_uid == (uid_t)sel->uid))
{
*prefp++ = pp;
active_procs++;
}
}
}
/* if requested, sort the "interesting" processes */
if (compare != NULL)
{
qsort((char *)pref, active_procs, sizeof(struct proc *), proc_compare);
}
/* remember active and total counts */
si->p_total = total_procs;
si->p_active = pref_len = active_procs;
/* pass back a handle */
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char fmt[MAX_COLS]; /* static area where result is built */
char *format_next_process(handle, get_userid)
caddr_t handle;
char *(*get_userid)();
{
register struct proc *pp;
register long cputime;
register double pct;
int where;
struct user u;
struct handle *hp;
struct timeval time;
struct timezone timezone;
/* find and remember the next proc structure */
hp = (struct handle *)handle;
pp = *(hp->next_proc++);
hp->remaining--;
/* get the process's user struct and set cputime */
where = getu(pp, &u);
if (where == -1)
{
(void) strcpy(u.u_comm, "<swapped>");
cputime = 0;
}
else
{
/* set u_comm for system processes */
if (u.u_comm[0] == '\0')
{
if (pp->p_pid == 0)
{
(void) strcpy(u.u_comm, "Swapper");
}
else if (pp->p_pid == 2)
{
(void) strcpy(u.u_comm, "Pager");
}
}
if (where == 1) {
/*
* Print swapped processes as <pname>
*/
char buf[sizeof(u.u_comm)];
(void) strncpy(buf, u.u_comm, sizeof(u.u_comm));
u.u_comm[0] = '<';
(void) strncpy(&u.u_comm[1], buf, sizeof(u.u_comm) - 2);
u.u_comm[sizeof(u.u_comm) - 2] = '\0';
(void) strncat(u.u_comm, ">", sizeof(u.u_comm) - 1);
u.u_comm[sizeof(u.u_comm) - 1] = '\0';
}
cputime = __PST2P(pp, pst_cptickstotal) / hz;
}
/* calculate the base for cpu percentages */
pct = pctdouble(p_percentcpu(pp));
/* get time used for calculation in weighted_cpu */
gettimeofday(&time, &timezone);
/* format this entry */
sprintf(fmt,
Proc_format,
pp->p_pid,
(*get_userid)(pp->p_uid),
pp->p_pri - PZERO,
pp->p_nice - NZERO,
format_k(pagetok(PROCSIZE(pp))),
format_k(pagetok(P_RSSIZE(pp))),
state_abbrev[pp->p_stat],
format_time(cputime),
100.0 * weighted_cpu(pct, pp),
100.0 * pct,
printable(u.u_comm));
/* return the result */
return(fmt);
}
/*
* getu(p, u) - get the user structure for the process whose proc structure
* is pointed to by p. The user structure is put in the buffer pointed
* to by u. Return 0 if successful, -1 on failure (such as the process
* being swapped out).
*/
getu(p, u)
register struct proc *p;
struct user *u;
{
struct pst_status *ps;
char *s, *c;
int i;
if ((ps = (struct pst_status *) p->p_upreg) == NULL)
return -1;
memset(u, 0, sizeof(struct user));
c = ps->pst_cmd;
ps->pst_cmd[PST_CLEN - 1] = '\0'; /* paranoia */
s = strtok(ps->pst_cmd, "\t \n");
if (c = strrchr(s, '/'))
c++;
else
c = s;
if (*c == '-')
c++;
i = 0;
for (; i < MAXCOMLEN; i++) {
if (*c == '\0' || *c == ' ' || *c == '/')
break;
u->u_comm[i] = *c++;
}
#ifndef DOSWAP
return ((p->p_flag & SLOAD) == 0 ? 1 : 0);
#endif
return(0);
}
/*
* check_nlist(nlst) - checks the nlist to see if any symbols were not
* found. For every symbol that was not found, a one-line
* message is printed to stderr. The routine returns the
* number of symbols NOT found.
*/
int check_nlist(nlst)
register struct nlist *nlst;
{
register int i;
/* check to see if we got ALL the symbols we requested */
/* this will write one line to stderr for every symbol not found */
i = 0;
while (nlst->n_name != NULL)
{
if (nlst->n_type == 0)
{
/* this one wasn't found */
fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
i = 1;
}
nlst++;
}
return(i);
}
/*
* 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 (lseek(kmem, (long)offset, L_SET) == -1) {
if (*refstr == '!')
refstr++;
(void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
if (read(kmem, (char *) ptr, size) == -1) {
if (*refstr == '!')
return(0);
else {
(void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
refstr, strerror(errno));
quit(23);
}
}
return(1);
}
/* comparison routine for qsort */
/*
* 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 = p_percentcpu(p2) - p_percentcpu(p1)) == 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 = P_RSSIZE(p2) - P_RSSIZE(p1)) == 0)
{
/* use total memory to break the tie */
result = PROCSIZE(p2) - PROCSIZE(p1);
}
}
}
}
}
else
{
result = lresult < 0 ? -1 : 1;
}
return(result);
}
void (*signal(sig, func))()
int sig;
void (*func)();
{
struct sigvec osv, sv;
/*
* XXX: we should block the signal we are playing with,
* in case we get interrupted in here.
*/
if (sigvector(sig, NULL, &osv) == -1)
return BADSIG;
sv = osv;
sv.sv_handler = func;
#ifdef SV_BSDSIG
sv.sv_flags |= SV_BSDSIG;
#endif
if (sigvector(sig, &sv, NULL) == -1)
return BADSIG;
return osv.sv_handler;
}
int getpagesize() { return 1 << PGSHIFT; }
int setpriority(a, b, c) { errno = ENOSYS; return -1; }
/*
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
* the process does not exist.
* It is EXTREMLY IMPORTANT that this function work correctly.
* If top runs setuid root (as in SVR4), then this function
* is the only thing that stands in the way of a serious
* security problem. It validates requests for the "kill"
* and "renice" commands.
*/
int proc_owner(pid)
int pid;
{
register int cnt;
register struct proc **prefp;
register struct proc *pp;
prefp = pref;
cnt = pref_len;
while (--cnt >= 0)
{
if ((pp = *prefp++)->p_pid == (pid_t)pid)
{
return((int)pp->p_uid);
}
}
return(-1);
}

View File

@@ -0,0 +1,9 @@
.SH "HPUX 9 INFORMATION"
Under HP/UX 9, the kernel symbol _ccpu was eliminated. The author
believe that _cexp is a suitable substitute, but cannot be positive.
This seems to be confirmed by the fact that information produced using
this assumption correlates well with that produced by HP's version of top.
This port was adapted from the port for HP/UX version 8 (written by
Christos Zoulas). The adaptation was performed by Kevin Schmidt
<kevin@mcl.ucsb.edu>.

763
external/bsd/top/dist/machine/m_irix5.c vendored Normal file
View File

@@ -0,0 +1,763 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: any uniprocessor, 32 bit SGI machine running IRIX 5.3
*
* DESCRIPTION:
* This is the machine-dependent module for IRIX 5.3.
* It has been tested on Indys running 5.3 and Indigos running 5.3XFS
*
* LIBS: -lmld
* CFLAGS: -DHAVE_GETOPT
*
* AUTHOR: Sandeep Cariapa <cariapa@sgi.com>
* This is not a supported product of Silicon Graphics, Inc.
* Please do not call SGI for support.
*
*/
#define _KMEMUSER
#include "config.h"
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/swap.h>
#include <sys/proc.h>
#include <sys/procfs.h>
#include <sys/sysinfo.h>
#include <sys/sysmp.h>
#include <paths.h>
#include <dirent.h>
#include <stdio.h>
#include <nlist.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "top.h"
#include "machine.h"
#ifdef IRIX64
#define nlist nlist64
#define lseek lseek64
#define off_t off64_t
#endif
#define UNIX "/unix"
#define KMEM "/dev/kmem"
#define CPUSTATES 6
#ifndef FSCALE
#define FSHIFT 8 /* bits to right of fixed binary point */
#define FSCALE (1<<FSHIFT)
#endif /* FSCALE */
#ifdef FIXED_LOADAVG
typedef long 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
#define percent_cpu(pp) (*(double *)pp->pr_fill)
#define weighted_cpu(pp) (*(double *)&pp->pr_fill[2])
static int pagesize;
#define pagetok(size) ((size)*pagesize)
static int numcpus;
/*
* 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 %5s %5s %-5s %6s %5.2f%% %5.2f%% %.16s"
/* these are for detailing the process states */
char *state_abbrev[] =
{"", "sleep", "run\0\0\0", "zombie", "stop", "idle", "", "swap"};
int process_states[8];
char *procstatenames[] = {
"", " sleeping, ", " running, ", " zombie, ", " stopped, ",
" idle, ", "", " swapped, ",
NULL
};
/* these are for detailing the cpu states */
int cpu_states[CPUSTATES];
char *cpustatenames[] = {
"idle", "usr", "ker", "wait", "swp", "intr",
NULL
};
/* these are for detailing the memory statistics */
long memory_stats[5];
char *memorynames[] = {
"K max, ", "K avail, ", "K free, ", "K swap, ", "K free swap", NULL
};
/* useful externals */
extern int errno;
extern char *myname;
extern char *sys_errlist[];
extern char *format_k();
extern char *format_time();
extern long percentages();
/* forward references */
int proc_compare (void *pp1, void *pp2);
#define X_AVENRUN 0
#define X_NPROC 1
#define X_FREEMEM 2
#define X_MAXMEM 3
#define X_AVAILRMEM 4
#define X_MPID 5
static struct nlist nlst[] = {
{ "avenrun" }, /* 0. Array containing the 3 load averages. */
{ "nproc" }, /* 1. Kernel parameter: Max number of processes. */
{ "freemem" }, /* 2. Amount of free memory in system. */
{ "maxmem" }, /* 3. Maximum amount of memory usable by system. */
{ "availrmem" }, /* 4. Available real memory. */
#ifndef IRIX64
{ "mpid" }, /* 5. PID of last process. */
#endif
{ 0 }
};
static unsigned long avenrun_offset;
static unsigned long nproc_offset;
static unsigned long freemem_offset;
static unsigned long maxmem_offset;
static unsigned long availrmem_offset;
static unsigned long mpid_offset;
double load[3];
char fmt[MAX_COLS];
static int kmem;
static int nproc;
static int bytes;
static struct prpsinfo *pbase;
static struct prpsinfo **pref;
static DIR *procdir;
/* get_process_info passes back a handle. This is what it looks like: */
struct handle {
struct prpsinfo **next_proc;/* points to next valid proc pointer */
int remaining; /* number of pointers remaining */
};
static struct handle handle;
void getptable();
/*
* Structure for keeping track of CPU times from last time around
* the program. We keep these things in a hash table, which is
* recreated at every cycle.
*/
struct oldproc
{
pid_t oldpid;
double oldtime;
double oldpct;
};
static int oldprocs; /* size of table */
static struct oldproc *oldbase;
#define HASH(x) ((x << 1) % oldprocs)
#define PRPSINFOSIZE (sizeof(struct prpsinfo))
int machine_init(statics)
struct statics *statics;
{
struct oldproc *op, *endbase;
if ((kmem = open(KMEM, O_RDONLY)) == -1) {
perror(KMEM);
return(-1);
}
/* get the list of symbols we want to access in the kernel */
(void) nlist(UNIX, nlst);
if (nlst[0].n_type == 0) {
fprintf(stderr, "%s: nlist failed\n", myname);
return(-1);
}
/* Check if we got all of 'em. */
if (check_nlist(nlst) > 0) {
return(-1);
}
avenrun_offset = nlst[X_AVENRUN].n_value;
nproc_offset = nlst[X_NPROC].n_value;
freemem_offset = nlst[X_FREEMEM].n_value;
maxmem_offset = nlst[X_MAXMEM].n_value;
availrmem_offset = nlst[X_AVAILRMEM].n_value;
#ifndef IRIX64
mpid_offset = nlst[X_MPID].n_value;
#endif
/* Got to do this first so that we can map real estate for the
process array. */
(void) getkval(nproc_offset, (int *) (&nproc), sizeof(nproc), "nproc");
/* allocate space for proc structure array and array of pointers */
bytes = nproc * sizeof (struct prpsinfo);
pbase = (struct prpsinfo *) malloc (bytes);
pref = (struct prpsinfo **) malloc (nproc * sizeof (struct prpsinfo *));
oldbase = (struct oldproc *) malloc (2 * nproc * sizeof (struct oldproc));
/* Just in case ... */
if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL ||
oldbase == (struct oldproc *)NULL) {
(void) fprintf (stderr, "%s: can't allocate sufficient memory\n", myname);
return (-1);
}
oldprocs = 2 * nproc;
endbase = oldbase + oldprocs;
for (op = oldbase; op < endbase; op++) {
op->oldpid = -1;
}
if (!(procdir = opendir (_PATH_PROCFSPI))) {
(void) fprintf (stderr, "Unable to open %s\n", _PATH_PROCFSPI);
return (-1);
}
if (chdir (_PATH_PROCFSPI)) {
/* handy for later on when we're reading it */
(void) fprintf (stderr, "Unable to chdir to %s\n", _PATH_PROCFSPI);
return (-1);
}
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
pagesize = getpagesize()/1024;
/* all done! */
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);
}
void get_system_info(si)
struct system_info *si;
{
register int i;
int avenrun[3];
static int freemem;
static int maxmem;
static int availrmem;
struct sysinfo sysinfo;
static long cp_new[CPUSTATES];
static long cp_old[CPUSTATES];
static long cp_diff[CPUSTATES]; /* for cpu state percentages */
off_t fswap; /* current free swap in blocks */
off_t tswap; /* total swap in blocks */
(void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun), "avenrun");
for (i = 0; i < 3; i++) {
si->load_avg[i] = loaddouble (avenrun[i]);
si->load_avg[i] = si->load_avg[i]/1024.0;
}
(void) getkval(freemem_offset, (int *) (&freemem), sizeof(freemem),
"freemem");
(void) getkval(maxmem_offset, (int *) (&maxmem), sizeof(maxmem), "maxmem");
(void) getkval(availrmem_offset, (int *) (&availrmem), sizeof(availrmem),
"availrmem");
#ifdef IRIX64
si->last_pid = 0;
#else
(void) getkval(mpid_offset, &(si->last_pid), sizeof (si->last_pid), "mpid");
#endif
swapctl(SC_GETFREESWAP, &fswap);
swapctl(SC_GETSWAPTOT, &tswap);
memory_stats[0] = pagetok(maxmem);
memory_stats[1] = pagetok(availrmem);
memory_stats[2] = pagetok(freemem);
memory_stats[3] = tswap / 2;
memory_stats[4] = fswap / 2;
/* use sysmp() to get current sysinfo usage. Can run into all kinds of
problems if you try to nlist this kernel variable. */
if (sysmp(MP_SAGET, MPSA_SINFO, &sysinfo, sizeof(struct sysinfo)) == -1) {
perror("sysmp");
return;
}
/* copy sysinfo.cpu to an array of longs, as expected by percentages() */
for (i = 0; i < CPUSTATES; i++) {
cp_new[i] = sysinfo.cpu[i];
}
(void) percentages (CPUSTATES, cpu_states, cp_new, cp_old, cp_diff);
si->cpustates = cpu_states;
si->memory = memory_stats;
numcpus = sysmp(MP_NPROCS);
/* add a slash to the "run" state abbreviation */
if (numcpus > 1) {
state_abbrev[SRUN][3] = '/';
}
return;
}
caddr_t get_process_info(si, sel, x)
struct system_info *si;
struct process_select *sel;
int x;
{
register int i;
register int total_procs;
register int active_procs;
register struct prpsinfo **prefp;
register struct prpsinfo *pp;
/* these are copied out of sel for speed */
int show_idle;
int show_system;
int show_uid;
/* read all the proc structures */
getptable (pbase);
/* get a pointer to the states summary array */
si->procstates = process_states;
/* set up flags which define what we are going to select */
show_idle = sel->idle;
show_system = sel->system;
show_uid = sel->uid != -1;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
active_procs = 0;
(void) memset (process_states, 0, sizeof (process_states));
prefp = pref;
for (pp = pbase, i = 0; i < nproc; pp++, i++) {
/*
* Place pointers to each valid proc structure in pref[].
* Process slots that are actually in use have a non-zero
* status field. Processes with SSYS set are system
* processes---these get ignored unless show_system is set.
*/
if (pp->pr_state != 0 &&
(show_system || ((pp->pr_flag & SSYS) == 0))) {
total_procs++;
process_states[pp->pr_state]++;
if ((!pp->pr_zomb) &&
(show_idle || (pp->pr_state == SRUN)) &&
(!show_uid || pp->pr_uid == (uid_t) sel->uid)) {
*prefp++ = pp;
active_procs++;
}
}
}
/* if requested, sort the "interesting" processes */
if (compare != NULL)
qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *), proc_compare);
/* remember active and total counts */
si->p_total = total_procs;
si->p_active = active_procs;
/* pass back a handle */
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char *format_next_process(handle, get_userid)
caddr_t handle;
char *(*get_userid)();
{
register struct prpsinfo *pp;
struct handle *hp;
register long cputime;
register double pctcpu;
/* find and remember the next proc structure */
hp = (struct handle *) handle;
pp = *(hp->next_proc++);
hp->remaining--;
/* get the cpu usage and calculate the cpu percentages */
cputime = pp->pr_time.tv_sec;
pctcpu = percent_cpu (pp);
if (numcpus > 1) {
if (pp->pr_sonproc < 0)
state_abbrev[SRUN][4] = '*';
else
state_abbrev[SRUN][4] = pp->pr_sonproc + '0';
}
/* format this entry */
sprintf (fmt,
Proc_format,
pp->pr_pid,
(*get_userid) (pp->pr_uid),
pp->pr_pri - PZERO,
pp->pr_nice - NZERO,
format_k(pagetok(pp->pr_size)),
format_k(pagetok(pp->pr_rssize)),
state_abbrev[pp->pr_state],
format_time(cputime),
weighted_cpu (pp),
pctcpu,
pp->pr_fname);
/* return the result */
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).
*
*/
int getkval(offset, ptr, size, refstr)
off_t offset;
int *ptr;
int size;
char *refstr;
{
if (lseek(kmem, offset, SEEK_SET) == -1) {
if (*refstr == '!')
refstr++;
(void) fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
refstr, strerror(errno));
quit(0);
}
if (read(kmem, (char *) ptr, size) == -1) {
if (*refstr == '!')
return(0);
else {
(void) fprintf(stderr, "%s: reading %s: %s\n", KMEM,
refstr, strerror(errno));
quit(0);
}
}
return(1);
}
/*
* 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, idle, run. The
* array declaration below maps a process state index into a number
* that reflects this ordering.
*/
unsigned char sorted_state[] =
{
0, /* not used */
3, /* sleep */
6, /* run */
2, /* zombie */
4, /* stop */
5, /* idle */
0, /* not used */
1 /* being swapped (WAIT) */
};
int proc_compare (pp1, pp2)
void *pp1;
void *pp2;
{
register struct prpsinfo *p1;
register struct prpsinfo *p2;
register long result;
/* remove one level of indirection */
p1 = *(struct prpsinfo **)pp1;
p2 = *(struct prpsinfo **)pp2;
/* compare percent cpu (pctcpu) */
if ((result = (long) (p2->pr_cpu - p1->pr_cpu)) == 0) {
/* use cpticks to break the tie */
if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0) {
/* use process state to break the tie */
if ((result = (long) (sorted_state[p2->pr_state] -
sorted_state[p1->pr_state])) == 0) {
/* use priority to break the tie */
if ((result = p2->pr_oldpri - p1->pr_oldpri) == 0) {
/* use resident set size (rssize) to break the tie */
if ((result = p2->pr_rssize - p1->pr_rssize) == 0) {
/* use total memory to break the tie */
result = (p2->pr_size - p1->pr_size);
}
}
}
}
}
return (result);
}
/* return the owner of the specified process. */
int proc_owner (pid)
int pid;
{
register struct prpsinfo *p;
int i;
for (i = 0, p = pbase; i < nproc; i++, p++)
if (p->pr_pid == (oid_t)pid)
return ((int)p->pr_uid);
return (-1);
}
/*
* check_nlist(nlst) - checks the nlist to see if any symbols were not
* found. For every symbol that was not found, a one-line
* message is printed to stderr. The routine returns the
* number of symbols NOT found.
*/
int check_nlist(nlst)
register struct nlist *nlst;
{
register int i;
/* check to see if we got ALL the symbols we requested */
/* this will write one line to stderr for every symbol not found */
i = 0;
while (nlst->n_name != NULL) {
if (nlst->n_type == 0) {
/* this one wasn't found */
fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
i = 1;
}
nlst++;
}
return(i);
}
/* get process table */
void getptable (baseptr)
struct prpsinfo *baseptr;
{
struct prpsinfo *currproc; /* pointer to current proc structure */
int numprocs = 0;
int i;
struct dirent *directp;
struct oldproc *op;
static struct timeval lasttime =
{0L, 0L};
struct timeval thistime;
struct timezone thiszone;
double timediff;
double alpha, beta;
struct oldproc *endbase;
gettimeofday (&thistime, &thiszone);
/*
* To avoid divides, we keep times in nanoseconds. This is
* scaled by 1e7 rather than 1e9 so that when we divide we
* get percent.
*/
if (lasttime.tv_sec)
timediff = ((double) thistime.tv_sec * 1.0e7 +
((double) thistime.tv_usec * 10.0)) -
((double) lasttime.tv_sec * 1.0e7 +
((double) lasttime.tv_usec * 10.0));
else
timediff = 1.0e7;
/*
* constants for exponential average. avg = alpha * new + beta * avg
* The goal is 50% decay in 30 sec. However if the sample period
* is greater than 30 sec, there's not a lot we can do.
*/
if (timediff < 30.0e7)
{
alpha = 0.5 * (timediff / 30.0e7);
beta = 1.0 - alpha;
}
else
{
alpha = 0.5;
beta = 0.5;
}
endbase = oldbase + oldprocs;
currproc = baseptr;
for (rewinddir (procdir); directp = readdir (procdir);)
{
int fd;
if ((fd = open (directp->d_name, O_RDONLY)) < 0)
continue;
currproc = &baseptr[numprocs];
if (ioctl (fd, PIOCPSINFO, currproc) < 0)
{
(void) close (fd);
continue;
}
/*
* SVr4 doesn't keep track of CPU% in the kernel, so we have
* to do our own. See if we've heard of this process before.
* If so, compute % based on CPU since last time.
*/
op = oldbase + HASH (currproc->pr_pid);
while (1)
{
if (op->oldpid == -1) /* not there */
break;
if (op->oldpid == currproc->pr_pid)
{ /* found old data */
percent_cpu (currproc) =
((currproc->pr_time.tv_sec * 1.0e9 +
currproc->pr_time.tv_nsec)
- op->oldtime) / timediff;
weighted_cpu (currproc) =
op->oldpct * beta + percent_cpu (currproc) * alpha;
break;
}
op++; /* try next entry in hash table */
if (op == endbase) /* table wrapped around */
op = oldbase;
}
/* Otherwise, it's new, so use all of its CPU time */
if (op->oldpid == -1)
{
if (lasttime.tv_sec)
{
percent_cpu (currproc) =
(currproc->pr_time.tv_sec * 1.0e9 +
currproc->pr_time.tv_nsec) / timediff;
weighted_cpu (currproc) =
percent_cpu (currproc);
}
else
{ /* first screen -- no difference is possible */
percent_cpu (currproc) = 0.0;
weighted_cpu (currproc) = 0.0;
}
}
numprocs++;
(void) close (fd);
}
if (nproc != numprocs)
nproc = numprocs;
/*
* Save current CPU time for next time around
* For the moment recreate the hash table each time, as the code
* is easier that way.
*/
oldprocs = 2 * nproc;
endbase = oldbase + oldprocs;
for (op = oldbase; op < endbase; op++)
op->oldpid = -1;
for (i = 0, currproc = baseptr;
i < nproc;
i++, currproc = (struct prpsinfo *) ((char *) currproc + PRPSINFOSIZE))
{
/* find an empty spot */
op = oldbase + HASH (currproc->pr_pid);
while (1)
{
if (op->oldpid == -1)
break;
op++;
if (op == endbase)
op = oldbase;
}
op->oldpid = currproc->pr_pid;
op->oldtime = (currproc->pr_time.tv_sec * 1.0e9 +
currproc->pr_time.tv_nsec);
op->oldpct = weighted_cpu (currproc);
}
lasttime = thistime;
}

1109
external/bsd/top/dist/machine/m_irixsgi.c vendored Normal file

File diff suppressed because it is too large Load Diff

1355
external/bsd/top/dist/machine/m_linux.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
.SH "LINUX NOTES"
The Linux port was written by Richard Henderson <rth@tamu.edu>.
The CPU% calculation was brazenly stolen from the Solaris 2
port and should be attributed to one of the many names listed
in its man page.
The order support was stolen from SUNOS 5 port by
Alexey Klimkin <kad@klon.tme.mcst.ru>
Made to work under 2.4 by William LeFebvre.

1111
external/bsd/top/dist/machine/m_linuxthr.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
.SH "LINUX NOTES"
The Linux port was written by Richard Henderson <rth@tamu.edu>.
The CPU% calculation was brazenly stolen from the Solaris 2
port and should be attributed to one of the many names listed
in its man page.
The order support was stolen from the SunOS 5 port by
Alexey Klimkin <kad@klon.tme.mcst.ru>
Made to work under 2.4 by William LeFebvre.
This version of the Linux port includes automatic thread "eliding".
In Linux, a thread is treated as another process sharing the memory
space (as well as file table and other resources). Thus
multiple threads appear as separate processes in most system
utilities (see
.IR clone (2)).
This version of top detects child thread processes and does not
display them separately. Instead of displaying threads individually,
an extra column "THR" shows the number of thread processes for a
parent process. The cpu time and percentages are added to the
parent. This gives a display much closer to other thread-capable Unix
systems. However, threads are still counted as separate processes in
the process summary line.
A process is considered a thread of its parent if the
following values are identical to its parent: address space size,
resident set size, code start and end program counters, and stack
start. This heuristic can mistake a recently forked child as a thread,
until the child has either called exec or allocated space on its own.

956
external/bsd/top/dist/machine/m_macosx.c vendored Normal file
View File

@@ -0,0 +1,956 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* m_macosx.c
*
* AUTHOR: Andrew S. Townley
* based on m_bsd44.c and m_next32.c
* by Christos Zoulas and Tim Pugh
* CREATED: Tue Aug 11 01:51:35 CDT 1998
* SYNOPSIS: MacOS X Server (Rhapsody Developer Release 2)
* DESCRIPTION:
* MacOS X Server (Rhapsody Developer Release 2)
*
* CFLAGS: -DHAVE_STRERROR
* TERMCAP: none
* MATH: none
*/
/*
* normal stuff
*/
#include "config.h"
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include "os.h"
#include "top.h"
#include "machine.h"
#include "utils.h"
/*
* MacOS kernel stuff
*/
#include <kvm.h>
#include <fcntl.h>
#include <sys/dkstat.h>
#include <sys/sysctl.h>
#include <mach/message.h>
#include <mach/vm_statistics.h>
#include <mach/mach.h>
#include <mach/host_info.h>
#define VMUNIX "/mach_kernel"
#define MEM "/dev/mem"
#define SWAP NULL
#define NUM_AVERAGES 3
#define LOG1024 10
#define PP(pp, field) ((pp)->kp_proc . field)
#define EP(pp, field) ((pp)->kp_eproc . field)
#define VP(pp, field) ((pp)->kp_eproc.e_vm . field)
#define MPP(mp, field) (PP((mp)->kproc, field))
#define MEP(mp, field) (EP((mp)->kproc, field))
#define MVP(mp, field) (VP((mp)->kproc, field))
#define TP(mp, field) ((mp)->task_info . field)
#define RP(mp, field) ((mp)->thread_summary . field)
/* define what weighted cpu is */
#define weighted_cpu(pct, s) (s == 0 ? 0.0 : \
((pct) / (1.0 - exp(s * logcpu))))
/* what we consider to be process size: */
#ifdef notdef
#define PROCSIZE(pp) (VP((pp), vm_tsize) + VP((pp), vm_dsize) + VP((pp), vm_ssize))
#endif
#define PROCSIZE(pp) (EP(pp, e_xsize))
#define TASKSIZE(t) (TP(t, virtual_size) + TP(t, resident_size))
/* what we consider to be resident set size: */
#ifdef notdef
#define RSSIZE(pp) (MVP((pp), vm_rssize))
#endif
#define RSSIZE(pp) (MEP((pp), e_xrssize))
#define pctdouble(p) ((double)(p) / FSCALE)
/*
* globals
*/
static kvm_t *kd = NULL;
static int nproc;
static int onproc = -1;
static int pref_len;
static int maxmem;
static char fmt[MAX_COLS];
static double logcpu = 1.0;
/* process array stuff */
static struct kinfo_proc *kproc_list = NULL;
static struct macos_proc *proc_list = NULL;
static struct macos_proc **proc_ref = NULL;
static int process_states[7];
static struct handle handle;
/*
* The mach information hopefully will not be necessary
* when the kvm_* interfaces are supported completely.
*
* Since we're only concerned with task and thread info
* for 'interesting' processes, we're going to only allocate
* as many task and thread structures as needed.
*/
static struct task_basic_info *task_list = NULL;
/* memory statistics */
static int pageshift = 0;
static int pagesize = 0;
#define pagetok(size) ((size) << pageshift)
static int swappgsin = -1;
static int swappgsout = -1;
static vm_statistics_data_t vm_stats;
static long memory_stats[7];
/* CPU state percentages */
host_cpu_load_info_data_t cpuload;
static long cp_time[CPU_STATE_MAX];
static long cp_old[CPU_STATE_MAX];
static long cp_diff[CPU_STATE_MAX];
static int cpu_states[CPU_STATE_MAX];
/*
* types
*/
typedef long pctcpu;
//struct statics
//{
// char **procstate_names;
// char **cpustate_names;
// char **memory_names;
// char **order_names;
//};
//
//struct system_info
//{
// int last_pid;
// double load_avg[NUM_AVERAGES];
// int p_total; /* total # of processes */
// int p_active; /* number processes considered active */
// int *procstates;
// int *cpustates;
// int *memory;
//};
//
//struct process_select
//{
// int idle; /* show idle processes */
// int system; /* show system processes */
// int uid; /* show only this uid (unless -1) */
// char *command; /* only this command (unless NULL) */
//};
/*
* We need to declare a hybrid structure which will store all
* of the stuff we care about for each process.
*/
struct macos_proc
{
struct kinfo_proc *kproc;
task_t the_task;
struct task_basic_info task_info;
unsigned int thread_count;
struct thread_basic_info thread_summary;
};
struct handle
{
struct macos_proc **next_proc;
int remaining;
};
static char header[] =
" PID X PRI THRD SIZE RES STATE TIME MEM CPU COMMAND";
/* 0123456 -- field to fill in starts at header+6 */
#define UNAME_START 6
#define Proc_format \
"%5d %-8.8s %3d %4d %5s %5s %-5s %6s %5.2f%% %5.2f%% %.16s"
int proc_compare(const void *, const void *);
/*
* puke()
*
* This function is used to report errors to stderr.
*/
static void puke(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fputc('\n', stderr);
fflush(stderr);
}
/*
* kread()
*
* This function is a wrapper for the kvm_read() function
* with the addition of a message parameter per kvm_open().
*
* All other behavior is per kvm_read except the error reporting.
*/
static ssize_t kread(u_long addr, void *buf,
size_t nbytes, const char *errstr)
{
ssize_t s = 0;
s = kvm_read(kd, addr, buf, nbytes);
if(s == -1)
{
puke("error: kvm_read() failed for '%s' (%s)\n",
errstr, strerror(errno));
}
return s;
}
/*
* prototypes for functions which top needs
*/
char *printable();
/*
* definitions for offsets
*/
#define X_NPROC 0
#define X_HZ 1
#define X_MAXMEM 2
#define NLIST_LAST 3
static struct nlist nlst[] =
{
{ "_maxproc" }, /* 0 *** maximum processes */
{ "_hz" }, /* 1 */
{ "_mem_size" }, /* 2 */
{ 0 }
};
static char *procstates[] =
{
"",
" starting, ",
" running, ",
" sleeping, ",
" stopped, ",
" zombie, ",
" swapped ",
NULL
};
static char *cpustates[] =
{
"user",
"system",
"idle",
"nice",
NULL
};
static char *state_abbrev[] =
{
"",
"start",
"run\0\0\0",
"sleep",
"stop",
"zomb"
};
static char *mach_state[] =
{
"",
"R",
"T",
"S",
"U",
"H"
};
static char *thread_state[] =
{
"",
"run\0\0\0",
"stop",
"wait",
"uwait",
"halted",
};
static char *flags_state[] =
{
"",
"W",
"I"
};
static char *memnames[] =
{
"K Tot, ",
"K Free, ",
"K Act, ",
"K Inact, ",
"K Wired, ",
"K in, ",
"K out ",
NULL
};
/*
* format_header()
*
* This function is used to add the username into the
* header information.
*/
char *format_header(register char *uname_field)
{
register char *ptr;
ptr = header + UNAME_START;
while(*uname_field != '\0')
*ptr++ = *uname_field++;
return(header);
}
/*
* format_next_process()
*
* This function actuall is responsible for the formatting of
* each row which is displayed.
*/
char *format_next_process(caddr_t handle, char *(*getuserid)())
{
register struct macos_proc *pp;
register long cputime;
register double pct;
register int vsize;
register int rsize;
struct handle *hp;
/*
* we need to keep track of the next proc structure.
*/
hp = (struct handle*)handle;
pp = *(hp->next_proc++);
hp->remaining--;
/*
* get the process structure and take care of the cputime
*/
if((MPP(pp, p_flag) & P_INMEM) == 0)
{
/* we want to print swapped processes as <pname> */
char *comm = MPP(pp, p_comm);
#define COMSIZ sizeof(MPP(pp, p_comm))
char buf[COMSIZ];
strncpy(buf, comm, COMSIZ);
comm[0] = '<';
strncpy(&comm[1], buf, COMSIZ - 2);
comm[COMSIZ - 2] = '\0';
strncat(comm, ">", COMSIZ - 1);
comm[COMSIZ - 1] = '\0';
}
/*
* count the cpu time, but ignore the interrupts
*
* At the present time (DR2 8/1998), MacOS X doesn't
* correctly report this information through the
* kinfo_proc structure. We need to get it from the
* task threads.
*
* cputime = PP(pp, p_rtime).tv_sec;
*/
cputime = RP(pp, user_time).seconds + RP(pp, system_time).seconds;
/*
* calculate the base cpu percentages
*
* Again, at the present time, MacOS X doesn't report
* this information through the kinfo_proc. We need
* to talk to the threads.
*/
// pct = pctdouble(PP(pp, p_pctcpu));
pct = (double)(RP(pp, cpu_usage))/TH_USAGE_SCALE;
/*
* format the entry
*/
/*
* In the final version, I would expect this to work correctly,
* but it seems that not all of the fields in the proc
* structure are being used.
*
* For now, we'll attempt to get some of the things we need
* from the mach task info.
*/
sprintf(fmt,
Proc_format,
MPP(pp, p_pid),
(*getuserid)(MEP(pp, e_pcred.p_ruid)),
// TP(pp, base_priority),
0,
pp->thread_count,
format_k(TASKSIZE(pp) / 1024),
format_k(pagetok(RSSIZE(pp))),
state_abbrev[(u_char)MPP(pp, p_stat)],
format_time(cputime),
100.0 * TP(pp, resident_size) / maxmem,
// 100.0 * weighted_cpu(pct, (RP(pp, user_time).seconds + RP(pp, system_time).seconds)),
100.0 * pct,
printable(MPP(pp, p_comm)));
return(fmt);
}
/*
* get_process_info()
*
* This function returns information about the processes
* on the system.
*/
caddr_t get_process_info(struct system_info *si,
struct process_select *sel, int x)
{
register int i;
register int total_procs;
register int active_procs;
register struct macos_proc **prefp;
register struct macos_proc *pp;
register struct kinfo_proc *pp2;
register struct kinfo_proc **prefp2;
register struct thread_basic_info *thread;
/*
* these are copied out of sel for speed
*/
int show_idle;
int show_system;
int show_uid;
int show_command;
kproc_list = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
if(nproc > onproc)
{
proc_list = (struct macos_proc*)realloc(proc_list, sizeof(struct macos_proc) * nproc);
proc_ref = (struct macos_proc **)realloc(proc_ref, sizeof(struct macos_proc *) * (onproc = nproc));
}
if(proc_ref == NULL || proc_list == NULL || kproc_list == NULL)
{
puke("error: out of memory (%s)", strerror(errno));
return(NULL);
}
/*
* now, our task is to build the array of information we
* need to function correctly. This involves setting a pointer
* to each real kinfo_proc structure returned by kvm_getprocs()
* in addition to getting the mach information for each of
* those processes.
*/
for(pp2 = kproc_list, i = 0; i < nproc; pp2++, i++)
{
kern_return_t rc;
u_int info_count = TASK_BASIC_INFO_COUNT;
/*
* first, we set the pointer to the reference in
* the kproc list.
*/
proc_list[i].kproc = pp2;
/*
* then, we load all of the task info for the process
*/
if(PP(pp2, p_stat) != SZOMB)
{
rc = task_for_pid(mach_task_self(),
PP(pp2, p_pid),
&(proc_list[i].the_task));
if(rc != KERN_SUCCESS)
{
puke("error: get task info for pid %d failed with rc = %d", PP(pp2, p_pid), rc);
}
/*
* load the task information
*/
rc = task_info(proc_list[i].the_task, TASK_BASIC_INFO,
(task_info_t)&(proc_list[i].task_info),
&info_count);
if(rc != KERN_SUCCESS)
{
puke("error: couldn't get task info (%s); rc = %d", strerror(errno), rc);
}
/*
* load the thread summary information
*/
load_thread_info(&proc_list[i]);
}
}
/* get a pointer to the states summary array */
si->procstates = process_states;
/* set up flags which define what we are going to select */
show_idle = sel->idle;
show_system = sel->system;
show_uid = sel->uid != -1;
show_command = sel->command != NULL;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
active_procs = 0;
memset((char *)process_states, 0, sizeof(process_states));
prefp = proc_ref;
for(pp = proc_list, i = 0; i < nproc; pp++, i++)
{
/*
* Place pointers to each valid proc structure in
* proc_ref[]. Process slots that are actually in use
* have a non-zero status field. Processes with
* P_SYSTEM set are system processes---these get
* ignored unless show_sysprocs is set.
*/
if(MPP(pp, p_stat) != 0 &&
(show_system || ((MPP(pp, p_flag) & P_SYSTEM) == 0)))
{
total_procs++;
process_states[(unsigned char) MPP(pp, p_stat)]++;
if((MPP(pp, p_stat) != SZOMB) &&
(show_idle || (MPP(pp, p_pctcpu) != 0) ||
(MPP(pp, p_stat) == SRUN)) &&
(!show_uid || MEP(pp, e_pcred.p_ruid) == (uid_t)sel->uid))
{
*prefp++ = pp;
active_procs++;
}
}
}
/*
* if requested, sort the "interesting" processes
*/
qsort((char *)proc_ref, active_procs, sizeof(struct macos_proc *), proc_compare);
/* remember active and total counts */
si->p_total = total_procs;
si->p_active = pref_len = active_procs;
/* pass back a handle */
handle.next_proc = proc_ref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
/*
* get_system_info()
*
* This function is responsible for geting the periodic
* system information snapshot.
*/
void get_system_info(struct system_info *si)
{
register long total;
register int i;
unsigned int count = HOST_CPU_LOAD_INFO_COUNT;
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO,
(host_info_t)&cpuload, &count) == KERN_SUCCESS)
{
for (i = 0; i < CPU_STATE_MAX; i++)
{
cp_time[i] = cpuload.cpu_ticks[i];
}
}
#ifdef MAX_VERBOSE
/*
* print out the entries
*/
for(i = 0; i < CPU_STATE_MAX; i++)
printf("cp_time[%d] = %d\n", i, cp_time[i]);
fflush(stdout);
#endif /* MAX_VERBOSE */
/*
* get the load averages
*/
if(kvm_getloadavg(kd, si->load_avg, NUM_AVERAGES) == -1)
{
puke("error: kvm_getloadavg() failed (%s)", strerror(errno));
return;
}
#ifdef MAX_VERBOSE
printf("%-30s%03.2f, %03.2f, %03.2f\n",
"load averages:",
si->load_avg[0],
si->load_avg[1],
si->load_avg[2]);
#endif /* MAX_VERBOSE */
total = percentages(CPU_STATE_MAX, cpu_states, cp_time, cp_old, cp_diff);
/*
* get the memory statistics
*/
{
kern_return_t status;
count = HOST_VM_INFO_COUNT;
status = host_statistics(mach_host_self(), HOST_VM_INFO,
(host_info_t)&vm_stats, &count);
if(status != KERN_SUCCESS)
{
puke("error: vm_statistics() failed (%s)", strerror(errno));
return;
}
/*
* we already have the total memory, we just need
* to get it in the right format.
*/
memory_stats[0] = pagetok(maxmem / pagesize);
memory_stats[1] = pagetok(vm_stats.free_count);
memory_stats[2] = pagetok(vm_stats.active_count);
memory_stats[3] = pagetok(vm_stats.inactive_count);
memory_stats[4] = pagetok(vm_stats.wire_count);
if(swappgsin < 0)
{
memory_stats[5] = 1;
memory_stats[6] = 1;
}
else
{
memory_stats[5] = pagetok(((vm_stats.pageins - swappgsin)));
memory_stats[6] = pagetok(((vm_stats.pageouts - swappgsout)));
}
swappgsin = vm_stats.pageins;
swappgsout = vm_stats.pageouts;
}
si->cpustates = cpu_states;
si->memory = memory_stats;
si->last_pid = -1;
return;
}
/*
* machine_init()
*
* This function is responsible for filling in the values of the
* statics structure.
*/
int machine_init(struct statics *stat)
{
register int rc = 0;
register int i = 0;
size_t size;
size = sizeof(maxmem);
sysctlbyname("hw.physmem", &maxmem, &size, NULL, 0);
size = sizeof(nproc);
sysctlbyname("kern.maxproc", &nproc, &size, NULL, 0);
#ifdef MAX_VERBOSE
printf("%-30s%10d\n", "total system memory:", maxmem);
#endif /* MAX_VERBOSE */
/*
* calculate the pageshift from the system page size
*/
pagesize = getpagesize();
pageshift = 0;
while((pagesize >>= 1) > 0)
pageshift++;
pageshift -= LOG1024;
/*
* fill in the statics information
*/
stat->procstate_names = procstates;
stat->cpustate_names = cpustates;
stat->memory_names = memnames;
if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL)
return -1;
return(0);
}
/* comparison routine for qsort */
/*
* 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 */
};
int proc_compare(const void *pp1, const void *pp2)
{
register struct macos_proc *p1;
register struct macos_proc *p2;
register int result;
register pctcpu lresult;
/* remove one level of indirection */
p1 = *(struct macos_proc **) pp1;
p2 = *(struct macos_proc **) pp2;
/* compare percent cpu (pctcpu) */
if ((lresult = RP(p2, cpu_usage) - RP(p1, cpu_usage)) == 0)
{
/* use cpticks to break the tie */
if ((result = MPP(p2, p_cpticks) - MPP(p1, p_cpticks)) == 0)
{
/* use process state to break the tie */
if ((result = sorted_state[(unsigned char) MPP(p2, p_stat)] -
sorted_state[(unsigned char) MPP(p1, p_stat)]) == 0)
{
/* use priority to break the tie */
if ((result = MPP(p2, p_priority) - MPP(p1, p_priority)) == 0)
{
/* use resident set size (rssize) to break the tie */
if ((result = RSSIZE(p2) - RSSIZE(p1)) == 0)
{
/* use total memory to break the tie */
result = PROCSIZE(p2->kproc) - PROCSIZE(p1->kproc);
}
}
}
}
}
else
{
result = lresult < 0 ? -1 : 1;
}
return(result);
}
/*
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
* the process does not exist.
* It is EXTREMLY IMPORTANT that this function work correctly.
* If top runs setuid root (as in SVR4), then this function
* is the only thing that stands in the way of a serious
* security problem. It validates requests for the "kill"
* and "renice" commands.
*/
int proc_owner(pid)
int pid;
{
register int cnt;
register struct macos_proc **prefp;
register struct macos_proc *pp;
prefp = proc_ref;
cnt = pref_len;
while (--cnt >= 0)
{
pp = *prefp++;
if (MPP(pp, p_pid) == (pid_t)pid)
{
return((int)MEP(pp, e_pcred.p_ruid));
}
}
return(-1);
}
/*
* load_thread_info()
*
* This function will attempt to load the thread summary info
* for a Mach task. The task is located as part of the macos_proc
* structure.
*
* returns the kern_return_t value of any failed call or KERN_SUCCESS
* if everything works.
*/
int load_thread_info(struct macos_proc *mp)
{
register kern_return_t rc = 0;
register int i = 0;
register int t_utime = 0;
register int t_stime = 0;
register int t_cpu = 0;
register int t_state = 0;
register task_t the_task = mp->the_task;
thread_array_t thread_list = NULL;
/*
* We need to load all of the threads for the
* given task so we can get the performance
* data from them.
*/
mp->thread_count = 0;
rc = task_threads(the_task, &thread_list, &(mp->thread_count));
if(rc != KERN_SUCCESS)
{
// puke("error: unable to load threads for task (%s); rc = %d", strerror(errno), rc);
return(rc);
}
/*
* now, for each of the threads, we need to sum the stats
* so we can present the whole thing to the caller.
*/
for(i = 0; i < mp->thread_count; i++)
{
struct thread_basic_info t_info;
unsigned int icount = THREAD_BASIC_INFO_COUNT;
kern_return_t rc = 0;
rc = thread_info(thread_list[i], THREAD_BASIC_INFO,
(thread_info_t)&t_info, &icount);
if(rc != KERN_SUCCESS)
{
puke("error: unable to load thread info for task (%s); rc = %d", strerror(errno), rc);
return(rc);
}
t_utime += t_info.user_time.seconds;
t_stime += t_info.system_time.seconds;
t_cpu += t_info.cpu_usage;
}
vm_deallocate(mach_task_self(), (vm_address_t)thread_list, sizeof(thread_array_t)*(mp->thread_count));
/*
* Now, we load the values in the structure above.
*/
RP(mp, user_time).seconds = t_utime;
RP(mp, system_time).seconds = t_stime;
RP(mp, cpu_usage) = t_cpu;
return(KERN_SUCCESS);
}

View File

@@ -0,0 +1,20 @@
.SH "MacOS X NOTES"
The display is pretty close to the recommended display and also that
of a normal 4.4 BSD system. The NICE column has been changed to be
the number of threads for each process. The SIZE column reflects the
total size of the process (resident + non-resident) while the RES
column shows only the resident size. The STATE column uses
information taken from the kinfo_proc structure p_pstat member. It
will accurately display the state of stopped and zombie processes, but
I am not really sure about the other states. Finally, the MEM column
is included which displays the percent of total memory per the ps
command.
The MacOS X module was written by Andrew S. Townley <atownley@primenet.com>.
Many thanks to William LeFebvre who is the original author
of the top utility and to Mike Rhee who showed the utility
to me in the first place. Thanks also to Christos Zoulas
who wrote the 4.4 BSD implementation of the machine module.
I also got some pointers from the NEXTSTEP 3.2 and OSF/1
versions by Tim Pugh and Anthony Baxter, respectively.

1366
external/bsd/top/dist/machine/m_netbsd.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
.SH "NetBSD NOTES"
This module has been tested on NetBSD 1.6, NetBSD 2.0 and NetBSD 3.0.
It should also work on NetBSD 1.5, and probably any newer releases of
NetBSD with little or no changes.

874
external/bsd/top/dist/machine/m_sco5.c vendored Normal file
View File

@@ -0,0 +1,874 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: SCO UNIX OpenServer5
*
* DESCRIPTION:
* This is the machine-dependent module for SCO OpenServer5.
* Originally written for BSD4.3 system by Christos Zoulas.
* Modified to m_sco.c (3.2v4.2) by Gregory Shilin <shilin@onyx.co.il>
* Modified to m_sco5.c (3.2v5.*) by Mike Hopkirk <hops@sco.com>
* Works for:
* SCO UNIX 3.2v5.*
*
* CFLAGS: -DHAVE_GETOPT -DORDER
*
* AUTHOR: Mike Hopkirk (hops@sco.com)
* hops 10-Jul-98 - added sort fields
* 17-Jul-98 - add philiph's chopped cmd string support
* (define NO_COMMAND_ARGS to enable )
* 09-Dec-98 - provide RSS calculation
* 15-Mar-2000 - Fix broken lines and cleanup sysinfo access w macros
*/
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <nlist.h>
#include <math.h>
#include <signal.h>
#include <string.h>
#include <sys/dir.h>
#include <sys/immu.h>
#include <sys/region.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/sysinfo.h>
#include <sys/systm.h>
#include <sys/sysmacros.h>
#include <sys/var.h>
#include <sys/sysi86.h>
#include "top.h"
#include "machine.h"
#include "utils.h"
#include "loadavg.h"
/*
typedef unsigned long ulong;
typedef unsigned int uint;
typedef unsigned short ushort;
*/
typedef unsigned char uchar;
#define VMUNIX "/unix"
#define KMEM "/dev/kmem"
#define MEM "/dev/mem"
#define SI_ACTIVE(p) p->p_active
#define SI_TOTAL(p) p->p_total
/* get_process_info passes back a handle. This is what it looks like: */
struct handle {
struct proc **next_proc; /* points to next valid proc pointer */
int remaining; /* number of pointers remaining */
};
/* define what weighted cpu is */
#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
((pct) / (1.0 - exp((pp)->p_time * logcpu))))
#define bytetok(bytes) ((bytes) >> 10)
/* what we consider to be process size: */
#define PROCSIZE(up) bytetok(ctob((up)->u_tsize + (up)->u_dsize+(up)->u_ssize))
/* definitions for indices in the nlist array */
#define X_V 0 /* System configuration information */
#define X_PROC 1 /* process tables */
#define X_FREEMEM 2 /* current free memory */
#define X_AVAILRMEM 3 /* available resident (not swappable) mem in pages
*/
#define X_AVAILSMEM 4 /* available swappable memory in pages */
#define X_MAXMEM 5 /* maximum available free memory in clicks */
#define X_PHYSMEM 6 /* physical memory in clicks */
#define X_NSWAP 7 /* size of swap space in blocks */
#define X_HZ 8 /* ticks/second of the clock */
#define X_MPID 9 /* last process id */
#define X_SYSINFO 10 /* system information (cpu states) */
#define X_CUR_CPU 11
static struct nlist nlst[] = {
{ "v" }, /* 0 */
{ "proc" }, /* 1 */
{ "freemem" }, /* 2 */
{ "availrmem" }, /* 3 */
{ "availsmem" }, /* 4 */
{ "maxmem" }, /* 5 */
{ "physmem" }, /* 6 */
{ "nswap" }, /* 7 */
{ "Hz" }, /* 8 */
{ "mpid" }, /* 9 */
{ "sysinfo" }, /* 10 */
{ "cur_cpu" }, /* 11 */
{ NULL }
};
/*
* These definitions control the format of the per-process area
*/
static char header[] =
" PID X PRI NICE SIZE RES STATE TIME COMMAND";
/* 0123456 -- field to fill in starts at header+6 */
#define UNAME_START 6
#define Proc_format \
"%5d %-8.8s %3d %4d %5s %5dK %-5s %6s %.28s"
static int kmem, mem;
static double logcpu;
/* these are retrieved from the kernel in _init */
static int Hz;
static struct var v;
static ulong proca;
static load_avg cur_cpu;
/* these are for detailing the process states */
int process_states[8];
char *procstatenames[] = {
"", " sleeping, ", " running, ", " zombie, ", " stopped, ",
" created, ", " onproc, ", " xswapped, ",
NULL
};
/* process state names for the "STATE" column of the display */
char *state_abbrev[] = {
"", "sleep", "run", "zomb", "stop", "create", "onpr", "swap"
};
/* these are for calculating cpu state percentages */
#define CPUSTATES 5 /* definition from struct sysinfo */
static time_t cp_time[CPUSTATES];
static time_t cp_old[CPUSTATES];
static time_t cp_diff[CPUSTATES];
/* these are for detailing the cpu states */
int cpu_states[CPUSTATES];
char *cpustatenames[] = {
"idle", "user", "system", "wait", "sxbrk",
NULL
};
/* these are for detailing the memory statistics */
unsigned long memory_stats[6];
char *memorynames[] = {
"K phys, ", "K max, ", "K free, ", "K lck, ", "K unlck, ",
"K swap,", NULL
};
/* these are for keeping track of the proc array */
static int bytes;
static int pref_len;
static struct proc *pbase;
static struct proc **pref;
/* forward definitions for comparison functions */
int proc_compare();
int compare_cpu();
int compare_size();
int compare_time();
int (*proc_compares[])() = {
proc_compare, /* state, pri, time, size */
compare_cpu, /* cpu, time, state, pri, size */
compare_size, /* size, cpu, time, state pri */
compare_time, /* time, cpu, state, pri, size */
/* compare_res, /* res, cpu, time, state pri */
NULL };
/* these are names given to allowed sorting orders -- first is default */
char *ordernames[]={"state", "cpu", "size", "time", NULL}; /*hops*/
/* useful externals */
extern int errno;
extern char *sys_errlist[];
long time();
long percentages();
int
machine_init(struct statics *statics)
{
ulong ptr;
if ((kmem = open(KMEM, O_RDONLY)) == -1) {
perror(KMEM);
return -1;
}
if ((mem = open(MEM, O_RDONLY)) == -1) {
perror(MEM);
return -1;
}
/* get the list of symbols we want to access in the kernel */
if (nlist(VMUNIX, nlst) == -1) {
fprintf(stderr, "top: nlist failed\n");
return -1;
}
/* make sure they were all found */
/*ZZ
if (check_nlist(nlst) > 0)
return -1;
*/
proca = nlst[X_PROC].n_value;
/* get the symbol values out of kmem */
(void) getkval(nlst[X_CUR_CPU].n_value, (int *)(&cur_cpu), sizeof(cur_cpu),
nlst[X_CUR_CPU].n_name);
(void) getkval(nlst[X_HZ].n_value, (int *)(&Hz), sizeof(Hz),
nlst[X_HZ].n_name);
(void) getkval(nlst[X_V].n_value, (int *)(&v), sizeof(v),
nlst[X_V].n_name);
/* this is used in calculating WCPU -- calculate it ahead of time */
logcpu = log(fabs(loaddouble(cur_cpu)));
/* allocate space for proc structure array and array of pointers */
bytes = v.v_proc * sizeof(struct proc);
pbase = (struct proc *)malloc(bytes);
pref = (struct proc **)malloc(v.v_proc * sizeof(struct proc *));
if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL) {
fprintf(stderr, "top: cannot allocate sufficient memory\n");
return -1;
}
/* fill in the statics information */
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
statics->order_names = ordernames ; /* hops */
return 0;
}
char *
format_header(register char *uname_field)
{
register char *ptr;
ptr = header + UNAME_START;
while (*uname_field != '\0')
{
*ptr++ = *uname_field++;
}
return(header);
}
/* philiph - get run ave fm /dev/table info */
static int
tab_avenrun(double runave[])
{
FILE *fp = fopen("/dev/table/avenrun", "r");
int i;
for (i=0; i<3; i++)
runave[i] = -1.0;
if (fp==NULL)
return -1;
else
{
short rawave[3];
if (fread(rawave, sizeof(short), 3, fp) !=3 )
{
fclose(fp);
return -1;
}
else
{
int i;
for (i=0; i<3; i++)
runave[i] = (double) (rawave[i] / 256.0);
fclose(fp);
return 0;
}
}
}
struct pregion *
get_pregion(void *ptr)
{
static struct pregion preg;
long addr = (long)ptr;
(void) getkval(addr , (struct pregion *)(&preg),
sizeof(struct pregion), "pregion" );
return &preg;
}
struct region *
get_region(void *ptr)
{
static struct region reg;
long addr = (long)ptr;
(void) getkval( addr , (struct region *)(&reg),
sizeof(struct region), "region" );
return &reg;
}
static unsigned char shareable[RT_VM86 + 1]; /* 1 if shareable */
/*
* sum private referenced pages,
* treat shared pages depending on value of TREAT_SHARABLE_PAGES macro
* undefined : ignore (don't account for - default)
* 1: divide among # of references
* 2: accumulate as if private
*/
/* #define TREAT_SHAREABLE_PAGES 1 */
static long
proc_residentsize(struct proc *pp)
{
struct pregion *prp;
struct region *rp;
long rtot = 0;
long stot = 0;
long s1tot = 0;
/* init shareable region array */
if (shareable[RT_STEXT] == 0 )
shareable[RT_STEXT] = shareable[RT_SHMEM] = shareable[RT_MAPFILE] = 1
;
prp = pp->p_region;
if ( prp == 0)
return 0;
for( ; prp && (prp = get_pregion((void *)(prp))) &&
prp->p_reg && (rp = get_region((void*)(prp->p_reg)));
prp = prp->p_next)
{
if (shareable[rp->r_type] ) /* account for shared pgs separately
*/
{
stot += (rp->r_nvalid / rp->r_refcnt);
s1tot += rp->r_nvalid;
}
else
rtot += rp->r_nvalid;
}
#if defined(TREAT_SHAREABLE_PAGES) && TREAT_SHAREABLE_PAGES == 1
rtot += stot; /* accumulate and spread over users */
#endif
#if defined(TREAT_SHAREABLE_PAGES) && TREAT_SHAREABLE_PAGES == 1
rtot += s1tot; /* accumulate as if private */
#endif
return rtot * NBPP/1024; ;
}
void
get_system_info(struct system_info *si)
{
long total;
/* get process id of the last process */
(void) getkval(nlst[X_MPID].n_value, &(si->last_pid),
sizeof(si->last_pid),
nlst[X_MPID].n_name);
/* get the cp_time array */
(void) getkval(nlst[X_SYSINFO].n_value, (int *)cp_time, sizeof(cp_time),
nlst[X_SYSINFO].n_name);
/* convert cp_time counts to persentages */
total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
/* sum memory statistics */
(void) getkval(nlst[X_PHYSMEM].n_value, &memory_stats[0],
sizeof(memory_stats[0]), nlst[X_PHYSMEM].n_name);
(void) getkval(nlst[X_MAXMEM].n_value, &memory_stats[1],
sizeof(memory_stats[1]), nlst[X_MAXMEM].n_name);
(void) getkval(nlst[X_FREEMEM].n_value, &memory_stats[2],
sizeof(memory_stats[2]), nlst[X_FREEMEM].n_name);
(void) getkval(nlst[X_AVAILRMEM].n_value, &memory_stats[3],
sizeof(memory_stats[3]), nlst[X_AVAILRMEM].n_name);
(void) getkval(nlst[X_AVAILSMEM].n_value, &memory_stats[4],
sizeof(memory_stats[4]), nlst[X_AVAILSMEM].n_name);
(void) getkval(nlst[X_NSWAP].n_value, &memory_stats[5],
sizeof(memory_stats[5]), nlst[X_NSWAP].n_name);
memory_stats[0] = bytetok(ctob(memory_stats[0])); /* clicks -> bytes
*/
memory_stats[1] = bytetok(ctob(memory_stats[1])); /* clicks -> bytes
*/
memory_stats[2] = bytetok(ctob(memory_stats[2])); /* clicks -> bytes
*/
memory_stats[3] = bytetok(memory_stats[3] * NBPP); /* # bytes per page
*/
memory_stats[4] = bytetok(memory_stats[4] * NBPP); /* # bytes per page
*/
memory_stats[5] = bytetok(memory_stats[5] * NBPSCTR);/* # bytes per sector
*/
/* set arrays and strings */
/* Note: we keep memory_stats as an unsigned long to avoid sign
extension problems when shifting in bytetok. But the module
interface requires an array of signed longs. So we just cast
the pointer here and hope for the best. --wnl
*/
si->cpustates = cpu_states;
si->memory = (long *)memory_stats;
tab_avenrun(si->load_avg); /* philiph */
}
static struct handle handle;
caddr_t
get_process_info(struct system_info *si,
struct process_select *sel,
int idx)
{
register int i;
register int total_procs;
register int active_procs;
register struct proc **prefp;
register struct proc *pp;
/* set up flags of what we are going to select */
/* these are copied out of sel for simplicity */
int show_idle = sel->idle;
int show_system = sel->system;
int show_uid = sel->uid != -1;
int show_command = sel->command != NULL;
/* read all the proc structures in one fell swoop */
(void) getkval(proca, (int *)pbase, bytes, "proc array");
/* get a pointer to the states summary array */
si->procstates = process_states;
/* count up process states and get pointers to interesting procs */
total_procs = active_procs = 0;
memset((char *)process_states, 0, sizeof(process_states));
prefp = pref;
for (pp = pbase, i = 0; i < v.v_proc; pp++, i++) {
/*
* Place pointers to each valid proc structure in pref[].
* Process slots that are actually in use have a non-zero
* status field. Processes with SSYS set are system processes --
* these are ignored unless show_system is set.
*/
if (pp->p_stat && (show_system || ((pp->p_flag & SSYS) == 0))) {
total_procs++;
process_states[pp->p_stat]++;
if ((pp->p_stat != SZOMB) &&
(show_idle || (pp->p_stat == SRUN) || (pp->p_stat == SONPROC)) &&
(!show_uid || pp->p_uid == (ushort)sel->uid)) {
*prefp++ = pp;
active_procs++;
}
}
}
/* if requested, sort the "interesting" processes */
qsort((char *)pref, active_procs, sizeof(struct proc *), proc_compares[idx]);
/* remember active and total counts */
SI_TOTAL(si) = total_procs;
SI_ACTIVE(si) = pref_len = active_procs;
/* pass back a handle */
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char fmt[128]; /* static area where result is built */
char *
format_next_process(caddr_t handle, char *(*get_userid)())
{
register struct proc *pp;
register time_t cputime;
register double pct;
int where;
struct user u;
struct handle *hp;
char command[29];
char * process;
char * process2;
/* find and remember the next proc structure */
hp = (struct handle *)handle;
pp = *(hp->next_proc++);
hp->remaining--;
/* get the process's user struct and set cputime */
if ((where = sysi86(RDUBLK, pp->p_pid, &u, sizeof(struct user))) != -1)
where = (pp->p_flag & SLOAD) ? 0 : 1;
if (where == -1) {
strcpy(command, "<swapped>");
cputime = 0;
} else {
/* set u_comm for system processes */
if (u.u_comm[0] == '\0') {
if (pp->p_pid == 0)
strcpy(command, "Swapper");
else if (pp->p_pid == 2)
strcpy(command, "Pager");
else if (pp->p_pid == 3)
strcpy(command, "Sync'er");
} else if (where == 1) {
/* print swapped processes as <pname> */
register char *s1;
u.u_psargs[28 - 3] = '\0';
strcpy(command, "<");
strcat(command, strtok(u.u_psargs, " "));
strcat(command, ">");
while (s1 = (char *)strtok(NULL, " "))
strcat(command, s1);
} else {
sprintf(command, "%s", u.u_psargs);
}
cputime = u.u_utime + u.u_stime;
/* cputime = pp->p_utime + pp->p_stime; */
}
/* calculate the base for cpu percentages */
pct = pctdouble(pp->p_cpu);
/*
* psargs gives the absolute path of the process... strip it to only the
* command - [Changes by D. Currie & M. Muldner Aitt NS Canada]
*/
process = printable(command);
#if NO_COMMAND_ARGS
strtok(process," ");
#endif
process2 = strrchr(process,'/');
if(process2)
{
process = process2;
process++;
}
/* format this entry */
sprintf(fmt,
Proc_format,
pp->p_pid,
(*get_userid)(pp->p_uid),
pp->p_pri - PZERO,
pp->p_nice - NZERO,
format_k(PROCSIZE(&u)), /* same as pp->p_size * 4 */
proc_residentsize(pp),
state_abbrev[pp->p_stat],
format_time(cputime / Hz),
printable(process) );
return(fmt);
}
/*
* Checks the nlist to see if any symbols were not found.
* For every symbol that was not found, a one-line message
* is printed to stderr. The routine returns the number of
* symbols NOT founded.
*/
int check_nlist(register struct nlist *nlst)
{
register int i = 0;
while (nlst->n_name) {
if (nlst->n_type == 0) {
fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
i++;
}
nlst++;
}
return i;
}
/*
* 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).
*
*/
int
getkval(unsigned long offset, int *ptr, int size, char *refstr)
{
if (lseek(kmem, (long)offset, SEEK_SET) == -1) {
if (*refstr == '!')
refstr++;
fprintf(stderr, "%s: lseek to %s: %s\n", KMEM,
refstr, errmsg(errno));
quit(23);
}
if (read(kmem, (char *)ptr, size) == -1) {
if (*refstr == '!')
return 0;
fprintf(stderr, "%s: reading %s: %s\n", KMEM,
refstr, errmsg(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 */
5, /* sleep */
6, /* run */
2, /* zombie */
4, /* stop */
1, /* start */
7, /* onpr */
3, /* swap */
};
int
proc_compare(struct proc **pp1, struct proc **pp2)
{
register struct proc *p1;
register struct proc *p2;
register int result;
register ulong lresult;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
/* 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 time to break the tie */
if ((result = (p2->p_utime + p2->p_stime) -
(p1->p_utime + p1->p_stime)) == 0)
{
/* use resident set size (rssize) to break the tie */
if ((result = p2->p_size - p1->p_size) == 0)
{
result = 0;
}
}
}
}
return(result);
}
/* returns uid of owner of process pid */
int
proc_owner(int pid)
{
register int cnt;
register struct proc **prefp;
register struct proc *pp;
prefp = pref;
cnt = pref_len;
while (--cnt >= 0) {
if ((pp = *prefp++)->p_pid == (short)pid)
return ((int)pp->p_uid);
}
return(-1);
}
#if 0
int setpriority(int dummy, int who, int nicewal)
{
errno = 1;
return -1;
}
#endif
/* sigblock is not POSIX conformant */
sigset_t sigblock (sigset_t mask)
{
sigset_t oset;
sigemptyset(&oset);
sigprocmask(SIG_BLOCK, &mask, &oset);
return oset;
}
/* sigsetmask is not POSIX conformant */
sigsetmask(sigset_t mask)
{
sigset_t oset;
sigemptyset(&oset);
sigprocmask(SIG_SETMASK, &mask, &oset);
return oset;
}
/* ---------------- hops - comparison/ordering support ---------------- */
#define ORDERKEY_PCTCPU if (dresult = pctdouble(p2->p_cpu) - pctdouble(p1->p_cpu),\
(result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0)
#define ORDERKEY_MEMSIZE if ((result = (p2->p_size - p1->p_size)) == 0)
#define ORDERKEY_CPTIME if ((result = (long)(p2->p_utime + p2->p_stime) -\
(long)(p1->p_utime + p1->p_stime)) == 0)
#define ORDERKEY_STATE if ((result = (sorted_state[p2->p_stat] - \
sorted_state[p1->p_stat])) == 0)
#define ORDERKEY_PRIO if ((result = p2->p_pri - p1->p_pri) == 0)
int
compare_cpu ( struct proc **pp1, struct proc **pp2)
{
register struct proc *p1;
register struct proc *p2;
register int result;
double dresult;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
ORDERKEY_PCTCPU
ORDERKEY_CPTIME
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_MEMSIZE
;
return (result);
}
/* compare_size - the comparison function for sorting by process size */
int
compare_size ( struct proc **pp1, struct proc **pp2)
{
register struct proc *p1;
register struct proc *p2;
register int result;
double dresult;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
ORDERKEY_MEMSIZE
ORDERKEY_PCTCPU
ORDERKEY_CPTIME
ORDERKEY_STATE
ORDERKEY_PRIO
;
return (result);
}
/* compare_res - the comparison function for sorting by resident set size */
/* TODO: add shadow proc struct updating usr + sys times and RSS for use
* in comparison rtns, implement compare_res rtn as per compare_size()
*/
/* compare_time - the comparison function for sorting by total cpu time */
/* This is giving wrong results since its using the proc structure vals not
* the u struct vals we display above
* TODO: add shadow proc struct updating usr + sys times and RSS for use
* in comparison rtns
*/
int
compare_time ( struct proc **pp1, struct proc **pp2)
{
register struct proc *p1;
register struct proc *p2;
register int result;
double dresult;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
ORDERKEY_CPTIME
ORDERKEY_PCTCPU
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_MEMSIZE
;
return (result);
}

View File

@@ -0,0 +1,6 @@
.SH "SCO UNIX NOTES"
The SCO OpenServer5 port is a modification of the SCO Unix port
done by Mike Hopkirk (hops@sco.com).
OpenServer5 is a more normal Unix although the proc variables are still
somewhat funky. No easy access to RSS memory and CPUTICKS.
Added support for ordering and enabled use of setpriority().

979
external/bsd/top/dist/machine/m_sunos4.c vendored Normal file
View File

@@ -0,0 +1,979 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: any Sun running SunOS version 4.x
*
* DESCRIPTION:
* This is the machine-dependent module for SunOS 4.x.
* This makes top work on the following systems:
* SunOS 4.0
* SunOS 4.0.1
* SunOS 4.0.2 (including 386i architecture)
* SunOS 4.0.3
* SunOS 4.1
* SunOS 4.1.1
* SunOS 4.1.2 (including MP architectures)
* SunOS 4.1.3 (including MP architectures)
* SunOS 4.1.3_U1 (including MP architectures)
* SunOS 4.1.4 (including MP architectures)
* Solbourne OS/MP PRIOR to 4.1A
*
* LIBS: -lkvm
*
* CFLAGS: -DHAVE_GETOPT -DORDER
*
* AUTHOR: William LeFebvre <wnl@groupsys.com>
* Solbourne support by David MacKenzie <djm@eng.umd.edu>
*/
/*
* #ifdef MULTIPROCESSOR means Sun MP.
* #ifdef solbourne is for Solbourne.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/signal.h>
/* make sure param.h gets loaded with KERNEL defined to get PZERO & NZERO */
#define KERNEL
#include <sys/param.h>
#undef KERNEL
#include <stdio.h>
#include <kvm.h>
#include <nlist.h>
#include <math.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/dk.h>
#include <sys/vm.h>
#include <sys/file.h>
#include <sys/time.h>
#include <vm/page.h>
#ifdef solbourne
#include <sys/syscall.h>
#endif
/* Older versions of SunOS don't have a typedef for pid_t.
Hopefully this will catch all those cases without causing other problems.
*/
#ifndef __sys_stdtypes_h
typedef int pid_t;
#endif
#include "top.h"
#include "machine.h"
#include "utils.h"
/* declarations for load_avg */
#include "loadavg.h"
/* get_process_info passes back a handle. This is what it looks like: */
struct handle
{
struct proc **next_proc; /* points to next valid proc pointer */
int remaining; /* number of pointers remaining */
};
/* define what weighted cpu is. */
#define weighted_cpu(pct, pp) ((pp)->p_time == 0 ? 0.0 : \
((pct) / (1.0 - exp((pp)->p_time * logcpu))))
/* what we consider to be process size: */
#define PROCSIZE(pp) ((pp)->p_tsize + (pp)->p_dsize + (pp)->p_ssize)
/* definitions for indices in the nlist array */
#define X_AVENRUN 0
#define X_CCPU 1
#define X_MPID 2
#define X_NPROC 3
#define X_PROC 4
#define X_TOTAL 5
#define X_CP_TIME 6
#define X_PAGES 7
#define X_EPAGES 8
static struct nlist nlst[] = {
#ifdef i386
{ "avenrun" }, /* 0 */
{ "ccpu" }, /* 1 */
{ "mpid" }, /* 2 */
{ "nproc" }, /* 3 */
{ "proc" }, /* 4 */
{ "total" }, /* 5 */
{ "cp_time" }, /* 6 */
{ "pages" }, /* 7 */
{ "epages" }, /* 8 */
#else
{ "_avenrun" }, /* 0 */
{ "_ccpu" }, /* 1 */
{ "_mpid" }, /* 2 */
{ "_nproc" }, /* 3 */
{ "_proc" }, /* 4 */
{ "_total" }, /* 5 */
{ "_cp_time" }, /* 6 */
{ "_pages" }, /* 7 */
{ "_epages" }, /* 8 */
#ifdef MULTIPROCESSOR
{ "_ncpu" },
#define X_NCPU 9
{ "_xp_time" },
#define X_XP_TIME 10
#endif
#endif
{ 0 }
};
/*
* 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 %5s %5s %-5s %-6s %5.2f%% %5.2f%% %s"
/* process state names for the "STATE" column of the display */
/* the extra nulls in the string "run" are for adding a slash and
the processor number when needed */
char *state_abbrev[] =
{
"", "sleep", "WAIT", "run\0\0\0", "start", "zomb", "stop"
};
/* values that we stash away in _init and use in later routines */
static double logcpu;
kvm_t *kd;
/* these are retrieved from the kernel in _init */
static unsigned long proc;
static int nproc;
static load_avg ccpu;
static unsigned long pages;
static unsigned long epages;
static int ncpu = 0;
/* these are offsets obtained via nlist and used in the get_ functions */
static unsigned long mpid_offset;
static unsigned long avenrun_offset;
static unsigned long total_offset;
static unsigned long cp_time_offset;
#ifdef MULTIPROCESSOR
static unsigned long xp_time_offset;
#endif
/* these are for calculating cpu state percentages */
static long cp_time[CPUSTATES];
static long cp_old[CPUSTATES];
static long cp_diff[CPUSTATES];
#ifdef MULTIPROCESSOR
static long xp_time[NCPU][XPSTATES];
/* for now we only accumulate spin time, but extending this to pick up
other stuff in xp_time is trivial. */
static long xp_old[NCPU];
#endif
/* these are for detailing the process states */
int process_states[7];
char *procstatenames[] = {
"", " sleeping, ", " ABANDONED, ", " running, ", " starting, ",
" zombie, ", " stopped, ",
NULL
};
/* these are for detailing the cpu states */
int cpu_states[5];
char *cpustatenames[] = {
"user", "nice", "system", "idle",
#ifdef MULTIPROCESSOR
"spin",
#define XCP_SPIN 4
#endif
NULL
};
/* these are for detailing the memory statistics */
long memory_stats[4];
char *memorynames[] = {
"K available, ", "K in use, ", "K free, ", "K locked", NULL
};
/* these are names given to allowed sorting orders -- first is default */
char *ordernames[] =
{"cpu", "size", "res", NULL};
/* forward definitions for comparison functions */
int compare_cpu();
int compare_size();
int compare_res();
int (*proc_compares[])() = {
compare_cpu,
compare_size,
compare_res,
NULL };
/* these are for keeping track of the proc array */
static int bytes;
static int pref_len;
static struct proc *pbase;
static struct proc **pref;
/* these are for getting the memory statistics */
static struct page *physpage;
static int bytesize;
static int count;
static int pageshift; /* log base 2 of the pagesize */
/* define pagetok in terms of pageshift */
#define pagetok(size) ((size) << pageshift)
/* useful externals */
extern int errno;
extern char *sys_errlist[];
long lseek();
long time();
machine_init(statics)
struct statics *statics;
{
register int i;
register int pagesize;
/* initialize the kernel interface */
if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "top")) == NULL)
{
perror("kvm_open");
return(-1);
}
/* get the list of symbols we want to access in the kernel */
if ((i = kvm_nlist(kd, nlst)) < 0)
{
fprintf(stderr, "top: nlist failed\n");
return(-1);
}
#ifdef MULTIPROCESSOR
/* were ncpu and xp_time not found in the nlist? */
if (i > 0 && nlst[X_NCPU].n_type == 0 && nlst[X_XP_TIME].n_type == 0)
{
/* we were compiled on an MP system but we are not running on one */
/* so we will pretend this didn't happen and set ncpu = 1 */
i -= 2;
ncpu = 1;
}
#endif
#ifdef solbourne
{
unsigned int status, type;
/* Get the number of CPUs on this system. */
syscall(SYS_getcpustatus, &status, &ncpu, &type);
}
#endif
/* make sure they were all found */
if (i > 0 && check_nlist(nlst) > 0)
{
return(-1);
}
/* get the symbol values out of kmem */
(void) getkval(nlst[X_PROC].n_value, (int *)(&proc), sizeof(proc),
nlst[X_PROC].n_name);
(void) getkval(nlst[X_NPROC].n_value, &nproc, sizeof(nproc),
nlst[X_NPROC].n_name);
(void) getkval(nlst[X_CCPU].n_value, (int *)(&ccpu), sizeof(ccpu),
nlst[X_CCPU].n_name);
(void) getkval(nlst[X_PAGES].n_value, (int *)(&pages), sizeof(pages),
nlst[X_PAGES].n_name);
(void) getkval(nlst[X_EPAGES].n_value, (int *)(&epages), sizeof(epages),
nlst[X_EPAGES].n_name);
#ifdef MULTIPROCESSOR
if (ncpu == 0)
{
/* if ncpu > 0 then we are not really on an MP system */
(void) getkval(nlst[X_NCPU].n_value, (int *)(&ncpu), sizeof(ncpu),
nlst[X_NCPU].n_name);
}
#endif
/* stash away certain offsets for later use */
mpid_offset = nlst[X_MPID].n_value;
avenrun_offset = nlst[X_AVENRUN].n_value;
total_offset = nlst[X_TOTAL].n_value;
cp_time_offset = nlst[X_CP_TIME].n_value;
#ifdef MULTIPROCESSOR
xp_time_offset = nlst[X_XP_TIME].n_value;
#endif
/* this is used in calculating WCPU -- calculate it ahead of time */
logcpu = log(loaddouble(ccpu));
/* allocate space for proc structure array and array of pointers */
bytes = nproc * sizeof(struct proc);
pbase = (struct proc *)malloc(bytes);
pref = (struct proc **)malloc(nproc * sizeof(struct proc *));
/* Just in case ... */
if (pbase == (struct proc *)NULL || pref == (struct proc **)NULL)
{
fprintf(stderr, "top: can't allocate sufficient memory\n");
return(-1);
}
/* allocate a table to hold all the page structs */
bytesize = epages - pages;
count = bytesize / sizeof(struct page);
physpage = (struct page *)malloc(epages - pages);
if (physpage == NULL)
{
fprintf(stderr, "top: can't allocate sufficient memory\n");
return(-1);
}
/* get the page size with "getpagesize" and calculate pageshift from it */
pagesize = getpagesize();
pageshift = 0;
while (pagesize > 1)
{
pageshift++;
pagesize >>= 1;
}
/* we only need the amount of log(2)1024 for our conversion */
pageshift -= LOG1024;
#if defined(MULTIPROCESSOR) || defined(solbourne)
/* add a slash to the "run" state abbreviation */
if (ncpu > 1)
{
state_abbrev[SRUN][3] = '/';
}
#endif
/* fill in the statics information */
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
statics->order_names = ordernames;
/* all done! */
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);
}
void
get_system_info(si)
struct system_info *si;
{
load_avg avenrun[3];
long total;
#ifdef MULTIPROCESSOR
long half_total;
#endif
/* get the cp_time array */
(void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time),
"_cp_time");
#ifdef MULTIPROCESSOR
/* get the xp_time array as well */
if (ncpu > 1)
{
(void) getkval(xp_time_offset, (int *)xp_time, sizeof(xp_time),
"_xp_time");
}
#endif
/* get load average array */
(void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun),
"_avenrun");
/* get mpid -- process id of last process */
(void) getkval(mpid_offset, &(si->last_pid), sizeof(si->last_pid),
"_mpid");
/* get the array of physpage descriptors */
(void) getkval(pages, (int *)physpage, bytesize, "array _page");
/* convert load averages to doubles */
{
register int i;
register double *infoloadp;
register load_avg *sysloadp;
infoloadp = si->load_avg;
sysloadp = avenrun;
for (i = 0; i < 3; i++)
{
*infoloadp++ = loaddouble(*sysloadp++);
}
}
/* convert cp_time counts to percentages */
total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
#ifdef MULTIPROCESSOR
/* calculate spin time from all processors */
if (ncpu > 1)
{
register int c;
register int i;
register long sum;
register long change;
/* collect differences for each processor and add them */
sum = 0;
for (i = 0; i < ncpu; i++)
{
c = xp_time[i][XP_SPIN];
change = c - xp_old[i];
if (change < 0)
{
/* counter wrapped */
change = (long)((unsigned long)c -
(unsigned long)xp_old[i]);
}
sum += change;
xp_old[i] = c;
}
/*
* NOTE: I am assuming that the ticks found in xp_time are
* already included in the ticks accumulated in cp_time. To
* get an accurate reflection, therefore, we have to subtract
* the spin time from the system time and recompute those two
* percentages.
*/
half_total = total / 2l;
cp_diff[CP_SYS] -= sum;
cpu_states[CP_SYS] = (int)((cp_diff[CP_SYS] * 1000 + half_total) /
total);
cpu_states[XCP_SPIN] = (int)((sum * 1000 + half_total) / total);
}
#endif
/* sum memory statistics */
{
register struct page *pp;
register int cnt;
register int inuse;
register int free;
register int locked;
/* bop thru the array counting page types */
pp = physpage;
inuse = free = locked = 0;
for (cnt = count; --cnt >= 0; pp++)
{
if (pp->p_free)
free++;
else if (pp->p_lock || pp->p_keepcnt > 0)
locked++;
else
inuse++;
}
/* convert memory stats to Kbytes */
memory_stats[0] = pagetok(inuse + free);
memory_stats[1] = pagetok(inuse);
memory_stats[2] = pagetok(free);
memory_stats[3] = pagetok(locked);
}
/* set arrays and strings */
si->cpustates = cpu_states;
si->memory = memory_stats;
}
static struct handle handle;
caddr_t get_process_info(si, sel, compare_index)
struct system_info *si;
struct process_select *sel;
int compare_index;
{
register int i;
register int total_procs;
register int active_procs;
register struct proc **prefp;
register struct proc *pp;
/* these are copied out of sel for speed */
int show_idle;
int show_system;
int show_uid;
int show_command;
/* read all the proc structures in one fell swoop */
(void) getkval(proc, (int *)pbase, bytes, "proc array");
/* get a pointer to the states summary array */
si->procstates = process_states;
/* set up flags which define what we are going to select */
show_idle = sel->idle;
show_system = sel->system;
show_uid = sel->uid != -1;
show_command = sel->command != NULL;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
active_procs = 0;
bzero((char *)process_states, sizeof(process_states));
prefp = pref;
for (pp = pbase, i = 0; i < nproc; pp++, i++)
{
/*
* Place pointers to each valid proc structure in pref[].
* Process slots that are actually in use have a non-zero
* status field. Processes with SSYS set are system
* processes---these get ignored unless show_sysprocs is set.
*/
if (pp->p_stat != 0 &&
(show_system || ((pp->p_flag & SSYS) == 0)))
{
total_procs++;
process_states[pp->p_stat]++;
if ((pp->p_stat != SZOMB) &&
(show_idle || (pp->p_pctcpu != 0) || (pp->p_stat == SRUN)) &&
(!show_uid || pp->p_uid == (uid_t)sel->uid))
{
*prefp++ = pp;
active_procs++;
}
}
}
/* if requested, sort the "interesting" processes */
qsort((char *)pref, active_procs, sizeof(struct proc *),
proc_compares[compare_index]);
/* remember active and total counts */
si->p_total = total_procs;
si->p_active = pref_len = active_procs;
/* pass back a handle */
handle.next_proc = pref;
handle.remaining = active_procs;
return((caddr_t)&handle);
}
char fmt[MAX_COLS]; /* static area where result is built */
char *format_next_process(handle, get_userid)
caddr_t handle;
char *(*get_userid)();
{
register struct proc *pp;
register long cputime;
register double pct;
struct user u;
struct handle *hp;
/* find and remember the next proc structure */
hp = (struct handle *)handle;
pp = *(hp->next_proc++);
hp->remaining--;
/* get the process's user struct and set cputime */
if (getu(pp, &u) == -1)
{
(void) strcpy(u.u_comm, "<swapped>");
cputime = 0;
}
else
{
/* set u_comm for system processes */
if (u.u_comm[0] == '\0')
{
if (pp->p_pid == 0)
{
(void) strcpy(u.u_comm, "Swapper");
}
else if (pp->p_pid == 2)
{
(void) strcpy(u.u_comm, "Pager");
}
}
cputime = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec;
}
/* calculate the base for cpu percentages */
pct = pctdouble(pp->p_pctcpu);
#ifdef MULTIPROCESSOR
/*
* If there is more than one cpu then add the processor number to
* the "run/" string. Note that this will only show up if the
* process is in the run state. Also note: when they
* start making Suns with more than 9 processors this will break
* since the string will then be more than 5 characters.
*/
if (ncpu > 1)
{
state_abbrev[SRUN][4] = (pp->p_cpuid & 0xf) + '0';
}
#endif
#ifdef solbourne
if (ncpu > 1)
{
state_abbrev[SRUN][4] = (pp->p_lastcpu) + '0';
}
#endif
/* format this entry */
sprintf(fmt,
Proc_format,
pp->p_pid,
(*get_userid)(pp->p_uid),
pp->p_pri - PZERO,
pp->p_nice - NZERO,
format_k(pagetok(PROCSIZE(pp))),
format_k(pagetok(pp->p_rssize)),
state_abbrev[pp->p_stat],
format_time(cputime),
100.0 * weighted_cpu(pct, pp),
100.0 * pct,
printable(u.u_comm));
/* return the result */
return(fmt);
}
/*
* getu(p, u) - get the user structure for the process whose proc structure
* is pointed to by p. The user structure is put in the buffer pointed
* to by u. Return 0 if successful, -1 on failure (such as the process
* being swapped out).
*/
getu(p, u)
register struct proc *p;
struct user *u;
{
register struct user *lu;
lu = kvm_getu(kd, p);
if (lu == NULL)
{
return(-1);
}
else
{
*u = *lu;
return(0);
}
}
/*
* check_nlist(nlst) - checks the nlist to see if any symbols were not
* found. For every symbol that was not found, a one-line
* message is printed to stderr. The routine returns the
* number of symbols NOT found.
*/
int check_nlist(nlst)
register struct nlist *nlst;
{
register int i;
/* check to see if we got ALL the symbols we requested */
/* this will write one line to stderr for every symbol not found */
i = 0;
while (nlst->n_name != NULL)
{
#ifdef i386
if (nlst->n_value == 0)
#else
if (nlst->n_type == 0)
#endif
{
/* this one wasn't found */
fprintf(stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
i = 1;
}
nlst++;
}
return(i);
}
/*
* 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);
/*NOTREACHED*/
}
}
return(1);
}
/* comparison routines for qsort */
/*
* There are currently four possible comparison routines. main selects
* one of these by indexing in to the array proc_compares.
*
* Possible keys are defined as macros below. Currently these keys are
* defined: percent cpu, cpu ticks, process 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.
*/
/* First, the possible comparison keys. These are defined in such a way
that they can be merely listed in the source code to define the actual
desired ordering.
*/
#define ORDERKEY_PCTCPU if (lresult = p2->p_pctcpu - p1->p_pctcpu,\
(result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
#define ORDERKEY_CPTICKS if ((result = p2->p_cpticks - p1->p_cpticks) == 0)
#define ORDERKEY_STATE if ((result = sorted_state[p2->p_stat] - \
sorted_state[p1->p_stat]) == 0)
#define ORDERKEY_PRIO if ((result = p2->p_pri - p1->p_pri) == 0)
#define ORDERKEY_RSSIZE if ((result = p2->p_rssize - p1->p_rssize) == 0)
#define ORDERKEY_MEM if ((result = PROCSIZE(p2) - PROCSIZE(p1)) == 0)
/* Now the array that maps process state to a weight */
static unsigned char sorted_state[] =
{
0, /* not used */
3, /* sleep */
1, /* ABANDONED (WAIT) */
6, /* run */
5, /* start */
2, /* zombie */
4 /* stop */
};
/* compare_cpu - the comparison function for sorting by cpu percentage */
compare_cpu(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;
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
ORDERKEY_RSSIZE
ORDERKEY_MEM
;
return(result);
}
/* compare_size - the comparison function for sorting by total memory usage */
compare_size(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;
ORDERKEY_MEM
ORDERKEY_RSSIZE
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
;
return(result);
}
/* compare_res - the comparison function for sorting by resident set size */
compare_res(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;
ORDERKEY_RSSIZE
ORDERKEY_MEM
ORDERKEY_PCTCPU
ORDERKEY_CPTICKS
ORDERKEY_STATE
ORDERKEY_PRIO
;
return(result);
}
/*
* proc_owner(pid) - returns the uid that owns process "pid", or -1 if
* the process does not exist.
* It is EXTREMLY IMPORTANT that this function work correctly.
* If top runs setuid root (as in SVR4), then this function
* is the only thing that stands in the way of a serious
* security problem. It validates requests for the "kill"
* and "renice" commands.
*/
int proc_owner(pid)
int pid;
{
register int cnt;
register struct proc **prefp;
register struct proc *pp;
prefp = pref;
cnt = pref_len;
while (--cnt >= 0)
{
if ((pp = *prefp++)->p_pid == (pid_t)pid)
{
return((int)pp->p_uid);
}
}
return(-1);
}

View File

@@ -0,0 +1,23 @@
.SH "SUNOS 4 DIFFERENCES"
On multiprocessor machines, the amount of time the processors spend in
a spin lock is displayed along with the other processor state
percentages. The percentages shown for processor states are averages
across all processors. A process in run state also has its current
processor displayed in the STATE column, for example "run/2" indicates
running on processor 2. There is an extra column in the process
display indicating which processor each running process is assigned
to. Information about physical memory is displayed on the memory
status line, but information about virtual memory is not available.
Due to incompatabilities in kernel data structures, a top executable
compiled on a Sun 4 multiprocessor architecture machine (sun4m) will
not run correctly on a uniprocessor architecture machine (sun4), and
vice versa. You will have to compile and maintain separate executables
for these architectures. Yeah, I don't like it either.
Some processes may show up with a resident set size (RES column) larger
than total virtual memory size (SIZE column). This seems odd at first,
but is a consequence of shared libraries: shared memory is counted as
resident but is not counted in total size.
The SunOS 4 port was written by William LeFebvre.

2270
external/bsd/top/dist/machine/m_sunos5.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
.SH "SUNOS 5 NOTES"
CPU percentage is calculated as a fraction of total available computing
resources. Hence on a multiprocessor machine a single threaded process
can never consume cpu time in excess of 1 divided by the number of processors.
For example, on a 4 processor machine, a single threaded process will
never show a cpu percentage higher than 25%. The CPU percentage column
will always total approximately 100, regardless of the number of processors.
The kernel summary line shows the following information, all displayed
as a per-second rate:
.TP 9
.B ctxsw
Context switches.
.TP 9
.B trap
Number of traps.
.TP 9
.B intr
Number of interrupts.
.TP 9
.B syscall
Number of system calls.
.TP 9
.B fork
Number of forks and vforks.
.TP 9
.B flt
Number of page faults.
.TP 9
.B pgin
Number of kilobytes paged in to physical memory.
.TP 9
.B pgout
Number of kilobytes paged out from physical memory.
.PP
The memory summary line displays the following:
.TP 14
.B "phys mem"
Total amount of physical memory that can be allocated for use by processes
(it does not include memory reserved for the kernel's use).
.TP 14
.B "free mem"
The amount of unallocated physical memory.
.TP 14
.B "total swap"
The total amount of swap area allocated on disk.
.TP 14
.B "free swap"
The amount of swap area on disk that is still available.
.PP
Unlike previous versions of
.IR top ,
the swap figures will differ from the summary output of
.IR swap (1M)
since the latter includes physical memory as well.
.PP
The column
.B NLWP
indicates the number of lightweight processes in a process.
This usually corresponds to the number of threads in that process.
.PP
The display of individual threads can be toggled with the
synonymous commands
.B t
and
.BR H.
Information about state, priority, CPU time and percent CPU are
shown for each individual thread. Other information is identical
for all threads in the same process. In this display the column
.B LWP
replaces
.B NLWP
and shows the lightweight process id. The
column names
.B LWP
and
.B NLWP
are consistent with
.IR ps (1).
.PP
In BSD Unix, process priority was represented internally as a signed
offset from a zero value with an unsigned value. The "zero" value
was usually something like 20, allowing for a range of priorities
from -20 to 20. As implemented on SunOS 5, older versions of top
continued to interpret process priority in this manner, even though
it was no longer correct. Starting with top version 3.5, this was
changed to agree with the rest of the system.
.PP
Long options are not currently available in Solaris.
.PP
The SunOS 5 (Solaris 2) port was originally written by Torsten Kasch,
<torsten@techfak.uni-bielefeld.de>. Many contributions have been
provided by Casper Dik <Casper.Dik@sun.com>.
Support for multi-cpu, calculation of CPU% and memory stats provided by
Robert Boucher <boucher@sofkin.ca>, Marc Cohen <marc@aai.com>,
Charles Hedrick <hedrick@geneva.rutgers.edu>, and
William L. Jones <jones@chpc>.

757
external/bsd/top/dist/machine/m_svr4.c vendored Normal file
View File

@@ -0,0 +1,757 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* top - a top users display for Unix
*
* SYNOPSIS: Intel based System V Release 4
*
* DESCRIPTION:
* System V release 4.0.x for i486
* System V release 4 for Okidata M88100
* System V release 4 for NCR 3000 series OS Rel 1.00 to 2.02
* System V release 4 for NCR 3000 series OS Rel 02.03.00 and above
* and probably other svr4 ports
*
* LIBS: -lelf
*
* AUTHORS: Andrew Herbert <andrew@werple.apana.org.au>
* Robert Boucher <boucher@sofkin.ca>
* Ported to System 3000 Release 2.03 by:
* Jeff Janvrin <jeff.janvrinColumbiaSC.NCR.COM>
*/
#include "top.h"
#include "machine.h"
#include "utils.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <nlist.h>
#include <string.h>
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/procfs.h>
#include <sys/sysinfo.h>
#include <sys/sysmacros.h>
#include <sys/vmmeter.h>
#include <vm/anon.h>
#include <sys/priocntl.h>
#include <sys/rtpriocntl.h>
#include <sys/tspriocntl.h>
#include <sys/procset.h>
#include <sys/var.h>
#define UNIX "/stand/unix"
#define KMEM "/dev/kmem"
#define PROCFS "/proc"
#define CPUSTATES 5
#ifndef PRIO_MAX
#define PRIO_MAX 20
#endif
#ifndef PRIO_MIN
#define PRIO_MIN -20
#endif
#ifndef FSCALE
#define FSHIFT 8 /* bits to right of fixed binary point */
#define FSCALE (1<<FSHIFT)
#endif
#define loaddouble(x) ((double)(x) / FSCALE)
#define percent_cpu(x) ((double)(x)->pr_cpu / FSCALE)
#define weighted_cpu(pct, pp) ( ((pp)->pr_time.tv_sec) == 0 ? 0.0 : \
((pp)->pr_cpu) / ((pp)->pr_time.tv_sec) )
#define pagetok(size) ctob(size) >> LOG1024
/* definitions for the index in the nlist array */
#define X_AVENRUN 0
#define X_MPID 1
#define X_V 2
#define X_NPROC 3
#define X_ANONINFO 4
#define X_TOTAL 5
#define X_SYSINFO 6
static struct nlist nlst[] =
{
{"avenrun"}, /* 0 */
{"mpid"}, /* 1 */
{"v"}, /* 2 */
{"nproc"}, /* 3 */
{"anoninfo"}, /* 4 */
{"total"}, /* 5 */
{"sysinfo"}, /* 6 */
{NULL}
};
static unsigned long avenrun_offset;
static unsigned long mpid_offset;
static unsigned long nproc_offset;
static unsigned long anoninfo_offset;
static unsigned long total_offset;
static unsigned long sysinfo_offset;
/* get_process_info passes back a handle. This is what it looks like: */
struct handle
{
struct prpsinfo **next_proc;/* points to next valid proc pointer */
int remaining; /* number of pointers remaining */
};
/*
* 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 %5s %5s %-5s %6s %3d.0%% %5.2f%% %.16s"
char *state_abbrev[] =
{"", "sleep", "run", "zombie", "stop", "start", "cpu", "swap"};
int process_states[8];
char *procstatenames[] =
{
"", " sleeping, ", " running, ", " zombie, ", " stopped, ",
" starting, ", " on cpu, ", " swapped, ",
NULL
};
int cpu_states[CPUSTATES];
char *cpustatenames[] =
{"idle", "user", "kernel", "wait", "swap", NULL};
/* these are for detailing the memory statistics */
long memory_stats[5];
char *memorynames[] =
{"K real, ", "K active, ", "K free, ", "K swap, ", "K free swap", NULL};
/* forward reference for qsort comparison function */
int proc_compare();
static int kmem = -1;
static int nproc;
static int bytes;
static int use_stats = 0;
static struct prpsinfo *pbase;
static struct prpsinfo **pref;
static DIR *proc_dir;
/* useful externals */
extern int errno;
extern char *sys_errlist[];
extern char *myname;
extern int check_nlist ();
extern int getkval ();
extern void perror ();
extern void getptable ();
extern void quit ();
extern int nlist ();
int
machine_init (struct statics *statics)
{
static struct var v;
/* fill in the statics information */
statics->procstate_names = procstatenames;
statics->cpustate_names = cpustatenames;
statics->memory_names = memorynames;
/* get the list of symbols we want to access in the kernel */
if (nlist (UNIX, nlst))
{
(void) fprintf (stderr, "Unable to nlist %s\n", UNIX);
return (-1);
}
/* make sure they were all found */
if (check_nlist (nlst) > 0)
return (-1);
/* open kernel memory */
if ((kmem = open (KMEM, O_RDONLY)) == -1)
{
perror (KMEM);
return (-1);
}
/* get the symbol values out of kmem */
/* NPROC Tuning parameter for max number of processes */
(void) getkval (nlst[X_V].n_value, &v, sizeof (struct var), nlst[X_V].n_name);
nproc = v.v_proc;
/* stash away certain offsets for later use */
mpid_offset = nlst[X_MPID].n_value;
nproc_offset = nlst[X_NPROC].n_value;
avenrun_offset = nlst[X_AVENRUN].n_value;
anoninfo_offset = nlst[X_ANONINFO].n_value;
total_offset = nlst[X_TOTAL].n_value;
/* JJ this may need to be changed */
sysinfo_offset = nlst[X_SYSINFO].n_value;
/* allocate space for proc structure array and array of pointers */
bytes = nproc * sizeof (struct prpsinfo);
pbase = (struct prpsinfo *) malloc (bytes);
pref = (struct prpsinfo **) malloc (nproc * sizeof (struct prpsinfo *));
/* Just in case ... */
if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL)
{
(void) fprintf (stderr, "%s: can't allocate sufficient memory\n", myname);
return (-1);
}
if (!(proc_dir = opendir (PROCFS)))
{
(void) fprintf (stderr, "Unable to open %s\n", PROCFS);
return (-1);
}
if (chdir (PROCFS))
{ /* handy for later on when we're reading it */
(void) fprintf (stderr, "Unable to chdir to %s\n", PROCFS);
return (-1);
}
/* all done! */
return (0);
}
char *
format_header (char *uname_field)
{
register char *ptr;
ptr = header + UNAME_START;
while (*uname_field != '\0')
*ptr++ = *uname_field++;
return (header);
}
void
get_system_info (struct system_info *si)
{
long avenrun[3];
struct sysinfo sysinfo;
static struct sysinfo *mpinfo = NULL; /* array, per-processor sysinfo structures. */
struct vmtotal total;
struct anoninfo anoninfo;
static long cp_old[CPUSTATES];
static long cp_diff[CPUSTATES]; /* for cpu state percentages */
static int num_cpus;
static int fd_cpu = 0;
register int i;
if ( use_stats == 1) {
if ( fd_cpu == 0 ) {
if ((fd_cpu = open("/stats/cpuinfo", O_RDONLY)) == -1) {
(void) fprintf (stderr, "%s: Open of /stats/cpuinfo failed\n", myname);
quit(2);
}
if (read(fd_cpu, &num_cpus, sizeof(int)) != sizeof(int)) {
(void) fprintf (stderr, "%s: Read of /stats/cpuinfo failed\n", myname);
quit(2);
}
close(fd_cpu);
}
if (mpinfo == NULL) {
mpinfo = (struct sysinfo *)calloc(num_cpus, sizeof(mpinfo[0]));
if (mpinfo == NULL) {
(void) fprintf (stderr, "%s: can't allocate space for per-processor sysinfos\n", myname);
quit(12);
}
}
/* Read the per cpu sysinfo structures into mpinfo struct. */
read_sysinfos(num_cpus, mpinfo);
/* Add up all of the percpu sysinfos to get global sysinfo */
sysinfo_data(num_cpus, &sysinfo, mpinfo);
} else {
(void) getkval (sysinfo_offset, &sysinfo, sizeof (struct sysinfo), "sysinfo");
}
/* convert cp_time counts to percentages */
(void) percentages (CPUSTATES, cpu_states, sysinfo.cpu, cp_old, cp_diff);
/* get mpid -- process id of last process */
(void) getkval (mpid_offset, &(si->last_pid), sizeof (si->last_pid),
"mpid");
/* get load average array */
(void) getkval (avenrun_offset, (int *) avenrun, sizeof (avenrun), "avenrun");
/* convert load averages to doubles */
for (i = 0; i < 3; i++)
si->load_avg[i] = loaddouble (avenrun[i]);
/* get total -- systemwide main memory usage structure */
(void) getkval (total_offset, (int *) (&total), sizeof (total), "total");
/* convert memory stats to Kbytes */
memory_stats[0] = pagetok (total.t_rm);
memory_stats[1] = pagetok (total.t_arm);
memory_stats[2] = pagetok (total.t_free);
(void) getkval (anoninfo_offset, (int *) (&anoninfo), sizeof (anoninfo),
"anoninfo");
memory_stats[3] = pagetok (anoninfo.ani_max - anoninfo.ani_free);
memory_stats[4] = pagetok (anoninfo.ani_max - anoninfo.ani_resv);
/* set arrays and strings */
si->cpustates = cpu_states;
si->memory = memory_stats;
}
static struct handle handle;
caddr_t
get_process_info (
struct system_info *si,
struct process_select *sel,
int x)
{
register int i;
register int total_procs;
register int active_procs;
register struct prpsinfo **prefp;
register struct prpsinfo *pp;
/* these are copied out of sel for speed */
int show_idle;
int show_system;
int show_uid;
/* Get current number of processes */
(void) getkval (nproc_offset, (int *) (&nproc), sizeof (nproc), "nproc");
/* read all the proc structures */
getptable (pbase);
/* get a pointer to the states summary array */
si->procstates = process_states;
/* set up flags which define what we are going to select */
show_idle = sel->idle;
show_system = sel->system;
show_uid = sel->uid != -1;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
active_procs = 0;
(void) memset (process_states, 0, sizeof (process_states));
prefp = pref;
for (pp = pbase, i = 0; i < nproc; pp++, i++)
{
/*
* Place pointers to each valid proc structure in pref[].
* Process slots that are actually in use have a non-zero
* status field. Processes with SSYS set are system
* processes---these get ignored unless show_sysprocs is set.
*/
if (pp->pr_state != 0 &&
(show_system || ((pp->pr_flag & SSYS) == 0)))
{
total_procs++;
process_states[pp->pr_state]++;
if ((!pp->pr_zomb) &&
(show_idle || (pp->pr_state == SRUN) || (pp->pr_state == SONPROC)) &&
(!show_uid || pp->pr_uid == (uid_t) sel->uid))
{
*prefp++ = pp;
active_procs++;
}
}
}
/* if requested, sort the "interesting" processes */
qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *), proc_compare);
/* remember active and total counts */
si->p_total = total_procs;
si->p_active = active_procs;
/* pass back a handle */
handle.next_proc = pref;
handle.remaining = active_procs;
return ((caddr_t) & handle);
}
char fmt[MAX_COLS]; /* static area where result is built */
char *
format_next_process (
caddr_t handle,
char *(*get_userid) ())
{
register struct prpsinfo *pp;
struct handle *hp;
register long cputime;
register double pctcpu;
/* find and remember the next proc structure */
hp = (struct handle *) handle;
pp = *(hp->next_proc++);
hp->remaining--;
/* get the cpu usage and calculate the cpu percentages */
cputime = pp->pr_time.tv_sec;
pctcpu = percent_cpu (pp);
/* format this entry */
(void) sprintf (fmt,
Proc_format,
pp->pr_pid,
(*get_userid) (pp->pr_uid),
pp->pr_pri - PZERO,
pp->pr_nice - NZERO,
format_k(pagetok (pp->pr_size)),
format_k(pagetok (pp->pr_rssize)),
state_abbrev[pp->pr_state],
format_time(cputime),
(pp->pr_cpu & 0377),
100.0 * pctcpu,
printable(pp->pr_fname));
/* return the result */
return (fmt);
}
/*
* check_nlist(nlst) - checks the nlist to see if any symbols were not
* found. For every symbol that was not found, a one-line
* message is printed to stderr. The routine returns the
* number of symbols NOT found.
*/
int
check_nlist (register struct nlist *nlst)
{
register int i;
struct stat stat_buf;
/* check to see if we got ALL the symbols we requested */
/* this will write one line to stderr for every symbol not found */
i = 0;
while (nlst->n_name != NULL)
{
if (nlst->n_type == 0)
{
if (strcmp("sysinfo", nlst->n_name) == 0)
{
/* check to see if /stats file system exists. If so, */
/* ignore error. */
if ( !((stat("/stats/sysinfo", &stat_buf) == 0) &&
(stat_buf.st_mode & S_IFREG)) )
{
(void) fprintf (stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
i = 1;
} else {
use_stats = 1;
}
} else {
/* this one wasn't found */
(void) fprintf (stderr, "kernel: no symbol named `%s'\n", nlst->n_name);
i = 1;
}
}
nlst++;
}
return (i);
}
/*
* 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).
*
*/
int
getkval (
unsigned long offset,
int *ptr,
int size,
char *refstr)
{
#ifdef MIPS
if (lseek (kmem, (long) (offset & 0x7fffffff), 0) == -1)
#else
if (lseek (kmem, (long) offset, 0) == -1)
#endif
{
if (*refstr == '!')
refstr++;
(void) fprintf (stderr, "%s: lseek to %s: %s\n",
myname, refstr, sys_errlist[errno]);
quit (22);
}
if (read (kmem, (char *) ptr, size) == -1)
if (*refstr == '!')
/* we lost the race with the kernel, process isn't in memory */
return (0);
else
{
(void) fprintf (stderr, "%s: reading %s: %s\n",
myname, refstr, sys_errlist[errno]);
quit (23);
}
return (1);
}
/* comparison routine for qsort */
/*
* 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.
*/
unsigned char sorted_state[] =
{
0, /* not used */
3, /* sleep */
6, /* run */
2, /* zombie */
4, /* stop */
5, /* start */
7, /* run on a processor */
1 /* being swapped (WAIT) */
};
int
proc_compare (
struct prpsinfo **pp1,
struct prpsinfo **pp2)
{
register struct prpsinfo *p1;
register struct prpsinfo *p2;
register long result;
/* remove one level of indirection */
p1 = *pp1;
p2 = *pp2;
/* compare percent cpu (pctcpu) */
if ((result = (long) (p2->pr_cpu - p1->pr_cpu)) == 0)
{
/* use cpticks to break the tie */
if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
{
/* use process state to break the tie */
if ((result = (long) (sorted_state[p2->pr_state] -
sorted_state[p1->pr_state])) == 0)
{
/* use priority to break the tie */
if ((result = p2->pr_oldpri - p1->pr_oldpri) == 0)
{
/* use resident set size (rssize) to break the tie */
if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
{
/* use total memory to break the tie */
result = (p2->pr_size - p1->pr_size);
}
}
}
}
}
return (result);
}
/*
get process table
*/
void
getptable (struct prpsinfo *baseptr)
{
struct prpsinfo *currproc; /* pointer to current proc structure */
int numprocs = 0;
struct dirent *direntp;
for (rewinddir (proc_dir); direntp = readdir (proc_dir);)
{
int fd;
if ((fd = open (direntp->d_name, O_RDONLY)) < 0)
continue;
currproc = &baseptr[numprocs];
if (ioctl (fd, PIOCPSINFO, currproc) < 0)
{
(void) close (fd);
continue;
}
numprocs++;
(void) close (fd);
}
if (nproc != numprocs)
nproc = numprocs;
}
/* return the owner of the specified process, for use in commands.c as we're
running setuid root */
int
proc_owner (int pid)
{
register struct prpsinfo *p;
int i;
for (i = 0, p = pbase; i < nproc; i++, p++)
if (p->pr_pid == (pid_t)pid)
return (p->pr_uid);
return (-1);
}
#ifndef HAVE_SETPRIORITY
int
setpriority (int dummy, int who, int niceval)
{
int scale;
int prio;
pcinfo_t pcinfo;
pcparms_t pcparms;
tsparms_t *tsparms;
strcpy (pcinfo.pc_clname, "TS");
if (priocntl (0, 0, PC_GETCID, (caddr_t) & pcinfo) == -1)
return (-1);
prio = niceval;
if (prio > PRIO_MAX)
prio = PRIO_MAX;
else if (prio < PRIO_MIN)
prio = PRIO_MIN;
tsparms = (tsparms_t *) pcparms.pc_clparms;
scale = ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri;
tsparms->ts_uprilim = tsparms->ts_upri = -(scale * prio) / 20;
pcparms.pc_cid = pcinfo.pc_cid;
if (priocntl (P_PID, who, PC_SETPARMS, (caddr_t) & pcparms) == -1)
return (-1);
return (0);
}
#endif
/****************************************************************
* read_sysinfos() - *
* Read all of the CPU specific sysinfo sturctures in from *
* the /stats file system. *
****************************************************************/
read_sysinfos(num_cpus, buf)
int num_cpus;
struct sysinfo *buf;
{
static int fd1=0; /* file descriptor for /stats/sysinfo */
int read_sz;
/* Open /stats/sysinfo one time only and leave it open */
if (fd1==0) {
if ((fd1 = open("/stats/sysinfo", O_RDONLY)) == -1)
(void) fprintf (stderr, "%s: Open of /stats/sysinfo failed\n", myname);
}
/* reset the read pointer to the beginning of the file */
if (lseek(fd1, 0L, SEEK_SET) == -1)
(void) fprintf (stderr, "%s: lseek to beginning of /stats/sysinfo failed\n", myname);
read_sz = num_cpus * sizeof(buf[0]);
if (read(fd1, buf, read_sz) != read_sz)
(void) fprintf (stderr, "%s: Read of /stats/sysinfo failed\n", myname);
}
/****************************************************************
* sysinfo_data() - *
* Add up all of the CPU specific sysinfo sturctures to *
* make the GLOBAL sysinfo. *
****************************************************************/
sysinfo_data(num_cpus, global_si, percpu_si)
int num_cpus;
struct sysinfo *global_si;
struct sysinfo *percpu_si;
{
struct sysinfo *percpu_p;
int cpu, i, *global, *src;
/* null out the global statistics from last sample */
memset(global_si, 0, sizeof(struct sysinfo));
percpu_p = (struct sysinfo *)percpu_si;
for(cpu = 0; cpu < num_cpus; cpu++) {
global = (int *)global_si;
src = (int *)percpu_p;
/* assume sysinfo ends on an int boundary */
/* Currently, all of the struct sysinfo members are the same
* size as an int. If that changes, we may not be able to
* do this. But this should be safe.
*/
for(i=0; i<sizeof(struct sysinfo)/sizeof(int); i++) {
*global++ += *src++;
}
percpu_p++;
}
}

View File

@@ -0,0 +1,6 @@
.SH "SVR4 CREDITS"
The SVR4 port was initially written by Andrew Herbert. He was guided by a SVR4
port of top version 2.1 which was done by Andy Crump (andyc@bucky.intel.com).
Robert Boucher (boucher@sofkin.ca) adapted it to top version 3.1.
Ported to System 3000 Release 2.03 by
Jeff Janvrin (jeff.janvrinColumbiaSC.NCR.COM)

1448
external/bsd/top/dist/machine/m_svr5.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
.SH "SVR5 CREDITS"
The SVR5 port was generated by Mike Hopkirk from the SVR42 port by David Cutter
with lots of help from Kurt Gollhardt and Doug Souders

44
external/bsd/top/dist/message.h vendored Normal file
View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* interface declaration for display messages */
/* This is a small subset of the interface from display.c that
just contains the calls for displaying messages. Do not include
this and display.h at the same time. */
#ifndef _MESSAGE_H
#define _MESSAGE_H
void error_message(const char *msgfmt, ...);
void clear_message(void);
#endif /* _MESSAGE_H_ */

152
external/bsd/top/dist/os.h vendored Normal file
View File

@@ -0,0 +1,152 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#ifdef __NetBSD__
#include <util.h>
#else
#define emalloc malloc
#define estrdup strdup
#define ecalloc calloc
#define erealloc realloc
#endif
#if STDC_HEADERS
#include <string.h>
#include <stdlib.h>
#define setbuffer(f, b, s) setvbuf((f), (b), (b) ? _IOFBF : _IONBF, (s))
#define memzero(a, b) memset((a), 0, (b))
#else /* !STDC_HEADERS */
#ifndef HAVE_STRCHR
#define strchr(a, b) index((a), (b))
#define strrchr(a, b) rindex((a), (b))
#endif /* HAVE_STRCHR */
#ifdef HAVE_MEMCPY
#define memzero(a, b) memset((a), 0, (b))
#else
#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))
#endif /* HAVE_MEMCPY */
#ifdef HAVE_STRINGS_H
#include <strings.h>
#else
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#endif
char *getenv();
caddr_t malloc();
#endif /* STDC_HEADERS */
/* If snprintf or vsnprintf aren't available, we substitute our own.
But we have to include stdarg in order to be able to define them.
*/
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#ifndef HAVE_SNPRINTF
int ap_snprintf(char *buf, size_t len, const char *format,...);
#define snprintf ap_snprintf
#endif
#ifndef HAVE_VSNPRINTF
int ap_vsnprintf(char *buf, size_t len, const char *format,va_list ap);
#define vsnprintf ap_vsnprintf
#endif
#endif
#if !HAVE_PID_T
typedef long pid_t;
#endif
#if !HAVE_TIME_T
typedef long time_t;
#endif
#if !HAVE_UID_T
typedef long uid_t;
#endif
#ifndef INT_MAX
#define INT_MAX (0x7fffffff)
#endif
#ifndef UINT_MAX
#define UINT_MAX (0xffffffffU)
#endif
/* we must have both sighold and sigrelse to use them */
#if defined(HAVE_SIGHOLD) && !defined(HAVE_SIGRELSE)
#undef HAVE_SIGHOLD
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYSEXITS_H
#include <sysexits.h>
#else
#define EX_OK 0 /* successful termination */
#define EX_USAGE 64 /* command line usage error */
#define EX_DATAERR 65 /* data format error */
#define EX_NOINPUT 66 /* cannot open input */
#define EX_NOUSER 67 /* addressee unknown */
#define EX_NOHOST 68 /* host name unknown */
#define EX_UNAVAILABLE 69 /* service unavailable */
#define EX_SOFTWARE 70 /* internal software error */
#define EX_OSERR 71 /* system error (e.g., can't fork) */
#define EX_OSFILE 72 /* critical OS file missing */
#define EX_CANTCREAT 73 /* can't create (user) output file */
#define EX_IOERR 74 /* input/output error */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#define EX_PROTOCOL 76 /* remote error in protocol */
#define EX_NOPERM 77 /* permission denied */
#define EX_CONFIG 78 /* configuration error */
#endif

605
external/bsd/top/dist/screen.c vendored Normal file
View File

@@ -0,0 +1,605 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top users/processes display for Unix
* Version 3
*/
/* 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"
#if HAVE_CURSES_H && HAVE_TERM_H
#include <curses.h>
#include <term.h>
#else
#if HAVE_TERMCAP_H
#include <termcap.h>
#else
#if HAVE_CURSES_H
#include <curses.h>
#endif
#endif
#endif
#if !HAVE_DECL_TPUTS
int tputs(const char *, int, int (*)(int));
#endif
#if !HAVE_DECL_TGOTO
char *tgoto(const char *, int, int);
#endif
#if !HAVE_DECL_TGETENT
int tgetent(const char *, char *);
#endif
#if !HAVE_DECL_TGETFLAG
int tgetflag(const char *);
#endif
#if !HAVE_DECL_TGETNUM
int tgetnum(const char *);
#endif
#if !HAVE_DECL_TGETSTR
char *tgetstr(const char *, char **);
#endif
#include <sys/ioctl.h>
#ifdef CBREAK
# include <sgtty.h>
# define USE_SGTTY
#else
# ifdef TCGETA
# define USE_TERMIO
# include <termio.h>
# else
# define USE_TERMIOS
# include <termios.h>
# endif
#endif
#if defined(USE_TERMIO) || defined(USE_TERMIOS)
# ifndef TAB3
# ifdef OXTABS
# define TAB3 OXTABS
# else
# define TAB3 0
# endif
# endif
#endif
#include "screen.h"
#include "boolean.h"
#define putcap(str) ((str) != NULL ? (void)tputs(str, 1, putstdout) : (void)0)
extern char *myname;
char ch_erase;
char ch_kill;
char ch_werase;
char smart_terminal;
int screen_length;
int screen_width;
char PC;
static int tc_overstrike;
static char termcap_buf[1024];
static char string_buffer[1024];
static char home[15];
static char lower_left[15];
static char *tc_clear_line;
static char *tc_clear_screen;
static char *tc_clear_to_end;
static char *tc_cursor_motion;
static char *tc_start_standout;
static char *tc_end_standout;
static char *terminal_init;
static char *terminal_end;
#ifdef USE_SGTTY
static struct sgttyb old_settings;
static struct sgttyb new_settings;
#endif
#ifdef USE_TERMIO
static struct termio old_settings;
static struct termio new_settings;
#endif
#ifdef USE_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
/* This has to be defined as a subroutine for tputs (instead of a macro) */
static int
putstdout(TPUTS_PUTC_ARGTYPE ch)
{
return putchar((int)ch);
}
void
screen_getsize()
{
char *go;
#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 */
if ((go = tgoto(tc_cursor_motion, 0, screen_length - 1)) != NULL)
(void) strcpy(lower_left, go);
else
lower_left[0] = '\0';
}
int
screen_readtermcap(int interactive)
{
char *bufptr;
char *PCptr;
char *term_name;
char *go;
int status;
/* set defaults in case we aren't smart */
screen_width = MAX_COLS;
screen_length = 0;
if (interactive == No)
{
/* pretend we have a dumb terminal */
smart_terminal = No;
return No;
}
/* 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 No;
}
/* 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 No;
}
/* "hardcopy" immediately indicates a very stupid terminal */
if (tgetflag("hc"))
{
smart_terminal = No;
return No;
}
/* set up common terminal capabilities */
if ((screen_length = tgetnum("li")) <= 0)
{
screen_length = 0;
}
/* 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 */
tc_overstrike = tgetflag("os");
/* initialize the pointer into the termcap string buffer */
bufptr = string_buffer;
/* get "ce", clear to end */
if (!tc_overstrike)
{
tc_clear_line = tgetstr("ce", &bufptr);
}
/* get necessary capabilities */
if ((tc_clear_screen = tgetstr("cl", &bufptr)) == NULL ||
(tc_cursor_motion = tgetstr("cm", &bufptr)) == NULL)
{
smart_terminal = No;
return No;
}
/* get some more sophisticated stuff -- these are optional */
tc_clear_to_end = tgetstr("cd", &bufptr);
terminal_init = tgetstr("ti", &bufptr);
terminal_end = tgetstr("te", &bufptr);
tc_start_standout = tgetstr("so", &bufptr);
tc_end_standout = tgetstr("se", &bufptr);
/* pad character */
PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
/* set convenience strings */
if ((go = tgoto(tc_cursor_motion, 0, 0)) != NULL)
(void) strcpy(home, go);
else
home[0] = '\0';
/* (lower_left is set in screen_getsize) */
/* get the actual screen size with an ioctl, if needed */
/* This may change screen_width and screen_length, and it always
sets lower_left. */
screen_getsize();
/* If screen_length is 0 from both termcap and ioctl then we are dumb */
if (screen_length == 0)
{
smart_terminal = No;
return No;
}
/* if stdout is not a terminal, pretend we are a dumb terminal */
#ifdef USE_SGTTY
if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
{
smart_terminal = No;
}
#endif
#ifdef USE_TERMIO
if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
{
smart_terminal = No;
}
#endif
#ifdef USE_TERMIOS
if (tcgetattr(STDOUT, &old_settings) == -1)
{
smart_terminal = No;
}
#endif
return smart_terminal;
}
void
screen_init()
{
/* get the old settings for safe keeping */
#ifdef USE_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;
ch_werase = old_settings.sg_werase;
#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 USE_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];
ch_werase = old_settings.c_cc[VWERASE];
/* remember that it really is a terminal */
is_a_terminal = Yes;
/* send the termcap initialization string */
putcap(terminal_init);
}
#endif
#ifdef USE_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];
ch_werase = old_settings.c_cc[VWERASE];
/* 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
screen_end()
{
/* move to the lower left, clear the line and send "te" */
if (smart_terminal)
{
putcap(lower_left);
putcap(tc_clear_line);
fflush(stdout);
putcap(terminal_end);
}
/* if we have settings to reset, then do so */
if (is_a_terminal)
{
#ifdef USE_SGTTY
(void) ioctl(STDOUT, TIOCSETP, &old_settings);
#ifdef TOStop
(void) ioctl(STDOUT, TIOCLSET, &old_lword);
#endif
#endif
#ifdef USE_TERMIO
(void) ioctl(STDOUT, TCSETA, &old_settings);
#endif
#ifdef USE_TERMIOS
(void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
#endif
}
}
void
screen_reinit()
{
/* install our settings if it is a terminal */
if (is_a_terminal)
{
#ifdef USE_SGTTY
(void) ioctl(STDOUT, TIOCSETP, &new_settings);
#ifdef TOStop
(void) ioctl(STDOUT, TIOCLSET, &new_lword);
#endif
#endif
#ifdef USE_TERMIO
(void) ioctl(STDOUT, TCSETA, &new_settings);
#endif
#ifdef USE_TERMIOS
(void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
#endif
}
/* send init string */
if (smart_terminal)
{
putcap(terminal_init);
}
}
void
screen_move(int x, int y)
{
char *go = tgoto(tc_cursor_motion, x, y);
if (go)
tputs(go, 1, putstdout);
}
void
screen_standout(const char *msg)
{
if (smart_terminal)
{
putcap(tc_start_standout);
fputs(msg, stdout);
putcap(tc_end_standout);
}
else
{
fputs(msg, stdout);
}
}
void
screen_clear(void)
{
if (smart_terminal)
{
putcap(tc_clear_screen);
}
}
int
screen_cte(void)
{
if (smart_terminal)
{
if (tc_clear_to_end)
{
putcap(tc_clear_to_end);
return(Yes);
}
}
return(No);
}
void
screen_cleareol(int len)
{
int i;
if (smart_terminal && !tc_overstrike && len > 0)
{
if (tc_clear_line)
{
putcap(tc_clear_line);
return;
}
else
{
i = 0;
while (i++ < 0)
{
putchar(' ');
}
i = 0;
while (i++ < 0)
{
putchar('\b');
}
return;
}
}
return;
}
void
screen_home(void)
{
if (smart_terminal)
{
putcap(home);
}
}

65
external/bsd/top/dist/screen.h vendored Normal file
View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* 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"
*/
#ifndef _SCREEN_H_
#define _SCREEN_H_
extern char ch_erase; /* set to the user's erase character */
extern char ch_kill; /* set to the user's kill character */
extern char ch_werase; /* set to the user's werase character */
extern char smart_terminal; /* set if the terminal has sufficient termcap
capabilities for normal operation */
/* rows and columns on the screen according to termcap */
extern int screen_length;
extern int screen_width;
void screen_getsize(void);
int screen_readtermcap(int interactive);
void screen_init(void);
void screen_end(void);
void screen_reinit(void);
void screen_move(int x, int y);
void screen_standout(const char *msg);
void screen_clear(void);
int screen_cte(void);
void screen_cleareol(int len);
void screen_home(void);
#endif /* _SCREEN_H_ */

91
external/bsd/top/dist/sigconv.awk vendored Normal file
View File

@@ -0,0 +1,91 @@
# Copyright (c) 1984 through 2008, William LeFebvre
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of William LeFebvre nor the names of other
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Awk script converts an include file with definitions for signal names
# in to a predefined array that associates the signal numbers to the names.
#
BEGIN {
nsig = 0;
j = 0;
print "/* This file was automatically generated */"
print "/* by the awk script \"sigconv.awk\". */\n"
print "struct sigdesc {"
print " const char *name;"
print " int number;"
print "};\n"
print "struct sigdesc sigdesc[] = {"
}
/^#define[ \t][ \t]*SIG[A-Z]/ {
j = sprintf("%d", $3);
if (siglist[j] != "") next;
str = $2;
if (nsig < j)
nsig = j;
siglist[j] = sprintf("\"%s\",\t%2d", \
substr(str, 4), j);
}
/^#[ \t]*define[ \t][ \t]*SIG[A-Z]/ {
j = sprintf("%d", $4);
if (siglist[j] != "") next;
str = $3;
if (nsig < j)
nsig = j;
siglist[j] = sprintf("\"%s\",\t%2d", \
substr(str, 4), j);
}
/^#[ \t]*define[ \t][ \t]*_SIG[A-Z]/ {
j = sprintf("%d", $4);
if (siglist[j] != "") next;
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");
}

477
external/bsd/top/dist/top.1.in vendored Normal file
View File

@@ -0,0 +1,477 @@
.\" NOTE: changes to the manual page for "top" should be made in the
.\" file "top.1.in" and NOT in the file "top.1".
.nr N @DEFAULT_TOPN@
.nr D @DEFAULT_DELAY@
.nr L @HAVE_GETOPT_LONG@
.nr K @ENABLE_KILL@
.TH TOP 1 Local
.UC 4
.SH NAME
top \- display and update information about the top cpu processes
.SH SYNOPSIS
.B top
[
.B \-1CISTabcinqtuv
] [
.BI \-d count
] [
.BI \-m mode
] [
.BI \-o field
] [
.BI \-p pid
] [
.BI \-s time
] [
.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 5
.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
.if \nL==0 Long options are not available on this system.
.TP
.B "\-1, \-\-percpustates"
Display per-cpu states on a multi-processor machine.
.TP
.B "\-C, \-\-color"
Turn off the use of color in the display.
.TP
.B "\-I, \-\-idle-procs"
Do not display idle processes.
By default, top displays both active and idle processes.
.TP
.B "\-S, \-\-system-procs"
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 "\-T, \-\-tag-names"
List all available color tags and the current set of tests used for
color highlighting, then exit.
.TP
.B "\-a, \-\-all"
Show all processes for as long as possible. This is shorthand for
\*(lq-d all all\*(rq. This option is especially handy in batch mode.
.TP
.B "\-b, \-n, \-\-batch"
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 "\-c, \-\-full-commands"
Show the full command line for each process. Default is to show just the
command name. This option is not supported on all platforms.
.TP
.B "\-i, \-\-interactive"
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 "\-q, \-\-quick"
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 "\-t, \-\-threads"
Show individual threads on separate lines. By default, on systems
which support threading, each process is shown with a count of the number
of threads. This option shows each thread on a separate line. This option
is not supported on all platforms.
.TP
.B "\-u, \-\-uids"
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, \-\-version"
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 "\-d \fIcount\fP, \-\-displays \fIcount\fP"
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. Any proper prefix of the words \*(lqinfinity\*(rq,
\*(lqmaximum\*(rq,
or
\*(lqall\*(rq can be used to indicate an infinite number of displays.
The default for intelligent terminals is infinity.
The default for dumb terminals is 1.
.TP
.B "\-m \fImode\fP, \-\-mode=\fImode\fP"
Start the display in an alternate mode. Some platforms support multiple
process displays to show additional process information. The value
\fImode\fP is a number indicating which mode to display. The default is
0. On platforms that do not have multiple display modes this option has
no effect.
.TP
.B "\-o \fIfield\fP, \-\-sort-order=\fIfield\fP"
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. Likely
values are \*(lqcpu\*(rq, \*(lqsize\*(rq, \*(lqres\*(rq, and \*(lqtime\*(rq,
but may vary on different operating systems. Note that
not all operating systems support this option.
.TP
.B "\-p \fIpid\fP, \-\-pid=\fIpid\fP"
Only display the specified pid.
.TP
.B "\-s \fItime\fP, \-\-delay=\fItime\fP"
Set the delay between screen updates to
.I time
seconds. The default delay between updates is
.af D 1
seconds.
.TP
.B "\-U \fIusername\fP, \-\-user=\fIusername\fP"
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,
\fBinfinity\fP.
.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 \-C ,
.BR \-I ,
.BR \-S ,
and
.B \-u
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. Note that a control-L
(^L) always redraws the current screen and a space forces an immediate
update to the screen using new data.
.PP
These commands are currently recognized:
.TP
.I "\fBh\fP\ or\ \fB?\fP"
Display a summary of the commands (help screen). Version information
is included in this display.
.TP
.B 1
Toggle the display of per-cpu states.
.TP
.B C
Toggle the use of color in the display.
.TP
.B c
Display only processes whose commands match the specified string. An empty
string will display all processes. This command is not supported on all
platforms.
.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 f
Toggle the display of the full command line.
.TP
.B H
Toggle the display of threads on separate lines. By default, on systems
which support threading, each process is shown with a count of the number
of threads. This command shows each thread on a separate line. This command
is not supported on all platforms.
.TP
.B i
(or
.BR I )
Toggle the display of idle processes.
.if \nK==1 \{\
.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 M
Sort display by memory usage. Shorthand for \*(lqo size\*(rq.
.TP
.B m
Change to a different process display mode. Some systems provide multiple
display modes for the process display which shows different information.
This command toggles between the available modes. This command is not
supported on all platforms.
.TP
.B N
Sort by process id. Shorthand for \*(lqo pid\*(rq.
.TP
.B n or #
Change the number of processes to display (prompt for new number).
.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 fron system to system
but usually include: \*(lqcpu\*(rq, \*(lqres\*(rq, \*(lqsize\*(rq,
\*(lqtime\*(rq. The default is cpu.
.TP
.B P
Sort by CPU usage. Shorthand for \*(lqo cpu\*(rq.
.TP
.B q
Quit
.IR top.
.if \nK==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 s
Change the number of seconds to delay between displays
(prompt for new number).
.TP
.B T
Sort by CPU time. Shorthand for \*(lqo time\*(rq.
.TP
.B U
Toggle between displaying usernames and uids.
.TP
.B u
Display only processes owned by a specific username (prompt for username).
If the username specified is simply \*(lq+\*(rq, then processes belonging
to all users will be displayed.
.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 lines of the display show general information
about the state of the system. The first line shows
(on some systems) the last process id assigned to a process,
the three load averages,
the system uptime, and the current time.
The second line displays the total number of processes followed
by a breakdown of processes per state. Examples of states common
to Unix systems are sleeping, running, starting, stopped, and zombie.
The next line displays a percentage of time spent in each of the
processor states (typically user, nice, system, idle, and iowait).
These percentages show the processor activity during the time since
the last update. For multi-processor systems, this information is
a summation of time across all processors. The next line shows
kernel-related activity (not available on all systems). The numbers
shown on this line are per-second rates sampled since the last update.
The exact
information displayed varies between systems, but some examples are:
context switches, interrupts, traps, forks, and page faults. The last
one or two lines show a summary of memory and swap activity. These lines
vary between systems.
.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. The columns displayed by top will
differ slightly between operating systems. Generally, the following
fields are displayed:
.TP
.B PID
The process id.
.TP
.B USERNAME
Username of the process's owner (if
.B \-u
is specified, a UID column will be substituted for USERNAME).
.TP
.B THR
The number of threads in the processes (this column may also
be labeled NLWP).
.TP
.B PRI
Current priority of the process.
.TP
.B NICE
Nice amount in the range \-20 to 20, as established by the use of
the command
.IR nice .
.TP
.B SIZE
Total size of the process (text, data, and stack) given in kilobytes.
.TP
.B RES
Resident memory: current amount of process memory that resides in physical
memory, given in kilobytes.
.TP
.B STATE
Current state (typically one of \*(lqsleep\*(rq,
\*(lqrun\*(rq, \*(lqidl\*(rq, \*(lqzomb\*(rq, or \*(lqstop\*(rq).
.TP
.B TIME
Number of system and user cpu seconds that the process has used.
.TP
.B CPU
Percentage of available cpu time used by this process.
.TP
.B COMMAND
Name of the command that the process is currently running.
.SH COLOR
Top supports the use of ANSI color in its output. By default, color is
available but not used. The environment variable
.B TOPCOLORS
specifies colors to use and conditions for which they should be used.
At the present time, only numbers in the summay display area can be
colored. In a future version it will be possible to highlight numbers
in the process display area as well. The environment variable is the
only way to specify color: there is no equivalent command line option.
Note that the environment variable
.B TOPCOLOURS
is also understood. The British spelling takes precedence. The use of
color only works on terminals that understand and process ANSI color
escape sequences.
.PP
The environment variable is a sequence of color specifications, separated
by colons. Each specification takes the form tag=min,max#code where
.I tag
is the name of the value to check,
.I min
and
.I max
specify a range for the value, and
.I code
is an ANSI color code. Multiple color codes can be listed and separated
with semi-colons. A missing
.I min
implies the lowest possible value (usually 0)
and a missing
.I max
implies infinity. The comma must always be present. When specifying numbers
for load averages, they should be multiplied by 100.
For example, the specification
.B 1min=500,1000#31
indicates that a 1 minute load average between
5 and 10 should be displayed in red. Color attributes can be combined.
For example, the specification
.B 5min=1000,#37;41
indicates that a 5 minute load average higher than 10 should be displayed
with white characters on a red background. A special tag named
.I header
is used to control the color of the header for process display. It should
be specified with no lower and upper limits, specifically
.B header=,#
followed by the ANSI color code.
.PP
You can see a list of color codes recognized by this installation of top
with the
.B \-T
option. This will also show the current set of tests used for
color highligting, as specified in the environment.
.SH AUTHOR
William LeFebvre
.SH ENVIRONMENT
.DT
TOP user-configurable defaults for options.
TOPCOLORS color specification
.SH BUGS
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)
@MAN_SUPPLEMENT@
.SH COPYRIGHT
Copyright (C) 1984-2007 William LeFebvre. For additional licensing
information, see http://www.unixtop.org/license/

996
external/bsd/top/dist/top.c vendored Normal file
View File

@@ -0,0 +1,996 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const char *copyright =
"Copyright (c) 1984 through 2008, William LeFebvre";
/*
* Changes to other files that we can do at the same time:
* screen.c:init_termcap: get rid of the "interactive" argument and have it
* pass back something meaningful (such as success/failure/error).
*/
#include "os.h"
#include <signal.h>
#include <setjmp.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
/* definitions */
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
/* determine which type of signal functions to use */
/* cant have sigaction without sigprocmask */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGPROCMASK)
#undef HAVE_SIGACTION
#endif
/* always use sigaction when it is available */
#ifdef HAVE_SIGACTION
#undef HAVE_SIGHOLD
#else
/* use sighold/sigrelse, otherwise use old fashioned BSD signals */
#if !defined(HAVE_SIGHOLD) || !defined(HAVE_SIGRELSE)
#define BSD_SIGNALS
#endif
#endif
/* if FD_SET and friends aren't present, then fake something up */
#ifndef FD_SET
typedef int fd_set;
#define FD_ZERO(x) (*(x) = 0)
#define FD_SET(f, x) (*(x) = 1<<f)
#endif
/* includes specific to top */
#include "top.h"
#include "machine.h"
#include "globalstate.h"
#include "commands.h"
#include "display.h"
#include "screen.h"
#include "boolean.h"
#include "username.h"
#include "utils.h"
#include "version.h"
#ifdef ENABLE_COLOR
#include "color.h"
#endif
/* definitions */
#define BUFFERSIZE 4096
#define JMP_RESUME 1
#define JMP_RESIZE 2
/* externs for getopt: */
extern int optind;
extern char *optarg;
/* statics */
static char stdoutbuf[BUFFERSIZE];
static jmp_buf jmp_int;
/* globals */
char *myname;
void
quit(int status)
{
screen_end();
chdir("/tmp");
exit(status);
/* NOTREACHED */
}
/*
* signal handlers
*/
static void
set_signal(int sig, RETSIGTYPE (*handler)(int))
{
#ifdef HAVE_SIGACTION
struct sigaction action;
action.sa_handler = handler;
action.sa_flags = 0;
(void) sigaction(sig, &action, NULL);
#else
(void) signal(sig, handler);
#endif
}
static void
release_signal(int sig)
{
#ifdef HAVE_SIGACTION
sigset_t set;
sigemptyset(&set);
sigaddset(&set, sig);
sigprocmask(SIG_UNBLOCK, &set, NULL);
#endif
#ifdef HAVE_SIGHOLD
sigrelse(sig);
#endif
#ifdef BSD_SIGNALS
(void) sigsetmask(sigblock(0) & ~(sigmask(sig)));
#endif
}
static RETSIGTYPE
sig_leave(int i) /* exit under normal conditions -- INT handler */
{
screen_end();
exit(EX_OK);
}
static RETSIGTYPE
sig_tstop(int i) /* SIGTSTP handler */
{
/* move to the lower left */
screen_end();
fflush(stdout);
/* default the signal handler action */
set_signal(SIGTSTP, SIG_DFL);
/* unblock the TSTP signal */
release_signal(SIGTSTP);
/* send ourselves a TSTP to stop the process */
(void) kill(0, SIGTSTP);
/* reset the signal handler */
set_signal(SIGTSTP, sig_tstop);
/* reinit screen */
screen_reinit();
/* jump back to a known place in the main loop */
longjmp(jmp_int, JMP_RESUME);
/* NOTREACHED */
}
#ifdef SIGWINCH
static RETSIGTYPE
sig_winch(int i) /* SIGWINCH handler */
{
/* reascertain the screen dimensions */
screen_getsize();
/* jump back to a known place in the main loop */
longjmp(jmp_int, JMP_RESIZE);
}
#endif
#ifdef HAVE_SIGACTION
static sigset_t signalset;
#endif
static void *
hold_signals(void)
{
#ifdef HAVE_SIGACTION
sigemptyset(&signalset);
sigaddset(&signalset, SIGINT);
sigaddset(&signalset, SIGQUIT);
sigaddset(&signalset, SIGTSTP);
#ifdef SIGWINCH
sigaddset(&signalset, SIGWINCH);
#endif
sigprocmask(SIG_BLOCK, &signalset, NULL);
return (void *)(&signalset);
#endif
#ifdef HAVE_SIGHOLD
sighold(SIGINT);
sighold(SIGQUIT);
sighold(SIGTSTP);
#ifdef SIGWINCH
sighold(SIGWINCH);
return NULL;
#endif
#endif
#ifdef BSD_SIGNALS
int mask;
#ifdef SIGWINCH
mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) |
sigmask(SIGTSTP) | sigmask(SIGWINCH));
#else
mask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTSTP));
return (void *)mask;
#endif
#endif
}
static void
set_signals(void)
{
(void) set_signal(SIGINT, sig_leave);
(void) set_signal(SIGQUIT, sig_leave);
(void) set_signal(SIGTSTP, sig_tstop);
#ifdef SIGWINCH
(void) set_signal(SIGWINCH, sig_winch);
#endif
}
static void
release_signals(void *parm)
{
#ifdef HAVE_SIGACTION
sigprocmask(SIG_UNBLOCK, (sigset_t *)parm, NULL);
#endif
#ifdef HAVE_SIGHOLD
sigrelse(SIGINT);
sigrelse(SIGQUIT);
sigrelse(SIGTSTP);
#ifdef SIGWINCH
sigrelse(SIGWINCH);
#endif
#endif
#ifdef BSD_SIGNALS
(void) sigsetmask((int)parm);
#endif
}
/*
* void do_arguments(globalstate *gstate, int ac, char **av)
*
* Arguments processing. gstate points to the global state,
* ac and av are the arguments to process. This can be called
* multiple times with different sets of arguments.
*/
#ifdef HAVE_GETOPT_LONG
static struct option longopts[] = {
{ "percpustates", no_argument, NULL, '1' },
{ "color", no_argument, NULL, 'C' },
{ "debug", no_argument, NULL, 'D' },
{ "system-procs", no_argument, NULL, 'S' },
{ "idle-procs", no_argument, NULL, 'I' },
{ "tag-names", no_argument, NULL, 'T' },
{ "all", no_argument, NULL, 'a' },
{ "batch", no_argument, NULL, 'b' },
{ "full-commands", no_argument, NULL, 'c' },
{ "interactive", no_argument, NULL, 'i' },
{ "quick", no_argument, NULL, 'q' },
{ "threads", no_argument, NULL, 't' },
{ "uids", no_argument, NULL, 'u' },
{ "version", no_argument, NULL, 'v' },
{ "delay", required_argument, NULL, 's' },
{ "displays", required_argument, NULL, 'd' },
{ "user", required_argument, NULL, 'U' },
{ "sort-order", required_argument, NULL, 'o' },
{ "pid", required_argument, NULL, 'p' },
{ "display-mode", required_argument, NULL, 'm' },
{ NULL, 0, NULL, 0 },
};
#endif
static void
do_arguments(globalstate *gstate, int ac, char **av)
{
int i;
double f;
/* this appears to keep getopt happy */
optind = 1;
#ifdef HAVE_GETOPT_LONG
while ((i = getopt_long(ac, av, "1CDSITabcinp:qtuvs:d:U:o:m:", longopts, NULL)) != -1)
#else
while ((i = getopt(ac, av, "1CDSITabcinp:qtuvs:d:U:o:m:")) != EOF)
#endif
{
switch(i)
{
case '1':
gstate->percpustates = !gstate->percpustates;
break;
#ifdef ENABLE_COLOR
case 'C':
gstate->use_color = !gstate->use_color;
break;
#endif
case 'D':
debug_set(1);
break;
case 'v':
fprintf(stderr, "%s: version %s\n", myname, version_string());
exit(EX_OK);
break;
case 'b':
case 'n':
gstate->interactive = No;
break;
case 'a':
gstate->displays = Infinity;
gstate->topn = Infinity;
break;
case 'i':
gstate->interactive = Yes;
break;
case 'o':
gstate->order_name = optarg;
break;
case 'd':
i = atoiwi(optarg);
if (i == Invalid || i == 0)
{
message_error(" Bad display count");
}
else
{
gstate->displays = i;
}
break;
case 's':
f = atof(optarg);
if (f < 0 || (f == 0 && getuid() != 0))
{
message_error(" Bad seconds delay");
}
else
{
gstate->delay = f;
}
break;
case 'u':
gstate->show_usernames = !gstate->show_usernames;
break;
case 'U':
i = userid(optarg);
if (i == -1)
{
message_error(" Unknown user '%s'", optarg);
}
else
{
gstate->pselect.uid = i;
}
break;
case 'm':
i = atoi(optarg);
gstate->pselect.mode = i;
break;
case 'S':
gstate->pselect.system = !gstate->pselect.system;
break;
case 'I':
gstate->pselect.idle = !gstate->pselect.idle;
break;
#ifdef ENABLE_COLOR
case 'T':
gstate->show_tags = 1;
break;
#endif
case 'c':
gstate->pselect.fullcmd = !gstate->pselect.fullcmd;
break;
case 't':
gstate->pselect.threads = !gstate->pselect.threads;
break;
case 'p':
gstate->pselect.pid = atoi(optarg);
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
{
message_error(" Option -q can only be used by root");
}
break;
default:
fprintf(stderr, "\
Top version %s\n\
Usage: %s [-1CISTabcinqtuv] [-d count] [-m mode] [-o field] [-p pid]\n\
[-s time] [-U username] [number]\n",
version_string(), myname);
exit(EX_USAGE);
}
}
/* get count of top processes to display */
if (optind < ac && *av[optind])
{
if ((i = atoiwi(av[optind])) == Invalid)
{
message_error(" Process count not a number");
}
else
{
gstate->topn = i;
}
}
}
static void
do_display(globalstate *gstate)
{
int active_procs;
int i;
time_t curr_time;
caddr_t processes;
struct system_info system_info;
char *hdr;
/* get the time */
time_mark(&(gstate->now));
curr_time = (time_t)(gstate->now.tv_sec);
/* get the current stats */
get_system_info(&system_info);
/* get the current processes */
processes = get_process_info(&system_info, &(gstate->pselect), gstate->order_index);
/* determine number of processes to actually display */
if (gstate->topn > 0)
{
/* 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 > gstate->topn)
{
active_procs = gstate->topn;
}
if (active_procs > gstate->max_topn)
{
active_procs = gstate->max_topn;
}
}
else
{
/* dont show any */
active_procs = 0;
}
#ifdef HAVE_FORMAT_PROCESS_HEADER
/* get the process header to use */
hdr = format_process_header(&(gstate->pselect), processes, active_procs);
#else
hdr = gstate->header_text;
#endif
/* full screen or update? */
if (gstate->fulldraw)
{
display_clear();
i_loadave(system_info.last_pid, system_info.load_avg);
i_uptime(&(gstate->statics->boottime), &curr_time);
i_timeofday(&curr_time);
i_procstates(system_info.p_total, system_info.procstates, gstate->pselect.threads);
if (gstate->show_cpustates)
{
i_cpustates(system_info.cpustates);
}
else
{
if (smart_terminal)
{
z_cpustates();
}
gstate->show_cpustates = Yes;
}
i_kernel(system_info.kernel);
i_memory(system_info.memory);
i_swap(system_info.swap);
i_message(&(gstate->now));
i_header(hdr);
for (i = 0; i < active_procs; i++)
{
i_process(i, format_next_process(processes, gstate->get_userid));
}
i_endscreen();
if (gstate->smart_terminal)
{
gstate->fulldraw = No;
}
}
else
{
u_loadave(system_info.last_pid, system_info.load_avg);
u_uptime(&(gstate->statics->boottime), &curr_time);
i_timeofday(&curr_time);
u_procstates(system_info.p_total, system_info.procstates, gstate->pselect.threads);
u_cpustates(system_info.cpustates);
u_kernel(system_info.kernel);
u_memory(system_info.memory);
u_swap(system_info.swap);
u_message(&(gstate->now));
u_header(hdr);
for (i = 0; i < active_procs; i++)
{
u_process(i, format_next_process(processes, gstate->get_userid));
}
u_endscreen();
}
}
#ifdef DEBUG
void
timeval_xdprint(char *s, struct timeval tv)
{
xdprintf("%s %d.%06d\n", s, tv.tv_sec, tv.tv_usec);
}
#endif
static void
do_wait(globalstate *gstate)
{
struct timeval wait;
double2tv(&wait, gstate->delay);
select(0, NULL, NULL, NULL, &wait);
}
static void
do_command(globalstate *gstate)
{
int status;
struct timeval wait = {0, 0};
struct timeval now;
fd_set readfds;
unsigned char ch;
/* calculate new refresh time */
gstate->refresh = gstate->now;
double2tv(&now, gstate->delay);
timeradd(&now, &gstate->refresh, &gstate->refresh);
time_get(&now);
/* loop waiting for time to expire */
do {
/* calculate time to wait */
if (gstate->delay > 0)
{
wait = gstate->refresh;
wait.tv_usec -= now.tv_usec;
if (wait.tv_usec < 0)
{
wait.tv_usec += 1000000;
wait.tv_sec--;
}
wait.tv_sec -= now.tv_sec;
}
/* set up arguments for select on stdin (0) */
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
/* wait for something to read or time out */
if (select(32, &readfds, NULL, NULL, &wait) > 0)
{
/* read it */
if (read(STDIN_FILENO, &ch, 1) != 1)
{
/* read error */
message_error(" Read error on stdin");
quit(EX_DATAERR);
/*NOTREACHED*/
}
/* mark pending messages as old */
message_mark();
/* dispatch */
status = command_process(gstate, (int)ch);
switch(status)
{
case CMD_ERROR:
quit(EX_SOFTWARE);
/*NOTREACHED*/
case CMD_REFRESH:
return;
case CMD_UNKNOWN:
message_error(" Unknown command");
break;
case CMD_NA:
message_error(" Command not available");
}
}
/* get new time */
time_get(&now);
} while (timercmp(&now, &(gstate->refresh), < ));
}
static void
do_minidisplay(globalstate *gstate)
{
double real_delay;
struct system_info si;
/* save the real delay and substitute 1 second */
real_delay = gstate->delay;
gstate->delay = 1;
/* wait 1 second for a command */
time_mark(&(gstate->now));
do_command(gstate);
/* do a mini update that only updates the cpustates */
get_system_info(&si);
u_cpustates(si.cpustates);
/* restore the delay time */
gstate->delay = real_delay;
/* done */
i_endscreen();
}
int
main(int argc, char *argv[])
{
char *env_top;
char **preset_argv;
int preset_argc = 0;
void *mask;
volatile int need_mini = 1;
static char top[] = "top";
struct statics statics;
globalstate *gstate;
/* get our name */
if (argc > 0)
{
if ((myname = strrchr(argv[0], '/')) == 0)
{
myname = argv[0];
}
else
{
myname++;
}
} else
myname = top;
/* binary compatibility check */
#ifdef HAVE_UNAME
{
struct utsname uts;
if (uname(&uts) == 0)
{
if (strcmp(uts.machine, UNAME_HARDWARE) != 0)
{
fprintf(stderr, "%s: incompatible hardware platform\n",
myname);
exit(EX_UNAVAILABLE);
}
}
}
#endif
/* initialization */
gstate = ecalloc(1, sizeof(globalstate));
gstate->statics = &statics;
time_mark(NULL);
/* preset defaults for various options */
gstate->show_usernames = Yes;
gstate->topn = DEFAULT_TOPN;
gstate->delay = DEFAULT_DELAY;
gstate->fulldraw = Yes;
gstate->use_color = Yes;
gstate->interactive = Maybe;
gstate->percpustates = No;
/* preset defaults for process selection */
gstate->pselect.idle = Yes;
gstate->pselect.system = Yes;
gstate->pselect.fullcmd = No;
gstate->pselect.command = NULL;
gstate->pselect.uid = -1;
gstate->pselect.pid = -1;
gstate->pselect.mode = 0;
/* use a large buffer for stdout */
#ifdef HAVE_SETVBUF
setvbuf(stdout, stdoutbuf, _IOFBF, BUFFERSIZE);
#else
#ifdef HAVE_SETBUFFER
setbuffer(stdout, stdoutbuf, BUFFERSIZE);
#endif
#endif
/* get preset options from the environment */
if ((env_top = getenv("TOP")) != NULL)
{
preset_argv = argparse(env_top, &preset_argc);
preset_argv[0] = myname;
do_arguments(gstate, preset_argc, preset_argv);
}
/* process arguments */
do_arguments(gstate, argc, argv);
#ifdef ENABLE_COLOR
/* If colour has been turned on read in the settings. */
env_top = getenv("TOPCOLOURS");
if (!env_top)
{
env_top = getenv("TOPCOLORS");
}
/* must do something about error messages */
color_env_parse(env_top);
color_activate(gstate->use_color);
#endif
/* in order to support forward compatability, we have to ensure that
the entire statics structure is set to a known value before we call
machine_init. This way fields that a module does not know about
will retain their default values */
memzero((void *)&statics, sizeof(statics));
statics.boottime = -1;
/* call the platform-specific init */
if (machine_init(&statics) == -1)
{
exit(EX_SOFTWARE);
}
/* create a helper list of sort order names */
gstate->order_namelist = string_list(statics.order_names);
/* look up chosen sorting order */
if (gstate->order_name != NULL)
{
int i;
if (statics.order_names == NULL)
{
message_error(" This platform does not support arbitrary ordering");
}
else if ((i = string_index(gstate->order_name,
statics.order_names)) == -1)
{
message_error(" Sort order `%s' not recognized", gstate->order_name);
message_error(" Recognized sort orders: %s", gstate->order_namelist);
}
else
{
gstate->order_index = i;
}
}
/* initialize extensions */
init_username();
/* initialize termcap */
gstate->smart_terminal = screen_readtermcap(gstate->interactive);
/* determine interactive state */
if (gstate->interactive == Maybe)
{
gstate->interactive = smart_terminal;
}
/* if displays were not specified, choose an appropriate default */
if (gstate->displays == 0)
{
gstate->displays = gstate->smart_terminal ? Infinity: 1;
}
/* we don't need a mini display when delay is less than 2
seconds or when we are not on a smart terminal */
if (gstate->delay <= 1 || !smart_terminal)
{
need_mini = 0;
}
#ifndef HAVE_FORMAT_PROCESS_HEADER
/* set constants for username/uid display */
if (gstate->show_usernames)
{
gstate->header_text = format_header("USERNAME");
gstate->get_userid = username;
}
else
{
gstate->header_text = format_header(" UID ");
gstate->get_userid = itoa7;
}
#endif
gstate->pselect.usernames = gstate->show_usernames;
/* initialize display */
if ((gstate->max_topn = display_init(&statics, gstate->percpustates)) == -1)
{
fprintf(stderr, "%s: display too small\n", myname);
exit(EX_OSERR);
}
/* check for infinity and for overflowed screen */
if (gstate->topn == Infinity)
{
gstate->topn = INT_MAX;
}
else if (gstate->topn > gstate->max_topn)
{
message_error(" This terminal can only display %d processes",
gstate->max_topn);
}
#ifdef ENABLE_COLOR
/* producing a list of color tags is easy */
if (gstate->show_tags)
{
color_dump(stdout);
exit(EX_OK);
}
#endif
/* hold all signals while we initialize the screen */
mask = hold_signals();
screen_init();
/* set the signal handlers */
set_signals();
/* longjmp re-entry point */
/* set the jump buffer for long jumps out of signal handlers */
if (setjmp(jmp_int) != 0)
{
/* this is where we end up after processing sigwinch or sigtstp */
/* tell display to resize its buffers, and get the new length */
if ((gstate->max_topn = display_resize()) == -1)
{
/* thats bad */
quit(EX_OSERR);
/*NOTREACHED*/
}
/* set up for a full redraw, and get the current line count */
gstate->fulldraw = Yes;
/* safe to release the signals now */
release_signals(mask);
}
else
{
/* release the signals */
release_signals(mask);
/* some systems require a warmup */
/* always do a warmup for batch mode */
if (gstate->interactive == 0 || statics.flags.warmup)
{
struct system_info system_info;
struct timeval timeout;
time_mark(&(gstate->now));
get_system_info(&system_info);
(void)get_process_info(&system_info, &gstate->pselect, 0);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
select(0, NULL, NULL, NULL, &timeout);
/* if we've warmed up, then we can show good states too */
gstate->show_cpustates = Yes;
need_mini = 0;
}
}
/* main loop */
while ((gstate->displays == -1) || (--gstate->displays > 0))
{
do_display(gstate);
if (gstate->interactive)
{
if (need_mini)
{
do_minidisplay(gstate);
need_mini = 0;
}
do_command(gstate);
}
else
{
do_wait(gstate);
}
}
/* do one last display */
do_display(gstate);
quit(EX_OK);
/* NOTREACHED */
return 1; /* Keep compiler quiet. */
}

80
external/bsd/top/dist/top.h vendored Normal file
View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top - a top users display for Berkeley Unix
*
* General (global) definitions
*/
#ifndef _TOP_H_
#define _TOP_H_
#include <sys/time.h>
/* Maximum number of columns allowed for display */
#define MAX_COLS 255
/* Log base 2 of 1024 is 10 (2^10 == 1024) */
#define LOG1024 10
/* 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
struct ext_decl {
int (*f_minibar)(char *, int);
int (*f_display)(char *, int);
};
/*
* "Table_size" defines the size of the hash tables used to map uid to
* username. Things will work best if the number is a prime number.
* We use a number that should be suitable for most installations.
*/
#ifndef Table_size
#define Table_size 8191
#endif
void gettime(struct timeval *);
void quit(int);
#endif /* _TOP_H_ */

151
external/bsd/top/dist/username.c vendored Normal file
View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top users/processes display for Unix
* Version 3
*/
/*
* Username translation code for top.
*
* These routines handle uid to username mapping. They use a hash table to
* reduce reading overhead. Entries are refreshed every EXPIRETIME seconds.
*
* The old ad-hoc hash functions have been replaced with something a little
* more formal and (hopefully) more robust (found in hash.c)
*/
#include "os.h"
#include <pwd.h>
#include "top.h"
#include "utils.h"
#include "hash.h"
#include "username.h"
#define EXPIRETIME (60 * 5)
/* we need some sort of idea how long usernames can be */
#ifndef MAXLOGNAME
#ifdef _POSIX_LOGIN_NAME_MAX
#define MAXLOGNAME _POSIX_LOGIN_NAME_MAX
#else
#define MAXLOGNAME 9
#endif
#endif
struct hash_data {
int uid;
char name[MAXLOGNAME]; /* big enough? */
time_t expire;
};
hash_table *userhash;
void
init_username(void)
{
userhash = hash_create(211);
}
char *
username(int xuid)
{
struct hash_data *data;
struct passwd *pw;
time_t now;
/* what time is it? */
now = time(NULL);
/* get whatever is in the cache */
data = hash_lookup_uint(userhash, (unsigned int)xuid);
/* if we had a cache miss, then create space for a new entry */
if (data == NULL)
{
/* make space */
data = emalloc(sizeof(struct hash_data));
/* fill in some data, including an already expired time */
data->uid = xuid;
data->expire = (time_t)0;
/* add it to the hash: the rest gets filled in later */
hash_add_uint(userhash, xuid, data);
}
/* Now data points to the correct hash entry for "xuid". If this is
a new entry, then expire is 0 and the next test will be true. */
if (data->expire <= now)
{
if ((pw = getpwuid(xuid)) != NULL)
{
strncpy(data->name, pw->pw_name, MAXLOGNAME-1);
data->expire = now + EXPIRETIME;
dprintf("username: updating %d with %s, expires %d\n",
data->uid, data->name, data->expire);
}
else
{
/* username doesnt exist ... so invent one */
snprintf(data->name, sizeof(data->name), "%d", xuid);
data->expire = now + EXPIRETIME;
dprintf("username: updating %d with %s, expires %d\n",
data->uid, data->name, data->expire);
}
}
/* return what we have */
return data->name;
}
int
userid(char *xusername)
{
struct passwd *pwd;
if ((pwd = getpwnam(xusername)) == NULL)
{
return(-1);
}
/* return our result */
return(pwd->pw_uid);
}

42
external/bsd/top/dist/username.h vendored Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* interface for username.c */
#ifndef _USERNAME_H_
#define _USERNAME_H_
void init_username(void);
char *username(int uid);
int userid(char *username);
#endif /* _USERNAME_H_ */

752
external/bsd/top/dist/utils.c vendored Normal file
View File

@@ -0,0 +1,752 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top users/processes display for Unix
* Version 3
*/
/*
* This file contains various handy utilities used by top.
*/
#include "os.h"
#include <ctype.h>
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#else
#undef DEBUG
#endif
#include "top.h"
#include "utils.h"
static int
alldigits(char *s)
{
int ch;
while ((ch = *s++) != '\0')
{
if (!isdigit(ch))
{
return 0;
}
}
return 1;
}
int
atoiwi(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 (alldigits(str))
{
return(atoi(str));
}
else
{
return(Invalid);
}
}
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.
*/
char *
itoa(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 *
itoa_w(int val, int w)
{
char *ptr;
char *eptr;
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. */
if (w > 15)
{
w = 15;
}
eptr = ptr = buffer + sizeof(buffer);
*--ptr = '\0';
if (val == 0)
{
*--ptr = '0';
}
else while (val != 0)
{
*--ptr = (val % 10) + '0';
val /= 10;
}
while (ptr >= eptr - w)
{
*--ptr = ' ';
}
return(ptr);
}
char *
itoa7(int val)
{
return itoa_w(val, 7);
}
/*
* digits(val) - return number of decimal digits in val. Only works for
* positive numbers. If val < 0 then digits(val) == 0, but
* digits(0) == 1.
*/
int
digits(int val)
{
register int cnt = 0;
if (val == 0)
{
return 1;
}
while (val > 0)
{
cnt++;
val /= 10;
}
return(cnt);
}
/*
* printable(char *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(char *str)
{
register char *ptr;
register int ch;
ptr = str;
while ((ch = *ptr) != '\0')
{
if (!isprint(ch))
{
*ptr = '?';
}
ptr++;
}
return(str);
}
/*
* strcpyend(to, from) - copy string "from" into "to" and return a pointer
* to the END of the string "to".
*/
char *
strcpyend(char *to, const char *from)
{
while ((*to++ = *from++) != '\0');
return(--to);
}
/*
* char *
* homogenize(const char *str)
*
* Remove unwanted characters from "str" and make everything lower case.
* Newly allocated string is returned: the original is not altered.
*/
char *homogenize(const char *str)
{
char *ans;
char *fr;
char *to;
int ch;
to = fr = ans = estrdup(str);
while ((ch = *fr++) != '\0')
{
if (isalnum(ch))
{
*to++ = tolower(ch);
}
}
*to = '\0';
return ans;
}
/*
* string_index(string, array) - find string in array and return index
*/
int
string_index(const char *string, const char **array)
{
register int i = 0;
while (*array != NULL)
{
if (strcmp(string, *array) == 0)
{
return(i);
}
array++;
i++;
}
return(-1);
}
/*
* char *string_list(char **strings)
*
* Create a comma-separated list of the strings in the NULL-terminated
* "strings". Returned string is malloc-ed and should be freed when the
* caller is done. Note that this is not an efficient function.
*/
char *string_list(const char **strings)
{
int cnt = 0;
const char **pp;
const char *p;
char *result = NULL;
char *resp = NULL;
pp = strings;
while ((p = *pp++) != NULL)
{
cnt += strlen(p) + 2;
}
if (cnt > 0)
{
resp = result = emalloc(cnt);
pp = strings;
while ((p = *pp++) != NULL)
{
resp = strcpyend(resp, p);
if (*pp != NULL)
{
resp = strcpyend(resp, ", ");
}
}
}
return result;
}
/*
* 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(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 = emalloc(cnt * sizeof(char *));
/* allocate another array to hold the strings themselves */
args = emalloc(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(int cnt, int *out, long *new, 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;
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
#if !HAVE_DECL_SYS_ERRLIST
extern char *sys_errlist[];
#endif
extern int sys_nerr;
#endif
const char *
errmsg(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_percent(v) - format a double as a percentage in a manner that
* does not exceed 5 characters (excluding any trailing
* percent sign). Since it is possible for the value
* to exceed 100%, we format such values with no fractional
* component to fit within the 5 characters.
*/
char *
format_percent(double v)
{
static char result[10];
/* enumerate the possibilities */
if (v < 0 || v >= 100000.)
{
/* we dont want to try extreme values */
strcpy(result, " ???");
}
else if (v > 99.99)
{
sprintf(result, "%5.0f", v);
}
else
{
sprintf(result, "%5.2f", v);
}
return result;
}
/* 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(long seconds)
{
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", seconds / 60l, seconds % 60l);
}
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(long amt)
{
static char retarray[NUM_STRINGS][16];
static int idx = 0;
register char *ret;
register char tag = 'K';
ret = retarray[idx];
idx = (idx + 1) % NUM_STRINGS;
if (amt >= 10000)
{
amt = (amt + 512) / 1024;
tag = 'M';
if (amt >= 10000)
{
amt = (amt + 512) / 1024;
tag = 'G';
}
}
snprintf(ret, sizeof(retarray[idx])-1, "%ld%c", amt, tag);
return(ret);
}
/*
* Time keeping functions.
*/
static struct timeval lasttime = { 0, 0 };
static unsigned int elapsed_msecs = 0;
void
time_get(struct timeval *tv)
{
/* get the current time */
#ifdef HAVE_GETTIMEOFDAY
gettimeofday(tv, NULL);
#else
tv->tv_sec = (long)time(NULL);
tv->tv_usec = 0;
#endif
}
void
time_mark(struct timeval *tv)
{
struct timeval thistime;
struct timeval timediff;
/* if the caller didnt provide one then use our own */
if (tv == NULL)
{
tv = &thistime;
}
/* get the current time */
#ifdef HAVE_GETTIMEOFDAY
gettimeofday(tv, NULL);
#else
tv->tv_sec = (long)time(NULL);
tv->tv_usec = 0;
#endif
/* calculate the difference */
timediff.tv_sec = tv->tv_sec - lasttime.tv_sec;
timediff.tv_usec = tv->tv_usec - lasttime.tv_usec;
if (timediff.tv_usec < 0) {
timediff.tv_sec--;
timediff.tv_usec += 1000000;
}
/* convert to milliseconds */
elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000;
if (elapsed_msecs == 0)
{
elapsed_msecs = 1;
}
/* save for next time */
lasttime = *tv;
}
unsigned int
time_elapsed()
{
return elapsed_msecs;
}
unsigned int
diff_per_second(unsigned int x, unsigned int y)
{
return (y > x ? UINT_MAX - y + x + 1 : x - y) * 1000 / elapsed_msecs;
}
void
double2tv(struct timeval *tv, double d)
{
tv->tv_sec = (int)d;
tv->tv_usec = (d - tv->tv_sec) * 1000000;
}
static int debug_on = 0;
#ifdef DEBUG
FILE *debugfile;
#endif
void
debug_set(int i)
{
debug_on = i;
#ifdef DEBUG
debugfile = fopen("/tmp/top.debug", "w");
#endif
}
#ifdef DEBUG
void
xdprintf(char *fmt, ...)
{
va_list argp;
va_start(argp, fmt);
if (debug_on)
{
vfprintf(debugfile, fmt, argp);
fflush(debugfile);
}
va_end(argp);
}
#endif

79
external/bsd/top/dist/utils.h vendored Normal file
View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top users/processes display for Unix
*/
/* prototypes for functions found in utils.c */
#ifndef _UTILS_H
#define _UTILS_H
int atoiwi(char *);
char *itoa(int);
char *itoa_w(int, int);
char *itoa7(int);
int digits(int);
char *printable(char *);
char *strcpyend(char *, const char *);
char *homogenize(const char *);
int string_index(const char *, const char **);
char **argparse(char *, int *);
long percentages(int, int *, long *, long *, long *);
const char *errmsg(int);
char *format_percent(double);
char *format_time(long);
char *format_k(long);
char *string_list(const char **);
void time_get(struct timeval *);
void time_mark(struct timeval *);
void double2tv(struct timeval *, double);
unsigned int time_elapsed(void);
unsigned int diff_per_second(unsigned int, unsigned int);
void debug_set(int);
#ifdef DEBUG
#define dprintf xdprintf
void xdprintf(char *fmt, ...);
#else
#ifdef HAVE_C99_VARIADIC_MACROS
#define dprintf(...)
#else
#ifdef HAVE_GNU_VARIADIC_MACROS
#define dprintf(x...)
#else
#define dprintf if (0)
#endif
#endif
#endif
#endif

47
external/bsd/top/dist/version.c vendored Normal file
View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top users/processes display for Unix
* Version 3
*/
#include "config.h"
#include "top.h"
#include "version.h"
const char *
version_string(void)
{
return(PACKAGE_VERSION);
}

37
external/bsd/top/dist/version.h vendored Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 1984 through 2008, William LeFebvre
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of William LeFebvre nor the names of other
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Top users/processes display for Unix
*/
const char *version_string(void);

View File

@@ -8,7 +8,7 @@ SUBDIR+= diff
SUBDIR+= grep
SUBDIR+= mined
SUBDIR+= ministat
SUBDIR+= top
SUBDIR+= mtop
SUBDIR+= toproto
SUBDIR+= trace

View File

@@ -1,7 +1,9 @@
PROG= top
PROG= mtop
MAN=
DPADD+= ${LIBCURSES} ${LIBTERMINFO}
LDADD+= -lcurses -lterminfo
WARNS?= 5
.include <bsd.prog.mk>