./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
./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
SUBDIR= byacc \
fetch file flex less \
libarchive libevent mdocml \
- tmux
+ tmux top
.if (${MKATF} != "no")
SUBDIR+= atf
--- /dev/null
+# $NetBSD: Makefile,v 1.2 2008/07/17 10:46:56 lukem Exp $
+
+SUBDIR= bin
+
+.include <bsd.subdir.mk>
--- /dev/null
+# $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>
--- /dev/null
+/* 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 */
--- /dev/null
+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.
--- /dev/null
+ 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.
+
--- /dev/null
+ 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.
--- /dev/null
+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.
--- /dev/null
+# 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
--- /dev/null
+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.
+
+
--- /dev/null
+ 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
--- /dev/null
+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.
--- /dev/null
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This code is based on, and used with the permission of, the
+ * SIO stdio-replacement strx_* functions by Panos Tsirigotis
+ * <panos@alumni.cs.colorado.edu> for xinetd.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <netinet/in.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+typedef struct {
+ char *curpos;
+ char *endpos;
+} ap_vformatter_buff;
+
+
+#define API_EXPORT(type) type
+#define API_EXPORT_NONSTD(type) type
+
+#define ap_isalnum(c) (isalnum(((unsigned char)(c))))
+#define ap_isalpha(c) (isalpha(((unsigned char)(c))))
+#define ap_iscntrl(c) (iscntrl(((unsigned char)(c))))
+#define ap_isdigit(c) (isdigit(((unsigned char)(c))))
+#define ap_isgraph(c) (isgraph(((unsigned char)(c))))
+#define ap_islower(c) (islower(((unsigned char)(c))))
+#define ap_isprint(c) (isprint(((unsigned char)(c))))
+#define ap_ispunct(c) (ispunct(((unsigned char)(c))))
+#define ap_isspace(c) (isspace(((unsigned char)(c))))
+#define ap_isupper(c) (isupper(((unsigned char)(c))))
+#define ap_isxdigit(c) (isxdigit(((unsigned char)(c))))
+#define ap_tolower(c) (tolower(((unsigned char)(c))))
+#define ap_toupper(c) (toupper(((unsigned char)(c))))
+
+
+typedef enum {
+ NO = 0, YES = 1
+} boolean_e;
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef AP_LONGEST_LONG
+#define AP_LONGEST_LONG long
+#endif
+#define NUL '\0'
+#define WIDE_INT long
+#define WIDEST_INT AP_LONGEST_LONG
+
+typedef WIDE_INT wide_int;
+typedef unsigned WIDE_INT u_wide_int;
+typedef WIDEST_INT widest_int;
+#ifdef __TANDEM
+/* Although Tandem supports "long long" there is no unsigned variant. */
+typedef unsigned long u_widest_int;
+#else
+typedef unsigned WIDEST_INT u_widest_int;
+#endif
+typedef int bool_int;
+
+#define S_NULL "(null)"
+#define S_NULL_LEN 6
+
+#define FLOAT_DIGITS 6
+#define EXPONENT_LENGTH 10
+
+/*
+ * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
+ *
+ * XXX: this is a magic number; do not decrease it
+ */
+#define NUM_BUF_SIZE 512
+
+/*
+ * cvt.c - IEEE floating point formatting routines for FreeBSD
+ * from GNU libc-4.6.27. Modified to be thread safe.
+ */
+
+/*
+ * ap_ecvt converts to decimal
+ * the number of digits is specified by ndigit
+ * decpt is set to the position of the decimal point
+ * sign is set to 0 for positive, 1 for negative
+ */
+
+#define NDIG 80
+
+/* buf must have at least NDIG bytes */
+static char *ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf)
+{
+ register int r2;
+ double fi, fj;
+ register char *p, *p1;
+
+ if (ndigits >= NDIG - 1)
+ ndigits = NDIG - 2;
+ r2 = 0;
+ *sign = 0;
+ p = &buf[0];
+ if (arg < 0) {
+ *sign = 1;
+ arg = -arg;
+ }
+ arg = modf(arg, &fi);
+ p1 = &buf[NDIG];
+ /*
+ * Do integer part
+ */
+ if (fi != 0) {
+ p1 = &buf[NDIG];
+ while (p1 > &buf[0] && fi != 0) {
+ fj = modf(fi / 10, &fi);
+ *--p1 = (int) ((fj + .03) * 10) + '0';
+ r2++;
+ }
+ while (p1 < &buf[NDIG])
+ *p++ = *p1++;
+ }
+ else if (arg > 0) {
+ while ((fj = arg * 10) < 1) {
+ arg = fj;
+ r2--;
+ }
+ }
+ p1 = &buf[ndigits];
+ if (eflag == 0)
+ p1 += r2;
+ *decpt = r2;
+ if (p1 < &buf[0]) {
+ buf[0] = '\0';
+ return (buf);
+ }
+ while (p <= p1 && p < &buf[NDIG]) {
+ arg *= 10;
+ arg = modf(arg, &fj);
+ *p++ = (int) fj + '0';
+ }
+ if (p1 >= &buf[NDIG]) {
+ buf[NDIG - 1] = '\0';
+ return (buf);
+ }
+ p = p1;
+ *p1 += 5;
+ while (*p1 > '9') {
+ *p1 = '0';
+ if (p1 > buf)
+ ++ * --p1;
+ else {
+ *p1 = '1';
+ (*decpt)++;
+ if (eflag == 0) {
+ if (p > buf)
+ *p = '0';
+ p++;
+ }
+ }
+ }
+ *p = '\0';
+ return (buf);
+}
+
+static char *ap_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
+{
+ return (ap_cvt(arg, ndigits, decpt, sign, 1, buf));
+}
+
+static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
+{
+ return (ap_cvt(arg, ndigits, decpt, sign, 0, buf));
+}
+
+/*
+ * ap_gcvt - Floating output conversion to
+ * minimal length string
+ */
+
+static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
+{
+ int sign, decpt;
+ register char *p1, *p2;
+ register int i;
+ char buf1[NDIG];
+
+ p1 = ap_ecvt(number, ndigit, &decpt, &sign, buf1);
+ p2 = buf;
+ if (sign)
+ *p2++ = '-';
+ for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
+ ndigit--;
+ if ((decpt >= 0 && decpt - ndigit > 4)
+ || (decpt < 0 && decpt < -3)) { /* use E-style */
+ decpt--;
+ *p2++ = *p1++;
+ *p2++ = '.';
+ for (i = 1; i < ndigit; i++)
+ *p2++ = *p1++;
+ *p2++ = 'e';
+ if (decpt < 0) {
+ decpt = -decpt;
+ *p2++ = '-';
+ }
+ else
+ *p2++ = '+';
+ if (decpt / 100 > 0)
+ *p2++ = decpt / 100 + '0';
+ if (decpt / 10 > 0)
+ *p2++ = (decpt % 100) / 10 + '0';
+ *p2++ = decpt % 10 + '0';
+ }
+ else {
+ if (decpt <= 0) {
+ if (*p1 != '0')
+ *p2++ = '.';
+ while (decpt < 0) {
+ decpt++;
+ *p2++ = '0';
+ }
+ }
+ for (i = 1; i <= ndigit; i++) {
+ *p2++ = *p1++;
+ if (i == decpt)
+ *p2++ = '.';
+ }
+ if (ndigit < decpt) {
+ while (ndigit++ < decpt)
+ *p2++ = '0';
+ *p2++ = '.';
+ }
+ }
+ if (p2[-1] == '.' && !altform)
+ p2--;
+ *p2 = '\0';
+ return (buf);
+}
+
+/*
+ * The INS_CHAR macro inserts a character in the buffer and writes
+ * the buffer back to disk if necessary
+ * It uses the char pointers sp and bep:
+ * sp points to the next available character in the buffer
+ * bep points to the end-of-buffer+1
+ * While using this macro, note that the nextb pointer is NOT updated.
+ *
+ * NOTE: Evaluation of the c argument should not have any side-effects
+ */
+#define INS_CHAR(c, sp, bep, cc) \
+ { \
+ if (sp >= bep) { \
+ vbuff->curpos = sp; \
+ if (flush_func(vbuff)) \
+ return -1; \
+ sp = vbuff->curpos; \
+ bep = vbuff->endpos; \
+ } \
+ *sp++ = (c); \
+ cc++; \
+ }
+
+#define NUM( c ) ( c - '0' )
+
+#define STR_TO_DEC( str, num ) \
+ num = NUM( *str++ ) ; \
+ while ( ap_isdigit( *str ) ) \
+ { \
+ num *= 10 ; \
+ num += NUM( *str++ ) ; \
+ }
+
+/*
+ * This macro does zero padding so that the precision
+ * requirement is satisfied. The padding is done by
+ * adding '0's to the left of the string that is going
+ * to be printed. We don't allow precision to be large
+ * enough that we continue past the start of s.
+ *
+ * NOTE: this makes use of the magic info that s is
+ * always based on num_buf with a size of NUM_BUF_SIZE.
+ */
+#define FIX_PRECISION( adjust, precision, s, s_len ) \
+ if ( adjust ) { \
+ int p = precision < NUM_BUF_SIZE - 1 ? precision : NUM_BUF_SIZE - 1; \
+ while ( s_len < p ) \
+ { \
+ *--s = '0' ; \
+ s_len++ ; \
+ } \
+ }
+
+/*
+ * Macro that does padding. The padding is done by printing
+ * the character ch.
+ */
+#define PAD( width, len, ch ) do \
+ { \
+ INS_CHAR( ch, sp, bep, cc ) ; \
+ width-- ; \
+ } \
+ while ( width > len )
+
+/*
+ * Prefix the character ch to the string str
+ * Increase length
+ * Set the has_prefix flag
+ */
+#define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES
+
+
+/*
+ * Convert num to its decimal format.
+ * Return value:
+ * - a pointer to a string containing the number (no sign)
+ * - len contains the length of the string
+ * - is_negative is set to TRUE or FALSE depending on the sign
+ * of the number (always set to FALSE if is_unsigned is TRUE)
+ *
+ * The caller provides a buffer for the string: that is the buf_end argument
+ * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
+ * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * Note: we have 2 versions. One is used when we need to use quads
+ * (conv_10_quad), the other when we don't (conv_10). We're assuming the
+ * latter is faster.
+ */
+static char *conv_10(register wide_int num, register bool_int is_unsigned,
+ register bool_int *is_negative, char *buf_end,
+ register int *len)
+{
+ register char *p = buf_end;
+ register u_wide_int magnitude;
+
+ if (is_unsigned) {
+ magnitude = (u_wide_int) num;
+ *is_negative = FALSE;
+ }
+ else {
+ *is_negative = (num < 0);
+
+ /*
+ * On a 2's complement machine, negating the most negative integer
+ * results in a number that cannot be represented as a signed integer.
+ * Here is what we do to obtain the number's magnitude:
+ * a. add 1 to the number
+ * b. negate it (becomes positive)
+ * c. convert it to unsigned
+ * d. add 1
+ */
+ if (*is_negative) {
+ wide_int t = num + 1;
+
+ magnitude = ((u_wide_int) -t) + 1;
+ }
+ else
+ magnitude = (u_wide_int) num;
+ }
+
+ /*
+ * We use a do-while loop so that we write at least 1 digit
+ */
+ do {
+ register u_wide_int new_magnitude = magnitude / 10;
+
+ *--p = (char) (magnitude - new_magnitude * 10 + '0');
+ magnitude = new_magnitude;
+ }
+ while (magnitude);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+static char *conv_10_quad(widest_int num, register bool_int is_unsigned,
+ register bool_int *is_negative, char *buf_end,
+ register int *len)
+{
+ register char *p = buf_end;
+ u_widest_int magnitude;
+
+ /*
+ * We see if we can use the faster non-quad version by checking the
+ * number against the largest long value it can be. If <=, we
+ * punt to the quicker version.
+ */
+ if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned))
+ return(conv_10( (wide_int)num, is_unsigned, is_negative,
+ buf_end, len));
+
+ if (is_unsigned) {
+ magnitude = (u_widest_int) num;
+ *is_negative = FALSE;
+ }
+ else {
+ *is_negative = (num < 0);
+
+ /*
+ * On a 2's complement machine, negating the most negative integer
+ * results in a number that cannot be represented as a signed integer.
+ * Here is what we do to obtain the number's magnitude:
+ * a. add 1 to the number
+ * b. negate it (becomes positive)
+ * c. convert it to unsigned
+ * d. add 1
+ */
+ if (*is_negative) {
+ widest_int t = num + 1;
+
+ magnitude = ((u_widest_int) -t) + 1;
+ }
+ else
+ magnitude = (u_widest_int) num;
+ }
+
+ /*
+ * We use a do-while loop so that we write at least 1 digit
+ */
+ do {
+ u_widest_int new_magnitude = magnitude / 10;
+
+ *--p = (char) (magnitude - new_magnitude * 10 + '0');
+ magnitude = new_magnitude;
+ }
+ while (magnitude);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+
+
+static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
+{
+ unsigned addr = ntohl(ia->s_addr);
+ char *p = buf_end;
+ bool_int is_negative;
+ int sub_len;
+
+ p = conv_10((addr & 0x000000FF) , TRUE, &is_negative, p, &sub_len);
+ *--p = '.';
+ p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len);
+ *--p = '.';
+ p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
+ *--p = '.';
+ p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+
+
+static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
+{
+ char *p = buf_end;
+ bool_int is_negative;
+ int sub_len;
+
+ p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
+ *--p = ':';
+ p = conv_in_addr(&si->sin_addr, p, &sub_len);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+
+
+/*
+ * Convert a floating point number to a string formats 'f', 'e' or 'E'.
+ * The result is placed in buf, and len denotes the length of the string
+ * The sign is returned in the is_negative argument (and is not placed
+ * in buf).
+ */
+static char *conv_fp(register char format, register double num,
+ boolean_e add_dp, int precision, bool_int *is_negative,
+ char *buf, int *len)
+{
+ register char *s = buf;
+ register char *p;
+ int decimal_point;
+ char buf1[NDIG];
+
+ if (format == 'f')
+ p = ap_fcvt(num, precision, &decimal_point, is_negative, buf1);
+ else /* either e or E format */
+ p = ap_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
+
+ /*
+ * Check for Infinity and NaN
+ */
+ if (ap_isalpha(*p)) {
+ *len = strlen(strcpy(buf, p));
+ *is_negative = FALSE;
+ return (buf);
+ }
+
+ if (format == 'f') {
+ if (decimal_point <= 0) {
+ *s++ = '0';
+ if (precision > 0) {
+ *s++ = '.';
+ while (decimal_point++ < 0)
+ *s++ = '0';
+ }
+ else if (add_dp)
+ *s++ = '.';
+ }
+ else {
+ while (decimal_point-- > 0)
+ *s++ = *p++;
+ if (precision > 0 || add_dp)
+ *s++ = '.';
+ }
+ }
+ else {
+ *s++ = *p++;
+ if (precision > 0 || add_dp)
+ *s++ = '.';
+ }
+
+ /*
+ * copy the rest of p, the NUL is NOT copied
+ */
+ while (*p)
+ *s++ = *p++;
+
+ if (format != 'f') {
+ char temp[EXPONENT_LENGTH]; /* for exponent conversion */
+ int t_len;
+ bool_int exponent_is_negative;
+
+ *s++ = format; /* either e or E */
+ decimal_point--;
+ if (decimal_point != 0) {
+ p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative,
+ &temp[EXPONENT_LENGTH], &t_len);
+ *s++ = exponent_is_negative ? '-' : '+';
+
+ /*
+ * Make sure the exponent has at least 2 digits
+ */
+ if (t_len == 1)
+ *s++ = '0';
+ while (t_len--)
+ *s++ = *p++;
+ }
+ else {
+ *s++ = '+';
+ *s++ = '0';
+ *s++ = '0';
+ }
+ }
+
+ *len = s - buf;
+ return (buf);
+}
+
+
+/*
+ * Convert num to a base X number where X is a power of 2. nbits determines X.
+ * For example, if nbits is 3, we do base 8 conversion
+ * Return value:
+ * a pointer to a string containing the number
+ *
+ * The caller provides a buffer for the string: that is the buf_end argument
+ * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
+ * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
+ *
+ * As with conv_10, we have a faster version which is used when
+ * the number isn't quad size.
+ */
+static char *conv_p2(register u_wide_int num, register int nbits,
+ char format, char *buf_end, register int *len)
+{
+ register int mask = (1 << nbits) - 1;
+ register char *p = buf_end;
+ static const char low_digits[] = "0123456789abcdef";
+ static const char upper_digits[] = "0123456789ABCDEF";
+ register const char *digits = (format == 'X') ? upper_digits : low_digits;
+
+ do {
+ *--p = digits[num & mask];
+ num >>= nbits;
+ }
+ while (num);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+static char *conv_p2_quad(u_widest_int num, register int nbits,
+ char format, char *buf_end, register int *len)
+{
+ register int mask = (1 << nbits) - 1;
+ register char *p = buf_end;
+ static const char low_digits[] = "0123456789abcdef";
+ static const char upper_digits[] = "0123456789ABCDEF";
+ register const char *digits = (format == 'X') ? upper_digits : low_digits;
+
+ if (num <= ULONG_MAX)
+ return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));
+
+ do {
+ *--p = digits[num & mask];
+ num >>= nbits;
+ }
+ while (num);
+
+ *len = buf_end - p;
+ return (p);
+}
+
+
+/*
+ * Do format conversion placing the output in buffer
+ */
+API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
+ ap_vformatter_buff *vbuff, const char *fmt, va_list ap)
+{
+ register char *sp;
+ register char *bep;
+ register int cc = 0;
+ register int i;
+
+ register char *s = NULL;
+ char *q;
+ int s_len;
+
+ register int min_width = 0;
+ int precision = 0;
+ enum {
+ LEFT, RIGHT
+ } adjust;
+ char pad_char;
+ char prefix_char;
+
+ double fp_num;
+ widest_int i_quad = (widest_int) 0;
+ u_widest_int ui_quad;
+ wide_int i_num = (wide_int) 0;
+ u_wide_int ui_num;
+
+ char num_buf[NUM_BUF_SIZE];
+ char char_buf[2]; /* for printing %% and %<unknown> */
+
+ enum var_type_enum {
+ IS_QUAD, IS_LONG, IS_SHORT, IS_INT
+ };
+ enum var_type_enum var_type = IS_INT;
+
+ /*
+ * Flag variables
+ */
+ boolean_e alternate_form;
+ boolean_e print_sign;
+ boolean_e print_blank;
+ boolean_e adjust_precision;
+ boolean_e adjust_width;
+ bool_int is_negative;
+
+ sp = vbuff->curpos;
+ bep = vbuff->endpos;
+
+ while (*fmt) {
+ if (*fmt != '%') {
+ INS_CHAR(*fmt, sp, bep, cc);
+ }
+ else {
+ /*
+ * Default variable settings
+ */
+ adjust = RIGHT;
+ alternate_form = print_sign = print_blank = NO;
+ pad_char = ' ';
+ prefix_char = NUL;
+
+ fmt++;
+
+ /*
+ * Try to avoid checking for flags, width or precision
+ */
+ if (!ap_islower(*fmt)) {
+ /*
+ * Recognize flags: -, #, BLANK, +
+ */
+ for (;; fmt++) {
+ if (*fmt == '-')
+ adjust = LEFT;
+ else if (*fmt == '+')
+ print_sign = YES;
+ else if (*fmt == '#')
+ alternate_form = YES;
+ else if (*fmt == ' ')
+ print_blank = YES;
+ else if (*fmt == '0')
+ pad_char = '0';
+ else
+ break;
+ }
+
+ /*
+ * Check if a width was specified
+ */
+ if (ap_isdigit(*fmt)) {
+ STR_TO_DEC(fmt, min_width);
+ adjust_width = YES;
+ }
+ else if (*fmt == '*') {
+ min_width = va_arg(ap, int);
+ fmt++;
+ adjust_width = YES;
+ if (min_width < 0) {
+ adjust = LEFT;
+ min_width = -min_width;
+ }
+ }
+ else
+ adjust_width = NO;
+
+ /*
+ * Check if a precision was specified
+ */
+ if (*fmt == '.') {
+ adjust_precision = YES;
+ fmt++;
+ if (ap_isdigit(*fmt)) {
+ STR_TO_DEC(fmt, precision);
+ }
+ else if (*fmt == '*') {
+ precision = va_arg(ap, int);
+ fmt++;
+ if (precision < 0)
+ precision = 0;
+ }
+ else
+ precision = 0;
+ }
+ else
+ adjust_precision = NO;
+ }
+ else
+ adjust_precision = adjust_width = NO;
+
+ /*
+ * Modifier check
+ */
+ if (*fmt == 'q') {
+ var_type = IS_QUAD;
+ fmt++;
+ }
+ else if (*fmt == 'l') {
+ var_type = IS_LONG;
+ fmt++;
+ }
+ else if (*fmt == 'h') {
+ var_type = IS_SHORT;
+ fmt++;
+ }
+ else {
+ var_type = IS_INT;
+ }
+
+ /*
+ * Argument extraction and printing.
+ * First we determine the argument type.
+ * Then, we convert the argument to a string.
+ * On exit from the switch, s points to the string that
+ * must be printed, s_len has the length of the string
+ * The precision requirements, if any, are reflected in s_len.
+ *
+ * NOTE: pad_char may be set to '0' because of the 0 flag.
+ * It is reset to ' ' by non-numeric formats
+ */
+ switch (*fmt) {
+ case 'u':
+ if (var_type == IS_QUAD) {
+ i_quad = va_arg(ap, u_widest_int);
+ s = conv_10_quad(i_quad, 1, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ i_num = (wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ i_num = (wide_int) va_arg(ap, unsigned int);
+ s = conv_10(i_num, 1, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ FIX_PRECISION(adjust_precision, precision, s, s_len);
+ break;
+
+ case 'd':
+ case 'i':
+ if (var_type == IS_QUAD) {
+ i_quad = va_arg(ap, widest_int);
+ s = conv_10_quad(i_quad, 0, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ i_num = (wide_int) va_arg(ap, wide_int);
+ else if (var_type == IS_SHORT)
+ i_num = (wide_int) (short) va_arg(ap, int);
+ else
+ i_num = (wide_int) va_arg(ap, int);
+ s = conv_10(i_num, 0, &is_negative,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ FIX_PRECISION(adjust_precision, precision, s, s_len);
+
+ if (is_negative)
+ prefix_char = '-';
+ else if (print_sign)
+ prefix_char = '+';
+ else if (print_blank)
+ prefix_char = ' ';
+ break;
+
+
+ case 'o':
+ if (var_type == IS_QUAD) {
+ ui_quad = va_arg(ap, u_widest_int);
+ s = conv_p2_quad(ui_quad, 3, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ ui_num = (u_wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ ui_num = (u_wide_int) va_arg(ap, unsigned int);
+ s = conv_p2(ui_num, 3, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ FIX_PRECISION(adjust_precision, precision, s, s_len);
+ if (alternate_form && *s != '0') {
+ *--s = '0';
+ s_len++;
+ }
+ break;
+
+
+ case 'x':
+ case 'X':
+ if (var_type == IS_QUAD) {
+ ui_quad = va_arg(ap, u_widest_int);
+ s = conv_p2_quad(ui_quad, 4, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ else {
+ if (var_type == IS_LONG)
+ ui_num = (u_wide_int) va_arg(ap, u_wide_int);
+ else if (var_type == IS_SHORT)
+ ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
+ else
+ ui_num = (u_wide_int) va_arg(ap, unsigned int);
+ s = conv_p2(ui_num, 4, *fmt,
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+ FIX_PRECISION(adjust_precision, precision, s, s_len);
+ if (alternate_form && i_num != 0) {
+ *--s = *fmt; /* 'x' or 'X' */
+ *--s = '0';
+ s_len += 2;
+ }
+ break;
+
+
+ case 's':
+ s = va_arg(ap, char *);
+ if (s != NULL) {
+ s_len = strlen(s);
+ if (adjust_precision && precision < s_len)
+ s_len = precision;
+ }
+ else {
+ s = S_NULL;
+ s_len = S_NULL_LEN;
+ }
+ pad_char = ' ';
+ break;
+
+
+ case 'f':
+ case 'e':
+ case 'E':
+ fp_num = va_arg(ap, double);
+ /*
+ * * We use &num_buf[ 1 ], so that we have room for the sign
+ */
+#ifdef HAVE_ISNAN
+ if (isnan(fp_num)) {
+ s = "nan";
+ s_len = 3;
+ }
+ else
+#endif
+#ifdef HAVE_ISINF
+ if (isinf(fp_num)) {
+ s = "inf";
+ s_len = 3;
+ }
+ else
+#endif
+ {
+ s = conv_fp(*fmt, fp_num, alternate_form,
+ (adjust_precision == NO) ? FLOAT_DIGITS : precision,
+ &is_negative, &num_buf[1], &s_len);
+ if (is_negative)
+ prefix_char = '-';
+ else if (print_sign)
+ prefix_char = '+';
+ else if (print_blank)
+ prefix_char = ' ';
+ }
+ break;
+
+
+ case 'g':
+ case 'G':
+ if (adjust_precision == NO)
+ precision = FLOAT_DIGITS;
+ else if (precision == 0)
+ precision = 1;
+ /*
+ * * We use &num_buf[ 1 ], so that we have room for the sign
+ */
+ s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],
+ alternate_form);
+ if (*s == '-')
+ prefix_char = *s++;
+ else if (print_sign)
+ prefix_char = '+';
+ else if (print_blank)
+ prefix_char = ' ';
+
+ s_len = strlen(s);
+
+ if (alternate_form && (q = strchr(s, '.')) == NULL) {
+ s[s_len++] = '.';
+ s[s_len] = '\0'; /* delimit for following strchr() */
+ }
+ if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
+ *q = 'E';
+ break;
+
+
+ case 'c':
+ char_buf[0] = (char) (va_arg(ap, int));
+ s = &char_buf[0];
+ s_len = 1;
+ pad_char = ' ';
+ break;
+
+
+ case '%':
+ char_buf[0] = '%';
+ s = &char_buf[0];
+ s_len = 1;
+ pad_char = ' ';
+ break;
+
+
+ case 'n':
+ if (var_type == IS_QUAD)
+ *(va_arg(ap, widest_int *)) = cc;
+ else if (var_type == IS_LONG)
+ *(va_arg(ap, long *)) = cc;
+ else if (var_type == IS_SHORT)
+ *(va_arg(ap, short *)) = cc;
+ else
+ *(va_arg(ap, int *)) = cc;
+ break;
+
+ /*
+ * This is where we extend the printf format, with a second
+ * type specifier
+ */
+ case 'p':
+ switch(*++fmt) {
+ /*
+ * If the pointer size is equal to or smaller than the size
+ * of the largest unsigned int, we convert the pointer to a
+ * hex number, otherwise we print "%p" to indicate that we
+ * don't handle "%p".
+ */
+ case 'p':
+#ifdef AP_VOID_P_IS_QUAD
+ if (sizeof(void *) <= sizeof(u_widest_int)) {
+ ui_quad = (u_widest_int) va_arg(ap, void *);
+ s = conv_p2_quad(ui_quad, 4, 'x',
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+#else
+ if (sizeof(void *) <= sizeof(u_wide_int)) {
+ ui_num = (u_wide_int) va_arg(ap, void *);
+ s = conv_p2(ui_num, 4, 'x',
+ &num_buf[NUM_BUF_SIZE], &s_len);
+ }
+#endif
+ else {
+ s = "%p";
+ s_len = 2;
+ prefix_char = NUL;
+ }
+ pad_char = ' ';
+ break;
+
+ /* print a struct sockaddr_in as a.b.c.d:port */
+ case 'I':
+ {
+ struct sockaddr_in *si;
+
+ si = va_arg(ap, struct sockaddr_in *);
+ if (si != NULL) {
+ s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
+ if (adjust_precision && precision < s_len)
+ s_len = precision;
+ }
+ else {
+ s = S_NULL;
+ s_len = S_NULL_LEN;
+ }
+ pad_char = ' ';
+ }
+ break;
+
+ /* print a struct in_addr as a.b.c.d */
+ case 'A':
+ {
+ struct in_addr *ia;
+
+ ia = va_arg(ap, struct in_addr *);
+ if (ia != NULL) {
+ s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
+ if (adjust_precision && precision < s_len)
+ s_len = precision;
+ }
+ else {
+ s = S_NULL;
+ s_len = S_NULL_LEN;
+ }
+ pad_char = ' ';
+ }
+ break;
+
+ case NUL:
+ /* if %p ends the string, oh well ignore it */
+ continue;
+
+ default:
+ s = "bogus %p";
+ s_len = 8;
+ prefix_char = NUL;
+ break;
+ }
+ break;
+
+ case NUL:
+ /*
+ * The last character of the format string was %.
+ * We ignore it.
+ */
+ continue;
+
+
+ /*
+ * The default case is for unrecognized %'s.
+ * We print %<char> to help the user identify what
+ * option is not understood.
+ * This is also useful in case the user wants to pass
+ * the output of format_converter to another function
+ * that understands some other %<char> (like syslog).
+ * Note that we can't point s inside fmt because the
+ * unknown <char> could be preceded by width etc.
+ */
+ default:
+ char_buf[0] = '%';
+ char_buf[1] = *fmt;
+ s = char_buf;
+ s_len = 2;
+ pad_char = ' ';
+ break;
+ }
+
+ if (prefix_char != NUL && s != S_NULL && s != char_buf) {
+ *--s = prefix_char;
+ s_len++;
+ }
+
+ if (adjust_width && adjust == RIGHT && min_width > s_len) {
+ if (pad_char == '0' && prefix_char != NUL) {
+ INS_CHAR(*s, sp, bep, cc);
+ s++;
+ s_len--;
+ min_width--;
+ }
+ PAD(min_width, s_len, pad_char);
+ }
+
+ /*
+ * Print the string s.
+ */
+ for (i = s_len; i != 0; i--) {
+ INS_CHAR(*s, sp, bep, cc);
+ s++;
+ }
+
+ if (adjust_width && adjust == LEFT && min_width > s_len)
+ PAD(min_width, s_len, pad_char);
+ }
+ fmt++;
+ }
+ vbuff->curpos = sp;
+
+ return cc;
+}
+
+
+static int snprintf_flush(ap_vformatter_buff *vbuff)
+{
+ /* if the buffer fills we have to abort immediately, there is no way
+ * to "flush" an ap_snprintf... there's nowhere to flush it to.
+ */
+ return -1;
+}
+
+
+API_EXPORT_NONSTD(int) ap_snprintf(char *buf, size_t len, const char *format,...)
+{
+ int cc;
+ va_list ap;
+ ap_vformatter_buff vbuff;
+
+ if (len == 0)
+ return 0;
+
+ /* save one byte for nul terminator */
+ vbuff.curpos = buf;
+ vbuff.endpos = buf + len - 1;
+ va_start(ap, format);
+ cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
+ va_end(ap);
+ *vbuff.curpos = '\0';
+ return (cc == -1) ? len : cc;
+}
+
+
+API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
+ va_list ap)
+{
+ int cc;
+ ap_vformatter_buff vbuff;
+
+ if (len == 0)
+ return 0;
+
+ /* save one byte for nul terminator */
+ vbuff.curpos = buf;
+ vbuff.endpos = buf + len - 1;
+ cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
+ *vbuff.curpos = '\0';
+ return (cc == -1) ? len : cc;
+}
--- /dev/null
+/* My favorite names for boolean values */
+#define No 0
+#define Yes 1
+#define Maybe 2 /* tri-state boolean, actually */
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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 implement some of the interactive
+ * mode commands. Note that some of the commands are implemented in-line
+ * in "main". This is necessary because they change the global state of
+ * "top" (i.e.: changing the number of processes to display).
+ */
+
+#include "os.h"
+#include <ctype.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <color.h>
+#include <errno.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#if defined(HAVE_DECL_SYS_SIGLIST) & defined(HAVE_STRCASECMP)
+#define USE_SYS_SIGLIST
+#endif
+
+#ifdef USE_SYS_SIGLIST
+extern const char * const sys_siglist[];
+extern const char * const sys_signame[];
+#else
+#include "sigdesc.h" /* generated automatically */
+#endif
+#include "top.h"
+#include "machine.h"
+#include "globalstate.h"
+#include "boolean.h"
+#include "color.h"
+#include "commands.h"
+#include "display.h"
+#include "screen.h"
+#include "username.h"
+#include "utils.h"
+#include "version.h"
+
+extern char *copyright;
+
+typedef struct command {
+ int ch;
+ int (*cmd_func)(globalstate *);
+ const char *help;
+} command;
+
+/*
+ * Some of the commands make system calls that could generate errors.
+ * These errors are collected up in an array of structures for later
+ * contemplation and display. Such routines return a string containing an
+ * error message, or NULL if no errors occurred. We need an upper limit on
+ * the number of errors, so we arbitrarily choose 20.
+ */
+
+#define ERRMAX 20
+
+struct errs /* structure for a system-call error */
+{
+ int errnum; /* value of errno (that is, the actual error) */
+ char *arg; /* argument that caused the error */
+};
+
+static struct errs errs[ERRMAX];
+static int errcnt;
+
+/* These macros get used to reset and log the errors */
+#define ERR_RESET errcnt = 0
+#define ERROR(p, e) if (errcnt < ERRMAX) \
+ { \
+ errs[errcnt].arg = (p); \
+ errs[errcnt++].errnum = (e); \
+ }
+
+/*
+ * err_compar(p1, p2) - comparison routine used by "qsort"
+ * for sorting errors.
+ */
+
+static int
+err_compar(const void *p1, const void *p2)
+
+{
+ register int result;
+
+ if ((result = ((const struct errs *)p1)->errnum -
+ ((const struct errs *)p2)->errnum) == 0)
+ {
+ return(strcmp(((const struct errs *)p1)->arg,
+ ((const struct errs *)p2)->arg));
+ }
+ return(result);
+}
+
+/*
+ * str_adderr(str, len, err) - add an explanation of error "err" to
+ * the string "str" without overflowing length "len". return
+ * number of characters remaining in str, or 0 if overflowed.
+ */
+
+static int
+str_adderr(char *str, int len, int err)
+
+{
+ register const char *msg;
+ register int msglen;
+
+ msg = err == 0 ? "Not a number" : errmsg(err);
+ msglen = strlen(msg) + 2;
+ if (len <= msglen)
+ {
+ return(0);
+ }
+ (void) strcat(str, ": ");
+ (void) strcat(str, msg);
+ return(len - msglen);
+}
+
+/*
+ * str_addarg(str, len, arg, first) - add the string argument "arg" to
+ * the string "str" without overflowing length "len". This is the
+ * first in the group when "first" is set (indicating that a comma
+ * should NOT be added to the front). Return number of characters
+ * remaining in str, or 0 if overflowed.
+ */
+
+static int
+str_addarg(char *str, int len, char *arg, int first)
+
+{
+ register int arglen;
+
+ arglen = strlen(arg);
+ if (!first)
+ {
+ arglen += 2;
+ }
+ if (len <= arglen)
+ {
+ return(0);
+ }
+ if (!first)
+ {
+ (void) strcat(str, ", ");
+ }
+ (void) strcat(str, arg);
+ return(len - arglen);
+}
+
+/*
+ * void err_string()
+ *
+ * Use message_error to log errors in the errs array. This function
+ * will combine identical errors to make the message short, but if
+ * there is more than one type of error it will call message_error
+ * for each one.
+ */
+
+#define STRMAX 80
+
+static void
+err_string(void)
+
+{
+ register struct errs *errp;
+ register int cnt = 0;
+ register int first = Yes;
+ register int currerr = -1;
+ int stringlen = 0; /* characters still available in "string" */
+ char string[STRMAX];
+
+ /* if there are no errors, our job is easy */
+ if (errcnt == 0)
+ {
+ return;
+ }
+
+ /* sort the errors */
+ qsort((char *)errs, errcnt, sizeof(struct errs), err_compar);
+
+ /* initialize the buffer (probably not necessary) */
+ string[0] = '\0';
+ stringlen = STRMAX - 1;
+
+ /* loop thru the sorted list, logging errors */
+ while (cnt < errcnt)
+ {
+ /* point to the current error */
+ errp = &(errs[cnt++]);
+
+ /* note that on overflow "stringlen" will become 0 and all
+ subsequent calls to str_addarg or str_adderr will return 0 */
+
+ /* if the error number is different then add the error string */
+ if (errp->errnum != currerr)
+ {
+ if (currerr != -1)
+ {
+ /* add error string and log the error */
+ stringlen = str_adderr(string, stringlen, currerr);
+ message_error(" %s", string);
+
+ }
+ /* reset the buffer */
+ string[0] = '\0';
+ stringlen = STRMAX - 1;
+
+ /* move to next error num */
+ currerr = errp->errnum;
+ first = Yes;
+ }
+
+ /* add this arg */
+ stringlen = str_addarg(string, stringlen, errp->arg, first);
+ first = No;
+ }
+
+ /* add final message */
+ stringlen = str_adderr(string, stringlen, currerr);
+
+ /* write the error string */
+ message_error(" %s", string);
+}
+
+/*
+ * Utility routines that help with some of the commands.
+ */
+
+static char *
+next_field(char *str)
+
+
+{
+ if ((str = strchr(str, ' ')) == NULL)
+ {
+ return(NULL);
+ }
+ *str = '\0';
+ while (*++str == ' ') /* loop */;
+
+ /* if there is nothing left of the string, return NULL */
+ /* This fix is dedicated to Greg Earle */
+ return(*str == '\0' ? NULL : str);
+}
+
+static int
+scanint(char *str, int *intp)
+
+{
+ register int val = 0;
+ register int ch;
+
+ /* if there is nothing left of the string, flag it as an error */
+ /* This fix is dedicated to Greg Earle */
+ if (*str == '\0')
+ {
+ return(-1);
+ }
+
+ while ((ch = *str++) != '\0')
+ {
+ if (isdigit(ch))
+ {
+ val = val * 10 + (ch - '0');
+ }
+ else if (isspace(ch))
+ {
+ break;
+ }
+ else
+ {
+ return(-1);
+ }
+ }
+ *intp = val;
+ return(0);
+}
+
+#ifdef notdef
+/*
+ * error_count() - return the number of errors currently logged.
+ */
+
+static int
+error_count(void)
+
+{
+ return(errcnt);
+}
+
+/*
+ * show_errors() - display on stdout the current log of errors.
+ */
+
+static void
+show_errors(void)
+
+{
+ register int cnt = 0;
+ register struct errs *errp = errs;
+
+ printf("%d error%s:\n\n", errcnt, errcnt == 1 ? "" : "s");
+ while (cnt++ < errcnt)
+ {
+ printf("%5s: %s\n", errp->arg,
+ errp->errnum == 0 ? "Not a number" : errmsg(errp->errnum));
+ errp++;
+ }
+}
+#endif
+
+/*
+ * kill_procs(str) - send signals to processes, much like the "kill"
+ * command does; invoked in response to 'k'.
+ */
+
+static void
+kill_procs(char *str)
+
+{
+ register char *nptr;
+ int signum = SIGTERM; /* default */
+ int procnum;
+ int uid;
+ int owner;
+#ifndef USE_SYS_SIGLIST
+ struct sigdesc *sigp;
+#endif
+
+ /* reset error array */
+ ERR_RESET;
+
+ /* remember our uid */
+ uid = getuid();
+
+ /* skip over leading white space */
+ while (isspace((int)*str)) str++;
+
+ if (str[0] == '-')
+ {
+ /* explicit signal specified */
+ if ((nptr = next_field(str)) == NULL)
+ {
+ message_error(" kill: no processes specified");
+ return;
+ }
+
+ str++;
+ if (isdigit((int)str[0]))
+ {
+ (void) scanint(str, &signum);
+ if (signum <= 0 || signum >= NSIG)
+ {
+ message_error(" kill: invalid signal number");
+ return;
+ }
+ }
+ else
+ {
+ /* translate the name into a number */
+#ifdef USE_SYS_SIGLIST
+ for (signum = 1; signum < NSIG; signum++)
+ {
+ if (strcasecmp(sys_signame[signum], str) == 0)
+ {
+ break;
+ }
+ }
+ if (signum == NSIG)
+ {
+ message_error(" kill: bad signal name");
+ return;
+ }
+#else
+ for (sigp = sigdesc; sigp->name != NULL; sigp++)
+ {
+#ifdef HAVE_STRCASECMP
+ if (strcasecmp(sigp->name, str) == 0)
+#else
+ if (strcmp(sigp->name, str) == 0)
+#endif
+ {
+ signum = sigp->number;
+ break;
+ }
+ }
+
+ /* was it ever found */
+ if (sigp->name == NULL)
+ {
+ message_error(" kill: bad signal name");
+ return;
+ }
+#endif
+ }
+ /* put the new pointer in place */
+ str = nptr;
+ }
+
+ /* loop thru the string, killing processes */
+ do
+ {
+ if (scanint(str, &procnum) == -1)
+ {
+ ERROR(str, 0);
+ }
+ else
+ {
+ /* check process owner if we're not root */
+ owner = proc_owner(procnum);
+ if (uid && (uid != owner))
+ {
+ ERROR(str, owner == -1 ? ESRCH : EACCES);
+ }
+ /* go in for the kill */
+ else if (kill(procnum, signum) == -1)
+ {
+ /* chalk up an error */
+ ERROR(str, errno);
+ }
+ }
+ } while ((str = next_field(str)) != NULL);
+
+ /* process errors */
+ err_string();
+}
+
+/*
+ * renice_procs(str) - change the "nice" of processes, much like the
+ * "renice" command does; invoked in response to 'r'.
+ */
+
+static void
+renice_procs(char *str)
+
+{
+ register char negate;
+ int prio;
+ int procnum;
+ int uid;
+
+ ERR_RESET;
+ uid = getuid();
+
+ /* allow for negative priority values */
+ if ((negate = (*str == '-')) != 0)
+ {
+ /* move past the minus sign */
+ str++;
+ }
+
+ /* use procnum as a temporary holding place and get the number */
+ procnum = scanint(str, &prio);
+
+ /* negate if necessary */
+ if (negate)
+ {
+ prio = -prio;
+ }
+
+#if defined(PRIO_MIN) && defined(PRIO_MAX)
+ /* check for validity */
+ if (procnum == -1 || prio < PRIO_MIN || prio > PRIO_MAX)
+ {
+ message_error(" renice: bad priority value");
+ return;
+ }
+#endif
+
+ /* move to the first process number */
+ if ((str = next_field(str)) == NULL)
+ {
+ message_error(" remice: no processes specified");
+ return;
+ }
+
+#ifdef HAVE_SETPRIORITY
+ /* loop thru the process numbers, renicing each one */
+ do
+ {
+ if (scanint(str, &procnum) == -1)
+ {
+ ERROR(str, 0);
+ }
+
+ /* check process owner if we're not root */
+ else if (uid && (uid != proc_owner(procnum)))
+ {
+ ERROR(str, EACCES);
+ }
+ else if (setpriority(PRIO_PROCESS, procnum, prio) == -1)
+ {
+ ERROR(str, errno);
+ }
+ } while ((str = next_field(str)) != NULL);
+ err_string();
+#else
+ message_error(" renice operation not supported");
+#endif
+}
+
+/* COMMAND ROUTINES */
+
+/*
+ * Each command routine is called by command_process and is passed a
+ * pointer to the current global state. Command routines are free
+ * to change anything in the global state, although changes to the
+ * statics structure are discouraged. Whatever a command routine
+ * returns will be returned by command_process.
+ */
+
+static void
+cmd_quit(globalstate *gstate)
+
+{
+ quit(EX_OK);
+ /*NOTREACHED*/
+}
+
+static int
+cmd_update(globalstate *gstate)
+
+{
+ /* go home for visual feedback */
+ screen_home();
+ fflush(stdout);
+ message_expire();
+ return CMD_REFRESH;
+}
+
+static int
+cmd_redraw(globalstate *gstate)
+
+{
+ gstate->fulldraw = Yes;
+ return CMD_REFRESH;
+}
+
+static int
+cmd_color(globalstate *gstate)
+
+{
+ gstate->use_color = color_activate(-1);
+ gstate->fulldraw = Yes;
+ return CMD_REFRESH;
+}
+
+static int
+cmd_number(globalstate *gstate)
+
+{
+ int newval;
+ char tmpbuf[20];
+
+ message_prompt("Number of processes to show: ");
+ newval = readline(tmpbuf, 8, Yes);
+ if (newval > -1)
+ {
+ if (newval > gstate->max_topn)
+ {
+ message_error(" This terminal can only display %d processes",
+ gstate->max_topn);
+ }
+
+ if (newval == 0)
+ {
+ /* inhibit the header */
+ display_header(No);
+ }
+
+ else if (gstate->topn == 0)
+ {
+ display_header(Yes);
+ }
+
+ gstate->topn = newval;
+ }
+ return CMD_REFRESH;
+}
+
+static int
+cmd_delay(globalstate *gstate)
+
+{
+ double newval;
+ char tmpbuf[20];
+
+ message_prompt("Seconds to delay: ");
+ if (readline(tmpbuf, 8, No) > 0)
+ {
+ newval = atof(tmpbuf);
+ if (newval == 0 && getuid() != 0)
+ {
+ gstate->delay = 1;
+ }
+ else
+ {
+ gstate->delay = newval;
+ }
+ }
+ return CMD_REFRESH;
+}
+
+static int
+cmd_idle(globalstate *gstate)
+
+{
+ gstate->pselect.idle = !gstate->pselect.idle;
+ message_error(" %sisplaying idle processes.",
+ gstate->pselect.idle ? "D" : "Not d");
+ return CMD_REFRESH;
+}
+
+static int
+cmd_displays(globalstate *gstate)
+
+{
+ int i;
+ char tmpbuf[20];
+
+ message_prompt("Displays to show (currently %s): ",
+ gstate->displays == -1 ? "infinite" :
+ itoa(gstate->displays));
+
+ if ((i = readline(tmpbuf, 10, Yes)) > 0)
+ {
+ gstate->displays = i;
+ }
+ else if (i == 0)
+ {
+ quit(EX_OK);
+ /*NOTREACHED*/
+ }
+ return CMD_OK;
+}
+
+static int
+cmd_cmdline(globalstate *gstate)
+
+{
+ if (gstate->statics->flags.fullcmds)
+ {
+ gstate->pselect.fullcmd = !gstate->pselect.fullcmd;
+ message_error(" %sisplaying full command lines.",
+ gstate->pselect.fullcmd ? "D" : "Not d");
+ return CMD_REFRESH;
+ }
+ message_error(" Full command display not supported.");
+ return CMD_OK;
+}
+
+static int
+cmd_order(globalstate *gstate)
+
+{
+ char tmpbuf[MAX_COLS];
+ int i;
+
+ if (gstate->statics->order_names != NULL)
+ {
+ message_prompt("Column to sort: ");
+ if (readline(tmpbuf, sizeof(tmpbuf), No) > 0)
+ {
+ if ((i = string_index(tmpbuf, gstate->statics->order_names)) == -1)
+ {
+ message_error(" Sort order \"%s\" not recognized", tmpbuf);
+ }
+ else
+ {
+ gstate->order_index = i;
+ return CMD_REFRESH;
+ }
+ }
+ }
+ return CMD_OK;
+}
+
+static int
+cmd_order_x(globalstate *gstate, const char *name, ...)
+
+{
+ va_list ap;
+ char *p;
+ const char **names;
+ int i;
+
+ names = gstate->statics->order_names;
+ if (names != NULL)
+ {
+ if ((i = string_index(name, names)) == -1)
+ {
+ /* check the alternate list */
+ va_start(ap, name);
+ p = va_arg(ap, char *);
+ while (p != NULL)
+ {
+ if ((i = string_index(p, names)) != -1)
+ {
+ gstate->order_index = i;
+ return CMD_REFRESH;
+ }
+ p = va_arg(ap, char *);
+ }
+ message_error(" Sort order not recognized");
+ }
+ else
+ {
+ gstate->order_index = i;
+ return CMD_REFRESH;
+ }
+ }
+ return CMD_OK;
+}
+
+static int
+cmd_order_cpu(globalstate *gstate)
+
+{
+ return cmd_order_x(gstate, "cpu", NULL);
+}
+
+static int
+cmd_order_pid(globalstate *gstate)
+
+{
+ return cmd_order_x(gstate, "pid", NULL);
+}
+
+static int
+cmd_order_mem(globalstate *gstate)
+
+{
+ return cmd_order_x(gstate, "mem", "size", NULL);
+}
+
+static int
+cmd_order_time(globalstate *gstate)
+
+{
+ return cmd_order_x(gstate, "time");
+}
+
+#ifdef ENABLE_KILL
+
+static int
+cmd_kill(globalstate *gstate)
+
+{
+ char tmpbuf[MAX_COLS];
+
+ message_prompt_plain("kill ");
+ if (readline(tmpbuf, sizeof(tmpbuf), No) > 0)
+ {
+ kill_procs(tmpbuf);
+ }
+ return CMD_OK;
+}
+
+static int
+cmd_renice(globalstate *gstate)
+
+{
+ char tmpbuf[MAX_COLS];
+
+ message_prompt_plain("renice ");
+ if (readline(tmpbuf, sizeof(tmpbuf), No) > 0)
+ {
+ renice_procs(tmpbuf);
+ }
+ return CMD_OK;
+}
+
+#endif
+
+static int
+cmd_pid(globalstate *gstate)
+
+{
+ char tmpbuf[MAX_COLS];
+
+ message_prompt_plain("select pid ");
+ gstate->pselect.pid = -1;
+ if (readline(tmpbuf, sizeof(tmpbuf), No) > 0)
+ {
+ int pid;
+ if (scanint(tmpbuf, &pid) == 0)
+ gstate->pselect.pid = pid;
+ }
+ return CMD_OK;
+}
+
+static int
+cmd_user(globalstate *gstate)
+
+{
+ char linebuf[MAX_COLS];
+ int i;
+ int ret = CMD_OK;
+
+ message_prompt("Username to show: ");
+ if (readline(linebuf, sizeof(linebuf), No) > 0)
+ {
+ if (linebuf[0] == '+' &&
+ linebuf[1] == '\0')
+ {
+ gstate->pselect.uid = -1;
+ ret = CMD_REFRESH;
+ }
+ else if ((i = userid(linebuf)) == -1)
+ {
+ message_error(" %s: unknown user", linebuf);
+ }
+ else
+ {
+ gstate->pselect.uid = i;
+ ret = CMD_REFRESH;
+ }
+ }
+ return ret;
+}
+
+static int
+cmd_command(globalstate *gstate)
+
+{
+ char linebuf[MAX_COLS];
+
+ if (gstate->pselect.command != NULL)
+ {
+ free(gstate->pselect.command);
+ gstate->pselect.command = NULL;
+ }
+
+ message_prompt("Command to show: ");
+ if (readline(linebuf, sizeof(linebuf), No) > 0)
+ {
+ if (linebuf[0] != '\0')
+ {
+ gstate->pselect.command = estrdup(linebuf);
+ }
+ }
+ return CMD_REFRESH;
+}
+
+static int
+cmd_useruid(globalstate *gstate)
+
+{
+ gstate->pselect.usernames = !gstate->pselect.usernames;
+ display_header(2);
+ return CMD_REFRESH;
+}
+
+static int
+cmd_mode(globalstate *gstate)
+
+{
+ if (gstate->statics->modemax <= 1)
+ {
+ return CMD_NA;
+ }
+ gstate->pselect.mode = (gstate->pselect.mode + 1) % gstate->statics->modemax;
+ display_header(2);
+ return CMD_REFRESH;
+}
+
+static int
+cmd_system(globalstate *gstate)
+
+{
+ gstate->pselect.system = !gstate->pselect.system;
+ display_header(2);
+ return CMD_REFRESH;
+}
+
+static int
+cmd_threads(globalstate *gstate)
+
+{
+ if (gstate->statics->flags.threads)
+ {
+ gstate->pselect.threads = !gstate->pselect.threads;
+ display_header(2);
+ return CMD_REFRESH;
+ }
+ return CMD_NA;
+}
+
+static int
+cmd_percpustates(globalstate *gstate)
+{
+ gstate->percpustates = !gstate->percpustates;
+ gstate->fulldraw = Yes;
+ gstate->max_topn += display_setmulti(gstate->percpustates);
+ return CMD_REFRESH;
+}
+
+
+/* forward reference for cmd_help, as it needs to see the command_table */
+int cmd_help(globalstate *gstate);
+
+/* command table */
+command command_table[] = {
+ { '\014', cmd_redraw, "redraw screen" },
+ { ' ', cmd_update, "update screen" },
+ { '?', cmd_help, "help; show this text" },
+ { 'h', cmd_help, NULL },
+ { '1', cmd_percpustates, "toggle the display of cpu states per cpu" },
+ { 'C', cmd_color, "toggle the use of color" },
+ { 'H', cmd_threads, "toggle the display of individual threads" },
+ { 't', cmd_threads, NULL },
+ { 'M', cmd_order_mem, "sort by memory usage" },
+ { 'N', cmd_order_pid, "sort by process id" },
+ { 'P', cmd_order_cpu, "sort by CPU usage" },
+ { 'S', cmd_system, "toggle the display of system processes" },
+ { 'T', cmd_order_time, "sort by CPU time" },
+ { 'U', cmd_useruid, "toggle the display of usernames or uids" },
+ { 'c', cmd_command, "display processes by command name" },
+ { 'd', cmd_displays, "change number of displays to show" },
+ { 'f', cmd_cmdline, "toggle the display of full command paths" },
+ { 'i', cmd_idle, "toggle the displaying of idle processes" },
+ { 'I', cmd_idle, NULL },
+#ifdef ENABLE_KILL
+ { 'k', cmd_kill, "kill processes; send a signal to a list of processes" },
+#endif
+ { 'm', cmd_mode, "toggle between display modes" },
+ { 'n', cmd_number, "change number of processes to display" },
+ { '#', cmd_number, NULL },
+ { 'o', cmd_order, "specify sort order (see below)" },
+ { 'p', cmd_pid, "select a single pid" },
+ { 'q', (int (*)(globalstate *))cmd_quit, "quit" },
+#ifdef ENABLE_KILL
+ { 'r', cmd_renice, "renice a process" },
+#endif
+ { 's', cmd_delay, "change number of seconds to delay between updates" },
+ { 'u', cmd_user, "display processes for only one user (+ selects all users)" },
+ { '\0', NULL, NULL },
+};
+
+int
+cmd_help(globalstate *gstate)
+
+{
+ command *c;
+ char buf[12];
+ char *p;
+ const char *help;
+
+ display_pagerstart();
+
+ display_pager("Top version %s, %s\n", version_string(), copyright);
+ display_pager("Platform module: %s\n\n", MODULE);
+ display_pager("A top users display for Unix\n\n");
+ display_pager("These single-character commands are available:\n\n");
+
+ c = command_table;
+ while (c->cmd_func != NULL)
+ {
+ /* skip null help strings */
+ if ((help = c->help) == NULL)
+ {
+ continue;
+ }
+
+ /* translate character in to something readable */
+ if (c->ch < ' ')
+ {
+ buf[0] = '^';
+ buf[1] = c->ch + '@';
+ buf[2] = '\0';
+ }
+ else if (c->ch == ' ')
+ {
+ strcpy(buf, "<sp>");
+ }
+ else
+ {
+ buf[0] = c->ch;
+ buf[1] = '\0';
+ }
+
+ /* if the next command is the same, fold them onto one line */
+ if ((c+1)->cmd_func == c->cmd_func)
+ {
+ strcat(buf, " or ");
+ p = buf + strlen(buf);
+ *p++ = (c+1)->ch;
+ *p = '\0';
+ c++;
+ }
+
+ display_pager("%-7s - %s\n", buf, help);
+ c++;
+ }
+
+ display_pager("\nNot all commands are available on all systems.\n\n");
+ display_pager("Available sort orders: %s\n", gstate->order_namelist);
+ display_pagerend();
+ gstate->fulldraw = Yes;
+ return CMD_REFRESH;
+}
+
+/*
+ * int command_process(globalstate *gstate, int cmd)
+ *
+ * Process the single-character command "cmd". The global state may
+ * be modified by the command to alter the output. Returns CMD_ERROR
+ * if there was a serious error that requires an immediate exit, CMD_OK
+ * to indicate success, CMD_REFRESH to indicate that the screen needs
+ * to be refreshed immediately, CMD_UNKNOWN when the command is not known,
+ * and CMD_NA when the command is not available. Error messages for
+ * CMD_NA and CMD_UNKNOWN must be handled by the caller.
+ */
+
+int
+command_process(globalstate *gstate, int cmd)
+
+{
+ command *c;
+
+ c = command_table;
+ while (c->cmd_func != NULL)
+ {
+ if (c->ch == cmd)
+ {
+ return (c->cmd_func)(gstate);
+ }
+ c++;
+ }
+
+ return CMD_UNKNOWN;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+# 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
--- /dev/null
+# 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)
--- /dev/null
+# Standard install rule
+install: $(PROGRAM) install-man
+ mkdir -p $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \
+ $(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM)
--- /dev/null
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-07-02'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha*:OpenVMS:*:*)
+ echo alpha-hp-vms
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
+ # Determine whether the default compiler uses glibc.
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #if __GLIBC__ >= 2
+ LIBC=gnu
+ #else
+ LIBC=
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ # GNU/FreeBSD systems have a "k" prefix to indicate we are using
+ # FreeBSD's kernel, but not the complete OS.
+ case ${LIBC} in gnu) kernel_only='k' ;; esac
+ echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ case `uname -p` in
+ *86) UNAME_PROCESSOR=i686 ;;
+ powerpc) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+/* 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
--- /dev/null
+# 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
--- /dev/null
+# 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)
--- /dev/null
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-07-04'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | msp430 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | amd64-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* \
+ | m32r-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | msp430-* \
+ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nv1)
+ basic_machine=nv1-cray
+ os=-unicosmp
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for top 3.8beta1.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='top'
+PACKAGE_TARNAME='top'
+PACKAGE_VERSION='3.8beta1'
+PACKAGE_STRING='top 3.8beta1'
+PACKAGE_BUGREPORT=''
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+target
+target_cpu
+target_vendor
+target_os
+DEFAULT_TOPN
+NOMINAL_TOPN
+DEFAULT_DELAY
+ENABLE_KILL
+MAKE
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+AWK
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+ISAINFO
+ISAEXEC
+UNAME
+CPP
+GREP
+EGREP
+SIGNAL_H
+HAVE_GETOPT_LONG
+SRC
+OBJ
+CLEAN_EXTRA
+ARCHFLAG
+MODULE
+MODULE_CFLAGS
+INSTALL_OPTS_PROG
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files='FIRST_RULE
+INSTALL_RULE
+MAN_SUPPLEMENT'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures top 3.8beta1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/top]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of top 3.8beta1:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-debug enable support for debugging output
+ --disable-kill disable kill and renice commands
+ --disable-color disable the use of color
+ --disable-colour synonym for --disable-color
+ --enable-dualarch enable or disable a dual architecture (32-bit and
+ 64-bit) compile
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-module=NAME use the platform module NAME
+ --with-ext=EXT use the extension EXT
+ --with-default-topn=N use N as the default for number of processes
+ --with-nominal-topn=N use N as the default number of processes for
+ non-terminals
+ --with-default-delay=SEC
+ use a default delay of SEC seconds
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+top configure 3.8beta1
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by top $as_me 3.8beta1, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# AX_CHECK_VARIADIC_MACROS...
+# -----
+
+
+# AC_CHECK_CFLAG...
+# -----
+# AC_CHECK_CFLAG
+
+echo "Configuring $PACKAGE_STRING"
+
+ac_config_headers="$ac_config_headers config.h"
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking target system type" >&5
+echo $ECHO_N "checking target system type... $ECHO_C" >&6; }
+if test "${ac_cv_target+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+echo "${ECHO_T}$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+echo "$as_me: error: invalid value of canonical target" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+# options processing
+
+# Check whether --with-module was given.
+if test "${with_module+set}" = set; then
+ withval=$with_module; if test ! -f machine/m_$withval.c;
+ then { { echo "$as_me:$LINENO: error: No such module $withval" >&5
+echo "$as_me: error: No such module $withval" >&2;}
+ { (exit 1); exit 1; }; }; fi
+fi
+
+
+
+# Check whether --with-ext was given.
+if test "${with_ext+set}" = set; then
+ withval=$with_ext; if test -f ext/$withval.c; then
+
+cat >>confdefs.h <<\_ACEOF
+#define WITH_EXT 1
+_ACEOF
+
+ SRC="$SRC ext/$withval.c"
+ OBJ="$OBJ $withval.o"
+ else
+ { { echo "$as_me:$LINENO: error: No such extension $withval" >&5
+echo "$as_me: error: No such extension $withval" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+
+DEFAULT_TOPN=30
+
+# Check whether --with-default-topn was given.
+if test "${with_default_topn+set}" = set; then
+ withval=$with_default_topn; 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
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_TOPN $DEFAULT_TOPN
+_ACEOF
+
+
+
+NOMINAL_TOPN=40
+
+# Check whether --with-nominal-topn was given.
+if test "${with_nominal_topn+set}" = set; then
+ withval=$with_nominal_topn; 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
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define NOMINAL_TOPN $NOMINAL_TOPN
+_ACEOF
+
+
+
+DEFAULT_DELAY=5
+
+# Check whether --with-default-delay was given.
+if test "${with_default_delay+set}" = set; then
+ withval=$with_default_delay; if test x`echo $with_default_delay | tr -d '0-9+-'` = x; then
+ DEFAULT_DELAY=$with_default_delay
+ fi
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_DELAY $DEFAULT_DELAY
+_ACEOF
+
+
+
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval=$enable_debug;
+fi
+
+if test "x$enable_debug" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define DEBUG 1
+_ACEOF
+
+fi
+
+ENABLE_KILL=0
+# Check whether --enable-kill was given.
+if test "${enable_kill+set}" = set; then
+ enableval=$enable_kill;
+fi
+
+if test x$enable_kill != xno; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_KILL 1
+_ACEOF
+
+ ENABLE_KILL=1
+fi
+
+
+
+# Check whether --enable-color was given.
+if test "${enable_color+set}" = set; then
+ enableval=$enable_color;
+fi
+
+# Check whether --enable-colour was given.
+if test "${enable_colour+set}" = set; then
+ enableval=$enable_colour;
+fi
+
+if test x$enable_color != xno -a x$enable_colour != xno; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_COLOR 1
+_ACEOF
+
+fi
+
+# Check whether --enable-dualarch was given.
+if test "${enable_dualarch+set}" = set; then
+ enableval=$enable_dualarch;
+fi
+
+
+# check for needed programs
+for ac_prog in make
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_MAKE+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$MAKE"; then
+ ac_cv_prog_MAKE="$MAKE" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_MAKE="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+MAKE=$ac_cv_prog_MAKE
+if test -n "$MAKE"; then
+ { echo "$as_me:$LINENO: result: $MAKE" >&5
+echo "${ECHO_T}$MAKE" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$MAKE" && break
+done
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test "$ac_cv_c_compiler_gnu" = "yes"; then
+ ax_cv_c_compiler_vendor="gnu"
+else
+
+
+{ echo "$as_me:$LINENO: checking for C compiler vendor" >&5
+echo $ECHO_N "checking for C compiler vendor... $ECHO_C" >&6; }
+if test "${ax_cv_c_compiler_vendor+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ax_cv_c_compiler_vendor=unknown
+ # note: don't check for gcc first since some other compilers define __GNUC__
+ for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale:__PATHCC__,__PATHSCALE__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
+ vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+#if !($vencpp)
+ thisisanerror;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ax_cv_c_compiler_vendor=`echo $ventest | cut -d: -f1`; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+
+fi
+{ echo "$as_me:$LINENO: result: $ax_cv_c_compiler_vendor" >&5
+echo "${ECHO_T}$ax_cv_c_compiler_vendor" >&6; }
+
+fi
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+for ac_prog in isainfo
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_ISAINFO+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $ISAINFO in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ISAINFO="$ISAINFO" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_ISAINFO="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ISAINFO=$ac_cv_path_ISAINFO
+if test -n "$ISAINFO"; then
+ { echo "$as_me:$LINENO: result: $ISAINFO" >&5
+echo "${ECHO_T}$ISAINFO" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ISAINFO" && break
+done
+
+for ac_prog in isaexec
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_ISAEXEC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $ISAEXEC in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ISAEXEC="$ISAEXEC" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="$PATH:/usr/lib:/lib"
+for as_dir in $as_dummy
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_ISAEXEC="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ISAEXEC=$ac_cv_path_ISAEXEC
+if test -n "$ISAEXEC"; then
+ { echo "$as_me:$LINENO: result: $ISAEXEC" >&5
+echo "${ECHO_T}$ISAEXEC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ISAEXEC" && break
+done
+
+for ac_prog in uname
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_UNAME+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $UNAME in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_UNAME="$UNAME" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_UNAME="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+UNAME=$ac_cv_path_UNAME
+if test -n "$UNAME"; then
+ { echo "$as_me:$LINENO: result: $UNAME" >&5
+echo "${ECHO_T}$UNAME" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$UNAME" && break
+done
+
+
+
+# system checks require uname
+if test "$UNAME"; then
+ # we make the version number available as a C preprocessor definition
+ { echo "$as_me:$LINENO: checking OS revision number" >&5
+echo $ECHO_N "checking OS revision number... $ECHO_C" >&6; }
+ osrev=`$UNAME -r | tr -cd ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`
+
+ if test "$osrev" != "unknown" ; then
+
+cat >>confdefs.h <<_ACEOF
+#define OSREV $osrev
+_ACEOF
+
+ osmajor=`$UNAME -r | sed 's/^\([0-9]*\).*$/\1/'`
+ if test -n "$osmajor"; then
+
+cat >>confdefs.h <<_ACEOF
+#define OSMAJOR $osmajor
+_ACEOF
+
+ fi
+ else
+ cat >>confdefs.h <<\_ACEOF
+#define OSREV ""
+_ACEOF
+
+ fi
+ { echo "$as_me:$LINENO: result: $osrev" >&5
+echo "${ECHO_T}$osrev" >&6; }
+
+ # we make the non-canonicalized hardware type available
+ { echo "$as_me:$LINENO: checking hardware platform" >&5
+echo $ECHO_N "checking hardware platform... $ECHO_C" >&6; }
+ UNAME_HARDWARE=`$UNAME -m`
+ if test "$UNAME_HARDWARE" != "unknown"; then
+
+cat >>confdefs.h <<_ACEOF
+#define UNAME_HARDWARE "$UNAME_HARDWARE"
+_ACEOF
+
+ fi
+ { echo "$as_me:$LINENO: result: $UNAME_HARDWARE" >&5
+echo "${ECHO_T}$UNAME_HARDWARE" >&6; }
+fi
+
+# checks for libraries
+
+{ echo "$as_me:$LINENO: checking for elf32_getphdr in -lelf" >&5
+echo $ECHO_N "checking for elf32_getphdr in -lelf... $ECHO_C" >&6; }
+if test "${ac_cv_lib_elf_elf32_getphdr+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lelf $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char elf32_getphdr ();
+int
+main ()
+{
+return elf32_getphdr ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_elf_elf32_getphdr=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_elf_elf32_getphdr=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_elf_elf32_getphdr" >&5
+echo "${ECHO_T}$ac_cv_lib_elf_elf32_getphdr" >&6; }
+if test $ac_cv_lib_elf_elf32_getphdr = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBELF 1
+_ACEOF
+
+ LIBS="-lelf $LIBS"
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for kstat_open in -lkstat" >&5
+echo $ECHO_N "checking for kstat_open in -lkstat... $ECHO_C" >&6; }
+if test "${ac_cv_lib_kstat_kstat_open+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkstat $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kstat_open ();
+int
+main ()
+{
+return kstat_open ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_kstat_kstat_open=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_kstat_kstat_open=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_kstat_kstat_open" >&5
+echo "${ECHO_T}$ac_cv_lib_kstat_kstat_open" >&6; }
+if test $ac_cv_lib_kstat_kstat_open = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBKSTAT 1
+_ACEOF
+
+ LIBS="-lkstat $LIBS"
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for kvm_open in -lkvm" >&5
+echo $ECHO_N "checking for kvm_open in -lkvm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_kvm_kvm_open+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkvm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kvm_open ();
+int
+main ()
+{
+return kvm_open ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_kvm_kvm_open=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_kvm_kvm_open=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_kvm_kvm_open" >&5
+echo "${ECHO_T}$ac_cv_lib_kvm_kvm_open" >&6; }
+if test $ac_cv_lib_kvm_kvm_open = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBKVM 1
+_ACEOF
+
+ LIBS="-lkvm $LIBS"
+
+fi
+
+# -lmld -lmach
+
+{ echo "$as_me:$LINENO: checking for vm_statistics in -lmach" >&5
+echo $ECHO_N "checking for vm_statistics in -lmach... $ECHO_C" >&6; }
+if test "${ac_cv_lib_mach_vm_statistics+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmach $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char vm_statistics ();
+int
+main ()
+{
+return vm_statistics ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_mach_vm_statistics=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_mach_vm_statistics=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_mach_vm_statistics" >&5
+echo "${ECHO_T}$ac_cv_lib_mach_vm_statistics" >&6; }
+if test $ac_cv_lib_mach_vm_statistics = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBMACH 1
+_ACEOF
+
+ LIBS="-lmach $LIBS"
+
+fi
+
+{ echo "$as_me:$LINENO: checking for library containing tgetent" >&5
+echo $ECHO_N "checking for library containing tgetent... $ECHO_C" >&6; }
+if test "${ac_cv_search_tgetent+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tgetent ();
+int
+main ()
+{
+return tgetent ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' termcap curses ncurses; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_tgetent=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_tgetent+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_tgetent+set}" = set; then
+ :
+else
+ ac_cv_search_tgetent=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_tgetent" >&5
+echo "${ECHO_T}$ac_cv_search_tgetent" >&6; }
+ac_res=$ac_cv_search_tgetent
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for exp in -lm" >&5
+echo $ECHO_N "checking for exp in -lm... $ECHO_C" >&6; }
+if test "${ac_cv_lib_m_exp+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char exp ();
+int
+main ()
+{
+return exp ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_m_exp=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_m_exp=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_exp" >&5
+echo "${ECHO_T}$ac_cv_lib_m_exp" >&6; }
+if test $ac_cv_lib_m_exp = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+fi
+
+
+# check for libraries required by extension
+extlibs=""
+if test -n "$with_ext" -a -f "${srcdir}/ext/$with_ext.libs"; then
+ { echo "$as_me:$LINENO: checking for libraries needed by extensions" >&5
+echo $ECHO_N "checking for libraries needed by extensions... $ECHO_C" >&6; }
+ for lib in `cat "${srcdir}/ext/$with_ext.libs"`
+ do
+ saveLIBS=$LIBS
+ LIBS="$LIBS -l$lib"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+exit(0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ extlibs="$extlibs -l$lib"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$saveLIBS
+ done
+ { echo "$as_me:$LINENO: result: $extlibs" >&5
+echo "${ECHO_T}$extlibs" >&6; }
+ LIBS="$LIBS$extlibs"
+fi
+
+# checks for header files
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in 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
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in term.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#if HAVE_CURSES_H
+#include <curses.h>
+#endif
+
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; }
+if test "${ac_cv_header_time+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_time=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_time=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for a good signal.h" >&5
+echo $ECHO_N "checking for a good signal.h... $ECHO_C" >&6; }
+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
+{ echo "$as_me:$LINENO: result: $SIGNAL_H" >&5
+echo "${ECHO_T}$SIGNAL_H" >&6; }
+if test "$SIGNAL_H" = "no"; then
+ SIGNAL_H="/dev/null"
+fi
+
+
+# checks for typedefs, structures, and compiler characteristics.
+{ echo "$as_me:$LINENO: checking for variadic macros" >&5
+echo $ECHO_N "checking for variadic macros... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define a(x, ...) (x, __VA_ARGS__)
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ax_cv_c99_variadic=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ax_cv_c99_variadic=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define a(x...) (x)
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ax_cv_gnu_variadic=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ax_cv_gnu_variadic=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+_result=""
+if test "$ax_cv_c99_variadic" = "yes"; then
+ _result=" c99"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_C99_VARIADIC_MACROS 1
+_ACEOF
+
+fi
+if test "$ax_cv_gnu_variadic" = "yes"; then
+ _result="$_result gnu"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GNU_VARIADIC_MACROS 1
+_ACEOF
+
+fi
+if test "x$_result" = x; then
+ _result="no"
+fi
+{ echo "$as_me:$LINENO: result: $_result" >&5
+echo "${ECHO_T}$_result" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether sys_errlist is declared" >&5
+echo $ECHO_N "checking whether sys_errlist is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_sys_errlist+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+#ifndef sys_errlist
+ (void) sys_errlist;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_sys_errlist=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_sys_errlist=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_sys_errlist" >&5
+echo "${ECHO_T}$ac_cv_have_decl_sys_errlist" >&6; }
+if test $ac_cv_have_decl_sys_errlist = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SYS_ERRLIST 1
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SYS_ERRLIST 0
+_ACEOF
+
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking whether sys_signame is declared" >&5
+echo $ECHO_N "checking whether sys_signame is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_sys_signame+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <signal.h>
+/* NetBSD declares sys_siglist in unistd.h. */
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+
+int
+main ()
+{
+#ifndef sys_signame
+ (void) sys_signame;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_sys_signame=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_sys_signame=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_sys_signame" >&5
+echo "${ECHO_T}$ac_cv_have_decl_sys_signame" >&6; }
+if test $ac_cv_have_decl_sys_signame = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SYS_SIGNAME 1
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SYS_SIGNAME 0
+_ACEOF
+
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking whether tputs is declared" >&5
+echo $ECHO_N "checking whether tputs is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_tputs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.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
+
+
+int
+main ()
+{
+#ifndef tputs
+ (void) tputs;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_tputs=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_tputs=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_tputs" >&5
+echo "${ECHO_T}$ac_cv_have_decl_tputs" >&6; }
+if test $ac_cv_have_decl_tputs = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TPUTS 1
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TPUTS 0
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking whether tgoto is declared" >&5
+echo $ECHO_N "checking whether tgoto is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_tgoto+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.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
+
+
+int
+main ()
+{
+#ifndef tgoto
+ (void) tgoto;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_tgoto=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_tgoto=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_tgoto" >&5
+echo "${ECHO_T}$ac_cv_have_decl_tgoto" >&6; }
+if test $ac_cv_have_decl_tgoto = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGOTO 1
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGOTO 0
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking whether tgetent is declared" >&5
+echo $ECHO_N "checking whether tgetent is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_tgetent+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.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
+
+
+int
+main ()
+{
+#ifndef tgetent
+ (void) tgetent;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_tgetent=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_tgetent=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_tgetent" >&5
+echo "${ECHO_T}$ac_cv_have_decl_tgetent" >&6; }
+if test $ac_cv_have_decl_tgetent = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGETENT 1
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGETENT 0
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking whether tgetflag is declared" >&5
+echo $ECHO_N "checking whether tgetflag is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_tgetflag+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.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
+
+
+int
+main ()
+{
+#ifndef tgetflag
+ (void) tgetflag;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_tgetflag=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_tgetflag=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_tgetflag" >&5
+echo "${ECHO_T}$ac_cv_have_decl_tgetflag" >&6; }
+if test $ac_cv_have_decl_tgetflag = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGETFLAG 1
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGETFLAG 0
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking whether tgetnum is declared" >&5
+echo $ECHO_N "checking whether tgetnum is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_tgetnum+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.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
+
+
+int
+main ()
+{
+#ifndef tgetnum
+ (void) tgetnum;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_tgetnum=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_tgetnum=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_tgetnum" >&5
+echo "${ECHO_T}$ac_cv_have_decl_tgetnum" >&6; }
+if test $ac_cv_have_decl_tgetnum = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGETNUM 1
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGETNUM 0
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking whether tgetstr is declared" >&5
+echo $ECHO_N "checking whether tgetstr is declared... $ECHO_C" >&6; }
+if test "${ac_cv_have_decl_tgetstr+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.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
+
+
+int
+main ()
+{
+#ifndef tgetstr
+ (void) tgetstr;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_have_decl_tgetstr=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_have_decl_tgetstr=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_tgetstr" >&5
+echo "${ECHO_T}$ac_cv_have_decl_tgetstr" >&6; }
+if test $ac_cv_have_decl_tgetstr = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGETSTR 1
+_ACEOF
+
+
+else
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TGETSTR 0
+_ACEOF
+
+
+fi
+
+
+
+# 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.
+{ echo "$as_me:$LINENO: checking argument type of tputs putc function" >&5
+echo $ECHO_N "checking argument type of tputs putc function... $ECHO_C" >&6; }
+_savedwerror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#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) { }
+int
+main ()
+{
+tputs("a", 1, f);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_tputs_putc="char"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_tputs_putc="int"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_cv_type_tputs_putc" >&5
+echo "${ECHO_T}$ac_cv_type_tputs_putc" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define TPUTS_PUTC_ARGTYPE $ac_cv_type_tputs_putc
+_ACEOF
+
+ac_c_werror_flag=$_savedwerror_flag
+
+# Determine presence of needed types
+{ echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; }
+if test "${ac_cv_type_signal+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_signal=int
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_signal=void
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking for id_t" >&5
+echo $ECHO_N "checking for id_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_id_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef id_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_id_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_id_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_id_t" >&5
+echo "${ECHO_T}$ac_cv_type_id_t" >&6; }
+if test $ac_cv_type_id_t = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ID_T 1
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking for lwpid_t" >&5
+echo $ECHO_N "checking for lwpid_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_lwpid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef lwpid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_lwpid_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_lwpid_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_lwpid_t" >&5
+echo "${ECHO_T}$ac_cv_type_lwpid_t" >&6; }
+if test $ac_cv_type_lwpid_t = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LWPID_T 1
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking for pid_t" >&5
+echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_pid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef pid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_pid_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_pid_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+echo "${ECHO_T}$ac_cv_type_pid_t" >&6; }
+if test $ac_cv_type_pid_t = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_PID_T 1
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking for time_t" >&5
+echo $ECHO_N "checking for time_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_time_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef time_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_time_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_time_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_time_t" >&5
+echo "${ECHO_T}$ac_cv_type_time_t" >&6; }
+if test $ac_cv_type_time_t = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_TIME_T 1
+_ACEOF
+
+
+fi
+{ echo "$as_me:$LINENO: checking for uid_t" >&5
+echo $ECHO_N "checking for uid_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_uid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef uid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_uid_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_uid_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5
+echo "${ECHO_T}$ac_cv_type_uid_t" >&6; }
+if test $ac_cv_type_uid_t = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UID_T 1
+_ACEOF
+
+
+fi
+
+
+# Checks for library functions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in getopt getopt_long gettimeofday memcpy setbuffer setpriority setvbuf strcasecmp strchr strerror snprintf sighold sigrelse sigaction sigprocmask sysconf uname vsnprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# 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
+
+
+# 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
+{ echo "$as_me:$LINENO: checking for correct ls options" >&5
+echo $ECHO_N "checking for correct ls options... $ECHO_C" >&6; }
+lslong="ls -l"
+if test `$lslong -d . | wc -w` -lt 9; then
+ lslong="ls -lg"
+fi
+{ echo "$as_me:$LINENO: result: $lslong" >&5
+echo "${ECHO_T}$lslong" >&6; }
+
+
+# determine correct module
+{ echo "$as_me:$LINENO: checking for a platform module" >&5
+echo $ECHO_N "checking for a platform module... $ECHO_C" >&6; }
+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"
+ { { echo "$as_me:$LINENO: error: macosx module unsupported" >&5
+echo "$as_me: error: macosx module unsupported" >&2;}
+ { (exit 1); exit 1; }; };;
+ *) 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 ""
+ { { echo "$as_me:$LINENO: error: System type $target_os unrecognized" >&5
+echo "$as_me: error: System type $target_os unrecognized" >&2;}
+ { (exit 1); exit 1; }; }
+ esac
+fi
+{ echo "$as_me:$LINENO: result: $MODULE" >&5
+echo "${ECHO_T}$MODULE" >&6; }
+SRC="$SRC machine/m_$MODULE.c"
+OBJ="$OBJ m_$MODULE.o"
+CLEAN_EXTRA=""
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define MODULE "$MODULE"
+_ACEOF
+
+
+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)
+
+{ echo "$as_me:$LINENO: checking for perfstat_cpu_total in -lperfstat" >&5
+echo $ECHO_N "checking for perfstat_cpu_total in -lperfstat... $ECHO_C" >&6; }
+if test "${ac_cv_lib_perfstat_perfstat_cpu_total+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lperfstat $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char perfstat_cpu_total ();
+int
+main ()
+{
+return perfstat_cpu_total ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_perfstat_perfstat_cpu_total=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_perfstat_perfstat_cpu_total=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_perfstat_perfstat_cpu_total" >&5
+echo "${ECHO_T}$ac_cv_lib_perfstat_perfstat_cpu_total" >&6; }
+if test $ac_cv_lib_perfstat_perfstat_cpu_total = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPERFSTAT 1
+_ACEOF
+
+ LIBS="-lperfstat $LIBS"
+
+fi
+
+ if test -f /usr/sbin/bootinfo; then
+ bits="`/usr/sbin/bootinfo -K`"
+ extra_flag="-q64"
+ fi
+ ;;
+ svr5)
+ # -lmas
+
+{ echo "$as_me:$LINENO: checking for mas_open in -lmas" >&5
+echo $ECHO_N "checking for mas_open in -lmas... $ECHO_C" >&6; }
+if test "${ac_cv_lib_mas_mas_open+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmas $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char mas_open ();
+int
+main ()
+{
+return mas_open ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_mas_mas_open=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_mas_mas_open=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_mas_mas_open" >&5
+echo "${ECHO_T}$ac_cv_lib_mas_mas_open" >&6; }
+if test $ac_cv_lib_mas_mas_open = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBMAS 1
+_ACEOF
+
+ LIBS="-lmas $LIBS"
+
+fi
+
+ ;;
+ 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
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FORMAT_PROCESS_HEADER 1
+_ACEOF
+
+fi
+
+# if we are 64-bit, try to turn on the appropriate flags
+{ echo "$as_me:$LINENO: checking address space size" >&5
+echo $ECHO_N "checking address space size... $ECHO_C" >&6; }
+ARCHFLAG=""
+if test "$bits" = "64"; then
+ { echo "$as_me:$LINENO: result: 64" >&5
+echo "${ECHO_T}64" >&6; }
+ if test "$ax_cv_c_compiler_vendor" = "gnu"; then
+ extra_flag="-m64"
+ fi
+# Make sure our compiler accepts the flag we want to use
+ { echo "$as_me:$LINENO: checking whether compiler accepts $extra_flag" >&5
+echo $ECHO_N "checking whether compiler accepts $extra_flag... $ECHO_C" >&6; }
+as_ac_Flag=`echo "ac_cv_cflag_$extra_flag" | $as_tr_sh`
+_savedcflags=$CFLAGS
+_savedwerror_flag=$ac_c_werror_flag
+ac_c_werror_flag=yes
+CFLAGS=$CFLAGS" $extra_flag"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_Flag=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Flag=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Flag'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Flag'}'`" >&6; }
+CFLAGS=$_savedcflags
+ac_c_werror_flag=$_savedwerror_flag
+if test `eval echo '${'$as_ac_Flag'}'` = yes; then
+ ARCHFLAG="$extra_flag"
+else
+ enable_dualarch="no"
+fi
+
+else
+ { echo "$as_me:$LINENO: result: $bits" >&5
+echo "${ECHO_T}$bits" >&6; }
+fi
+
+
+# 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
+ { echo "$as_me:$LINENO: checking for dual architecture compilation" >&5
+echo $ECHO_N "checking for dual architecture compilation... $ECHO_C" >&6; }
+ 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
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ 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
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ fi
+fi
+
+if test x$enable_dualarch = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ENABLE_DUALARCH 1
+_ACEOF
+
+fi
+
+
+
+
+{ echo "$as_me:$LINENO: checking for installation settings" >&5
+echo $ECHO_N "checking for installation settings... $ECHO_C" >&6; }
+# 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"
+
+{ echo "$as_me:$LINENO: result: $result" >&5
+echo "${ECHO_T}$result" >&6; }
+
+# add extra cflags if the compiler accepts them
+{ echo "$as_me:$LINENO: checking CFLAGS for maximum warnings" >&5
+echo $ECHO_N "checking CFLAGS for maximum warnings... $ECHO_C" >&6; }
+if test "${ac_cv_cflags_warn_all+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_warn_all="no, unknown"
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+for ac_arg in "-pedantic % -Wall" "-xstrconst % -v" "-std1 % -verbose -w0 -warnprotos" "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" "-ansi -ansiE % -fullwarn" "+ESlit % +w1" "-Xc % -pvctl,fullmsg" "-h conform % -h msglevel 2" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_cflags_warn_all=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cflags_warn_all" >&5
+echo "${ECHO_T}$ac_cv_cflags_warn_all" >&6; }
+case ".$ac_cv_cflags_warn_all" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*)
+ ;;
+ *)
+ if echo " $CFLAGS " | grep " $ac_cv_cflags_warn_all " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : CFLAGS does contain \$ac_cv_cflags_warn_all") >&5
+ (: CFLAGS does contain $ac_cv_cflags_warn_all) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_warn_all\"") >&5
+ (: CFLAGS="$CFLAGS $ac_cv_cflags_warn_all") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ CFLAGS="$CFLAGS $ac_cv_cflags_warn_all"
+ fi
+ ;;
+esac
+
+MODULE_CFLAGS=""
+if test "$ax_cv_c_compiler_vendor" = "gnu"; then
+ { echo "$as_me:$LINENO: checking MODULE_CFLAGS for gcc -fno-strict-aliasing" >&5
+echo $ECHO_N "checking MODULE_CFLAGS for gcc -fno-strict-aliasing... $ECHO_C" >&6; }
+if test "${ac_cv_cflags_gcc_option__fno_strict_aliasing+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_gcc_option__fno_strict_aliasing="no, unknown"
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+for ac_arg in "-pedantic -Werror % -fno-strict-aliasing" "-pedantic % -fno-strict-aliasing %% no, obsolete" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_cflags_gcc_option__fno_strict_aliasing=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cflags_gcc_option__fno_strict_aliasing" >&5
+echo "${ECHO_T}$ac_cv_cflags_gcc_option__fno_strict_aliasing" >&6; }
+case ".$ac_cv_cflags_gcc_option__fno_strict_aliasing" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*) ;;
+ *)
+ if echo " $MODULE_CFLAGS " | grep " $ac_cv_cflags_gcc_option__fno_strict_aliasing " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : MODULE_CFLAGS does contain \$ac_cv_cflags_gcc_option__fno_strict_aliasing") >&5
+ (: MODULE_CFLAGS does contain $ac_cv_cflags_gcc_option__fno_strict_aliasing) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : MODULE_CFLAGS=\"\$MODULE_CFLAGS \$ac_cv_cflags_gcc_option__fno_strict_aliasing\"") >&5
+ (: MODULE_CFLAGS="$MODULE_CFLAGS $ac_cv_cflags_gcc_option__fno_strict_aliasing") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ MODULE_CFLAGS="$MODULE_CFLAGS $ac_cv_cflags_gcc_option__fno_strict_aliasing"
+ fi
+ ;;
+esac
+
+ if test "$target_cpu" = "alpha"; then
+ { echo "$as_me:$LINENO: checking CFLAGS for gcc -mfp-trap-mode=sui -mtrap-precision=i" >&5
+echo $ECHO_N "checking CFLAGS for gcc -mfp-trap-mode=sui -mtrap-precision=i... $ECHO_C" >&6; }
+if test "${ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i="no, unknown"
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ ac_save_CFLAGS="$CFLAGS"
+for ac_arg in "-pedantic -Werror % -mfp-trap-mode=sui -mtrap-precision=i" "-pedantic % -mfp-trap-mode=sui -mtrap-precision=i %% no, obsolete" #
+do CFLAGS="$ac_save_CFLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i=`echo $ac_arg | sed -e 's,.*% *,,'` ; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+ CFLAGS="$ac_save_CFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i" >&5
+echo "${ECHO_T}$ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i" >&6; }
+case ".$ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i" in
+ .ok|.ok,*) ;;
+ .|.no|.no,*) ;;
+ *)
+ if echo " $CFLAGS " | grep " $ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i " 2>&1 >/dev/null
+ then { (echo "$as_me:$LINENO: : CFLAGS does contain \$ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i") >&5
+ (: CFLAGS does contain $ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ else { (echo "$as_me:$LINENO: : CFLAGS=\"\$CFLAGS \$ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i\"") >&5
+ (: CFLAGS="$CFLAGS $ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ CFLAGS="$CFLAGS $ac_cv_cflags_gcc_option__mfp_trap_mode_sui__mtrap_precision_i"
+ fi
+ ;;
+esac
+
+ fi
+fi
+
+# Define man page supplement
+MAN_SUPPLEMENT=machine/m_$MODULE.man
+
+
+# Extra things we want substituted
+
+
+
+
+# wrapup
+
+ac_config_files="$ac_config_files Makefile top.1"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by top $as_me 3.8beta1, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+top config.status 3.8beta1
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "top.1") CONFIG_FILES="$CONFIG_FILES top.1" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+# Create sed commands to just substitute file output variables.
+
+# Remaining file output variables are in a fragment that also has non-file
+# output varibles.
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+target!$target$ac_delim
+target_cpu!$target_cpu$ac_delim
+target_vendor!$target_vendor$ac_delim
+target_os!$target_os$ac_delim
+DEFAULT_TOPN!$DEFAULT_TOPN$ac_delim
+NOMINAL_TOPN!$NOMINAL_TOPN$ac_delim
+DEFAULT_DELAY!$DEFAULT_DELAY$ac_delim
+ENABLE_KILL!$ENABLE_KILL$ac_delim
+MAKE!$MAKE$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+AWK!$AWK$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+ISAINFO!$ISAINFO$ac_delim
+ISAEXEC!$ISAEXEC$ac_delim
+UNAME!$UNAME$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+SIGNAL_H!$SIGNAL_H$ac_delim
+HAVE_GETOPT_LONG!$HAVE_GETOPT_LONG$ac_delim
+SRC!$SRC$ac_delim
+OBJ!$OBJ$ac_delim
+CLEAN_EXTRA!$CLEAN_EXTRA$ac_delim
+ARCHFLAG!$ARCHFLAG$ac_delim
+MODULE!$MODULE$ac_delim
+MODULE_CFLAGS!$MODULE_CFLAGS$ac_delim
+INSTALL_OPTS_PROG!$INSTALL_OPTS_PROG$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 82; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+/^[ ]*@FIRST_RULE@[ ]*$/{
+r $FIRST_RULE
+d
+}
+/^[ ]*@INSTALL_RULE@[ ]*$/{
+r $INSTALL_RULE
+d
+}
+/^[ ]*@MAN_SUPPLEMENT@[ ]*$/{
+r $MAN_SUPPLEMENT
+d
+}
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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 display information on the screen.
+ * Each section of the screen has two routines: one for initially writing
+ * all constant and dynamic text, and one for only updating the text that
+ * changes. The prefix "i_" is used on all the "initial" routines and the
+ * prefix "u_" is used for all the "updating" routines.
+ *
+ * ASSUMPTIONS:
+ * None of the "i_" routines use any of the termcap capabilities.
+ * In this way, those routines can be safely used on terminals that
+ * have minimal (or nonexistant) terminal capabilities.
+ *
+ * The routines should be called in this order: *_loadave, *_uptime,
+ * i_timeofday, *_procstates, *_cpustates, *_memory, *_swap,
+ * *_message, *_header, *_process, *_endscreen.
+ */
+
+#include "os.h"
+#include <ctype.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include "top.h"
+#include "machine.h"
+#include "screen.h" /* interface to screen package */
+#include "layout.h" /* defines for screen position layout */
+#include "display.h"
+#include "boolean.h"
+#include "utils.h"
+
+#ifdef ENABLE_COLOR
+#include "color.h"
+#endif
+
+#define CURSOR_COST 8
+
+#define MESSAGE_DISPLAY_TIME 5
+
+/* imported from screen.c */
+extern int overstrike;
+
+static int lmpid = -1;
+static int display_width = MAX_COLS;
+static int ncpu = 0;
+
+/* cursor positions of key points on the screen are maintained here */
+/* layout.h has static definitions, but we may change our minds on some
+ of the positions as we make decisions about what needs to be displayed */
+
+static int x_lastpid = X_LASTPID;
+static int y_lastpid = Y_LASTPID;
+static int x_loadave = X_LOADAVE;
+static int y_loadave = Y_LOADAVE;
+static int x_minibar = X_MINIBAR;
+static int y_minibar = Y_MINIBAR;
+static int x_uptime = X_UPTIME;
+static int y_uptime = Y_UPTIME;
+static int x_procstate = X_PROCSTATE;
+static int y_procstate = Y_PROCSTATE;
+static int x_cpustates = X_CPUSTATES;
+static int y_cpustates = Y_CPUSTATES;
+static int x_kernel = X_KERNEL;
+static int y_kernel = Y_KERNEL;
+static int x_mem = X_MEM;
+static int y_mem = Y_MEM;
+static int x_swap = X_SWAP;
+static int y_swap = Y_SWAP;
+static int y_message = Y_MESSAGE;
+static int x_header = X_HEADER;
+static int y_header = Y_HEADER;
+static int x_idlecursor = X_IDLECURSOR;
+static int y_idlecursor = Y_IDLECURSOR;
+static int y_procs = Y_PROCS;
+
+/* buffer and colormask that describes the content of the screen */
+/* these are singly dimensioned arrays -- the row boundaries are
+ determined on the fly.
+*/
+static char *screenbuf = NULL;
+static char *colorbuf = NULL;
+static char scratchbuf[MAX_COLS];
+static int bufsize = 0;
+static int multi = 0;
+
+/* lineindex tells us where the beginning of a line is in the buffer */
+#define lineindex(l) ((l)*MAX_COLS)
+
+/* screen's cursor */
+static int curr_x, curr_y;
+static int curr_color;
+
+/* virtual cursor */
+static int virt_x, virt_y;
+
+static const char **procstate_names;
+static const char **cpustate_names;
+static const char **memory_names;
+static const char **swap_names;
+static const char **kernel_names;
+
+static int num_procstates;
+static int num_cpustates;
+static int num_memory;
+static int num_swap;
+static int num_kernel;
+
+static int *lprocstates;
+static int *lcpustates;
+
+static int *cpustate_columns;
+static int cpustate_total_length;
+
+static int header_status = Yes;
+
+/* pending messages are stored in a circular buffer, where message_first
+ is the next one to display, and message_last is the last one
+ in the buffer. Counters wrap around at MAX_MESSAGES. The buffer is
+ empty when message_first == message_last and full when
+ message_last + 1 == message_first. The pointer message_current holds
+ the message currently being displayed, or "" if there is none.
+*/
+#define MAX_MESSAGES 16
+static char *message_buf[MAX_MESSAGES];
+static int message_first = 0;
+static int message_last = 0;
+static struct timeval message_time = {0, 0};
+static char *message_current = NULL;
+static int message_length = 0;
+static int message_hold = 1;
+static int message_barrier = No;
+
+#ifdef ENABLE_COLOR
+static int load_cidx[3];
+static int header_cidx;
+static int *cpustate_cidx;
+static int *memory_cidx;
+static int *swap_cidx;
+static int *kernel_cidx;
+#else
+#define memory_cidx NULL
+#define swap_cidx NULL
+#define kernel_cidx NULL
+#endif
+
+
+/* internal support routines */
+
+/*
+ * static int string_count(char **pp)
+ *
+ * Pointer "pp" points to an array of string pointers, which is
+ * terminated by a NULL. Return the number of string pointers in
+ * this array.
+ */
+
+static int
+string_count(const char **pp)
+
+{
+ register int cnt = 0;
+
+ if (pp != NULL)
+ {
+ while (*pp++ != NULL)
+ {
+ cnt++;
+ }
+ }
+ return(cnt);
+}
+
+void
+display_clear(void)
+
+{
+ dprintf("display_clear\n");
+ screen_clear();
+ memzero(screenbuf, bufsize);
+ memzero(colorbuf, bufsize);
+ curr_x = curr_y = 0;
+}
+
+/*
+ * void display_move(int x, int y)
+ *
+ * Efficiently move the cursor to x, y. This assumes the cursor is
+ * currently located at curr_x, curr_y, and will only use cursor
+ * addressing when it is less expensive than overstriking what's
+ * already on the screen.
+ */
+
+static void
+display_move(int x, int y)
+
+{
+ char buff[128];
+ char *p;
+ char *bufp;
+ char *colorp;
+ int cnt = 0;
+ int color = curr_color;
+
+ dprintf("display_move(%d, %d): curr_x %d, curr_y %d\n", x, y, curr_x, curr_y);
+
+ /* are we in a position to do this without cursor addressing? */
+ if (curr_y < y || (curr_y == y && curr_x <= x))
+ {
+ /* start buffering up what it would take to move there by rewriting
+ what's on the screen */
+ cnt = CURSOR_COST;
+ p = buff;
+
+ /* one newline for every line */
+ while (cnt > 0 && curr_y < y)
+ {
+#ifdef ENABLE_COLOR
+ if (color != 0)
+ {
+ p = strcpyend(p, color_setstr(0));
+ color = 0;
+ cnt -= 5;
+ }
+#endif
+ *p++ = '\n';
+ curr_y++;
+ curr_x = 0;
+ cnt--;
+ }
+
+ /* write whats in the screenbuf */
+ bufp = &screenbuf[lineindex(curr_y) + curr_x];
+ colorp = &colorbuf[lineindex(curr_y) + curr_x];
+ while (cnt > 0 && curr_x < x)
+ {
+#ifdef ENABLE_COLOR
+ if (color != *colorp)
+ {
+ color = *colorp;
+ p = strcpyend(p, color_setstr(color));
+ cnt -= 5;
+ }
+#endif
+ if ((*p = *bufp) == '\0')
+ {
+ /* somwhere on screen we haven't been before */
+ *p = *bufp = ' ';
+ }
+ p++;
+ bufp++;
+ colorp++;
+ curr_x++;
+ cnt--;
+ }
+ }
+
+ /* move the cursor */
+ if (cnt > 0)
+ {
+ /* screen rewrite is cheaper */
+ *p = '\0';
+ fputs(buff, stdout);
+ curr_color = color;
+ }
+ else
+ {
+ screen_move(x, y);
+ }
+
+ /* update our position */
+ curr_x = x;
+ curr_y = y;
+}
+
+/*
+ * display_write(int x, int y, int newcolor, int eol, char *new)
+ *
+ * Optimized write to the display. This writes characters to the
+ * screen in a way that optimizes the number of characters actually
+ * sent, by comparing what is being written to what is already on
+ * the screen (according to screenbuf and colorbuf). The string to
+ * write is "new", the first character of "new" should appear at
+ * screen position x, y. If x is -1 then "new" begins wherever the
+ * cursor is currently positioned. The string is written with color
+ * "newcolor". If "eol" is true then the remainder of the line is
+ * cleared. It is expected that "new" will have no newlines and no
+ * escape sequences.
+ */
+
+static void
+display_write(int x, int y, int newcolor, int eol, const char *new)
+
+{
+ char *bufp;
+ char *colorp;
+ int ch;
+ int diff;
+
+ dprintf("display_write(%d, %d, %d, %d, \"%s\")\n",
+ x, y, newcolor, eol, new);
+
+ /* dumb terminal handling here */
+ if (!smart_terminal)
+ {
+ if (x != -1)
+ {
+ /* make sure we are on the right line */
+ while (curr_y < y)
+ {
+ putchar('\n');
+ curr_y++;
+ curr_x = 0;
+ }
+
+ /* make sure we are on the right column */
+ while (curr_x < x)
+ {
+ putchar(' ');
+ curr_x++;
+ }
+ }
+
+ /* write */
+ fputs(new, stdout);
+ curr_x += strlen(new);
+
+ return;
+ }
+
+ /* adjust for "here" */
+ if (x == -1)
+ {
+ x = virt_x;
+ y = virt_y;
+ }
+ else
+ {
+ virt_x = x;
+ virt_y = y;
+ }
+
+ /* a pointer to where we start */
+ bufp = &screenbuf[lineindex(y) + x];
+ colorp = &colorbuf[lineindex(y) + x];
+
+ /* main loop */
+ while ((ch = *new++) != '\0')
+ {
+ /* if either character or color are different, an update is needed */
+ /* but only when the screen is wide enough */
+ if (x < display_width && (ch != *bufp || newcolor != *colorp))
+ {
+ /* check cursor */
+ if (y != curr_y || x != curr_x)
+ {
+ /* have to move the cursor */
+ display_move(x, y);
+ }
+
+ /* write character */
+#ifdef ENABLE_COLOR
+ if (curr_color != newcolor)
+ {
+ fputs(color_setstr(newcolor), stdout);
+ curr_color = newcolor;
+ }
+#endif
+ putchar(ch);
+ *bufp = ch;
+ *colorp = curr_color;
+ curr_x++;
+ }
+
+ /* move */
+ x++;
+ virt_x++;
+ bufp++;
+ colorp++;
+ }
+
+ /* eol handling */
+ if (eol && *bufp != '\0')
+ {
+ dprintf("display_write: clear-eol (bufp = \"%s\")\n", bufp);
+ /* make sure we are color 0 */
+#ifdef ENABLE_COLOR
+ if (curr_color != 0)
+ {
+ fputs(color_setstr(0), stdout);
+ curr_color = 0;
+ }
+#endif
+
+ /* make sure we are at the end */
+ if (x != curr_x || y != curr_y)
+ {
+ screen_move(x, y);
+ curr_x = x;
+ curr_y = y;
+ }
+
+ /* clear to end */
+ screen_cleareol(strlen(bufp));
+
+ /* clear out whats left of this line's buffer */
+ diff = display_width - x;
+ if (diff > 0)
+ {
+ memzero(bufp, diff);
+ memzero(colorp, diff);
+ }
+ }
+}
+
+static void
+display_fmt(int x, int y, int newcolor, int eol, const char *fmt, ...)
+
+{
+ va_list argp;
+
+ va_start(argp, fmt);
+
+ vsnprintf(scratchbuf, MAX_COLS, fmt, argp);
+ display_write(x, y, newcolor, eol, scratchbuf);
+}
+
+static void
+display_cte(void)
+
+{
+ int len;
+ int y;
+ char *p;
+ int need_clear = 0;
+
+ /* is there anything out there that needs to be cleared? */
+ p = &screenbuf[lineindex(virt_y) + virt_x];
+ if (*p != '\0')
+ {
+ need_clear = 1;
+ }
+ else
+ {
+ /* this line is clear, what about the rest? */
+ y = virt_y;
+ while (++y < screen_length)
+ {
+ if (screenbuf[lineindex(y)] != '\0')
+ {
+ need_clear = 1;
+ break;
+ }
+ }
+ }
+
+ if (need_clear)
+ {
+ dprintf("display_cte: clearing\n");
+
+ /* we will need this later */
+ len = lineindex(virt_y) + virt_x;
+
+ /* move to x and y, then clear to end */
+ display_move(virt_x, virt_y);
+ if (!screen_cte())
+ {
+ /* screen has no clear to end, so do it by hand */
+ p = &screenbuf[len];
+ len = strlen(p);
+ if (len > 0)
+ {
+ screen_cleareol(len);
+ }
+ while (++virt_y < screen_length)
+ {
+ display_move(0, virt_y);
+ p = &screenbuf[lineindex(virt_y)];
+ len = strlen(p);
+ if (len > 0)
+ {
+ screen_cleareol(len);
+ }
+ }
+ }
+
+ /* clear the screenbuf */
+ memzero(&screenbuf[len], bufsize - len);
+ memzero(&colorbuf[len], bufsize - len);
+ }
+}
+
+static void
+summary_format(int x, int y, int *numbers, const char **names, int *cidx)
+
+{
+ register int num;
+ register const char *thisname;
+ register const char *lastname = NULL;
+ register int color;
+
+ /* format each number followed by its string */
+ while ((thisname = *names++) != NULL)
+ {
+ /* get the number to format */
+ num = *numbers++;
+ color = 0;
+
+ /* display only non-zero numbers */
+ if (num != 0)
+ {
+ /* write the previous name */
+ if (lastname != NULL)
+ {
+ display_write(-1, -1, 0, 0, lastname);
+ }
+
+#ifdef ENABLE_COLOR
+ if (cidx != NULL)
+ {
+ /* choose a color */
+ color = color_test(*cidx++, num);
+ }
+#endif
+
+ /* write this number if positive */
+ if (num > 0)
+ {
+ display_write(x, y, color, 0, itoa(num));
+ }
+
+ /* defer writing this name */
+ lastname = thisname;
+
+ /* next iteration will not start at x, y */
+ x = y = -1;
+ }
+ }
+
+ /* if the last string has a separator on the end, it has to be
+ written with care */
+ if (lastname != NULL)
+ {
+ if ((num = strlen(lastname)) > 1 &&
+ lastname[num-2] == ',' && lastname[num-1] == ' ')
+ {
+ display_fmt(-1, -1, 0, 1, "%.*s", num-2, lastname);
+ }
+ else
+ {
+ display_write(-1, -1, 0, 1, lastname);
+ }
+ }
+}
+
+static void
+summary_format_memory(int x, int y, long *numbers, const char **names, int *cidx)
+
+{
+ register long num;
+ register int color;
+ register const char *thisname;
+ register const char *lastname = NULL;
+
+ /* format each number followed by its string */
+ while ((thisname = *names++) != NULL)
+ {
+ /* get the number to format */
+ num = *numbers++;
+ color = 0;
+
+ /* display only non-zero numbers */
+ if (num != 0)
+ {
+ /* write the previous name */
+ if (lastname != NULL)
+ {
+ display_write(-1, -1, 0, 0, lastname);
+ }
+
+ /* defer writing this name */
+ lastname = thisname;
+
+#ifdef ENABLE_COLOR
+ /* choose a color */
+ color = color_test(*cidx++, num);
+#endif
+
+ /* is this number in kilobytes? */
+ if (thisname[0] == 'K')
+ {
+ display_write(x, y, color, 0, format_k(num));
+ lastname++;
+ }
+ else
+ {
+ display_write(x, y, color, 0, itoa((int)num));
+ }
+
+ /* next iteration will not start at x, y */
+ x = y = -1;
+ }
+ }
+
+ /* if the last string has a separator on the end, it has to be
+ written with care */
+ if (lastname != NULL)
+ {
+ if ((num = strlen(lastname)) > 1 &&
+ lastname[num-2] == ',' && lastname[num-1] == ' ')
+ {
+ display_fmt(-1, -1, 0, 1, "%.*s", num-2, lastname);
+ }
+ else
+ {
+ display_write(-1, -1, 0, 1, lastname);
+ }
+ }
+}
+
+/*
+ * int display_resize()
+ *
+ * Reallocate buffer space needed by the display package to accomodate
+ * a new screen size. Must be called whenever the screen's size has
+ * changed. Returns the number of lines available for displaying
+ * processes or -1 if there was a problem allocating space.
+ */
+
+int
+display_resize()
+
+{
+ register int top_lines;
+ register int newsize;
+
+ /* calculate the current dimensions */
+ /* if operating in "dumb" mode, we only need one line */
+ top_lines = smart_terminal ? screen_length : 1;
+
+ /* we don't want more than MAX_COLS columns, since the machine-dependent
+ modules make static allocations based on MAX_COLS and we don't want
+ to run off the end of their buffers */
+ display_width = screen_width;
+ if (display_width >= MAX_COLS)
+ {
+ display_width = MAX_COLS - 1;
+ }
+
+ /* see how much space we need */
+ newsize = top_lines * (MAX_COLS + 1);
+
+ /* reallocate only if we need more than we already have */
+ if (newsize > bufsize)
+ {
+ /* deallocate any previous buffer that may have been there */
+ if (screenbuf != NULL)
+ {
+ free(screenbuf);
+ }
+ if (colorbuf != NULL)
+ {
+ free(colorbuf);
+ }
+
+ /* allocate space for the screen and color buffers */
+ bufsize = newsize;
+ screenbuf = ecalloc(bufsize, sizeof(char));
+ colorbuf = ecalloc(bufsize, sizeof(char));
+ if (screenbuf == NULL || colorbuf == NULL)
+ {
+ /* oops! */
+ return(-1);
+ }
+ }
+ else
+ {
+ /* just clear them out */
+ memzero(screenbuf, bufsize);
+ memzero(colorbuf, bufsize);
+ }
+
+ /* for dumb terminals, pretend like we can show any amount */
+ if (!smart_terminal)
+ return Largest;
+
+ /* adjust total lines on screen to lines available for procs */
+ if (top_lines < y_procs)
+ top_lines = 0;
+ else
+ top_lines -= y_procs;
+
+ /* return number of lines available */
+ return top_lines;
+}
+
+int
+display_lines()
+
+{
+ return(smart_terminal ? screen_length : Largest);
+}
+
+int
+display_columns()
+
+{
+ return(display_width);
+}
+
+/*
+ * int display_init(struct statics *statics)
+ *
+ * Initialize the display system based on information in the statics
+ * structure. Returns the number of lines available for displaying
+ * processes or -1 if there was an error.
+ */
+
+int
+display_setmulti(int m)
+{
+ int i;
+ if (m == multi)
+ return 0;
+ if ((multi = m) != 0) {
+ for (i = 1; i < ncpu; i++)
+ {
+ /* adjust screen placements */
+ y_kernel++;
+ y_mem++;
+ y_swap++;
+ y_message++;
+ y_header++;
+ y_idlecursor++;
+ y_procs++;
+ }
+ return -(ncpu - 1);
+ } else {
+ for (i = 1; i < ncpu; i++)
+ {
+ /* adjust screen placements */
+ y_kernel--;
+ y_mem--;
+ y_swap--;
+ y_message--;
+ y_header--;
+ y_idlecursor--;
+ y_procs--;
+ }
+ return (ncpu - 1);
+ }
+}
+
+int
+display_init(struct statics *statics, int percpuinfo)
+
+{
+ register int top_lines;
+ register const char **pp;
+ register char *p;
+ register int *ip;
+ register int i;
+
+ /* certain things may influence the screen layout,
+ so look at those first */
+
+ ncpu = statics->ncpu ? statics->ncpu : 1;
+ /* a kernel line shifts parts of the display down */
+ kernel_names = statics->kernel_names;
+ if ((num_kernel = string_count(kernel_names)) > 0)
+ {
+ /* adjust screen placements */
+ y_mem++;
+ y_swap++;
+ y_message++;
+ y_header++;
+ y_idlecursor++;
+ y_procs++;
+ }
+
+ (void)display_setmulti(percpuinfo);
+
+ /* a swap line shifts parts of the display down one */
+ swap_names = statics->swap_names;
+ if ((num_swap = string_count(swap_names)) > 0)
+ {
+ /* adjust screen placements */
+ y_message++;
+ y_header++;
+ y_idlecursor++;
+ y_procs++;
+ }
+
+ /* call resize to do the dirty work */
+ top_lines = display_resize();
+
+ /* only do the rest if we need to */
+ if (top_lines > -1)
+ {
+ /* save pointers and allocate space for names */
+ procstate_names = statics->procstate_names;
+ num_procstates = string_count(procstate_names);
+ lprocstates = ecalloc(num_procstates, sizeof(int));
+
+ cpustate_names = statics->cpustate_names;
+ num_cpustates = string_count(cpustate_names);
+ lcpustates = ecalloc(num_cpustates, sizeof(int) * ncpu);
+ cpustate_columns = ecalloc(num_cpustates, sizeof(int));
+ memory_names = statics->memory_names;
+ num_memory = string_count(memory_names);
+
+ /* calculate starting columns where needed */
+ cpustate_total_length = 0;
+ pp = cpustate_names;
+ ip = cpustate_columns;
+ while (*pp != NULL)
+ {
+ *ip++ = cpustate_total_length;
+ if ((i = strlen(*pp++)) > 0)
+ {
+ cpustate_total_length += i + 8;
+ }
+ }
+ cpustate_total_length -= 2;
+ }
+
+#ifdef ENABLE_COLOR
+ /* set up color tags for loadavg */
+ load_cidx[0] = color_tag("1min");
+ load_cidx[1] = color_tag("5min");
+ load_cidx[2] = color_tag("15min");
+
+ /* find header color */
+ header_cidx = color_tag("header");
+
+ /* color tags for cpu states */
+ cpustate_cidx = emalloc(num_cpustates * sizeof(int));
+ i = 0;
+ p = strcpyend(scratchbuf, "cpu.");
+ while (i < num_cpustates)
+ {
+ strcpy(p, cpustate_names[i]);
+ cpustate_cidx[i++] = color_tag(scratchbuf);
+ }
+
+ /* color tags for kernel */
+ if (num_kernel > 0)
+ {
+ kernel_cidx = emalloc(num_kernel * sizeof(int));
+ i = 0;
+ p = strcpyend(scratchbuf, "kernel.");
+ while (i < num_kernel)
+ {
+ strcpy(p, homogenize(kernel_names[i]+1));
+ kernel_cidx[i++] = color_tag(scratchbuf);
+ }
+ }
+
+ /* color tags for memory */
+ memory_cidx = emalloc(num_memory * sizeof(int));
+ i = 0;
+ p = strcpyend(scratchbuf, "memory.");
+ while (i < num_memory)
+ {
+ strcpy(p, homogenize(memory_names[i]+1));
+ memory_cidx[i++] = color_tag(scratchbuf);
+ }
+
+ /* color tags for swap */
+ if (num_swap > 0)
+ {
+ swap_cidx = emalloc(num_swap * sizeof(int));
+ i = 0;
+ p = strcpyend(scratchbuf, "swap.");
+ while (i < num_swap)
+ {
+ strcpy(p, homogenize(swap_names[i]+1));
+ swap_cidx[i++] = color_tag(scratchbuf);
+ }
+ }
+#endif
+
+ /* return number of lines available (or error) */
+ return(top_lines);
+}
+
+static void
+pr_loadavg(double avg, int i)
+
+{
+ int color = 0;
+
+#ifdef ENABLE_COLOR
+ color = color_test(load_cidx[i], (int)(avg * 100));
+#endif
+ display_fmt(x_loadave + X_LOADAVEWIDTH * i, y_loadave, color, 0,
+ avg < 10.0 ? " %5.2f" : " %5.1f", avg);
+ display_write(-1, -1, 0, 0, (i < 2 ? "," : ";"));
+}
+
+void
+i_loadave(int mpid, double *avenrun)
+
+{
+ register int i;
+
+ /* mpid == -1 implies this system doesn't have an _mpid */
+ if (mpid != -1)
+ {
+ display_fmt(0, 0, 0, 0,
+ "last pid: %5d; load avg:", mpid);
+ x_loadave = X_LOADAVE;
+ }
+ else
+ {
+ display_write(0, 0, 0, 0, "load averages:");
+ x_loadave = X_LOADAVE - X_LASTPIDWIDTH;
+ }
+ for (i = 0; i < 3; i++)
+ {
+ pr_loadavg(avenrun[i], i);
+ }
+
+ lmpid = mpid;
+}
+
+void
+u_loadave(int mpid, double *avenrun)
+
+{
+ register int i;
+
+ if (mpid != -1)
+ {
+ /* change screen only when value has really changed */
+ if (mpid != lmpid)
+ {
+ display_fmt(x_lastpid, y_lastpid, 0, 0,
+ "%5d", mpid);
+ lmpid = mpid;
+ }
+ }
+
+ /* display new load averages */
+ for (i = 0; i < 3; i++)
+ {
+ pr_loadavg(avenrun[i], i);
+ }
+}
+
+static char minibar_buffer[64];
+#define MINIBAR_WIDTH 20
+
+void
+i_minibar(int (*formatter)(char *, int))
+{
+ (void)((*formatter)(minibar_buffer, MINIBAR_WIDTH));
+
+ display_write(x_minibar, y_minibar, 0, 0, minibar_buffer);
+}
+
+void
+u_minibar(int (*formatter)(char *, int))
+{
+ (void)((*formatter)(minibar_buffer, MINIBAR_WIDTH));
+
+ display_write(x_minibar, y_minibar, 0, 0, minibar_buffer);
+}
+
+static int uptime_days;
+static int uptime_hours;
+static int uptime_mins;
+static int uptime_secs;
+
+void
+i_uptime(time_t *bt, time_t *tod)
+
+{
+ time_t uptime;
+
+ if (*bt != -1)
+ {
+ uptime = *tod - *bt;
+ uptime += 30;
+ uptime_days = uptime / 86400;
+ uptime %= 86400;
+ uptime_hours = uptime / 3600;
+ uptime %= 3600;
+ uptime_mins = uptime / 60;
+ uptime_secs = uptime % 60;
+
+ /*
+ * Display the uptime.
+ */
+
+ display_fmt(x_uptime, y_uptime, 0, 0,
+ " up %d+%02d:%02d:%02d",
+ uptime_days, uptime_hours, uptime_mins, uptime_secs);
+ }
+}
+
+void
+u_uptime(time_t *bt, time_t *tod)
+
+{
+ i_uptime(bt, tod);
+}
+
+
+void
+i_timeofday(time_t *tod)
+
+{
+ /*
+ * Display the current time.
+ * "ctime" always returns a string that looks like this:
+ *
+ * Sun Sep 16 01:03:52 1973
+ * 012345678901234567890123
+ * 1 2
+ *
+ * We want indices 11 thru 18 (length 8).
+ */
+
+ int x;
+
+ /* where on the screen do we start? */
+ x = (smart_terminal ? screen_width : 79) - 8;
+
+ /* but don't bump in to uptime */
+ if (x < x_uptime + 19)
+ {
+ x = x_uptime + 19;
+ }
+
+ /* display it */
+ display_fmt(x, 0, 0, 1, "%-8.8s", &(ctime(tod)[11]));
+}
+
+static int ltotal = 0;
+static int lthreads = 0;
+
+/*
+ * *_procstates(total, brkdn, names) - print the process summary line
+ */
+
+
+void
+i_procstates(int total, int *brkdn, int threads)
+
+{
+ /* write current number of processes and remember the value */
+ display_fmt(0, y_procstate, 0, 0,
+ "%d %s: ", total, threads ? "threads" : "processes");
+ ltotal = total;
+
+ /* remember where the summary starts */
+ x_procstate = virt_x;
+
+ if (total > 0)
+ {
+ /* format and print the process state summary */
+ summary_format(-1, -1, brkdn, procstate_names, NULL);
+
+ /* save the numbers for next time */
+ memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
+ lthreads = threads;
+ }
+}
+
+void
+u_procstates(int total, int *brkdn, int threads)
+
+{
+ /* if threads state has changed, do a full update */
+ if (lthreads != threads)
+ {
+ i_procstates(total, brkdn, threads);
+ return;
+ }
+
+ /* update number of processes only if it has changed */
+ if (ltotal != total)
+ {
+ display_fmt(0, y_procstate, 0, 0,
+ "%d", total);
+
+ /* if number of digits differs, rewrite the label */
+ if (digits(total) != digits(ltotal))
+ {
+ display_fmt(-1, -1, 0, 0, " %s: ", threads ? "threads" : "processes");
+ x_procstate = virt_x;
+ }
+
+ /* save new total */
+ ltotal = total;
+ }
+
+ /* see if any of the state numbers has changed */
+ if (total > 0 && memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
+ {
+ /* format and update the line */
+ summary_format(x_procstate, y_procstate, brkdn, procstate_names, NULL);
+ memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
+ }
+}
+
+/*
+ * *_cpustates(states, names) - print the cpu state percentages
+ */
+
+/* cpustates_tag() calculates the correct tag to use to label the line */
+
+static char *
+cpustates_tag(int c)
+
+{
+ unsigned width, u;
+
+ static char fmttag[100];
+
+ const char *short_tag = !multi || ncpu <= 1 ? "CPU: " : "CPU%0*d: ";
+ const char *long_tag = !multi || ncpu <= 1 ?
+ "CPU states: " : "CPU%0*d states: ";
+
+ for (width = 0, u = ncpu - 1; u > 0; u /= 10) {
+ ++width;
+ }
+ /* if length + strlen(long_tag) > screen_width, then we have to
+ use the shorter tag */
+
+ snprintf(fmttag, sizeof(fmttag), long_tag, width, c);
+
+ if (cpustate_total_length + (signed)strlen(fmttag) > screen_width) {
+ snprintf(fmttag, sizeof(fmttag), short_tag, width, c);
+ }
+
+ /* set x_cpustates accordingly then return result */
+ x_cpustates = strlen(fmttag);
+ return(fmttag);
+}
+
+void
+i_cpustates(int *states)
+
+{
+ int value;
+ const char **names;
+ const char *thisname;
+ int *colp;
+ int color = 0;
+#ifdef ENABLE_COLOR
+ int *cidx;
+#endif
+ int c, i;
+
+ if (multi == 0 && ncpu > 1)
+ {
+ for (c = 1; c < ncpu; c++)
+ for (i = 0; i < num_cpustates; i++)
+ states[i] += states[c * num_cpustates + i];
+ for (i = 0; i < num_cpustates; i++)
+ states[i] /= ncpu;
+ }
+
+ for (c = 0; c < (multi ? ncpu : 1); c++)
+ {
+#ifdef ENABLE_COLOR
+ cidx = cpustate_cidx;
+#endif
+
+ /* print tag */
+ display_write(0, y_cpustates + c, 0, 0, cpustates_tag(c));
+ colp = cpustate_columns;
+
+ /* now walk thru the names and print the line */
+ for (i = 0, names = cpustate_names; ((thisname = *names++) != NULL);)
+ {
+ if (*thisname != '\0')
+ {
+ /* retrieve the value and remember it */
+ value = *states;
+
+#ifdef ENABLE_COLOR
+ /* determine color number to use */
+ color = color_test(*cidx++, value/10);
+#endif
+
+ /* if percentage is >= 1000, print it as 100% */
+ display_fmt(x_cpustates + *colp, y_cpustates + c,
+ color, 0,
+ (value >= 1000 ? "%4.0f%% %s%s" : "%4.1f%% %s%s"),
+ ((float)value)/10.,
+ thisname,
+ *names != NULL ? ", " : "");
+
+ }
+ /* increment */
+ colp++;
+ states++;
+ }
+ }
+
+ /* copy over values into "last" array */
+ memcpy(lcpustates, states, num_cpustates * sizeof(int) * ncpu);
+}
+
+void
+u_cpustates(int *states)
+
+{
+ int value;
+ const char **names;
+ const char *thisname;
+ int *lp;
+ int *colp;
+ int color = 0;
+#ifdef ENABLE_COLOR
+ int *cidx;
+#endif
+ int c, i;
+
+ lp = lcpustates;
+
+ if (multi == 0 && ncpu > 1)
+ {
+ for (c = 1; c < ncpu; c++)
+ for (i = 0; i < num_cpustates; i++)
+ states[i] += states[c * num_cpustates + i];
+ for (i = 0; i < num_cpustates; i++)
+ states[i] /= ncpu;
+ }
+
+ for (c = 0; c < (multi ? ncpu : 1); c++)
+ {
+#ifdef ENABLE_COLOR
+ cidx = cpustate_cidx;
+#endif
+ colp = cpustate_columns;
+ /* we could be much more optimal about this */
+ for (names = cpustate_names; (thisname = *names++) != NULL;)
+ {
+ if (*thisname != '\0')
+ {
+ /* did the value change since last time? */
+ if (*lp != *states)
+ {
+ /* yes, change it */
+ /* retrieve value and remember it */
+ value = *states;
+
+#ifdef ENABLE_COLOR
+ /* determine color number to use */
+ color = color_test(*cidx, value/10);
+#endif
+
+ /* if percentage is >= 1000, print it as 100% */
+ display_fmt(x_cpustates + *colp, y_cpustates + c, color, 0,
+ (value >= 1000 ? "%4.0f" : "%4.1f"),
+ ((double)value)/10.);
+
+ /* remember it for next time */
+ *lp = value;
+ }
+#ifdef ENABLE_COLOR
+ cidx++;
+#endif
+ }
+
+ /* increment and move on */
+ lp++;
+ states++;
+ colp++;
+ }
+ }
+}
+
+void
+z_cpustates()
+
+{
+ register int i, c;
+ register const char **names = cpustate_names;
+ register const char *thisname;
+ register int *lp;
+
+ /* print tag */
+ for (c = 0; c < (multi ? ncpu : 1); c++)
+ {
+ display_write(0, y_cpustates + c, 0, 0, cpustates_tag(c));
+
+ for (i = 0, names = cpustate_names; (thisname = *names++) != NULL;)
+ {
+ if (*thisname != '\0')
+ {
+ display_fmt(-1, -1, 0, 0, "%s %% %s", i++ == 0 ? "" : ", ",
+ thisname);
+ }
+ }
+ }
+
+ /* fill the "last" array with all -1s, to insure correct updating */
+ lp = lcpustates;
+ i = num_cpustates * ncpu;
+ while (--i >= 0)
+ {
+ *lp++ = -1;
+ }
+}
+
+/*
+ * *_kernel(stats) - print "Kernel: " followed by the kernel summary string
+ *
+ * Assumptions: cursor is on "lastline", the previous line
+ */
+
+void
+i_kernel(int *stats)
+
+{
+ if (num_kernel > 0)
+ {
+ display_write(0, y_kernel, 0, 0, "Kernel: ");
+
+ /* format and print the kernel summary */
+ summary_format(x_kernel, y_kernel, stats, kernel_names, kernel_cidx);
+ }
+}
+
+void
+u_kernel(int *stats)
+
+{
+ if (num_kernel > 0)
+ {
+ /* format the new line */
+ summary_format(x_kernel, y_kernel, stats, kernel_names, kernel_cidx);
+ }
+}
+
+/*
+ * *_memory(stats) - print "Memory: " followed by the memory summary string
+ *
+ * Assumptions: cursor is on "lastline", the previous line
+ */
+
+void
+i_memory(long *stats)
+
+{
+ display_write(0, y_mem, 0, 0, "Memory: ");
+
+ /* format and print the memory summary */
+ summary_format_memory(x_mem, y_mem, stats, memory_names, memory_cidx);
+}
+
+void
+u_memory(long *stats)
+
+{
+ /* format the new line */
+ summary_format_memory(x_mem, y_mem, stats, memory_names, memory_cidx);
+}
+
+/*
+ * *_swap(stats) - print "Swap: " followed by the swap summary string
+ *
+ * Assumptions: cursor is on "lastline", the previous line
+ *
+ * These functions only print something when num_swap > 0
+ */
+
+void
+i_swap(long *stats)
+
+{
+ if (num_swap > 0)
+ {
+ /* print the tag */
+ display_write(0, y_swap, 0, 0, "Swap: ");
+
+ /* format and print the swap summary */
+ summary_format_memory(x_swap, y_swap, stats, swap_names, swap_cidx);
+ }
+}
+
+void
+u_swap(long *stats)
+
+{
+ if (num_swap > 0)
+ {
+ /* format the new line */
+ summary_format_memory(x_swap, y_swap, stats, swap_names, swap_cidx);
+ }
+}
+
+/*
+ * *_message() - print the next pending message line, or erase the one
+ * that is there.
+ *
+ * Note that u_message is (currently) the same as i_message.
+ *
+ * Assumptions: lastline is consistent
+ */
+
+/*
+ * i_message is funny because it gets its message asynchronously (with
+ * respect to screen updates). Messages are taken out of the
+ * circular message_buf and displayed one at a time.
+ */
+
+void
+i_message(struct timeval *now)
+
+{
+ struct timeval my_now;
+ int i = 0;
+
+ dprintf("i_message(%08x)\n", now);
+
+ /* if now is NULL we have to get it ourselves */
+ if (now == NULL)
+ {
+ time_get(&my_now);
+ now = &my_now;
+ }
+
+ /* now that we have been called, messages no longer need to be held */
+ message_hold = 0;
+
+ dprintf("i_message: now %d, message_time %d\n",
+ now->tv_sec, message_time.tv_sec);
+
+ if (smart_terminal)
+ {
+ /* is it time to change the message? */
+ if (timercmp(now, &message_time, > ))
+ {
+ /* yes, free the current message */
+ dprintf("i_message: timer expired\n");
+ if (message_current != NULL)
+ {
+ free(message_current);
+ message_current = NULL;
+ }
+
+ /* is there a new message to be displayed? */
+ if (message_first != message_last)
+ {
+ /* move index to next message */
+ if (++message_first == MAX_MESSAGES) message_first = 0;
+
+ /* make the next message the current one */
+ message_current = message_buf[message_first];
+
+ /* show it */
+ dprintf("i_message: showing \"%s\"\n", message_current);
+ display_move(0, y_message);
+ screen_standout(message_current);
+ i = strlen(message_current);
+
+ /* set the expiration timer */
+ message_time = *now;
+ message_time.tv_sec += MESSAGE_DISPLAY_TIME;
+
+ /* clear the rest of the line */
+ screen_cleareol(message_length - i);
+ putchar('\r');
+ message_length = i;
+ }
+ else
+ {
+ /* just clear what was there before, if anything */
+ if (message_length > 0)
+ {
+ display_move(0, y_message);
+ screen_cleareol(message_length);
+ putchar('\r');
+ message_length = 0;
+ }
+ }
+ }
+ }
+}
+
+void
+u_message(struct timeval *now)
+
+{
+ i_message(now);
+}
+
+static int header_length;
+
+/*
+ * *_header(text) - print the header for the process area
+ *
+ * Assumptions: cursor is on the previous line and lastline is consistent
+ */
+
+void
+i_header(char *text)
+
+{
+ int header_color = 0;
+
+#ifdef ENABLE_COLOR
+ header_color = color_test(header_cidx, 0);
+#endif
+ header_length = strlen(text);
+ if (header_status)
+ {
+ display_write(x_header, y_header, header_color, 1, text);
+ }
+}
+
+/*ARGSUSED*/
+void
+u_header(char *text)
+
+{
+ int header_color = 0;
+
+#ifdef ENABLE_COLOR
+ header_color = color_test(header_cidx, 0);
+#endif
+ display_write(x_header, y_header, header_color, 1,
+ header_status ? text : "");
+}
+
+/*
+ * *_process(line, thisline) - print one process line
+ *
+ * Assumptions: lastline is consistent
+ */
+
+void
+i_process(int line, char *thisline)
+
+{
+ /* truncate the line to conform to our current screen width */
+ thisline[display_width] = '\0';
+
+ /* write the line out */
+ display_write(0, y_procs + line, 0, 1, thisline);
+}
+
+void
+u_process(int line, char *new_line)
+
+{
+ i_process(line, new_line);
+}
+
+void
+i_endscreen()
+
+{
+ if (smart_terminal)
+ {
+ /* move the cursor to a pleasant place */
+ display_move(x_idlecursor, y_idlecursor);
+ }
+ else
+ {
+ /* separate this display from the next with some vertical room */
+ fputs("\n\n", stdout);
+ }
+ fflush(stdout);
+}
+
+void
+u_endscreen()
+
+{
+ if (smart_terminal)
+ {
+ /* clear-to-end the display */
+ display_cte();
+
+ /* move the cursor to a pleasant place */
+ display_move(x_idlecursor, y_idlecursor);
+ fflush(stdout);
+ }
+ else
+ {
+ /* separate this display from the next with some vertical room */
+ fputs("\n\n", stdout);
+ }
+}
+
+void
+display_header(int t)
+
+{
+ header_status = t != 0;
+}
+
+void
+message_mark(void)
+
+{
+ message_barrier = Yes;
+}
+
+void
+message_expire(void)
+
+{
+ message_time.tv_sec = 0;
+ message_time.tv_usec = 0;
+}
+
+static void
+message_flush(void)
+
+{
+ message_first = message_last;
+ message_time.tv_sec = 0;
+ message_time.tv_usec = 0;
+}
+
+/*
+ * void new_message_v(char *msgfmt, va_list ap)
+ *
+ * Display a message in the message area. This function takes a va_list for
+ * the arguments. Safe to call before display_init. This function only
+ * queues a message for display, and allowed for multiple messages to be
+ * queued. The i_message function drains the queue and actually writes the
+ * messages on the display.
+ */
+
+
+static void
+new_message_v(const char *msgfmt, va_list ap)
+
+{
+ int i;
+ int empty;
+ char msg[MAX_COLS];
+
+ /* if message_barrier is active, remove all pending messages */
+ if (message_barrier)
+ {
+ message_flush();
+ message_barrier = No;
+ }
+
+ /* first, format the message */
+ (void) vsnprintf(msg, sizeof(msg), msgfmt, ap);
+
+ /* where in the buffer will it go? */
+ i = message_last + 1;
+ if (i >= MAX_MESSAGES) i = 0;
+
+ /* make sure the buffer is not full */
+ if (i != message_first)
+ {
+ /* insert it in to message_buf */
+ message_buf[i] = estrdup(msg);
+ dprintf("new_message_v: new message inserted in slot %d\n", i);
+
+ /* remember if the buffer is empty and set the index */
+ empty = message_last == message_first;
+ message_last = i;
+
+ /* is message_buf otherwise empty and have we started displaying? */
+ if (empty && !message_hold)
+ {
+ /* we can display the message now */
+ i_message(NULL);
+ }
+ }
+}
+
+/*
+ * void new_message(int type, char *msgfmt, ...)
+ *
+ * Display a message in the message area. It is safe to call this function
+ * before display_init. Messages logged before the display is drawn will be
+ * held and displayed later.
+ */
+
+void
+new_message(const char *msgfmt, ...)
+
+{
+ va_list ap;
+
+ va_start(ap, msgfmt);
+ new_message_v(msgfmt, ap);
+ va_end(ap);
+}
+
+/*
+ * void message_error(char *msgfmt, ...)
+ *
+ * Put an error message in the message area. It is safe to call this function
+ * before display_init. Messages logged before the display is drawn will be
+ * held and displayed later.
+ */
+
+void
+message_error(const char *msgfmt, ...)
+
+{
+ va_list ap;
+
+ va_start(ap, msgfmt);
+ new_message_v(msgfmt, ap);
+ fflush(stdout);
+ va_end(ap);
+}
+
+/*
+ * void message_clear()
+ *
+ * Clear message area and flush all pending messages.
+ */
+
+void
+message_clear()
+
+{
+ /* remove any existing message */
+ if (message_current != NULL)
+ {
+ display_move(0, y_message);
+ screen_cleareol(message_length);
+ free(message_current);
+ message_current = 0;
+ }
+
+ /* flush all pending messages */
+ message_flush();
+}
+
+/*
+ * void message_prompt_v(int so, char *msgfmt, va_list ap)
+ *
+ * Place a prompt in the message area. A prompt is different from a
+ * message as follows: it is displayed immediately, overwriting any
+ * message that may already be there, it may be highlighted in standout
+ * mode (if "so" is true), the cursor is left to rest at the end of the
+ * prompt. This call causes all pending messages to be flushed.
+ */
+
+static void
+message_prompt_v(int so, const char *msgfmt, va_list ap)
+
+{
+ char msg[MAX_COLS];
+ int i;
+
+ /* clear out the message buffer */
+ message_flush();
+
+ /* format the message */
+ i = vsnprintf(msg, sizeof(msg), msgfmt, ap);
+
+ /* this goes over any existing message */
+ display_move(0, y_message);
+
+ /* clear the entire line */
+ screen_cleareol(message_length);
+
+ /* show the prompt */
+ if (so)
+ {
+ screen_standout(msg);
+ }
+ else
+ {
+ fputs(msg, stdout);
+ }
+
+ /* make it all visible */
+ fflush(stdout);
+
+ /* even though we dont keep a copy of the prompt, track its length */
+ message_length = i < MAX_COLS ? i : MAX_COLS;
+}
+
+/*
+ * void message_prompt(char *msgfmt, ...)
+ *
+ * Place a prompt in the message area (see message_prompt_v).
+ */
+
+void
+message_prompt(const char *msgfmt, ...)
+
+{
+ va_list ap;
+
+ va_start(ap, msgfmt);
+ message_prompt_v(Yes, msgfmt, ap);
+ va_end(ap);
+}
+
+void
+message_prompt_plain(const char *msgfmt, ...)
+
+{
+ va_list ap;
+
+ va_start(ap, msgfmt);
+ message_prompt_v(No, msgfmt, ap);
+ va_end(ap);
+}
+
+/*
+ * int readline(char *buffer, int size, int numeric)
+ *
+ * Read a line of input from the terminal. The line is placed in
+ * "buffer" not to exceed "size". If "numeric" is true then the input
+ * can only consist of digits. This routine handles all character
+ * editing while keeping the terminal in cbreak mode. If "numeric"
+ * is true then the number entered is returned. Otherwise the number
+ * of character read in to "buffer" is returned.
+ */
+
+int
+readline(char *buffer, int size, int numeric)
+
+{
+ register char *ptr = buffer;
+ register char ch;
+ register char cnt = 0;
+
+ /* allow room for null terminator */
+ size -= 1;
+
+ /* read loop */
+ while ((fflush(stdout), read(0, ptr, 1) > 0))
+ {
+ /* newline or return means we are done */
+ if ((ch = *ptr) == '\n' || ch == '\r')
+ {
+ break;
+ }
+
+ /* handle special editing characters */
+ if (ch == ch_kill)
+ {
+ /* return null string */
+ *buffer = '\0';
+ putchar('\r');
+ return(-1);
+ }
+ else if (ch == ch_werase)
+ {
+ /* erase previous word */
+ if (cnt <= 0)
+ {
+ /* none to erase! */
+ putchar('\7');
+ }
+ else
+ {
+ /*
+ * First: remove all spaces till the first-non-space
+ * Second: remove all non-spaces till the first-space
+ */
+ while(cnt > 0 && ptr[-1] == ' ')
+ {
+ fputs("\b \b", stdout);
+ ptr--;
+ cnt--;
+ }
+ while(cnt > 0 && ptr[-1] != ' ')
+ {
+ fputs("\b \b", stdout);
+ ptr--;
+ cnt--;
+ }
+ }
+ }
+ else if (ch == ch_erase)
+ {
+ /* erase previous character */
+ if (cnt <= 0)
+ {
+ /* none to erase! */
+ putchar('\7');
+ }
+ else
+ {
+ fputs("\b \b", stdout);
+ ptr--;
+ cnt--;
+ }
+ }
+ /* check for character validity and buffer overflow */
+ else if (cnt == size || (numeric && !isdigit((int)ch)) ||
+ !isprint((int)ch))
+ {
+ /* not legal */
+ putchar('\7');
+ }
+ else
+ {
+ /* echo it and store it in the buffer */
+ putchar(ch);
+ ptr++;
+ cnt++;
+ }
+ }
+
+ /* all done -- null terminate the string */
+ *ptr = '\0';
+
+ /* add response length to message_length */
+ message_length += cnt;
+
+ /* return either inputted number or string length */
+ putchar('\r');
+ return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
+}
+
+void
+display_pagerstart()
+
+{
+ display_clear();
+}
+
+void
+display_pagerend()
+
+{
+ char ch;
+
+ screen_standout("Hit any key to continue: ");
+ fflush(stdout);
+ (void) read(0, &ch, 1);
+}
+
+void
+display_pager(const char *fmt, ...)
+
+{
+ va_list ap;
+
+ int ch;
+ char readch;
+ char buffer[MAX_COLS];
+ char *data;
+
+ /* format into buffer */
+ va_start(ap, fmt);
+ (void) vsnprintf(buffer, MAX_COLS, fmt, ap);
+ va_end(ap);
+ data = buffer;
+
+ while ((ch = *data++) != '\0')
+ {
+ putchar(ch);
+ if (ch == '\n')
+ {
+ if (++curr_y >= screen_length - 1)
+ {
+ screen_standout("...More...");
+ fflush(stdout);
+ (void) read(0, &readch, 1);
+ putchar('\r');
+ switch(readch)
+ {
+ case '\r':
+ case '\n':
+ curr_y--;
+ break;
+
+ case 'q':
+ return;
+
+ default:
+ curr_y = 0;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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 "os.h"
+
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+
+#include "hash.h"
+
+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);
+}
+
+static void ll_init(llist *q)
+
+{
+ q->head = NULL;
+ q->count = 0;
+}
+
+static llistitem *ll_newitem(int size)
+
+{
+ llistitem *qi;
+
+ qi = emalloc(sizeof(llistitem) + size);
+ qi->datum = ((char *)qi + sizeof(llistitem));
+ return qi;
+}
+
+static void ll_freeitem(llistitem *li)
+
+{
+ free(li);
+}
+
+static void ll_add(llist *q, llistitem *new)
+
+{
+ new->next = q->head;
+ q->head = new;
+ q->count++;
+}
+
+static 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)
+#define LL_NEXT(q, qi) ((qi) != NULL ? (qi)->next : NULL)
+#define LL_ISEMPTY(ll) ((ll)->count == 0)
+
+#ifdef notdef
+static llistitem *
+ll_first(llist *q)
+
+{
+ return q->head;
+}
+
+static llistitem *
+ll_next(llist *q, llistitem *qi)
+
+{
+ return (qi != NULL ? qi->next : NULL);
+}
+
+static int
+ll_isempty(llist *ll)
+
+{
+ return (ll->count == 0);
+}
+#endif
+
+/*
+ * 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 = emalloc(sizeof(hash_table));
+
+ /* adjust bucket count to be prime */
+ num = next_prime(num);
+
+ /* create the buckets */
+ bytes = sizeof(bucket_t) * num;
+ result->buckets = b = emalloc(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.
+ */
+
+#ifdef notdef
+static 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;
+}
+#endif
+
+/*
+ * 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++;
+ }
+}
+
+
+
+
+
+
+
+/*
+ * void hash_add_uint(hash_table *ht, unsigned int 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 unsigned int
+ */
+
+void *
+hash_add_uint(hash_table *ht, unsigned int key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_uint *hi;
+ hash_item_uint *h;
+ llist *ll;
+ llistitem *li;
+ llistitem *newli;
+ unsigned int k1;
+
+ /* allocate the space we will need */
+ newli = ll_newitem(sizeof(hash_item_uint));
+ hi = (hash_item_uint *)newli->datum;
+
+ /* fill in the values */
+ hi->key = key;
+ hi->value = value;
+
+ /* hash to the bucket */
+ bucket = &(ht->buckets[(key % ht->num_buckets)]);
+
+ /* 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_uint *)li->datum;
+ k1 = h->key;
+ if (key == k1)
+ {
+ /* 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_uint *)(li->datum))->value;
+ }
+}
+
+/*
+ * void *hash_replace_uint(hash_table *ht, unsigned int 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 unsigned int
+ */
+
+void *
+hash_replace_uint(hash_table *ht, unsigned int key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_uint *hi;
+ llist *ll;
+ llistitem *li;
+ void *result = NULL;
+ unsigned int k1;
+
+ /* find the bucket */
+ bucket = &(ht->buckets[(key % ht->num_buckets)]);
+
+ /* walk the list until we find the existing item */
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ hi = (hash_item_uint *)li->datum;
+ k1 = hi->key;
+ if (key == k1)
+ {
+ /* 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_uint));
+ hi = (hash_item_uint *)li->datum;
+ hi->key = key;
+ hi->value = value;
+ ll_add(&(bucket->list), li);
+ }
+
+ /* return the old value (so it can be freed) */
+ return result;
+}
+
+/*
+ * void *hash_lookup_uint(hash_table *ht, unsigned int key)
+ *
+ * Look up "key" in "ht" and return the associated value. If "key"
+ * is not found, return NULL. Key type is unsigned int
+ */
+
+void *
+hash_lookup_uint(hash_table *ht, unsigned int key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ hash_item_uint *h;
+ void *result;
+ unsigned int k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ h = (hash_item_uint *)li->datum;
+ k1 = h->key;
+ if (key == k1)
+ {
+ result = h->value;
+ break;
+ }
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * void *hash_remove_uint(hash_table *ht, unsigned int 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_uint(hash_table *ht, unsigned int key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ llistitem *lilast;
+ hash_item_uint *hi;
+ void *result;
+ unsigned int k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ lilast = NULL;
+ while (li != NULL)
+ {
+ hi = (hash_item_uint *)li->datum;
+ k1 = hi->key;
+ if (key == k1)
+ {
+ ll_extract(ll, li, lilast);
+ result = hi->value;
+ key = hi->key;
+ ;
+ ll_freeitem(li);
+ break;
+ }
+ lilast = li;
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * hash_item_uint *hash_first_uint(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_uint *
+hash_first_uint(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_uint *)pos->ll_item->datum;
+}
+
+
+/*
+ * hash_item_uint *hash_next_uint(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_uint *
+hash_next_uint(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_uint *)li->datum;
+}
+
+/*
+ * void *hash_remove_pos_uint(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_uint(hash_pos *pos)
+
+{
+ llistitem *li;
+ void *ans;
+ hash_item_uint *hi;
+
+ /* 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_uint *)li->datum;
+ ans = hi->value;
+
+ 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;
+}
+
+
+
+/*
+ * void hash_add_pid(hash_table *ht, pid_t 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 pid_t
+ */
+
+void *
+hash_add_pid(hash_table *ht, pid_t key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_pid *hi;
+ hash_item_pid *h;
+ llist *ll;
+ llistitem *li;
+ llistitem *newli;
+ pid_t k1;
+
+ /* allocate the space we will need */
+ newli = ll_newitem(sizeof(hash_item_pid));
+ hi = (hash_item_pid *)newli->datum;
+
+ /* fill in the values */
+ hi->key = key;
+ hi->value = value;
+
+ /* hash to the bucket */
+ bucket = &(ht->buckets[(key % ht->num_buckets)]);
+
+ /* 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_pid *)li->datum;
+ k1 = h->key;
+ if (key == k1)
+ {
+ /* 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_pid *)(li->datum))->value;
+ }
+}
+
+/*
+ * void *hash_replace_pid(hash_table *ht, pid_t 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 pid_t
+ */
+
+void *
+hash_replace_pid(hash_table *ht, pid_t key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_pid *hi;
+ llist *ll;
+ llistitem *li;
+ void *result = NULL;
+ pid_t k1;
+
+ /* find the bucket */
+ bucket = &(ht->buckets[(key % ht->num_buckets)]);
+
+ /* walk the list until we find the existing item */
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ hi = (hash_item_pid *)li->datum;
+ k1 = hi->key;
+ if (key == k1)
+ {
+ /* 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_pid));
+ hi = (hash_item_pid *)li->datum;
+ hi->key = key;
+ hi->value = value;
+ ll_add(&(bucket->list), li);
+ }
+
+ /* return the old value (so it can be freed) */
+ return result;
+}
+
+/*
+ * void *hash_lookup_pid(hash_table *ht, pid_t key)
+ *
+ * Look up "key" in "ht" and return the associated value. If "key"
+ * is not found, return NULL. Key type is pid_t
+ */
+
+void *
+hash_lookup_pid(hash_table *ht, pid_t key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ hash_item_pid *h;
+ void *result;
+ pid_t k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ h = (hash_item_pid *)li->datum;
+ k1 = h->key;
+ if (key == k1)
+ {
+ result = h->value;
+ break;
+ }
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * void *hash_remove_pid(hash_table *ht, pid_t 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_pid(hash_table *ht, pid_t key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ llistitem *lilast;
+ hash_item_pid *hi;
+ void *result;
+ pid_t k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ lilast = NULL;
+ while (li != NULL)
+ {
+ hi = (hash_item_pid *)li->datum;
+ k1 = hi->key;
+ if (key == k1)
+ {
+ ll_extract(ll, li, lilast);
+ result = hi->value;
+ key = hi->key;
+ ;
+ ll_freeitem(li);
+ break;
+ }
+ lilast = li;
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * hash_item_pid *hash_first_pid(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_pid *
+hash_first_pid(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_pid *)pos->ll_item->datum;
+}
+
+
+/*
+ * hash_item_pid *hash_next_pid(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_pid *
+hash_next_pid(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_pid *)li->datum;
+}
+
+/*
+ * void *hash_remove_pos_pid(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_pid(hash_pos *pos)
+
+{
+ llistitem *li;
+ void *ans;
+ hash_item_pid *hi;
+
+ /* 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_pid *)li->datum;
+ ans = hi->value;
+
+ /* free up the space */
+ 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;
+}
+
+
+
+/*
+ * void hash_add_string(hash_table *ht, char * 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 char *
+ */
+
+void *
+hash_add_string(hash_table *ht, char * key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_string *hi;
+ hash_item_string *h;
+ llist *ll;
+ llistitem *li;
+ llistitem *newli;
+ char * k1;
+
+ /* allocate the space we will need */
+ newli = ll_newitem(sizeof(hash_item_string));
+ hi = (hash_item_string *)newli->datum;
+
+ /* fill in the values */
+ hi->key = estrdup(key);
+ hi->value = value;
+
+ /* hash to the bucket */
+ bucket = &(ht->buckets[string_hash(ht, key)]);
+
+ /* 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_string *)li->datum;
+ k1 = h->key;
+ if (strcmp(key, k1) == 0)
+ {
+ /* 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_string *)(li->datum))->value;
+ }
+}
+
+/*
+ * void *hash_replace_string(hash_table *ht, char * 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 char *
+ */
+
+void *
+hash_replace_string(hash_table *ht, char * key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_string *hi;
+ llist *ll;
+ llistitem *li;
+ void *result = NULL;
+ char * k1;
+
+ /* find the bucket */
+ bucket = &(ht->buckets[string_hash(ht, key)]);
+
+ /* walk the list until we find the existing item */
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ hi = (hash_item_string *)li->datum;
+ k1 = hi->key;
+ if (strcmp(key, k1) == 0)
+ {
+ /* 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_string));
+ hi = (hash_item_string *)li->datum;
+ hi->key = estrdup(key);
+ hi->value = value;
+ ll_add(&(bucket->list), li);
+ }
+
+ /* return the old value (so it can be freed) */
+ return result;
+}
+
+/*
+ * void *hash_lookup_string(hash_table *ht, char * key)
+ *
+ * Look up "key" in "ht" and return the associated value. If "key"
+ * is not found, return NULL. Key type is char *
+ */
+
+void *
+hash_lookup_string(hash_table *ht, char * key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ hash_item_string *h;
+ void *result;
+ char * k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[string_hash(ht, key)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ h = (hash_item_string *)li->datum;
+ k1 = h->key;
+ if (strcmp(key, k1) == 0)
+ {
+ result = h->value;
+ break;
+ }
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * void *hash_remove_string(hash_table *ht, char * 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_string(hash_table *ht, char * key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ llistitem *lilast;
+ hash_item_string *hi;
+ void *result;
+ char * k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[string_hash(ht, key)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ lilast = NULL;
+ while (li != NULL)
+ {
+ hi = (hash_item_string *)li->datum;
+ k1 = hi->key;
+ if (strcmp(key, k1) == 0)
+ {
+ ll_extract(ll, li, lilast);
+ result = hi->value;
+ key = hi->key;
+ free(key);
+ ll_freeitem(li);
+ break;
+ }
+ lilast = li;
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * hash_item_string *hash_first_string(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_string *
+hash_first_string(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_string *)pos->ll_item->datum;
+}
+
+
+/*
+ * hash_item_string *hash_next_string(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_string *
+hash_next_string(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_string *)li->datum;
+}
+
+/*
+ * void *hash_remove_pos_string(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_string(hash_pos *pos)
+
+{
+ llistitem *li;
+ void *ans;
+ hash_item_string *hi;
+ char * 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_string *)li->datum;
+ ans = hi->value;
+
+ /* free up the space */
+ key = hi->key;
+ free(key);
+ 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;
+}
+
+
+
+/*
+ * void hash_add_pidthr(hash_table *ht, pidthr_t 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 pidthr_t
+ */
+
+void *
+hash_add_pidthr(hash_table *ht, pidthr_t key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_pidthr *hi;
+ hash_item_pidthr *h;
+ llist *ll;
+ llistitem *li;
+ llistitem *newli;
+ pidthr_t k1;
+
+ /* allocate the space we will need */
+ newli = ll_newitem(sizeof(hash_item_pidthr));
+ hi = (hash_item_pidthr *)newli->datum;
+
+ /* fill in the values */
+ hi->key = key;
+ hi->value = value;
+
+ /* hash to the bucket */
+ bucket = &(ht->buckets[((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)]);
+
+ /* 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_pidthr *)li->datum;
+ k1 = h->key;
+ if ((key.k_pid == k1.k_pid && key.k_thr == k1.k_thr))
+ {
+ /* 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_pidthr *)(li->datum))->value;
+ }
+}
+
+/*
+ * void *hash_replace_pidthr(hash_table *ht, pidthr_t 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 pidthr_t
+ */
+
+void *
+hash_replace_pidthr(hash_table *ht, pidthr_t key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_pidthr *hi;
+ llist *ll;
+ llistitem *li;
+ void *result = NULL;
+ pidthr_t k1;
+
+ /* find the bucket */
+ bucket = &(ht->buckets[((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)]);
+
+ /* walk the list until we find the existing item */
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ hi = (hash_item_pidthr *)li->datum;
+ k1 = hi->key;
+ if ((key.k_pid == k1.k_pid && key.k_thr == k1.k_thr))
+ {
+ /* 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_pidthr));
+ hi = (hash_item_pidthr *)li->datum;
+ hi->key = key;
+ hi->value = value;
+ ll_add(&(bucket->list), li);
+ }
+
+ /* return the old value (so it can be freed) */
+ return result;
+}
+
+/*
+ * void *hash_lookup_pidthr(hash_table *ht, pidthr_t key)
+ *
+ * Look up "key" in "ht" and return the associated value. If "key"
+ * is not found, return NULL. Key type is pidthr_t
+ */
+
+void *
+hash_lookup_pidthr(hash_table *ht, pidthr_t key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ hash_item_pidthr *h;
+ void *result;
+ pidthr_t k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ h = (hash_item_pidthr *)li->datum;
+ k1 = h->key;
+ if ((key.k_pid == k1.k_pid && key.k_thr == k1.k_thr))
+ {
+ result = h->value;
+ break;
+ }
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * void *hash_remove_pidthr(hash_table *ht, pidthr_t 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_pidthr(hash_table *ht, pidthr_t key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ llistitem *lilast;
+ hash_item_pidthr *hi;
+ void *result;
+ pidthr_t k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[((key.k_thr * 10000 + key.k_pid) % ht->num_buckets)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ lilast = NULL;
+ while (li != NULL)
+ {
+ hi = (hash_item_pidthr *)li->datum;
+ k1 = hi->key;
+ if ((key.k_pid == k1.k_pid && key.k_thr == k1.k_thr))
+ {
+ ll_extract(ll, li, lilast);
+ result = hi->value;
+ key = hi->key;
+ ;
+ ll_freeitem(li);
+ break;
+ }
+ lilast = li;
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * hash_item_pidthr *hash_first_pidthr(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_pidthr *
+hash_first_pidthr(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_pidthr *)pos->ll_item->datum;
+}
+
+
+/*
+ * hash_item_pidthr *hash_next_pidthr(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_pidthr *
+hash_next_pidthr(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_pidthr *)li->datum;
+}
+
+/*
+ * void *hash_remove_pos_pidthr(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_pidthr(hash_pos *pos)
+
+{
+ llistitem *li;
+ void *ans;
+ hash_item_pidthr *hi;
+
+ /* 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_pidthr *)li->datum;
+ ans = hi->value;
+
+ /* free up the space */
+ 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;
+}
+
+#if HAVE_LWPID_T
+
+
+/*
+ * void hash_add_lwpid(hash_table *ht, lwpid_t 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 lwpid_t
+ */
+
+void *
+hash_add_lwpid(hash_table *ht, lwpid_t key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_lwpid *hi;
+ hash_item_lwpid *h;
+ llist *ll;
+ llistitem *li;
+ llistitem *newli;
+ lwpid_t k1;
+
+ /* allocate the space we will need */
+ newli = ll_newitem(sizeof(hash_item_lwpid));
+ hi = (hash_item_lwpid *)newli->datum;
+
+ /* fill in the values */
+ hi->key = key;
+ hi->value = value;
+
+ /* hash to the bucket */
+ bucket = &(ht->buckets[(key % ht->num_buckets)]);
+
+ /* 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_lwpid *)li->datum;
+ k1 = h->key;
+ if (key == k1)
+ {
+ /* 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_lwpid *)(li->datum))->value;
+ }
+}
+
+/*
+ * void *hash_replace_lwpid(hash_table *ht, lwpid_t 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 lwpid_t
+ */
+
+void *
+hash_replace_lwpid(hash_table *ht, lwpid_t key, void *value)
+
+{
+ bucket_t *bucket;
+ hash_item_lwpid *hi;
+ llist *ll;
+ llistitem *li;
+ void *result = NULL;
+ lwpid_t k1;
+
+ /* find the bucket */
+ bucket = &(ht->buckets[(key % ht->num_buckets)]);
+
+ /* walk the list until we find the existing item */
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ hi = (hash_item_lwpid *)li->datum;
+ k1 = hi->key;
+ if (key == k1)
+ {
+ /* 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_lwpid));
+ hi = (hash_item_lwpid *)li->datum;
+ hi->key = key;
+ hi->value = value;
+ ll_add(&(bucket->list), li);
+ }
+
+ /* return the old value (so it can be freed) */
+ return result;
+}
+
+/*
+ * void *hash_lookup_lwpid(hash_table *ht, lwpid_t key)
+ *
+ * Look up "key" in "ht" and return the associated value. If "key"
+ * is not found, return NULL. Key type is lwpid_t
+ */
+
+void *
+hash_lookup_lwpid(hash_table *ht, lwpid_t key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ hash_item_lwpid *h;
+ void *result;
+ lwpid_t k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ while (li != NULL)
+ {
+ h = (hash_item_lwpid *)li->datum;
+ k1 = h->key;
+ if (key == k1)
+ {
+ result = h->value;
+ break;
+ }
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * void *hash_remove_lwpid(hash_table *ht, lwpid_t 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_lwpid(hash_table *ht, lwpid_t key)
+
+{
+ bucket_t *bucket;
+ llist *ll;
+ llistitem *li;
+ llistitem *lilast;
+ hash_item_lwpid *hi;
+ void *result;
+ lwpid_t k1;
+
+ result = NULL;
+ if ((bucket = &(ht->buckets[(key % ht->num_buckets)])) != NULL)
+ {
+ ll = &(bucket->list);
+ li = LL_FIRST(ll);
+ lilast = NULL;
+ while (li != NULL)
+ {
+ hi = (hash_item_lwpid *)li->datum;
+ k1 = hi->key;
+ if (key == k1)
+ {
+ ll_extract(ll, li, lilast);
+ result = hi->value;
+ key = hi->key;
+ ;
+ ll_freeitem(li);
+ break;
+ }
+ lilast = li;
+ li = LL_NEXT(ll, li);
+ }
+ }
+ return result;
+}
+
+/*
+ * hash_item_lwpid *hash_first_lwpid(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_lwpid *
+hash_first_lwpid(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_lwpid *)pos->ll_item->datum;
+}
+
+
+/*
+ * hash_item_lwpid *hash_next_lwpid(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_lwpid *
+hash_next_lwpid(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_lwpid *)li->datum;
+}
+
+/*
+ * void *hash_remove_pos_lwpid(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_lwpid(hash_pos *pos)
+
+{
+ llistitem *li;
+ void *ans;
+ hash_item_lwpid *hi;
+
+ /* 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_lwpid *)li->datum;
+ ans = hi->value;
+
+ /* free up the space */
+ 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;
+}
+
+#endif
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+#!/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
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
+
+
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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));
+}
+
--- /dev/null
+.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.
--- /dev/null
+/*
+ * 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: For FreeBSD 5.x, 6.x, 7.x, 8.x
+ *
+ * DESCRIPTION:
+ * Originally written for BSD4.4 system by Christos Zoulas.
+ * Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider
+ * Order support hacked in from top-3.5beta6/machine/m_aix41.c
+ * by Monte Mitzelfelt
+ * Ported to FreeBSD 5.x and higher by William LeFebvre
+ *
+ * AUTHOR: Christos Zoulas <christos@ee.cornell.edu>
+ * Steven Wallace <swallace@freebsd.org>
+ * Wolfram Schneider <wosch@FreeBSD.org>
+ */
+
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/param.h>
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <nlist.h>
+#include <math.h>
+#include <kvm.h>
+#include <pwd.h>
+#include <sys/errno.h>
+#include <sys/sysctl.h>
+#include <sys/dkstat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/vmmeter.h>
+#include <sys/resource.h>
+#include <sys/rtprio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Swap */
+#include <stdlib.h>
+#include <sys/conf.h>
+
+#include <osreldate.h> /* for changes in kernel structures */
+
+#include "top.h"
+#include "machine.h"
+#include "utils.h"
+#include "username.h"
+#include "hash.h"
+#include "display.h"
+
+extern char* printable __P((char *));
+int swapmode __P((int *retavail, int *retfree));
+static int smpmode;
+static int namelength;
+
+/*
+ * Versions prior to 5.x do not track threads in kinfo_proc, so we
+ * simply do not display any information about them.
+ * Versions 5.x, 6.x, and 7.x track threads but the data reported
+ * as runtime for each thread is actually per-process and is just
+ * duplicated across all threads. It would be very wrong to show
+ * this data individually for each thread. Therefore we will show
+ * a THR column (number of threads) but not provide any sort of
+ * per-thread display. We distinguish between these three ways of
+ * handling threads as follows: HAS_THREADS indicates that the
+ * system has and tracks kernel threads (a THR column will appear
+ * in the display). HAS_SHOWTHREADS indicates that the system
+ * reports correct per-thread information and we will provide a
+ * per-thread display (the 'H' and 't' command) upon request.
+ * HAS_SHOWTHREADS implies HAS_THREADS.
+ */
+
+/* HAS_THREADS for anything 5.x and up */
+#if OSMAJOR >= 5
+#define HAS_THREADS
+#endif
+
+/* HAS_SHOWTHREADS for anything 8.x and up */
+#if OSMAJOR >=8
+#define HAS_SHOWTHREADS
+#endif
+
+/* get_process_info passes back a handle. This is what it looks like: */
+
+struct handle
+{
+ struct kinfo_proc **next_proc; /* points to next valid proc pointer */
+ int remaining; /* number of pointers remaining */
+};
+
+/* declarations for load_avg */
+#include "loadavg.h"
+
+/*
+ * Macros to access process information:
+ * In versions 4.x and earlier the kinfo_proc structure was a collection of
+ * substructures (kp_proc and kp_eproc). Starting with 5.0 kinfo_proc was
+ * redesigned and "flattene" so that most of the information was available
+ * in a single structure. We use macros to access the various types of
+ * information and define these macros according to the OS revision. The
+ * names PP, EP, and VP are due to the fact that information was originally
+ * contained in the different substructures. We retain these names in the
+ * code for backward compatibility. These macros use ANSI concatenation.
+ * PP: proc
+ * EP: extented proc
+ * VP: vm (virtual memory information)
+ * PRUID: Real uid
+ * RP: rusage
+ * PPCPU: where we store calculated cpu% data
+ * SPPTR: where we store pointer to extra calculated data
+ * SP: access to the extra calculated data pointed to by SPPTR
+ */
+#if OSMAJOR <= 4
+#define PP(pp, field) ((pp)->kp_proc . p_##field)
+#define EP(pp, field) ((pp)->kp_eproc . e_##field)
+#define VP(pp, field) ((pp)->kp_eproc.e_vm . vm_##field)
+#define PRUID(pp) ((pp)->kp_eproc.e_pcred.p_ruid)
+#else
+#define PP(pp, field) ((pp)->ki_##field)
+#define EP(pp, field) ((pp)->ki_##field)
+#define VP(pp, field) ((pp)->ki_##field)
+#define PRUID(pp) ((pp)->ki_ruid)
+#define RP(pp, field) ((pp)->ki_rusage.ru_##field)
+#define PPCPU(pp) ((pp)->ki_sparelongs[0])
+#define SPPTR(pp) ((pp)->ki_spareptrs[0])
+#define SP(pp, field) (((struct save_proc *)((pp)->ki_spareptrs[0]))->sp_##field)
+#endif
+
+/* what we consider to be process size: */
+#if OSMAJOR <= 4
+#define PROCSIZE(pp) (VP((pp), map.size) / 1024)
+#else
+#define PROCSIZE(pp) (((pp)->ki_size) / 1024)
+#endif
+
+/* calculate a per-second rate using milliseconds */
+#define per_second(n, msec) (((n) * 1000) / (msec))
+
+/* 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[] =
+{
+ "?", "START", "RUN", "SLEEP", "STOP", "ZOMB", "WAIT", "LOCK"
+};
+#define NUM_STATES 8
+
+/* kernel access */
+static kvm_t *kd;
+
+/* these are for dealing with sysctl-based data */
+#define MAXMIBLEN 8
+struct sysctl_mib {
+ char *name;
+ int mib[MAXMIBLEN];
+ size_t miblen;
+};
+static struct sysctl_mib mibs[] = {
+ { "vm.stats.sys.v_swtch" },
+#define V_SWTCH 0
+ { "vm.stats.sys.v_trap" },
+#define V_TRAP 1
+ { "vm.stats.sys.v_intr" },
+#define V_INTR 2
+ { "vm.stats.sys.v_soft" },
+#define V_SOFT 3
+ { "vm.stats.vm.v_forks" },
+#define V_FORKS 4
+ { "vm.stats.vm.v_vforks" },
+#define V_VFORKS 5
+ { "vm.stats.vm.v_rforks" },
+#define V_RFORKS 6
+ { "vm.stats.vm.v_vm_faults" },
+#define V_VM_FAULTS 7
+ { "vm.stats.vm.v_swapin" },
+#define V_SWAPIN 8
+ { "vm.stats.vm.v_swapout" },
+#define V_SWAPOUT 9
+ { "vm.stats.vm.v_tfree" },
+#define V_TFREE 10
+ { "vm.stats.vm.v_vnodein" },
+#define V_VNODEIN 11
+ { "vm.stats.vm.v_vnodeout" },
+#define V_VNODEOUT 12
+ { "vm.stats.vm.v_active_count" },
+#define V_ACTIVE_COUNT 13
+ { "vm.stats.vm.v_inactive_count" },
+#define V_INACTIVE_COUNT 14
+ { "vm.stats.vm.v_wire_count" },
+#define V_WIRE_COUNT 15
+ { "vm.stats.vm.v_cache_count" },
+#define V_CACHE_COUNT 16
+ { "vm.stats.vm.v_free_count" },
+#define V_FREE_COUNT 17
+ { "vm.stats.vm.v_swappgsin" },
+#define V_SWAPPGSIN 18
+ { "vm.stats.vm.v_swappgsout" },
+#define V_SWAPPGSOUT 19
+ { "vfs.bufspace" },
+#define VFS_BUFSPACE 20
+ { "kern.cp_time" },
+#define K_CP_TIME 21
+#ifdef HAS_SHOWTHREADS
+ { "kern.proc.all" },
+#else
+ { "kern.proc.proc" },
+#endif
+#define K_PROC 22
+ { NULL }
+};
+
+
+/* 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[8];
+char *procstatenames[] = {
+ "", " starting, ", " running, ", " sleeping, ", " stopped, ", " zombie, ",
+ " waiting, ", " locked, ",
+ NULL
+};
+
+/* these are for detailing the cpu states */
+
+int cpu_states[CPUSTATES];
+char *cpustatenames[] = {
+ "user", "nice", "system", "interrupt", "idle", NULL
+};
+
+/* these are for detailing the kernel information */
+
+int kernel_stats[9];
+char *kernelnames[] = {
+ " ctxsw, ", " trap, ", " intr, ", " soft, ", " fork, ",
+ " flt, ", " pgin, ", " pgout, ", " fr",
+ NULL
+};
+
+/* these are for detailing the memory statistics */
+
+long memory_stats[7];
+char *memorynames[] = {
+ "K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ", "K Free",
+ NULL
+};
+
+long swap_stats[7];
+char *swapnames[] = {
+/* 0 1 2 3 4 5 */
+ "K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
+ NULL
+};
+
+
+/*
+ * pbase points to the array that holds the kinfo_proc structures. pref
+ * (pronounced p-ref) points to an array of kinfo_proc pointers and is where
+ * we build up a list of processes we wish to display. Both pbase and pref are
+ * potentially resized on every call to get_process_info. psize is the number
+ * of procs for which we currently have space allocated. pref_len is the number
+ * of valid pointers in pref (this is used by proc_owner). We start psize off
+ * at -1 to ensure that space gets allocated on the first call to
+ * get_process_info.
+ */
+
+static int psize = -1;
+static int pref_len;
+static struct kinfo_proc *pbase = NULL;
+static struct kinfo_proc **pref = NULL;
+
+/* this structure retains information from the proc array between samples */
+struct save_proc {
+ pid_t sp_pid;
+ u_int64_t sp_runtime;
+ long sp_vcsw;
+ long sp_ivcsw;
+ long sp_inblock;
+ long sp_oublock;
+ long sp_majflt;
+ long sp_totalio;
+ long sp_old_nvcsw;
+ long sp_old_nivcsw;
+ long sp_old_inblock;
+ long sp_old_oublock;
+ long sp_old_majflt;
+};
+hash_table *procs;
+
+struct proc_field {
+ char *name;
+ int width;
+ int rjust;
+ int min_screenwidth;
+ int (*format)(char *, int, struct kinfo_proc *);
+};
+
+/* these are for getting the memory statistics */
+
+static int pagesize; /* kept from getpagesize */
+static int pageshift; /* log base 2 of the pagesize */
+
+/* define pagetok in terms of pageshift */
+
+#define pagetok(size) ((size) << pageshift)
+
+/* things that we track between updates */
+static u_int ctxsws = 0;
+static u_int traps = 0;
+static u_int intrs = 0;
+static u_int softs = 0;
+static u_int64_t forks = 0;
+static u_int pfaults;
+static u_int pagein;
+static u_int pageout;
+static u_int tfreed;
+static int swappgsin = -1;
+static int swappgsout = -1;
+extern struct timeval timeout;
+static struct timeval lasttime = { 0, 0 };
+static long elapsed_time;
+static long elapsed_msecs;
+
+/* things that we track during an update */
+static long total_io;
+static int show_fullcmd;
+static struct handle handle;
+static int username_length;
+static int show_usernames;
+static int display_mode;
+static int *display_fields;
+#ifdef HAS_SHOWTHREADS
+static int show_threads = 0;
+#endif
+
+
+/* sorting orders. first is default */
+char *ordernames[] = {
+ "cpu", "size", "res", "time", "pri", "io", "pid", NULL
+};
+
+/* compare routines */
+int proc_compare(), compare_size(), compare_res(), compare_time(),
+ compare_prio(), compare_io(), compare_pid();
+
+int (*proc_compares[])() = {
+ proc_compare,
+ compare_size,
+ compare_res,
+ compare_time,
+ compare_prio,
+ compare_io,
+ compare_pid,
+ NULL
+};
+
+/* swap related calculations */
+
+static int mib_swapinfo[16];
+static int *mib_swapinfo_idx;
+static int mib_swapinfo_size = 0;
+
+void
+swap_init()
+
+{
+ size_t m;
+
+ m = sizeof(mib_swapinfo) / sizeof(mib_swapinfo[0]);
+ if (sysctlnametomib("vm.swap_info", mib_swapinfo, &m) != -1)
+ {
+ mib_swapinfo_size = m + 1;
+ mib_swapinfo_idx = &(mib_swapinfo[m]);
+ }
+}
+
+int
+swap_getdata(long long *retavail, long long *retfree)
+
+{
+ int n;
+ size_t size;
+ long long total = 0;
+ long long used = 0;
+ struct xswdev xsw;
+
+ n = 0;
+ if (mib_swapinfo_size > 0)
+ {
+ *mib_swapinfo_idx = 0;
+ while (size = sizeof(xsw),
+ sysctl(mib_swapinfo, mib_swapinfo_size, &xsw, &size, NULL, 0) != -1)
+ {
+ dprintf("swap_getdata: swaparea %d: nblks %d, used %d\n",
+ n, xsw.xsw_nblks, xsw.xsw_used);
+ total += (long long)xsw.xsw_nblks;
+ used += (long long)xsw.xsw_used;
+ *mib_swapinfo_idx = ++n;
+ }
+
+ *retavail = pagetok(total);
+ *retfree = pagetok(total) - pagetok(used);
+
+ if (total > 0)
+ {
+ n = (int)((double)used * 100.0 / (double)total);
+ }
+ else
+ {
+ n = 0;
+ }
+ }
+ else
+ {
+ *retavail = 0;
+ *retfree = 0;
+ }
+
+ dprintf("swap_getdata: avail %lld, free %lld, %d%%\n",
+ *retavail, *retfree, n);
+ return(n);
+}
+
+/*
+ * getkval(offset, ptr, size) - 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).
+ * Return 0 on success, -1 on any kind of failure.
+ */
+
+static int
+getkval(unsigned long offset, int *ptr, int size)
+
+{
+ if (kd != NULL)
+ {
+ if (kvm_read(kd, offset, (char *) ptr, size) == size)
+ {
+ return(0);
+ }
+ }
+ return(-1);
+}
+
+int
+get_sysctl_mibs()
+
+{
+ struct sysctl_mib *mp;
+ size_t len;
+
+ mp = mibs;
+ while (mp->name != NULL)
+ {
+ len = MAXMIBLEN;
+ if (sysctlnametomib(mp->name, mp->mib, &len) == -1)
+ {
+ message_error(" sysctlnametomib: %s", strerror(errno));
+ return -1;
+ }
+ mp->miblen = len;
+ mp++;
+ }
+ return 0;
+}
+
+int
+get_sysctl(int idx, void *v, size_t l)
+
+{
+ struct sysctl_mib *m;
+ size_t len;
+
+ m = &(mibs[idx]);
+ len = l;
+ if (sysctl(m->mib, m->miblen, v, &len, NULL, 0) == -1)
+ {
+ message_error(" sysctl: %s", strerror(errno));
+ return -1;
+ }
+ return len;
+}
+
+size_t
+get_sysctlsize(int idx)
+
+{
+ size_t len;
+ struct sysctl_mib *m;
+
+ m = &(mibs[idx]);
+ if (sysctl(m->mib, m->miblen, NULL, &len, NULL, 0) == -1)
+ {
+ message_error(" sysctl (size): %s", strerror(errno));
+ len = 0;
+ }
+ return len;
+}
+
+int
+fmt_pid(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6d", PP(pp, pid));
+}
+
+int
+fmt_username(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%-*.*s",
+ username_length, username_length, username(PRUID(pp)));
+}
+
+int
+fmt_uid(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6d", PRUID(pp));
+}
+
+int
+fmt_thr(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%3d", PP(pp, numthreads));
+}
+
+int
+fmt_pri(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+#if OSMAJOR <= 4
+ return snprintf(buf, sz, "%3d", PP(pp, priority));
+#else
+ return snprintf(buf, sz, "%3d", PP(pp, pri.pri_level));
+#endif
+}
+
+int
+fmt_nice(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%4d", PP(pp, nice) - NZERO);
+}
+
+int
+fmt_size(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%5s", format_k(PROCSIZE(pp)));
+}
+
+int
+fmt_res(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%5s", format_k(pagetok(VP(pp, rssize))));
+}
+
+int
+fmt_state(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ int state;
+ char status[16];
+
+ state = PP(pp, stat);
+ switch(state)
+ {
+ case SRUN:
+ if (smpmode && PP(pp, oncpu) != 0xff)
+ sprintf(status, "CPU%d", PP(pp, oncpu));
+ else
+ strcpy(status, "RUN");
+ break;
+
+ case SSLEEP:
+ if (EP(pp, wmesg) != NULL) {
+ sprintf(status, "%.6s", EP(pp, wmesg));
+ break;
+ }
+ /* fall through */
+ default:
+ if (state >= 0 && state < NUM_STATES)
+ sprintf(status, "%.6s", state_abbrev[(unsigned char) state]);
+ else
+ sprintf(status, "?%-5d", state);
+ break;
+ }
+
+ return snprintf(buf, sz, "%-6.6s", status);
+}
+
+int
+fmt_flags(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ long flag;
+ char chrs[12];
+ char *p;
+
+ flag = PP(pp, flag);
+ p = chrs;
+ if (PP(pp, nice) < NZERO)
+ *p++ = '<';
+ else if (PP(pp, nice) > NZERO)
+ *p++ = 'N';
+ if (flag & P_TRACED)
+ *p++ = 'X';
+ if (flag & P_WEXIT && PP(pp, stat) != SZOMB)
+ *p++ = 'E';
+ if (flag & P_PPWAIT)
+ *p++ = 'V';
+ if (flag & P_SYSTEM || PP(pp, lock) > 0)
+ *p++ = 'L';
+ if (PP(pp, kiflag) & KI_SLEADER)
+ *p++ = 's';
+ if (flag & P_CONTROLT)
+ *p++ = '+';
+ if (flag & P_JAILED)
+ *p++ = 'J';
+ *p = '\0';
+
+ return snprintf(buf, sz, "%-3.3s", chrs);
+}
+
+int
+fmt_c(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%1x", PP(pp, lastcpu));
+}
+
+int
+fmt_time(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6s",
+ format_time((PP(pp, runtime) + 500000) / 1000000));
+}
+
+int
+fmt_cpu(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%5.2f%%", (double)PPCPU(pp) / 100.0);
+}
+
+int
+fmt_command(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ int inmem;
+ char cmd[MAX_COLS];
+ char *bufp;
+ struct pargs pargs;
+ int len;
+
+#if OSMAJOR <= 4
+ inmem = (PP(pp, flag) & P_INMEM);
+#else
+ inmem = (PP(pp, sflag) & PS_INMEM);
+#endif
+
+ if (show_fullcmd && inmem)
+ {
+ /* get the pargs structure */
+ if (getkval((unsigned long)PP(pp, args), (int *)&pargs, sizeof(pargs)) != -1)
+ {
+ /* determine workable length */
+ if ((len = pargs.ar_length) >= MAX_COLS)
+ {
+ len = MAX_COLS - 1;
+ }
+
+ /* get the string from that */
+ if (len > 0 && getkval((unsigned long)PP(pp, args) +
+ sizeof(pargs.ar_ref) +
+ sizeof(pargs.ar_length),
+ (int *)cmd, len) != -1)
+ {
+ /* successfull retrieval: now convert nulls in to spaces */
+ bufp = cmd;
+ while (len-- > 0)
+ {
+ if (*bufp == '\0')
+ {
+ *bufp = ' ';
+ }
+ bufp++;
+ }
+
+ /* null terminate cmd */
+ *--bufp = '\0';
+
+ /* format cmd as our answer */
+ return snprintf(buf, sz, "%s", cmd);
+ }
+ }
+ }
+
+ /* for anything else we just display comm */
+ return snprintf(buf, sz, inmem ? "%s" : "<%s>", printable(PP(pp, comm)));
+}
+
+int
+fmt_vcsw(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6ld", per_second(SP(pp, vcsw), elapsed_msecs));
+}
+
+int
+fmt_ivcsw(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6ld", per_second(SP(pp, ivcsw), elapsed_msecs));
+}
+
+int
+fmt_read(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6ld", per_second(SP(pp, inblock), elapsed_msecs));
+}
+
+int
+fmt_write(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6ld", per_second(SP(pp, oublock), elapsed_msecs));
+}
+
+int
+fmt_fault(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6ld", per_second(SP(pp, majflt), elapsed_msecs));
+}
+
+int
+fmt_iototal(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6ld", per_second(SP(pp, totalio), elapsed_msecs));
+}
+
+int
+fmt_iopct(char *buf, int sz, struct kinfo_proc *pp)
+
+{
+ return snprintf(buf, sz, "%6.2f", (SP(pp, totalio) * 100.) / total_io);
+}
+
+
+struct proc_field proc_field[] = {
+ { "PID", 6, 1, 0, fmt_pid },
+ { "USERNAME", 8, 0, 0, fmt_username },
+#define FIELD_USERNAME 1
+ { "UID", 6, 1, 0, fmt_uid },
+#define FIELD_UID 2
+ { "THR", 3, 1, 0, fmt_thr },
+ { "PRI", 3, 1, 0, fmt_pri },
+ { "NICE", 4, 1, 0, fmt_nice },
+ { "SIZE", 5, 1, 0, fmt_size },
+ { "RES", 5, 1, 0, fmt_res },
+ { "STATE", 6, 0, 0, fmt_state },
+ { "FLG", 3, 0, 84, fmt_flags },
+ { "C", 1, 0, 0, fmt_c },
+ { "TIME", 6, 1, 0, fmt_time },
+ { "CPU", 6, 1, 0, fmt_cpu },
+ { "COMMAND", 7, 0, 0, fmt_command },
+ { "VCSW", 6, 1, 0, fmt_vcsw },
+ { "IVCSW", 6, 1, 0, fmt_ivcsw },
+ { "READ", 6, 1, 0, fmt_read },
+ { "WRITE", 6, 1, 0, fmt_write },
+ { "FAULT", 6, 1, 0, fmt_fault },
+ { "TOTAL", 6, 1, 0, fmt_iototal },
+ { "PERCENT", 7, 1, 0, fmt_iopct },
+ { NULL, 0, 0, 0, NULL }
+};
+#define MAX_FIELDS 24
+
+static int mode0_display[MAX_FIELDS];
+static int mode0thr_display[MAX_FIELDS];
+static int mode1_display[MAX_FIELDS];
+
+int
+field_index(char *col)
+
+{
+ struct proc_field *fp;
+ int i = 0;
+
+ fp = proc_field;
+ while (fp->name != NULL)
+ {
+ if (strcmp(col, fp->name) == 0)
+ {
+ return i;
+ }
+ fp++;
+ i++;
+ }
+
+ return -1;
+}
+
+void
+field_subst(int *fp, int old, int new)
+
+{
+ while (*fp != -1)
+ {
+ if (*fp == old)
+ {
+ *fp = new;
+ }
+ fp++;
+ }
+}
+
+int
+machine_init(struct statics *statics)
+
+{
+ int i = 0;
+ size_t len;
+ int *ip;
+
+ struct timeval boottime;
+
+ len = sizeof(smpmode);
+ if ((sysctlbyname("machdep.smp_active", &smpmode, &len, NULL, 0) < 0 &&
+ sysctlbyname("smp.smp_active", &smpmode, &len, NULL, 0) < 0) ||
+ len != sizeof(smpmode))
+ {
+ smpmode = 0;
+ }
+ smpmode = smpmode != 0;
+
+ /* kvm_open the active kernel: its okay if this fails */
+ kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
+
+ /* get boot time */
+ len = sizeof(boottime);
+ if (sysctlbyname("kern.boottime", &boottime, &len, NULL, 0) == -1)
+ {
+ /* we have no boottime to report */
+ boottime.tv_sec = -1;
+ }
+
+ pbase = NULL;
+ pref = NULL;
+
+ /* get the page size with "getpagesize" and calculate pageshift from it */
+ i = pagesize = getpagesize();
+ pageshift = 0;
+ while (i > 1)
+ {
+ pageshift++;
+ i >>= 1;
+ }
+
+ /* translate sysctl paths to mibs for faster access */
+ get_sysctl_mibs();
+
+ /* initialize swap stuff */
+ swap_init();
+
+ /* create the hash table that remembers proc data */
+ procs = hash_create(2039);
+
+ /* 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->kernel_names = kernelnames;
+ statics->boottime = boottime.tv_sec;
+ statics->swap_names = swapnames;
+ statics->order_names = ordernames;
+ statics->flags.warmup = 1;
+ statics->modemax = 2;
+#ifdef HAS_SHOWTHREADS
+ statics->flags.threads = 1;
+#endif
+
+ /* we need kvm descriptor in order to show full commands */
+ statics->flags.fullcmds = kd != NULL;
+
+ /* set up the display indices for mode0 */
+ ip = mode0_display;
+ *ip++ = field_index("PID");
+ *ip++ = field_index("USERNAME");
+#ifdef HAS_THREADS
+ *ip++ = field_index("THR");
+#endif
+ *ip++ = field_index("PRI");
+ *ip++ = field_index("NICE");
+ *ip++ = field_index("SIZE");
+ *ip++ = field_index("RES");
+ *ip++ = field_index("STATE");
+ *ip++ = field_index("FLG");
+ if (smpmode)
+ *ip++ = field_index("C");
+ *ip++ = field_index("TIME");
+ *ip++ = field_index("CPU");
+ *ip++ = field_index("COMMAND");
+ *ip = -1;
+
+#ifdef HAS_SHOWTHREADS
+ /* set up the display indices for mode0 showing threads */
+ ip = mode0thr_display;
+ *ip++ = field_index("PID");
+ *ip++ = field_index("USERNAME");
+ *ip++ = field_index("PRI");
+ *ip++ = field_index("NICE");
+ *ip++ = field_index("SIZE");
+ *ip++ = field_index("RES");
+ *ip++ = field_index("STATE");
+ *ip++ = field_index("FLG");
+ if (smpmode)
+ *ip++ = field_index("C");
+ *ip++ = field_index("TIME");
+ *ip++ = field_index("CPU");
+ *ip++ = field_index("COMMAND");
+ *ip = -1;
+#endif
+
+ /* set up the display indices for mode1 */
+ ip = mode1_display;
+ *ip++ = field_index("PID");
+ *ip++ = field_index("USERNAME");
+ *ip++ = field_index("VCSW");
+ *ip++ = field_index("IVCSW");
+ *ip++ = field_index("READ");
+ *ip++ = field_index("WRITE");
+ *ip++ = field_index("FAULT");
+ *ip++ = field_index("TOTAL");
+ *ip++ = field_index("PERCENT");
+ *ip++ = field_index("COMMAND");
+ *ip = -1;
+
+ /* all done! */
+ return(0);
+}
+
+char *format_header(char *uname_field)
+
+{
+ return "";
+}
+
+void
+get_vm_sum(struct vmmeter *sum)
+
+{
+#define GET_VM_STAT(v, s) (void)get_sysctl(v, &(sum->s), sizeof(sum->s))
+
+ GET_VM_STAT(V_SWTCH, v_swtch);
+ GET_VM_STAT(V_TRAP, v_trap);
+ GET_VM_STAT(V_INTR, v_intr);
+ GET_VM_STAT(V_SOFT, v_soft);
+ GET_VM_STAT(V_VFORKS, v_vforks);
+ GET_VM_STAT(V_FORKS, v_forks);
+ GET_VM_STAT(V_RFORKS, v_rforks);
+ GET_VM_STAT(V_VM_FAULTS, v_vm_faults);
+ GET_VM_STAT(V_SWAPIN, v_swapin);
+ GET_VM_STAT(V_SWAPOUT, v_swapout);
+ GET_VM_STAT(V_TFREE, v_tfree);
+ GET_VM_STAT(V_VNODEIN, v_vnodein);
+ GET_VM_STAT(V_VNODEOUT, v_vnodeout);
+ GET_VM_STAT(V_ACTIVE_COUNT, v_active_count);
+ GET_VM_STAT(V_INACTIVE_COUNT, v_inactive_count);
+ GET_VM_STAT(V_WIRE_COUNT, v_wire_count);
+ GET_VM_STAT(V_CACHE_COUNT, v_cache_count);
+ GET_VM_STAT(V_FREE_COUNT, v_free_count);
+ GET_VM_STAT(V_SWAPPGSIN, v_swappgsin);
+ GET_VM_STAT(V_SWAPPGSOUT, v_swappgsout);
+}
+
+void
+get_system_info(struct system_info *si)
+
+{
+ long total;
+ struct timeval thistime;
+ struct timeval timediff;
+
+ /* timestamp and time difference */
+ gettimeofday(&thistime, 0);
+ timersub(&thistime, &lasttime, &timediff);
+ elapsed_time = timediff.tv_sec * 1000000 + timediff.tv_usec;
+ elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000;
+
+ /* get the load averages */
+ if (getloadavg(si->load_avg, NUM_AVERAGES) == -1)
+ {
+ /* failed: fill in with zeroes */
+ (void) memset(si->load_avg, 0, sizeof(si->load_avg));
+ }
+
+ /* get the cp_time array */
+ (void)get_sysctl(K_CP_TIME, &cp_time, sizeof(cp_time));
+
+ /* convert cp_time counts to percentages */
+ total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+
+ /* sum memory & swap statistics */
+ {
+ struct vmmeter sum;
+ static unsigned int swap_delay = 0;
+ static long long swapavail = 0;
+ static long long swapfree = 0;
+ static int bufspace = 0;
+
+ get_vm_sum(&sum);
+
+ /* get bufspace */
+ bufspace = 0;
+ (void) get_sysctl(VFS_BUFSPACE, &bufspace, sizeof(bufspace));
+
+ /* kernel stats */
+ dprintf("kernel: swtch %d, trap %d, intr %d, soft %d, vforks %d\n",
+ sum.v_swtch, sum.v_trap, sum.v_intr, sum.v_soft, sum.v_vforks);
+ kernel_stats[0] = per_second(sum.v_swtch - ctxsws, elapsed_msecs);
+ kernel_stats[1] = per_second(sum.v_trap - traps, elapsed_msecs);
+ kernel_stats[2] = per_second(sum.v_intr - intrs, elapsed_msecs);
+ kernel_stats[3] = per_second(sum.v_soft - softs, elapsed_msecs);
+ kernel_stats[4] = per_second(sum.v_vforks + sum.v_forks +
+ sum.v_rforks - forks, elapsed_msecs);
+ kernel_stats[5] = per_second(sum.v_vm_faults - pfaults, elapsed_msecs);
+ kernel_stats[6] = per_second(sum.v_swapin + sum.v_vnodein - pagein, elapsed_msecs);
+ kernel_stats[7] = per_second(sum.v_swapout + sum.v_vnodeout - pageout, elapsed_msecs);
+ kernel_stats[8] = per_second(sum.v_tfree - tfreed, elapsed_msecs);
+ ctxsws = sum.v_swtch;
+ traps = sum.v_trap;
+ intrs = sum.v_intr;
+ softs = sum.v_soft;
+ forks = (u_int64_t)sum.v_vforks + sum.v_forks + sum.v_rforks;
+ pfaults = sum.v_vm_faults;
+ pagein = sum.v_swapin + sum.v_vnodein;
+ pageout = sum.v_swapout + sum.v_vnodeout;
+ tfreed = sum.v_tfree;
+
+ /* convert memory stats to Kbytes */
+ memory_stats[0] = pagetok(sum.v_active_count);
+ memory_stats[1] = pagetok(sum.v_inactive_count);
+ memory_stats[2] = pagetok(sum.v_wire_count);
+ memory_stats[3] = pagetok(sum.v_cache_count);
+ memory_stats[4] = bufspace / 1024;
+ memory_stats[5] = pagetok(sum.v_free_count);
+ memory_stats[6] = -1;
+
+ /* first interval */
+ if (swappgsin < 0)
+ {
+ swap_stats[4] = 0;
+ swap_stats[5] = 0;
+ }
+
+ /* compute differences between old and new swap statistic */
+ else
+ {
+ swap_stats[4] = pagetok(sum.v_swappgsin - swappgsin);
+ swap_stats[5] = pagetok(sum.v_swappgsout - swappgsout);
+ }
+
+ swappgsin = sum.v_swappgsin;
+ swappgsout = sum.v_swappgsout;
+
+ /* call CPU heavy swap_getdata() only for changes */
+ if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0)
+ {
+ swap_stats[3] = swap_getdata(&swapavail, &swapfree);
+ swap_stats[0] = swapavail;
+ swap_stats[1] = swapavail - swapfree;
+ swap_stats[2] = swapfree;
+ }
+ swap_delay = 1;
+ swap_stats[6] = -1;
+ }
+
+ /* set arrays and strings */
+ si->cpustates = cpu_states;
+ si->kernel = kernel_stats;
+ si->memory = memory_stats;
+ si->swap = swap_stats;
+
+ si->last_pid = -1;
+
+ lasttime = thistime;
+}
+
+caddr_t
+get_process_info(struct system_info *si,
+ struct process_select *sel,
+ int compare_index)
+
+{
+ int i;
+ int total_procs;
+ int active_procs;
+ struct kinfo_proc **prefp;
+ struct kinfo_proc *pp;
+ struct kinfo_proc *prev_pp = NULL;
+ struct save_proc *savep;
+ long proc_io;
+ pid_t pid;
+ size_t size;
+ int nproc;
+
+ /* these are copied out of sel for speed */
+ int show_idle;
+ int show_self;
+ int show_system;
+ int show_uid;
+ char *show_command;
+
+ /* get proc table size and give it a boost */
+ nproc = (int)get_sysctlsize(K_PROC) / sizeof(struct kinfo_proc);
+ nproc += nproc >> 4;
+ size = nproc * sizeof(struct kinfo_proc);
+ dprintf("get_process_info: nproc %d, psize %d, size %d\n", nproc, psize, size);
+
+ /* make sure we have enough space allocated */
+ if (nproc > psize)
+ {
+ /* reallocate both pbase and pref */
+ pbase = (struct kinfo_proc *)realloc(pbase, size);
+ pref = (struct kinfo_proc **)realloc(pref,
+ sizeof(struct kinfo_proc *) * nproc);
+ psize = nproc;
+ }
+
+ /* make sure we got the space we asked for */
+ if (pref == NULL || pbase == NULL)
+ {
+ /* abandon all hope */
+ message_error(" Out of memory!");
+ nproc = psize = 0;
+ si->p_total = 0;
+ si->p_active = 0;
+ return NULL;
+ }
+
+ /* get all process information (threads, too) */
+ if (size > 0)
+ {
+ nproc = get_sysctl(K_PROC, pbase, size);
+ if (nproc == -1)
+ {
+ nproc = 0;
+ }
+ else
+ {
+ nproc /= sizeof(struct kinfo_proc);
+ }
+ }
+
+ /* 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_self = 0;
+ show_system = sel->system;
+ show_uid = sel->uid != -1;
+ show_fullcmd = sel->fullcmd;
+ show_command = sel->command;
+ show_usernames = sel->usernames;
+ display_mode = sel->mode;
+#ifdef HAS_SHOWTHREADS
+ show_threads = sel->threads;
+#endif
+
+ /* count up process states and get pointers to interesting procs */
+ total_procs = 0;
+ active_procs = 0;
+ total_io = 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 P_SYSTEM set are system
+ * processes---these get ignored unless show_sysprocs is set.
+ */
+ pid = PP(pp, pid);
+ if (PP(pp, stat) != 0)
+ {
+#ifdef HAS_SHOWTHREADS
+ int is_thread;
+ lwpid_t tid;
+
+ /* get thread id */
+ tid = PP(pp, tid);
+
+ /* is this just a thread? */
+ is_thread = (prev_pp != NULL && PP(prev_pp, pid) == pid);
+
+ /* count this process and its state */
+ /* only count threads if we are showing them */
+ if (show_threads || !is_thread)
+ {
+ total_procs++;
+ process_states[(unsigned char) PP(pp, stat)]++;
+ }
+
+ /* grab old data from hash */
+ if ((savep = hash_lookup_lwpid(procs, tid)) != NULL)
+ {
+ /* verify that this is not a new or different thread */
+ /* (freebsd reuses thread ids fairly quickly) */
+ /* pids must match and time can't have gone backwards */
+ if (pid != savep->sp_pid || PP(pp, runtime) < savep->sp_runtime)
+ {
+ /* not the same thread -- reuse the save_proc structure */
+ memset(savep, 0, sizeof(struct save_proc));
+ savep->sp_pid = pid;
+ }
+ }
+ else
+ {
+ /* havent seen this one before */
+ savep = (struct save_proc *)calloc(1, sizeof(struct save_proc));
+ savep->sp_pid = pid;
+ hash_add_lwpid(procs, tid, savep);
+ }
+
+#else /* !HAS_SHOWTHREADS */
+ total_procs++;
+ process_states[(unsigned char) PP(pp, stat)]++;
+
+ /* grab old data from hash */
+ if ((savep = hash_lookup_pid(procs, pid)) == NULL)
+ {
+ /* havent seen this one before */
+ savep = (struct save_proc *)calloc(1, sizeof(struct save_proc));
+ savep->sp_pid = pid;
+ hash_add_pid(procs, pid, savep);
+ }
+#endif
+
+ /* save the pointer to the sp struct */
+ SPPTR(pp) = (void *)savep;
+
+ /* calculate %cpu */
+ PPCPU(pp) = ((PP(pp, runtime) - savep->sp_runtime) * 10000) /
+ elapsed_time;
+ dprintf("%d (%d): runtime %lld, saved_pid %d, saved_runtime %lld, elapsed_time %d, ppcpu %d\n",
+ pid, PP(pp, tid), PP(pp, runtime), savep->sp_pid, savep->sp_runtime,
+ elapsed_time, PPCPU(pp));
+
+ /* calculate io differences */
+ proc_io = 0;
+ savep->sp_vcsw = (RP(pp, nvcsw) - savep->sp_old_nvcsw);
+ savep->sp_ivcsw = (RP(pp, nivcsw) - savep->sp_old_nivcsw);
+ proc_io += (savep->sp_inblock = (RP(pp, inblock) - savep->sp_old_inblock));
+ proc_io += (savep->sp_oublock = (RP(pp, oublock) - savep->sp_old_oublock));
+ proc_io += (savep->sp_majflt = (RP(pp, majflt) - savep->sp_old_majflt));
+ total_io += proc_io;
+ savep->sp_totalio = proc_io;
+
+ /* save data for next time */
+ savep->sp_runtime = PP(pp, runtime);
+ savep->sp_old_nvcsw = RP(pp, nvcsw);
+ savep->sp_old_nivcsw = RP(pp, nivcsw);
+ savep->sp_old_inblock = RP(pp, inblock);
+ savep->sp_old_oublock = RP(pp, oublock);
+ savep->sp_old_majflt = RP(pp, majflt);
+
+ /* is this one selected for viewing? */
+ if ((PP(pp, stat) != SZOMB) &&
+ (show_system || ((PP(pp, flag) & P_SYSTEM) == 0)) &&
+ (show_idle || (PP(pp, pctcpu) != 0) ||
+ (PP(pp, stat) == SRUN)) &&
+ (!show_uid || PRUID(pp) == (uid_t)sel->uid) &&
+ (show_command == NULL ||
+ strcasestr(PP(pp, comm), show_command) != NULL))
+ {
+#ifdef HAS_SHOWTHREADS
+ /* yes, but make sure it isn't just a thread */
+ if (show_threads || !is_thread)
+ {
+ /* we will be showing this thread */
+ *prefp++ = pp;
+ active_procs++;
+ }
+ else
+ {
+ /* we will not be showing this thread, but we need to roll
+ up its cpu usage in to its process */
+ PP(prev_pp, pctcpu) += PP(pp, pctcpu);
+ }
+#else /* !HAS_SHOWTHREADS */
+ /* we will be showing this process */
+ *prefp++ = pp;
+ active_procs++;
+#endif
+ }
+ prev_pp = pp;
+ }
+ }
+
+ dprintf("total_io: %d\n", total_io);
+ if (total_io == 0) total_io = 1;
+
+ /* if requested, sort the "interesting" processes */
+ if (active_procs > 1)
+ {
+ qsort((char *)pref, active_procs, sizeof(struct kinfo_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);
+}
+
+static char p_header[MAX_COLS];
+
+char *
+format_process_header(struct process_select *sel, caddr_t handle, int count)
+
+{
+ int cols;
+ int n;
+ int w;
+ char *p;
+ int *fi;
+ struct kinfo_proc **kip;
+ struct proc_field *fp;
+
+ /* check for null handle */
+ if (handle == NULL)
+ {
+ return("");
+ }
+
+ /* remember how many columns there are on the display */
+ cols = display_columns();
+
+ /* mode & threads dictate format */
+ fi = display_fields =
+ sel->mode == 0 ?
+ (sel->threads == 0 ? mode0_display : mode0thr_display) :
+ mode1_display;
+
+ /* set username field correctly */
+ if (!sel->usernames)
+ {
+ /* display uids */
+ field_subst(fi, FIELD_USERNAME, FIELD_UID);
+ }
+ else
+ {
+ /* display usernames */
+ field_subst(fi, FIELD_UID, FIELD_USERNAME);
+
+ /* we also need to determine the longest username for column width */
+ /* calculate namelength from first "count" processes */
+ kip = ((struct handle *)handle)->next_proc;
+ n = ((struct handle *)handle)->remaining;
+ if (n > count)
+ n = count;
+ namelength = 0;
+ while (n-- > 0)
+ {
+ w = strlen(username(PRUID(*kip)));
+ if (w > namelength) namelength = w;
+ kip++;
+ }
+ dprintf("format_process_header: namelength %d\n", namelength);
+
+ /* place it in bounds */
+ if (namelength < 8)
+ {
+ namelength = 8;
+ }
+
+ /* set the column width */
+ proc_field[FIELD_USERNAME].width = username_length = namelength;
+ }
+
+ /* walk thru fields and construct header */
+ /* are we worried about overflow??? */
+ p = p_header;
+ while (*fi != -1)
+ {
+ fp = &(proc_field[*fi++]);
+ if (fp->min_screenwidth <= cols)
+ {
+ p += sprintf(p, fp->rjust ? "%*s" : "%-*s", fp->width, fp->name);
+ *p++ = ' ';
+ }
+ }
+ *--p = '\0';
+
+ return p_header;
+}
+
+static char fmt[MAX_COLS]; /* static area where result is built */
+
+char *
+format_next_process(caddr_t handle, char *(*get_userid)(int))
+
+{
+ struct kinfo_proc *pp;
+ struct handle *hp;
+ struct proc_field *fp;
+ int *fi;
+ int i;
+ int cols;
+ char *p;
+ int len;
+ int x;
+
+ /* find and remember the next proc structure */
+ hp = (struct handle *)handle;
+ pp = *(hp->next_proc++);
+ hp->remaining--;
+
+ /* mode & threads dictate format */
+ fi = display_fields;
+
+ /* screen width is a consideration, too */
+ cols = display_columns();
+
+ /* build output by field */
+ p = fmt;
+ len = MAX_COLS;
+ while ((i = *fi++) != -1)
+ {
+ fp = &(proc_field[i]);
+ if (len > 0 && fp->min_screenwidth <= cols)
+ {
+ x = (*(fp->format))(p, len, pp);
+ if (x >= len)
+ {
+ dprintf("format_next_process: formatter overflow: x %d, len %d, p %08x => %08x, fmt %08x - %08x\n",
+ x, len, p, p + len, fmt, fmt + sizeof(fmt));
+ p += len;
+ len = 0;
+ }
+ else
+ {
+ p += x;
+ *p++ = ' ';
+ len -= x + 1;
+ }
+ }
+ }
+ *--p = '\0';
+
+ /* return the result */
+ return(fmt);
+}
+
+/* comparison routines 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 */
+};
+
+
+#define ORDERKEY_PCTCPU \
+ if (lresult = (long) PPCPU(p2) - (long) PPCPU(p1), \
+ (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
+
+#define ORDERKEY_CPTICKS \
+ if ((result = PP(p2, runtime) > PP(p1, runtime) ? 1 : \
+ PP(p2, runtime) < PP(p1, runtime) ? -1 : 0) == 0)
+
+#define ORDERKEY_STATE \
+ if ((result = sorted_state[(unsigned char) PP(p2, stat)] - \
+ sorted_state[(unsigned char) PP(p1, stat)]) == 0)
+
+#if OSMAJOR <= 4
+#define ORDERKEY_PRIO \
+ if ((result = PP(p2, priority) - PP(p1, priority)) == 0)
+#else
+#define ORDERKEY_PRIO \
+ if ((result = PP(p2, pri.pri_level) - PP(p1, pri.pri_level)) == 0)
+#endif
+
+#define ORDERKEY_RSSIZE \
+ if ((result = VP(p2, rssize) - VP(p1, rssize)) == 0)
+
+#define ORDERKEY_MEM \
+ if ( (result = PROCSIZE(p2) - PROCSIZE(p1)) == 0 )
+
+#define ORDERKEY_IO \
+ if ( (result = SP(p2, totalio) - SP(p1, totalio)) == 0)
+
+#define ORDERKEY_PID \
+ if ( (result = PP(p1, pid) - PP(p2, pid)) == 0)
+
+/* compare_cpu - the comparison function for sorting by cpu percentage */
+
+int
+proc_compare(struct proc **pp1, struct proc **pp2)
+
+{
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) 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 */
+
+int
+compare_size(struct proc **pp1, struct proc **pp2)
+
+{
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) 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 */
+
+int
+compare_res(struct proc **pp1, struct proc **pp2)
+
+{
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) 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 */
+
+int
+compare_time(struct proc **pp1, struct proc **pp2)
+
+{
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return(result);
+ }
+
+/* compare_prio - the comparison function for sorting by priority */
+
+int
+compare_prio(struct proc **pp1, struct proc **pp2)
+
+{
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_PRIO
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return(result);
+}
+
+/* compare_io - the comparison function for sorting by io count */
+
+int
+compare_io(struct proc **pp1, struct proc **pp2)
+
+{
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+ pctcpu lresult;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_IO
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return(result);
+}
+
+/* compare_pid - the comparison function for sorting by process id */
+
+int
+compare_pid(struct proc **pp1, struct proc **pp2)
+
+{
+ struct kinfo_proc *p1;
+ struct kinfo_proc *p2;
+ int result;
+
+ /* remove one level of indirection */
+ p1 = *(struct kinfo_proc **) pp1;
+ p2 = *(struct kinfo_proc **) pp2;
+
+ ORDERKEY_PID
+ ;
+
+ 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(int pid)
+
+{
+ int cnt;
+ struct kinfo_proc **prefp;
+ struct kinfo_proc *pp;
+
+ prefp = pref;
+ cnt = pref_len;
+ while (--cnt >= 0)
+ {
+ pp = *prefp++;
+ if (PP(pp, pid) == (pid_t)pid)
+ {
+ return((int)PRUID(pp));
+ }
+ }
+ return(-1);
+}
+
--- /dev/null
+.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.
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+.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>.
+
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+.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>.
--- /dev/null
+/*
+ * 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;
+
+}
+
--- /dev/null
+/*
+ * 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 SGI machine running IRIX 6.2 and up
+ *
+ * DESCRIPTION:
+ * This is the machine-dependent module for IRIX as supplied by
+ * engineers at SGI.
+ *
+ * CFLAGS: -DHAVE_GETOPT -D_OLD_TERMIOS -DORDER
+ *
+ * AUTHOR: Sandeep Cariapa <cariapa@sgi.com>
+ * AUTHOR: Larry McVoy <lm@sgi.com>
+ * Sandeep did all the hard work; I ported to 6.2 and fixed up some formats.
+ * AUTHOR: John Schimmel <jes@sgi.com>
+ * He did the all irix merge.
+ * AUTHOR: Ariel Faigon <ariel@sgi.com>
+ * Ported to Ficus/Kudzu (IRIX 6.4+).
+ * Got rid of all nlist and different (elf64, elf32, COFF) kernel
+ * dependencies
+ * Various small fixes and enhancements: multiple CPUs, nicer formats.
+ * Added -DORDER process display ordering
+ * cleaned most -fullwarn'ings.
+ * Need -D_OLD_TERMIOS when compiling on IRIX 6.4 to work on 6.2 systems
+ * Support much bigger values in memory sizes (over Peta-byte)
+ * AUTHOR: William LeFebvre
+ * Converted to ANSI C and updated to new module interface
+ */
+
+#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 <sys/utsname.h>
+#include <sys/schedctl.h> /* for < 6.4 NDPHIMAX et al. */
+#include <paths.h>
+#include <assert.h>
+#include <values.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+
+#include "top.h"
+#include "machine.h"
+#include "utils.h"
+
+#define KMEM "/dev/kmem"
+
+typedef double load_avg;
+#define loaddouble(la) (la)
+#define intload(i) ((double)(i))
+
+/*
+ * 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 pagetok(pages) ((((uint64_t) pages) * pagesize) >> 10)
+
+/*
+ * Ugly hack, save space and complexity of allocating and maintaining
+ * parallel arrays to the prpsinfo array: use spare space (pr_fill area)
+ * in prpsinfo structures to store %CPU calculated values
+ */
+#define D_align(addr) (((unsigned long)(addr) & ~0x0fU))
+#define percent_cpu(pp) (* (double *) D_align(&((pp)->pr_fill[0])))
+#define weighted_cpu(pp) (* (double *) D_align(&((pp)->pr_fill[4])))
+
+
+/* Username field to fill in starts at: */
+#define UNAME_START 16
+
+/*
+ * These definitions control the format of the per-process area
+ */
+static char header[] =
+" PID PGRP X PRI SIZE RES STATE TIME %WCPU %CPU COMMAND";
+/*
+ 012345678901234567890123456789012345678901234567890123456789012345678901234567
+ 10 20 30 40 50 60 70
+ */
+
+/* PID PGRP USER PRI SIZE RES STATE TIME %WCPU %CPU CMD */
+#define Proc_format \
+ "%7d %7d %-8.8s %4.4s %6.6s %5.5s %-6.6s %6.6s %5.2f %5.2f %-.10s"
+
+
+/*
+ * these are for detailing the cpu states
+ * Data is taken from the sysinfo structure (see <sys/sysinfo.h>)
+ * We rely on the following values:
+ *
+ * #define CPU_IDLE 0
+ * #define CPU_USER 1
+ * #define CPU_KERNEL 2
+ * #define CPU_WAIT 3
+ * #define CPU_SXBRK 4
+ * #define CPU_INTR 5
+ */
+#ifndef CPU_STATES /* defined only in 6.4 and up */
+# define CPU_STATES 6
+#endif
+
+int cpu_states[CPU_STATES];
+char *cpustatenames[] = {
+ "idle", "usr", "ker", "wait", "xbrk", "intr",
+ NULL
+};
+
+/* these are for detailing the memory statistics */
+
+#define MEMSTATS 10
+int memory_stats[MEMSTATS];
+char *memorynames[] = {
+ "K max, ", "K avail, ", "K free, ", "K swap, ", "K free swap", NULL
+};
+
+char uname_str[40];
+double load[3];
+static char fmt[MAX_COLS + 2];
+int numcpus;
+
+/* useful externals */
+extern int errno;
+extern char *sys_errlist[];
+
+extern char *myname;
+extern char *format_k();
+extern char *format_time();
+extern long percentages();
+
+static int kmem;
+static unsigned long avenrun_offset;
+
+static float irix_ver; /* for easy numeric comparison */
+
+static struct prpsinfo *pbase;
+static struct prpsinfo **pref;
+static struct oldproc *oldbase;
+static int oldprocs; /* size of table */
+
+static DIR *procdir;
+
+static int ptable_size; /* allocated process table size */
+static int nproc; /* estimated process table size */
+static int pagesize;
+
+/* 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(struct prpsinfo *baseptr);
+void size(int fd, struct prpsinfo *ps);
+
+extern char *ordernames[];
+
+/*
+ * Process states letters are mapped into numbers
+ * 6.5 seems to have changed the semantics of prpsinfo.pr_state
+ * so we rely, (like ps does) on the char value pr_sname.
+ * The order we use here is what may be most interesting
+ * to top users: Most interesting state on top, least on bottom.
+ * 'S' (sleeping) is the most common case so I put it _after_
+ * zombie, even though it is more "active" than zombie.
+ *
+ * State letters and their meanings:
+ *
+ * R Process is running (may not have a processor yet)
+ * I Process is in intermediate state of creation
+ * X Process is waiting for memory
+ * T Process is stopped
+ * Z Process is terminated and parent not waiting (zombie)
+ * S Process is sleeping, waiting for a resource
+ */
+
+/* abbreviated process states */
+static char *state_abbrev[] =
+{ "", "sleep", "zomb", "stop", "swap", "start", "ready", "run", NULL };
+
+/* Same but a little "wordier", used in CPU activity summary */
+int process_states[8]; /* per state counters */
+char *procstatenames[] = {
+ /* ready to run is considered running here */
+ "", " sleeping, ", " zombie, ", " stopped, ",
+ " swapped, ", " starting, ", " ready, ", " running, ",
+ NULL
+};
+
+#define S_RUNNING 7
+#define S_READY 6
+#define S_STARTING 5
+#define S_SWAPPED 4
+#define S_STOPPED 3
+#define S_ZOMBIE 2
+#define S_SLEEPING 1
+
+#define IS_ACTIVE(pp) \
+ (first_screen ? proc_state(pp) >= S_STARTING : percent_cpu(pp) > 0.0)
+
+/*
+ * proc_state
+ * map the pr_sname value to an integer.
+ * used as an index into state_abbrev[]
+ * as well as an "order" key
+ */
+static int proc_state(struct prpsinfo *pp)
+{
+ char psname = pp->pr_sname;
+
+ switch (psname) {
+ case 'R': return
+ (pp->pr_sonproc >= 0 && pp->pr_sonproc < numcpus) ?
+ S_RUNNING /* on a processor */ : S_READY;
+ case 'I': return S_STARTING;
+ case 'X': return S_SWAPPED;
+ case 'T': return S_STOPPED;
+ case 'Z': return S_ZOMBIE;
+ case 'S': return S_SLEEPING;
+ default : return 0;
+ }
+}
+
+
+/*
+ * To avoid nlist'ing the kernel (with all the different kernel type
+ * complexities), we estimate the size of the needed working process
+ * table by scanning /proc/pinfo and taking the number of entries
+ * multiplied by some reasonable factor.
+ * Assume current dir is _PATH_PROCFSPI
+ */
+static int active_proc_count()
+{
+ DIR *dirp;
+ int pcnt;
+
+ if ((dirp = opendir(".")) == NULL) {
+ (void) fprintf(stderr, "%s: Unable to open %s\n",
+ myname, _PATH_PROCFSPI);
+ exit(1);
+ }
+ for (pcnt = 0; readdir(dirp) != NULL; pcnt++)
+ ;
+ closedir(dirp);
+
+ return pcnt;
+}
+
+/*
+ * allocate space for:
+ * proc structure array
+ * array of pointers to the above (used for sorting)
+ * array for storing per-process old CPU usage
+ */
+void
+allocate_proc_tables()
+{
+ int n_active = active_proc_count();
+
+ if (pbase != NULL) /* && n_active < ptable_size */
+ return;
+
+ /* Need to realloc if we exceed, but factor should be enough */
+ nproc = n_active * 5;
+ oldprocs = 2 * nproc;
+
+ pbase = (struct prpsinfo *)
+ malloc(nproc * sizeof(struct prpsinfo));
+ pref = (struct prpsinfo **)
+ malloc(nproc * sizeof(struct prpsinfo *));
+ oldbase = (struct oldproc *)
+ malloc (oldprocs * sizeof(struct oldproc));
+
+ ptable_size = nproc;
+
+ if (pbase == NULL || pref == NULL || oldbase == NULL) {
+ (void) fprintf(stderr, "%s: malloc: out of memory\n", myname);
+ exit (1);
+ }
+}
+
+int
+machine_init(struct statics *statics)
+{
+ struct oldproc *op, *endbase;
+ int pcnt = 0;
+ struct utsname utsname;
+ char tmpbuf[20];
+
+ uname(&utsname);
+ irix_ver = (float) atof((const char *)utsname.release);
+ strncpy(tmpbuf, utsname.release, 9);
+ tmpbuf[9] = '\0';
+ sprintf(uname_str, "%s %-.14s %s %s",
+ utsname.sysname, utsname.nodename,
+ tmpbuf, utsname.machine);
+
+ pagesize = getpagesize();
+
+ if ((kmem = open(KMEM, O_RDONLY)) == -1) {
+ perror(KMEM);
+ return -1;
+ }
+
+ if (chdir(_PATH_PROCFSPI)) {
+ /* handy for later on when we're reading it */
+ (void) fprintf(stderr, "%s: Unable to chdir to %s\n",
+ myname, _PATH_PROCFSPI);
+ return -1;
+ }
+ if ((procdir = opendir(".")) == NULL) {
+ (void) fprintf(stderr, "%s: Unable to open %s\n",
+ myname, _PATH_PROCFSPI);
+ return -1;
+ }
+
+ if ((avenrun_offset = sysmp(MP_KERNADDR, MPKA_AVENRUN)) == -1) {
+ perror("sysmp(MP_KERNADDR, MPKA_AVENRUN)");
+ return -1;
+ }
+
+ allocate_proc_tables();
+
+ oldprocs = 2 * nproc;
+ endbase = oldbase + oldprocs;
+ for (op = oldbase; op < endbase; op++) {
+ op->oldpid = -1;
+ }
+
+ statics->cpustate_names = cpustatenames;
+ statics->memory_names = memorynames;
+ statics->order_names = ordernames;
+ statics->procstate_names = procstatenames;
+
+ 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);
+}
+
+void
+get_system_info(struct system_info *si)
+
+{
+ int i;
+ int avenrun[3];
+ struct rminfo realmem;
+ struct sysinfo sysinfo;
+ static time_t cp_old [CPU_STATES];
+ static time_t cp_diff[CPU_STATES]; /* 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] /= 1024.0;
+ }
+
+ if ((numcpus = sysmp(MP_NPROCS)) == -1) {
+ perror("sysmp(MP_NPROCS)");
+ return;
+ }
+
+ if (sysmp(MP_SAGET, MPSA_RMINFO, &realmem, sizeof(realmem)) == -1) {
+ perror("sysmp(MP_SAGET,MPSA_RMINFO, ...)");
+ return;
+ }
+
+ swapctl(SC_GETFREESWAP, &fswap);
+ swapctl(SC_GETSWAPTOT, &tswap);
+
+ memory_stats[0] = pagetok(realmem.physmem);
+ memory_stats[1] = pagetok(realmem.availrmem);
+ memory_stats[2] = pagetok(realmem.freemem);
+ memory_stats[3] = tswap / 2;
+ memory_stats[4] = fswap / 2;
+
+ if (sysmp(MP_SAGET,MPSA_SINFO, &sysinfo,sizeof(struct sysinfo)) == -1) {
+ perror("sysmp(MP_SAGET,MPSA_SINFO)");
+ return;
+ }
+ (void) percentages(CPU_STATES, cpu_states, sysinfo.cpu, cp_old, cp_diff);
+
+ si->cpustates = cpu_states;
+ si->memory = memory_stats;
+ si->last_pid = -1;
+
+ return;
+}
+
+caddr_t
+get_process_info(struct system_info *si, struct process_select *sel, int compare_index)
+
+{
+ int i, total_procs, active_procs;
+ struct prpsinfo **prefp;
+ struct prpsinfo *pp;
+ int show_uid;
+ static char first_screen = 1;
+
+ /* 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_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.
+ * Ariel: IRIX 6.4 had to redefine "system processes"
+ * They do not exist outside the kernel in new kernels.
+ * Now defining as uid==0 and ppid==1 (init children)
+ */
+ if (pp->pr_state &&
+ (sel->system || !(pp->pr_uid==0 && pp->pr_ppid==1))) {
+ total_procs++;
+ process_states[proc_state(pp)]++;
+ /*
+ * zombies are actually interesting (to avoid)
+ * although they are not active, so I leave them
+ * displayed.
+ */
+ if (/* (! pp->pr_zomb) && */
+ (sel->idle || IS_ACTIVE(pp)) &&
+ (! show_uid || pp->pr_uid == (uid_t) sel->uid)) {
+ *prefp++ = pp;
+ active_procs++;
+ }
+ }
+ }
+ first_screen = 0;
+
+ /* if requested, sort the "interesting" processes */
+ qsort((char *) pref, active_procs, sizeof(struct prpsinfo *),
+ proc_compares[compare_index]);
+
+ /* 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);
+}
+
+/*
+ * Added cpu_id to running processes, add 'ready' (to run) state
+ */
+static char *
+format_state(struct prpsinfo *pp)
+
+{
+ static char state_str[16];
+ int state = proc_state(pp);
+
+ if (state == S_RUNNING) {
+ /*
+ * Alert: 6.2 (MP only?) binary incompatibility
+ * pp->pr_sonproc apparently (?) has a different
+ * offset on 6.2 machines... I've seen cases where
+ * a 6.4 compiled top running on 6.2 printed
+ * a garbage CPU-id. To be safe, I print the CPU-id
+ * only if it falls within range [0..numcpus-1]
+ */
+ sprintf(state_str, "run/%d", pp->pr_sonproc);
+ return state_str;
+ }
+
+ /* default */
+ return state_abbrev[state];
+}
+
+static char *
+format_prio(struct prpsinfo *pp)
+
+{
+ static char prio_str[10];
+
+ if (irix_ver < 6.4) {
+ /*
+ * Note: this is _compiled_ on 6.x where x >= 4 but I would like
+ * it to run on 6.2 6.3 as well (backward binary compatibility).
+ * Scheduling is completely different between these IRIX versions
+ * and some scheduling classes may even have different names.
+ *
+ * The solution: have more than one style of 'priority' depending
+ * on the OS version.
+ *
+ * See npri(1) + nice(2) + realtime(5) for scheduling classes,
+ * and priority values.
+ */
+ if (pp->pr_pri <= NDPHIMIN) /* real time? */
+ sprintf(prio_str, "+%d", pp->pr_pri);
+ else if (pp->pr_pri <= NDPNORMMIN) /* normal interactive */
+ sprintf(prio_str, "%d", pp->pr_pri);
+ else /* batch: low prio */
+ sprintf(prio_str, "b%d", pp->pr_pri);
+
+ } else {
+
+ /* copied from Kostadis's code */
+
+ if (strcmp(pp->pr_clname, "RT") == 0) /* real time */
+ sprintf(prio_str, "+%d", pp->pr_pri);
+ else if (strcmp(pp->pr_clname, "DL") == 0) /* unsupported ? */
+ sprintf(prio_str, "d%d", pp->pr_pri);
+ else if (strcmp(pp->pr_clname, "GN") == 0)
+ sprintf(prio_str, "g%d", pp->pr_pri);
+ else if (strcmp(pp->pr_clname, "GB") == 0)
+ sprintf(prio_str, "p%d", pp->pr_pri);
+
+ else if (strcmp(pp->pr_clname, "WL") == 0) /* weightless */
+ return "w";
+ else if (strcmp(pp->pr_clname, "BC") == 0)
+ return "bc"; /* batch critical */
+ else if (strcmp(pp->pr_clname, "B") == 0)
+ return "b"; /* batch */
+ else
+ sprintf(prio_str, "%d", pp->pr_pri);
+ }
+ return prio_str;
+}
+
+static double
+clip_percent(double pct)
+
+{
+ if (pct < 0) {
+ return 0.0;
+ } else if (pct >= 100) {
+ return 99.99;
+ }
+ return pct;
+}
+
+char *
+format_next_process(caddr_t handle, char *(*get_userid)())
+
+{
+ struct prpsinfo *pp;
+ struct handle *hp;
+ long cputime;
+
+ /* find and remember the next proc structure */
+ hp = (struct handle *) handle;
+ pp = *(hp->next_proc++);
+ hp->remaining--;
+
+ /* get the process cpu usage since startup */
+ cputime = pp->pr_time.tv_sec;
+
+ /* format this entry */
+ sprintf(fmt,
+ Proc_format,
+ pp->pr_pid,
+ pp->pr_pgrp,
+ (*get_userid) (pp->pr_uid),
+ format_prio(pp),
+ format_k(pagetok(pp->pr_size)),
+ format_k(pagetok(pp->pr_rssize)),
+ format_state(pp),
+ format_time(cputime),
+ clip_percent(weighted_cpu(pp)),
+ clip_percent(percent_cpu(pp)),
+ printable(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(unsigned long offset, int *ptr, int size, char *refstr)
+
+{
+ if (lseek(kmem, (long) offset, SEEK_SET) == -1) {
+ if (*refstr == '!')
+ refstr++;
+ (void) fprintf(stderr, "%s: %s: lseek to %s: %s\n",
+ myname, KMEM, refstr, strerror(errno));
+ exit(0);
+ }
+ if (read(kmem, (char *) ptr, size) == -1) {
+ if (*refstr == '!')
+ return (0);
+ else {
+ (void) fprintf(stderr, "%s: %s: reading %s: %s\n",
+ myname, KMEM, refstr, strerror(errno));
+ exit(0);
+ }
+ }
+ return (1);
+}
+
+/*
+ * compare_K - comparison functions for "qsort"
+ * Compares the resource consumption of two processes using five
+ * distinct keys. The keys 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.
+ * Different comparison functions are used for different orderings.
+ */
+
+/* these are names given to allowed sorting orders -- first is default */
+char *ordernames[] = {
+ /*
+ * Aliases for user convenience/friendliness:
+ * mem == size
+ * rss == res
+ */
+ "cpu", "size", "mem", "res", "rss",
+ "time", "state", "command", "prio", NULL
+};
+
+/* forward definitions for comparison functions */
+int compare_cpu(struct prpsinfo **pp1, struct prpsinfo **pp2);
+int compare_size(struct prpsinfo **pp1, struct prpsinfo **pp2);
+int compare_res(struct prpsinfo **pp1, struct prpsinfo **pp2);
+int compare_time(struct prpsinfo **pp1, struct prpsinfo **pp2);
+int compare_state(struct prpsinfo **pp1, struct prpsinfo **pp2);
+int compare_cmd(struct prpsinfo **pp1, struct prpsinfo **pp2);
+int compare_prio(struct prpsinfo **pp1, struct prpsinfo **pp2);
+
+int (*proc_compares[])() = {
+ compare_cpu,
+ compare_size,
+ compare_size,
+ compare_res,
+ compare_res,
+ compare_time,
+ compare_state,
+ compare_cmd,
+ compare_prio,
+ NULL
+};
+
+
+/*
+ * The possible comparison expressions. 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 (dresult = percent_cpu(p2) - percent_cpu(p1),\
+ (result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0)
+#define ORDERKEY_CPTICKS \
+ if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
+#define ORDERKEY_STATE if ((result = proc_state(p2) - proc_state(p1)) == 0)
+#define ORDERKEY_PRIO if ((result = p2->pr_oldpri - p1->pr_oldpri) == 0)
+#define ORDERKEY_RSSIZE if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
+#define ORDERKEY_MEM if ((result = (p2->pr_size - p1->pr_size)) == 0)
+#define ORDERKEY_CMD if ((result = strcmp(p1->pr_fname,p2->pr_fname)) == 0)
+
+int compare_cpu(struct prpsinfo **pp1, struct prpsinfo **pp2)
+{
+ struct prpsinfo *p1, *p2;
+ int result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+ /*
+ * order by various keys, resorting to the next one
+ * whenever there's a tie in comparisons
+ */
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+ return (result);
+}
+
+int compare_size(struct prpsinfo **pp1, struct prpsinfo **pp2)
+{
+ struct prpsinfo *p1, *p2;
+ int result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+ /*
+ * order by various keys, resorting to the next one
+ * whenever there's a tie in comparisons
+ */
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+ return (result);
+}
+
+int compare_res(struct prpsinfo **pp1, struct prpsinfo **pp2)
+{
+ struct prpsinfo *p1, *p2;
+ int result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+ /*
+ * order by various keys, resorting to the next one
+ * whenever there's a tie in comparisons
+ */
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+ return (result);
+}
+
+int compare_time(struct prpsinfo **pp1, struct prpsinfo **pp2)
+{
+ struct prpsinfo *p1, *p2;
+ int result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+ /*
+ * order by various keys, resorting to the next one
+ * whenever there's a tie in comparisons
+ */
+ ORDERKEY_CPTICKS
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+ return (result);
+}
+
+int compare_cmd(struct prpsinfo **pp1, struct prpsinfo **pp2)
+{
+ struct prpsinfo *p1, *p2;
+ int result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+ /*
+ * order by various keys, resorting to the next one
+ * whenever there's a tie in comparisons
+ */
+ ORDERKEY_CMD
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_RSSIZE
+ ;
+ return (result);
+}
+
+int compare_state(struct prpsinfo **pp1, struct prpsinfo **pp2)
+{
+ struct prpsinfo *p1, *p2;
+ int result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+ /*
+ * order by various keys, resorting to the next one
+ * whenever there's a tie in comparisons
+ */
+ ORDERKEY_STATE
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_RSSIZE
+ ;
+ return (result);
+}
+
+int compare_prio(struct prpsinfo **pp1, struct prpsinfo **pp2)
+{
+ struct prpsinfo *p1, *p2;
+ int result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+ /*
+ * order by various keys, resorting to the next one
+ * whenever there's a tie in comparisons
+ */
+ ORDERKEY_PRIO
+ ORDERKEY_PCTCPU
+ ;
+ return (result);
+}
+
+
+
+/* return the owner of the specified process. */
+uid_t
+proc_owner(pid_t pid)
+
+{
+ register struct prpsinfo *p;
+ int i;
+
+ for (i = 0, p = pbase; i < nproc; i++, p++)
+ if (p->pr_pid == pid)
+ return (p->pr_uid);
+
+ return (-1);
+}
+
+#ifdef DO_MAPSIZE
+static void
+size(int fd, struct prpsinfo *ps)
+
+{
+ prmap_sgi_arg_t maparg;
+ struct prmap_sgi maps[256];
+ int nmaps;
+ double sz;
+ int i;
+
+ maparg.pr_vaddr = (caddr_t) maps;
+ maparg.pr_size = sizeof maps;
+ if ((nmaps = ioctl(fd, PIOCMAP_SGI, &maparg)) == -1) {
+ /* XXX - this will be confusing */
+ return;
+ }
+ for (i = 0, sz = 0; i < nmaps; ++i) {
+ sz += (double) maps[i].pr_wsize / MA_WSIZE_FRAC;
+ }
+ ps->pr_rssize = (long) sz;
+}
+#endif
+
+/* get process table */
+void
+getptable(struct prpsinfo *baseptr)
+
+{
+ struct prpsinfo *currproc; /* ptr to current proc struct */
+ int i, numprocs;
+ struct dirent *direntp;
+ struct oldproc *op, *endbase;
+ static struct timeval lasttime, thistime;
+ static double timediff, alpha, beta;
+
+ /* measure time between last call to getptable and current call */
+ gettimeofday (&thistime, NULL);
+
+ /*
+ * To avoid divides, we keep times in nanoseconds. This is
+ * scaled by 1e7 rather than 1e9 so that when we divide we
+ * get percent.
+ */
+ timediff = ((double) thistime.tv_sec * 1.0e7 -
+ (double) lasttime.tv_sec * 1.0e7)
+ +
+ ((double) thistime.tv_usec * 10 -
+ (double) lasttime.tv_usec * 10);
+
+ /*
+ * Under extreme load conditions, sca has experienced
+ * an assert(timediff > 0) failure here. His guess is that
+ * sometimes timed resets the time backwards and gettimeofday
+ * returns a lower number on a later call.
+ * To be on the safe side I fix it here by setting timediff
+ * to some arbitrary small value (in nanoseconds).
+ */
+ if (timediff <= 0.0) timediff = 100.0;
+
+ lasttime = thistime; /* prepare for next round */
+
+ /*
+ * constants for exponential decaying 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 / 15.0e7);
+ beta = 1.0 - alpha;
+ } else {
+ alpha = 0.5;
+ beta = 0.5;
+ }
+ assert(alpha >= 0); assert(alpha <= 1);
+ assert(beta >= 0); assert(beta <= 1);
+
+ endbase = oldbase + oldprocs;
+ currproc = baseptr;
+
+ for (numprocs = 0, rewinddir(procdir); direntp = readdir(procdir);) {
+ 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;
+ }
+
+ /*
+ * 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);
+ for (;;) {
+ 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 wrap 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;
+ }
+ }
+
+#ifdef DO_MAPSIZE
+ size(fd, currproc);
+#endif
+ numprocs++;
+ (void) close(fd);
+
+ /*
+ * Bug: in case process count grew so dramatically
+ * as to exceed to table size. We give up on a full scan.
+ * the chances of this to happen are extremely slim due to
+ * the big factor we're using. getting nproc from nlist
+ * is not worth the headache. realloc wouldn't work either
+ * because we have pointers to the proc table so we cannot
+ * move it around.
+ */
+ if (numprocs >= ptable_size) {
+ fprintf(stderr,
+ "preallocated proc table size (%d) exceeded, "
+ "skipping some processes\n", ptable_size);
+ break;
+ }
+ }
+ 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++) {
+
+ /* find an empty spot */
+ op = oldbase + HASH (currproc->pr_pid);
+ for (;;) {
+ 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);
+ }
+}
+
--- /dev/null
+/*
+ * 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: Linux 1.2.x, 1.3.x, 2.x, using the /proc filesystem
+ *
+ * DESCRIPTION:
+ * This is the machine-dependent module for Linux 1.2.x, 1.3.x or 2.x.
+ *
+ * LIBS:
+ *
+ * CFLAGS: -DHAVE_GETOPT -DHAVE_STRERROR -DORDER
+ *
+ * TERMCAP: -lcurses
+ *
+ * AUTHOR: Richard Henderson <rth@tamu.edu>
+ * Order support added by Alexey Klimkin <kad@klon.tme.mcst.ru>
+ * Ported to 2.4 by William LeFebvre
+ * Additions for 2.6 by William LeFebvre
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <time.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <dirent.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+
+#include <sys/param.h> /* for HZ */
+#include <asm/page.h> /* for PAGE_SHIFT */
+
+#if 0
+#include <linux/proc_fs.h> /* for PROC_SUPER_MAGIC */
+#else
+#define PROC_SUPER_MAGIC 0x9fa0
+#endif
+
+#include "top.h"
+#include "hash.h"
+#include "machine.h"
+#include "utils.h"
+#include "username.h"
+
+#define PROCFS "/proc"
+extern char *myname;
+
+/*=PROCESS INFORMATION==================================================*/
+
+struct top_proc
+{
+ pid_t pid;
+ uid_t uid;
+ char *name;
+ int pri, nice, threads;
+ unsigned long size, rss, shared; /* in k */
+ int state;
+ unsigned long time;
+ unsigned long start_time;
+ double pcpu;
+ struct top_proc *next;
+};
+
+
+/*=STATE IDENT STRINGS==================================================*/
+
+#define NPROCSTATES 7
+static char *state_abbrev[NPROCSTATES+1] =
+{
+ "", "run", "sleep", "disk", "zomb", "stop", "swap",
+ NULL
+};
+
+static char *procstatenames[NPROCSTATES+1] =
+{
+ "", " running, ", " sleeping, ", " uninterruptable, ",
+ " zombie, ", " stopped, ", " swapping, ",
+ NULL
+};
+
+#define NCPUSTATES 5
+static char *cpustatenames[NCPUSTATES+1] =
+{
+ "user", "nice", "system", "idle", "iowait",
+ NULL
+};
+static int show_iowait = 0;
+
+#define KERNELCTXT 0
+#define KERNELFLT 1
+#define KERNELINTR 2
+#define KERNELNEWPROC 3
+#define NKERNELSTATS 4
+static char *kernelnames[NKERNELSTATS+1] =
+{
+ " ctxsw, ", " flt, ", " intr, ", " newproc",
+ NULL
+};
+
+#define MEMUSED 0
+#define MEMFREE 1
+#define MEMSHARED 2
+#define MEMBUFFERS 3
+#define MEMCACHED 4
+#define NMEMSTATS 5
+static char *memorynames[NMEMSTATS+1] =
+{
+ "K used, ", "K free, ", "K shared, ", "K buffers, ", "K cached",
+ NULL
+};
+
+#define SWAPUSED 0
+#define SWAPFREE 1
+#define SWAPCACHED 2
+#define NSWAPSTATS 3
+static char *swapnames[NSWAPSTATS+1] =
+{
+ "K used, ", "K free, ", "K cached",
+ NULL
+};
+
+static char fmt_header[] =
+" PID X THR PRI NICE SIZE RES STATE TIME CPU COMMAND";
+
+static char proc_header_thr[] =
+" PID %-9s THR PRI NICE SIZE RES SHR STATE TIME CPU COMMAND";
+
+static char proc_header_nothr[] =
+" PID %-9s PRI NICE SIZE RES SHR STATE TIME CPU COMMAND";
+
+/* these are names given to allowed sorting orders -- first is default */
+char *ordernames[] =
+{"cpu", "size", "res", "time", "command", NULL};
+
+/* forward definitions for comparison functions */
+int compare_cpu();
+int compare_size();
+int compare_res();
+int compare_time();
+int compare_cmd();
+
+int (*proc_compares[])() = {
+ compare_cpu,
+ compare_size,
+ compare_res,
+ compare_time,
+ compare_cmd,
+ NULL };
+
+/*=SYSTEM STATE INFO====================================================*/
+
+/* these are for calculating cpu state percentages */
+
+static long cp_time[NCPUSTATES];
+static long cp_old[NCPUSTATES];
+static long cp_diff[NCPUSTATES];
+
+/* for calculating the exponential average */
+
+static struct timeval lasttime = { 0, 0 };
+static struct timeval timediff = { 0, 0 };
+static long elapsed_msecs;
+
+/* these are for keeping track of processes and tasks */
+
+#define HASH_SIZE (1003)
+#define INITIAL_ACTIVE_SIZE (256)
+#define PROCBLOCK_SIZE (32)
+static hash_table *ptable;
+static hash_table *tasktable;
+static struct top_proc **pactive;
+static struct top_proc **nextactive;
+static unsigned int activesize = 0;
+static time_t boottime = -1;
+static int have_task = 0;
+
+/* these are counters that need to be track */
+static unsigned long last_ctxt = 0;
+static unsigned long last_intr = 0;
+static unsigned long last_newproc = 0;
+static unsigned long last_flt = 0;
+
+/* these are for passing data back to the machine independant portion */
+
+static int cpu_states[NCPUSTATES];
+static int process_states[NPROCSTATES];
+static int kernel_stats[NKERNELSTATS];
+static long memory_stats[NMEMSTATS];
+static long swap_stats[NSWAPSTATS];
+
+/* useful macros */
+#define bytetok(x) (((x) + 512) >> 10)
+#define pagetok(x) ((x) << (PAGE_SHIFT - 10))
+#define HASH(x) (((x) * 1686629713U) % HASH_SIZE)
+
+/* calculate a per-second rate using milliseconds */
+#define per_second(n, msec) (((n) * 1000) / (msec))
+
+/*======================================================================*/
+
+static inline char *
+skip_ws(const char *p)
+{
+ while (isspace(*p)) p++;
+ return (char *)p;
+}
+
+static inline char *
+skip_token(const char *p)
+{
+ while (isspace(*p)) p++;
+ while (*p && !isspace(*p)) p++;
+ return (char *)p;
+}
+
+static void
+xfrm_cmdline(char *p, int len)
+{
+ while (--len > 0)
+ {
+ if (*p == '\0')
+ {
+ *p = ' ';
+ }
+ p++;
+ }
+}
+
+static void
+update_procname(struct top_proc *proc, char *cmd)
+
+{
+ printable(cmd);
+
+ if (proc->name == NULL)
+ {
+ proc->name = strdup(cmd);
+ }
+ else if (strcmp(proc->name, cmd) != 0)
+ {
+ free(proc->name);
+ proc->name = strdup(cmd);
+ }
+}
+
+/*
+ * Process structures are allocated and freed as needed. Here we
+ * keep big pools of them, adding more pool as needed. When a
+ * top_proc structure is freed, it is added to a freelist and reused.
+ */
+
+static struct top_proc *freelist = NULL;
+static struct top_proc *procblock = NULL;
+static struct top_proc *procmax = NULL;
+
+static struct top_proc *
+new_proc()
+{
+ struct top_proc *p;
+
+ if (freelist)
+ {
+ p = freelist;
+ freelist = freelist->next;
+ }
+ else if (procblock)
+ {
+ p = procblock;
+ if (++procblock >= procmax)
+ {
+ procblock = NULL;
+ }
+ }
+ else
+ {
+ p = procblock = (struct top_proc *)calloc(PROCBLOCK_SIZE,
+ sizeof(struct top_proc));
+ procmax = procblock++ + PROCBLOCK_SIZE;
+ }
+
+ /* initialization */
+ if (p->name != NULL)
+ {
+ free(p->name);
+ p->name = NULL;
+ }
+
+ return p;
+}
+
+static void
+free_proc(struct top_proc *proc)
+{
+ proc->next = freelist;
+ freelist = proc;
+}
+
+
+int
+machine_init(struct statics *statics)
+
+{
+ /* make sure the proc filesystem is mounted */
+ {
+ struct statfs sb;
+ if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC)
+ {
+ fprintf(stderr, "%s: proc filesystem not mounted on " PROCFS "\n",
+ myname);
+ return -1;
+ }
+ }
+
+ /* chdir to the proc filesystem to make things easier */
+ chdir(PROCFS);
+
+ /* a few preliminary checks */
+ {
+ int fd;
+ char buff[128];
+ char *p;
+ int cnt = 0;
+ unsigned long uptime;
+ struct timeval tv;
+ struct stat st;
+
+ /* get a boottime */
+ if ((fd = open("uptime", 0)) != -1)
+ {
+ if (read(fd, buff, sizeof(buff)) > 0)
+ {
+ uptime = strtoul(buff, &p, 10);
+ gettimeofday(&tv, 0);
+ boottime = tv.tv_sec - uptime;
+ }
+ close(fd);
+ }
+
+ /* see how many states we get from stat */
+ if ((fd = open("stat", 0)) != -1)
+ {
+ if (read(fd, buff, sizeof(buff)) > 0)
+ {
+ if ((p = strchr(buff, '\n')) != NULL)
+ {
+ *p = '\0';
+ p = buff;
+ while (*p != '\0')
+ {
+ if (*p++ == ' ')
+ {
+ cnt++;
+ }
+ }
+ }
+ }
+
+ close(fd);
+ }
+ if (cnt > 5)
+ {
+ /* we have iowait */
+ show_iowait = 1;
+ }
+
+ /* see if we have task subdirs */
+ if (stat("self/task", &st) != -1 && S_ISDIR(st.st_mode))
+ {
+ dprintf("we have task directories\n");
+ have_task = 1;
+ }
+ }
+
+ /* if we aren't showing iowait, then we have to tweak cpustatenames */
+ if (!show_iowait)
+ {
+ cpustatenames[4] = NULL;
+ }
+
+ /* fill in the statics information */
+ statics->procstate_names = procstatenames;
+ statics->cpustate_names = cpustatenames;
+ statics->kernel_names = kernelnames;
+ statics->memory_names = memorynames;
+ statics->swap_names = swapnames;
+ statics->order_names = ordernames;
+ statics->boottime = boottime;
+ statics->flags.fullcmds = 1;
+ statics->flags.warmup = 1;
+ statics->flags.threads = 1;
+
+ /* allocate needed space */
+ pactive = (struct top_proc **)malloc(sizeof(struct top_proc *) * INITIAL_ACTIVE_SIZE);
+ activesize = INITIAL_ACTIVE_SIZE;
+
+ /* create process and task hashes */
+ ptable = hash_create(HASH_SIZE);
+ tasktable = hash_create(HASH_SIZE);
+
+ /* all done! */
+ return 0;
+}
+
+
+void
+get_system_info(struct system_info *info)
+
+{
+ char buffer[4096+1];
+ int fd, len;
+ char *p;
+ struct timeval thistime;
+ unsigned long intr = 0;
+ unsigned long ctxt = 0;
+ unsigned long newproc = 0;
+ unsigned long flt = 0;
+
+ /* timestamp and time difference */
+ gettimeofday(&thistime, 0);
+ timersub(&thistime, &lasttime, &timediff);
+ elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000;
+ lasttime = thistime;
+
+ /* get load averages */
+ if ((fd = open("loadavg", O_RDONLY)) != -1)
+ {
+ if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
+ {
+ buffer[len] = '\0';
+ info->load_avg[0] = strtod(buffer, &p);
+ info->load_avg[1] = strtod(p, &p);
+ info->load_avg[2] = strtod(p, &p);
+ p = skip_token(p); /* skip running/tasks */
+ p = skip_ws(p);
+ if (*p)
+ {
+ info->last_pid = atoi(p);
+ }
+ else
+ {
+ info->last_pid = -1;
+ }
+ }
+ close(fd);
+ }
+
+ /* get the cpu time info */
+ if ((fd = open("stat", O_RDONLY)) != -1)
+ {
+ if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
+ {
+ buffer[len] = '\0';
+ p = skip_token(buffer); /* "cpu" */
+ cp_time[0] = strtoul(p, &p, 0);
+ cp_time[1] = strtoul(p, &p, 0);
+ cp_time[2] = strtoul(p, &p, 0);
+ cp_time[3] = strtoul(p, &p, 0);
+ if (show_iowait)
+ {
+ cp_time[4] = strtoul(p, &p, 0);
+ }
+
+ /* convert cp_time counts to percentages */
+ percentages(NCPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+
+ /* get the rest of it */
+ p = strchr(p, '\n');
+ while (p != NULL)
+ {
+ p++;
+ if (strncmp(p, "intr ", 5) == 0)
+ {
+ p = skip_token(p);
+ intr = strtoul(p, &p, 10);
+ }
+ else if (strncmp(p, "ctxt ", 5) == 0)
+ {
+ p = skip_token(p);
+ ctxt = strtoul(p, &p, 10);
+ }
+ else if (strncmp(p, "processes ", 10) == 0)
+ {
+ p = skip_token(p);
+ newproc = strtoul(p, &p, 10);
+ }
+
+ p = strchr(p, '\n');
+ }
+
+ kernel_stats[KERNELINTR] = per_second(intr - last_intr, elapsed_msecs);
+ kernel_stats[KERNELCTXT] = per_second(ctxt - last_ctxt, elapsed_msecs);
+ kernel_stats[KERNELNEWPROC] = per_second(newproc - last_newproc, elapsed_msecs);
+ last_intr = intr;
+ last_ctxt = ctxt;
+ last_newproc = newproc;
+ }
+ close(fd);
+ }
+
+ /* get system wide memory usage */
+ if ((fd = open("meminfo", O_RDONLY)) != -1)
+ {
+ char *p;
+ int mem = 0;
+ int swap = 0;
+ unsigned long memtotal = 0;
+ unsigned long memfree = 0;
+ unsigned long swaptotal = 0;
+
+ if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
+ {
+ buffer[len] = '\0';
+ p = buffer-1;
+
+ /* iterate thru the lines */
+ while (p != NULL)
+ {
+ p++;
+ if (p[0] == ' ' || p[0] == '\t')
+ {
+ /* skip */
+ }
+ else if (strncmp(p, "Mem:", 4) == 0)
+ {
+ p = skip_token(p); /* "Mem:" */
+ p = skip_token(p); /* total memory */
+ memory_stats[MEMUSED] = strtoul(p, &p, 10);
+ memory_stats[MEMFREE] = strtoul(p, &p, 10);
+ memory_stats[MEMSHARED] = strtoul(p, &p, 10);
+ memory_stats[MEMBUFFERS] = strtoul(p, &p, 10);
+ memory_stats[MEMCACHED] = strtoul(p, &p, 10);
+ memory_stats[MEMUSED] = bytetok(memory_stats[MEMUSED]);
+ memory_stats[MEMFREE] = bytetok(memory_stats[MEMFREE]);
+ memory_stats[MEMSHARED] = bytetok(memory_stats[MEMSHARED]);
+ memory_stats[MEMBUFFERS] = bytetok(memory_stats[MEMBUFFERS]);
+ memory_stats[MEMCACHED] = bytetok(memory_stats[MEMCACHED]);
+ mem = 1;
+ }
+ else if (strncmp(p, "Swap:", 5) == 0)
+ {
+ p = skip_token(p); /* "Swap:" */
+ p = skip_token(p); /* total swap */
+ swap_stats[SWAPUSED] = strtoul(p, &p, 10);
+ swap_stats[SWAPFREE] = strtoul(p, &p, 10);
+ swap_stats[SWAPUSED] = bytetok(swap_stats[SWAPUSED]);
+ swap_stats[SWAPFREE] = bytetok(swap_stats[SWAPFREE]);
+ swap = 1;
+ }
+ else if (!mem && strncmp(p, "MemTotal:", 9) == 0)
+ {
+ p = skip_token(p);
+ memtotal = strtoul(p, &p, 10);
+ }
+ else if (!mem && memtotal > 0 && strncmp(p, "MemFree:", 8) == 0)
+ {
+ p = skip_token(p);
+ memfree = strtoul(p, &p, 10);
+ memory_stats[MEMUSED] = memtotal - memfree;
+ memory_stats[MEMFREE] = memfree;
+ }
+ else if (!mem && strncmp(p, "MemShared:", 10) == 0)
+ {
+ p = skip_token(p);
+ memory_stats[MEMSHARED] = strtoul(p, &p, 10);
+ }
+ else if (!mem && strncmp(p, "Buffers:", 8) == 0)
+ {
+ p = skip_token(p);
+ memory_stats[MEMBUFFERS] = strtoul(p, &p, 10);
+ }
+ else if (!mem && strncmp(p, "Cached:", 7) == 0)
+ {
+ p = skip_token(p);
+ memory_stats[MEMCACHED] = strtoul(p, &p, 10);
+ }
+ else if (!swap && strncmp(p, "SwapTotal:", 10) == 0)
+ {
+ p = skip_token(p);
+ swaptotal = strtoul(p, &p, 10);
+ }
+ else if (!swap && swaptotal > 0 && strncmp(p, "SwapFree:", 9) == 0)
+ {
+ p = skip_token(p);
+ memfree = strtoul(p, &p, 10);
+ swap_stats[SWAPUSED] = swaptotal - memfree;
+ swap_stats[SWAPFREE] = memfree;
+ }
+ else if (!mem && strncmp(p, "SwapCached:", 11) == 0)
+ {
+ p = skip_token(p);
+ swap_stats[SWAPCACHED] = strtoul(p, &p, 10);
+ }
+
+ /* move to the next line */
+ p = strchr(p, '\n');
+ }
+ }
+ close(fd);
+ }
+
+ /* get vm related stuff */
+ if ((fd = open("vmstat", O_RDONLY)) != -1)
+ {
+ char *p;
+
+ if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
+ {
+ buffer[len] = '\0';
+ p = buffer;
+
+ /* iterate thru the lines */
+ while (p != NULL)
+ {
+ if (strncmp(p, "pgmajfault ", 11) == 0)
+ {
+ p = skip_token(p);
+ flt = strtoul(p, &p, 10);
+ kernel_stats[KERNELFLT] = per_second(flt - last_flt, elapsed_msecs);
+ last_flt = flt;
+ break;
+ }
+
+ /* move to the next line */
+ p = strchr(p, '\n');
+ p++;
+ }
+ }
+ close(fd);
+ }
+
+ /* set arrays and strings */
+ info->cpustates = cpu_states;
+ info->memory = memory_stats;
+ info->swap = swap_stats;
+ info->kernel = kernel_stats;
+}
+
+static void
+read_one_proc_stat(pid_t pid, pid_t taskpid, struct top_proc *proc, struct process_select *sel)
+{
+ char buffer[4096], *p, *q;
+ int fd, len;
+ int fullcmd;
+
+ dprintf("reading proc %d - %d\n", pid, taskpid);
+
+ /* if anything goes wrong, we return with proc->state == 0 */
+ proc->state = 0;
+
+ /* full cmd handling */
+ fullcmd = sel->fullcmd;
+ if (fullcmd)
+ {
+ if (taskpid == -1)
+ {
+ sprintf(buffer, "%d/cmdline", pid);
+ }
+ else
+ {
+ sprintf(buffer, "%d/task/%d/cmdline", pid, taskpid);
+ }
+ if ((fd = open(buffer, O_RDONLY)) != -1)
+ {
+ /* read command line data */
+ /* (theres no sense in reading more than we can fit) */
+ if ((len = read(fd, buffer, MAX_COLS)) > 1)
+ {
+ buffer[len] = '\0';
+ xfrm_cmdline(buffer, len);
+ update_procname(proc, buffer);
+ }
+ else
+ {
+ fullcmd = 0;
+ }
+ close(fd);
+ }
+ else
+ {
+ fullcmd = 0;
+ }
+ }
+
+ /* grab the shared memory size */
+ sprintf(buffer, "%d/statm", pid);
+ fd = open(buffer, O_RDONLY);
+ len = read(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+ buffer[len] = '\0';
+ p = buffer;
+ p = skip_token(p); /* skip size */
+ p = skip_token(p); /* skip resident */
+ proc->shared = pagetok(strtoul(p, &p, 10));
+
+ /* grab the proc stat info in one go */
+ if (taskpid == -1)
+ {
+ sprintf(buffer, "%d/stat", pid);
+ }
+ else
+ {
+ sprintf(buffer, "%d/task/%d/stat", pid, taskpid);
+ }
+
+ fd = open(buffer, O_RDONLY);
+ len = read(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ buffer[len] = '\0';
+
+ proc->uid = (uid_t)proc_owner((int)pid);
+
+ /* parse out the status */
+
+ /* skip pid and locate command, which is in parentheses */
+ if ((p = strchr(buffer, '(')) == NULL)
+ {
+ return;
+ }
+ if ((q = strrchr(++p, ')')) == NULL)
+ {
+ return;
+ }
+
+ /* set the procname */
+ *q = '\0';
+ if (!fullcmd)
+ {
+ update_procname(proc, p);
+ }
+
+ /* scan the rest of the line */
+ p = q+1;
+ p = skip_ws(p);
+ switch (*p++) /* state */
+ {
+ case 'R': proc->state = 1; break;
+ case 'S': proc->state = 2; break;
+ case 'D': proc->state = 3; break;
+ case 'Z': proc->state = 4; break;
+ case 'T': proc->state = 5; break;
+ case 'W': proc->state = 6; break;
+ case '\0': return;
+ }
+
+ p = skip_token(p); /* skip ppid */
+ p = skip_token(p); /* skip pgrp */
+ p = skip_token(p); /* skip session */
+ p = skip_token(p); /* skip tty */
+ p = skip_token(p); /* skip tty pgrp */
+ p = skip_token(p); /* skip flags */
+ p = skip_token(p); /* skip min flt */
+ p = skip_token(p); /* skip cmin flt */
+ p = skip_token(p); /* skip maj flt */
+ p = skip_token(p); /* skip cmaj flt */
+
+ proc->time = strtoul(p, &p, 10); /* utime */
+ proc->time += strtoul(p, &p, 10); /* stime */
+
+ p = skip_token(p); /* skip cutime */
+ p = skip_token(p); /* skip cstime */
+
+ proc->pri = strtol(p, &p, 10); /* priority */
+ proc->nice = strtol(p, &p, 10); /* nice */
+ proc->threads = strtol(p, &p, 10); /* threads */
+
+ p = skip_token(p); /* skip it_real_val */
+ proc->start_time = strtoul(p, &p, 10); /* start_time */
+
+ proc->size = bytetok(strtoul(p, &p, 10)); /* vsize */
+ proc->rss = pagetok(strtoul(p, &p, 10)); /* rss */
+
+#if 0
+ /* for the record, here are the rest of the fields */
+ p = skip_token(p); /* skip rlim */
+ p = skip_token(p); /* skip start_code */
+ p = skip_token(p); /* skip end_code */
+ p = skip_token(p); /* skip start_stack */
+ p = skip_token(p); /* skip sp */
+ p = skip_token(p); /* skip pc */
+ p = skip_token(p); /* skip signal */
+ p = skip_token(p); /* skip sigblocked */
+ p = skip_token(p); /* skip sigignore */
+ p = skip_token(p); /* skip sigcatch */
+ p = skip_token(p); /* skip wchan */
+#endif
+
+}
+
+static int show_usernames;
+static int show_threads;
+
+
+caddr_t
+get_process_info(struct system_info *si,
+ struct process_select *sel,
+ int compare_index)
+{
+ struct top_proc *proc;
+ struct top_proc *taskproc;
+ pid_t pid;
+ pid_t taskpid;
+ unsigned long now;
+ unsigned long elapsed;
+ hash_item_pid *hi;
+ hash_pos pos;
+
+ /* round current time to a second */
+ now = (unsigned long)lasttime.tv_sec;
+ if (lasttime.tv_usec >= 500000)
+ {
+ now++;
+ }
+
+ /* calculate number of ticks since our last check */
+ elapsed = timediff.tv_sec * HZ + (timediff.tv_usec * HZ) / 1000000;
+ if (elapsed <= 0)
+ {
+ elapsed = 1;
+ }
+ dprintf("get_process_info: elapsed %d ticks\n", elapsed);
+
+ /* mark all hash table entries as not seen */
+ hi = hash_first_pid(ptable, &pos);
+ while (hi != NULL)
+ {
+ ((struct top_proc *)(hi->value))->state = 0;
+ hi = hash_next_pid(&pos);
+ }
+ /* mark all hash table entries as not seen */
+ hi = hash_first_pid(tasktable, &pos);
+ while (hi != NULL)
+ {
+ ((struct top_proc *)(hi->value))->state = 0;
+ hi = hash_next_pid(&pos);
+ }
+
+ /* read the process information */
+ {
+ DIR *dir = opendir(".");
+ DIR *taskdir;
+ struct dirent *ent;
+ struct dirent *taskent;
+ int total_procs = 0;
+ struct top_proc **active;
+ hash_item_pid *hi;
+ hash_pos pos;
+ char buffer[64];
+
+ int show_idle = sel->idle;
+ int show_uid = sel->uid != -1;
+ char *show_command = sel->command;
+
+ show_usernames = sel->usernames;
+ show_threads = sel->threads && have_task;
+
+ memset(process_states, 0, sizeof(process_states));
+
+ taskdir = NULL;
+ taskent = NULL;
+ taskpid = -1;
+
+ while ((ent = readdir(dir)) != NULL)
+ {
+ unsigned long otime;
+
+ if (!isdigit(ent->d_name[0]))
+ continue;
+
+ pid = atoi(ent->d_name);
+
+ /* look up hash table entry */
+ proc = hash_lookup_pid(ptable, pid);
+
+ /* if we came up empty, create a new entry */
+ if (proc == NULL)
+ {
+ proc = new_proc();
+ proc->pid = pid;
+ proc->time = 0;
+ hash_add_pid(ptable, pid, (void *)proc);
+ }
+
+ /* remember the previous cpu time */
+ otime = proc->time;
+
+ /* get current data */
+ read_one_proc_stat(pid, -1, proc, sel);
+
+ /* continue on if this isn't really a process */
+ if (proc->state == 0)
+ continue;
+
+ /* reset linked list (for threads) */
+ proc->next = NULL;
+
+ /* accumulate process state data */
+ total_procs++;
+ process_states[proc->state]++;
+
+ /* calculate pcpu */
+ if ((proc->pcpu = (proc->time - otime) / (double)elapsed) < 0.0001)
+ {
+ proc->pcpu = 0;
+ }
+
+ /* if we have task subdirs and this process has more than
+ one thread, collect data on each thread */
+ if (have_task && proc->threads > 1)
+ {
+ snprintf(buffer, sizeof(buffer), "%d/task", pid);
+ if ((taskdir = opendir(buffer)) != NULL)
+ {
+ while ((taskent = readdir(taskdir)) != NULL)
+ {
+ if (!isdigit(taskent->d_name[0]))
+ continue;
+
+ /* lookup entry in tasktable */
+ taskpid = atoi(taskent->d_name);
+ taskproc = hash_lookup_pid(tasktable, taskpid);
+
+ /* if we came up empty, create a new entry */
+ if (taskproc == NULL)
+ {
+ taskproc = new_proc();
+ taskproc->pid = taskpid;
+ taskproc->time = 0;
+ hash_add_pid(tasktable, taskpid, (void *)taskproc);
+ }
+
+ /* remember the previous cpu time */
+ otime = taskproc->time;
+
+ /* get current data */
+ read_one_proc_stat(pid, taskpid, taskproc, sel);
+
+ /* ignore if it isnt real */
+ if (taskproc->state == 0)
+ continue;
+
+ /* when showing threads, add this to the accumulated
+ process state data, but remember that the first
+ thread is already accounted for */
+ if (show_threads && pid != taskpid)
+ {
+ total_procs++;
+ process_states[taskproc->state]++;
+ }
+
+ /* calculate pcpu */
+ if ((taskproc->pcpu = (taskproc->time - otime) /
+ (double)elapsed) < 0.0)
+ {
+ taskproc->pcpu = 0;
+ }
+
+ /* link this in to the proc's list */
+ taskproc->next = proc->next;
+ proc->next = taskproc;
+ }
+ closedir(taskdir);
+ }
+ }
+ }
+ closedir(dir);
+
+ /* make sure we have enough slots for the active procs */
+ if (activesize < total_procs)
+ {
+ pactive = (struct top_proc **)realloc(pactive,
+ sizeof(struct top_proc *) * total_procs);
+ activesize = total_procs;
+ }
+
+ /* set up the active procs and flush dead entries */
+ active = pactive;
+ hi = hash_first_pid(ptable, &pos);
+ while (hi != NULL)
+ {
+ proc = (struct top_proc *)(hi->value);
+ if (proc->state == 0)
+ {
+ /* dead entry */
+ hash_remove_pos_pid(&pos);
+ free_proc(proc);
+ }
+ else
+ {
+ /* check to see if it qualifies as active */
+ if ((show_idle || proc->state == 1 || proc->pcpu) &&
+ (!show_uid || proc->uid == sel->uid) &&
+ (show_command == NULL ||
+ strstr(proc->name, show_command) != NULL))
+ {
+ /* are we showing threads and does this proc have any? */
+ if (show_threads && proc->threads > 1 && proc->next != NULL)
+ {
+ /* then add just the thread info -- the main process
+ info is included in the list */
+ proc = proc->next;
+ while (proc != NULL)
+ {
+ *active++ = proc;
+ proc = proc->next;
+ }
+ }
+ else
+ {
+ /* add the process */
+ *active++ = proc;
+ }
+ }
+ }
+
+ hi = hash_next_pid(&pos);
+ }
+
+ si->p_active = active - pactive;
+ si->p_total = total_procs;
+ si->procstates = process_states;
+ }
+
+ /* if requested, sort the "active" procs */
+ if (si->p_active)
+ qsort(pactive, si->p_active, sizeof(struct top_proc *),
+ proc_compares[compare_index]);
+
+ /* don't even pretend that the return value thing here isn't bogus */
+ nextactive = pactive;
+ return (caddr_t)0;
+}
+
+
+char *
+format_header(char *uname_field)
+
+{
+ int uname_len = strlen(uname_field);
+ if (uname_len > 8)
+ uname_len = 8;
+
+ memcpy(strchr(fmt_header, 'X'), uname_field, uname_len);
+
+ return fmt_header;
+}
+
+static char p_header[MAX_COLS];
+
+char *
+format_process_header(struct process_select *sel, caddr_t handle, int count)
+
+{
+ char *h;
+
+ h = sel->threads ? proc_header_nothr : proc_header_thr;
+
+ snprintf(p_header, MAX_COLS, h, sel->usernames ? "USERNAME" : "UID");
+
+ return p_header;
+}
+
+
+char *
+format_next_process(caddr_t handle, char *(*get_userid)(int))
+
+{
+ static char fmt[MAX_COLS]; /* static area where result is built */
+ struct top_proc *p = *nextactive++;
+ char *userbuf;
+
+ userbuf = show_usernames ? username(p->uid) : itoa_w(p->uid, 7);
+
+ if (show_threads)
+ {
+ snprintf(fmt, sizeof(fmt),
+ "%5d %-8.8s %3d %4d %5s %5s %5s %-5s %6s %5s%% %s",
+ p->pid,
+ userbuf,
+ p->pri < -99 ? -99 : p->pri,
+ p->nice,
+ format_k(p->size),
+ format_k(p->rss),
+ format_k(p->shared),
+ state_abbrev[p->state],
+ format_time(p->time / HZ),
+ format_percent(p->pcpu * 100.0),
+ p->name);
+ }
+ else
+ {
+ snprintf(fmt, sizeof(fmt),
+ "%5d %-8.8s %4d %3d %4d %5s %5s %5s %-5s %6s %5s%% %s",
+ p->pid,
+ userbuf,
+ p->threads <= 9999 ? p->threads : 9999,
+ p->pri < -99 ? -99 : p->pri,
+ p->nice,
+ format_k(p->size),
+ format_k(p->rss),
+ format_k(p->shared),
+ state_abbrev[p->state],
+ format_time(p->time / HZ),
+ format_percent(p->pcpu * 100.0),
+ p->name);
+ }
+
+ /* return the result */
+ return (fmt);
+}
+
+/* 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 (dresult = p2->pcpu - p1->pcpu,\
+ (result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0)
+#define ORDERKEY_CPTICKS if ((result = (long)p2->time - (long)p1->time) == 0)
+#define ORDERKEY_STATE if ((result = (sort_state[p2->state] - \
+ sort_state[p1->state])) == 0)
+#define ORDERKEY_PRIO if ((result = p2->pri - p1->pri) == 0)
+#define ORDERKEY_RSSIZE if ((result = p2->rss - p1->rss) == 0)
+#define ORDERKEY_MEM if ((result = p2->size - p1->size) == 0)
+#define ORDERKEY_NAME if ((result = strcmp(p1->name, p2->name)) == 0)
+
+/* Now the array that maps process state to a weight */
+
+unsigned char sort_state[] =
+{
+ 0, /* empty */
+ 6, /* run */
+ 3, /* sleep */
+ 5, /* disk wait */
+ 1, /* zombie */
+ 2, /* stop */
+ 4 /* swap */
+};
+
+
+/* compare_cpu - the comparison function for sorting by cpu percentage */
+
+int
+compare_cpu (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+ }
+
+/* compare_size - the comparison function for sorting by total memory usage */
+
+int
+compare_size (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+ }
+
+/* compare_res - the comparison function for sorting by resident set size */
+
+int
+compare_res (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+ }
+
+/* compare_time - the comparison function for sorting by total cpu time */
+
+int
+compare_time (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+ }
+
+
+/* compare_cmd - the comparison function for sorting by command name */
+
+int
+compare_cmd (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_NAME
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 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(int pid)
+
+{
+ struct stat sb;
+ char buffer[32];
+ sprintf(buffer, "%d", pid);
+
+ if (stat(buffer, &sb) < 0)
+ return -1;
+ else
+ return (int)sb.st_uid;
+}
--- /dev/null
+.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.
--- /dev/null
+/*
+ * 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: 2.x with thread eliding
+ *
+ * DESCRIPTION:
+ * This is the machine-dependent module for Linux 2.x that elides threads
+ * from the output.
+ *
+ * CFLAGS: -DHAVE_GETOPT -DHAVE_STRERROR -DORDER
+ *
+ * TERMCAP: -lcurses
+ *
+ * AUTHOR: Richard Henderson <rth@tamu.edu>
+ * Order support added by Alexey Klimkin <kad@klon.tme.mcst.ru>
+ * Ported to 2.4 by William LeFebvre
+ * Thread eliding by William LeFebvre
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <dirent.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+
+#include <sys/param.h> /* for HZ */
+#include <asm/page.h> /* for PAGE_SHIFT */
+
+#if 0
+#include <linux/proc_fs.h> /* for PROC_SUPER_MAGIC */
+#else
+#define PROC_SUPER_MAGIC 0x9fa0
+#endif
+
+#include "top.h"
+#include "machine.h"
+#include "utils.h"
+
+#define PROCFS "/proc"
+extern char *myname;
+
+/*=PROCESS INFORMATION==================================================*/
+
+struct top_proc
+{
+ pid_t pid;
+ pid_t ppid;
+ uid_t uid;
+ char *name;
+ int pri, nice;
+ unsigned long size, rss; /* in k */
+ int state;
+ unsigned long time;
+ unsigned long start_time;
+ unsigned long otime;
+ unsigned long start_code;
+ unsigned long end_code;
+ unsigned long start_stack;
+ unsigned int threads;
+ double pcpu, wcpu;
+ struct top_proc *next;
+};
+
+
+/*=STATE IDENT STRINGS==================================================*/
+
+#define NPROCSTATES 7
+static char *state_abbrev[NPROCSTATES+1] =
+{
+ "", "run", "sleep", "disk", "zomb", "stop", "swap",
+ NULL
+};
+
+static char *procstatenames[NPROCSTATES+1] =
+{
+ "", " running, ", " sleeping, ", " uninterruptable, ",
+ " zombie, ", " stopped, ", " swapping, ",
+ NULL
+};
+
+#define NCPUSTATES 4
+static char *cpustatenames[NCPUSTATES+1] =
+{
+ "user", "nice", "system", "idle",
+ NULL
+};
+
+#define MEMUSED 0
+#define MEMFREE 1
+#define MEMSHARED 2
+#define MEMBUFFERS 3
+#define MEMCACHED 4
+#define NMEMSTATS 5
+static char *memorynames[NMEMSTATS+1] =
+{
+ "K used, ", "K free, ", "K shared, ", "K buffers, ", "K cached",
+ NULL
+};
+
+#define SWAPUSED 0
+#define SWAPFREE 1
+#define SWAPCACHED 2
+#define NSWAPSTATS 3
+static char *swapnames[NSWAPSTATS+1] =
+{
+ "K used, ", "K free, ", "K cached",
+ NULL
+};
+
+static char fmt_header[] =
+" PID X THR PRI NICE SIZE RES STATE TIME CPU COMMAND";
+
+/* these are names given to allowed sorting orders -- first is default */
+char *ordernames[] =
+{"cpu", "size", "res", "time", "command", NULL};
+
+/* forward definitions for comparison functions */
+int compare_cpu();
+int compare_size();
+int compare_res();
+int compare_time();
+int compare_cmd();
+
+int (*proc_compares[])() = {
+ compare_cpu,
+ compare_size,
+ compare_res,
+ compare_time,
+ compare_cmd,
+ NULL };
+
+/*=SYSTEM STATE INFO====================================================*/
+
+/* these are for calculating cpu state percentages */
+
+static long cp_time[NCPUSTATES];
+static long cp_old[NCPUSTATES];
+static long cp_diff[NCPUSTATES];
+
+/* for calculating the exponential average */
+
+static struct timeval lasttime;
+
+/* these are for keeping track of processes */
+
+#define HASH_SIZE (1003)
+#define INITIAL_ACTIVE_SIZE (256)
+#define PROCBLOCK_SIZE (32)
+static struct top_proc *ptable[HASH_SIZE];
+static struct top_proc **pactive;
+static struct top_proc **nextactive;
+static unsigned int activesize = 0;
+static time_t boottime = -1;
+
+/* these are for passing data back to the machine independant portion */
+
+static int cpu_states[NCPUSTATES];
+static int process_states[NPROCSTATES];
+static long memory_stats[NMEMSTATS];
+static long swap_stats[NSWAPSTATS];
+
+/* usefull macros */
+#define bytetok(x) (((x) + 512) >> 10)
+#define pagetok(x) ((x) << (PAGE_SHIFT - 10))
+#define HASH(x) (((x) * 1686629713U) % HASH_SIZE)
+
+/*======================================================================*/
+
+static inline char *
+skip_ws(const char *p)
+{
+ while (isspace(*p)) p++;
+ return (char *)p;
+}
+
+static inline char *
+skip_token(const char *p)
+{
+ while (isspace(*p)) p++;
+ while (*p && !isspace(*p)) p++;
+ return (char *)p;
+}
+
+static void
+xfrm_cmdline(char *p, int len)
+{
+ while (--len > 0)
+ {
+ if (*p == '\0')
+ {
+ *p = ' ';
+ }
+ p++;
+ }
+}
+
+static void
+update_procname(struct top_proc *proc, char *cmd)
+
+{
+ printable(cmd);
+
+ if (proc->name == NULL)
+ {
+ proc->name = strdup(cmd);
+ }
+ else if (strcmp(proc->name, cmd) != 0)
+ {
+ free(proc->name);
+ proc->name = strdup(cmd);
+ }
+}
+
+
+
+
+/*
+ * Process structures are allocated and freed as needed. Here we
+ * keep big pools of them, adding more pool as needed. When a
+ * top_proc structure is freed, it is added to a freelist and reused.
+ */
+
+static struct top_proc *freelist = NULL;
+static struct top_proc *procblock = NULL;
+static struct top_proc *procmax = NULL;
+
+static struct top_proc *
+new_proc()
+{
+ struct top_proc *p;
+
+ if (freelist)
+ {
+ p = freelist;
+ freelist = freelist->next;
+ }
+ else if (procblock)
+ {
+ p = procblock;
+ if (++procblock >= procmax)
+ {
+ procblock = NULL;
+ }
+ }
+ else
+ {
+ p = procblock = (struct top_proc *)calloc(PROCBLOCK_SIZE,
+ sizeof(struct top_proc));
+ procmax = procblock++ + PROCBLOCK_SIZE;
+ }
+
+ /* initialization */
+ if (p->name != NULL)
+ {
+ free(p->name);
+ p->name = NULL;
+ }
+
+ return p;
+}
+
+static void
+free_proc(struct top_proc *proc)
+{
+ proc->next = freelist;
+ freelist = proc;
+}
+
+
+int
+machine_init(struct statics *statics)
+
+{
+ /* make sure the proc filesystem is mounted */
+ {
+ struct statfs sb;
+ if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC)
+ {
+ fprintf(stderr, "%s: proc filesystem not mounted on " PROCFS "\n",
+ myname);
+ return -1;
+ }
+ }
+
+ /* chdir to the proc filesystem to make things easier */
+ chdir(PROCFS);
+
+ /* get a boottime */
+ {
+ int fd;
+ char buff[64];
+ char *p;
+ unsigned long uptime;
+ struct timeval tv;
+
+ if ((fd = open("uptime", 0)) != -1)
+ {
+ if (read(fd, buff, sizeof(buff)) > 0)
+ {
+ uptime = strtoul(buff, &p, 10);
+ gettimeofday(&tv, 0);
+ boottime = tv.tv_sec - uptime;
+ }
+ close(fd);
+ }
+ }
+
+ /* fill in the statics information */
+ statics->procstate_names = procstatenames;
+ statics->cpustate_names = cpustatenames;
+ statics->memory_names = memorynames;
+ statics->swap_names = swapnames;
+ statics->order_names = ordernames;
+ statics->boottime = boottime;
+ statics->flags.fullcmds = 1;
+ statics->flags.warmup = 1;
+
+ /* allocate needed space */
+ pactive = (struct top_proc **)malloc(sizeof(struct top_proc *) * INITIAL_ACTIVE_SIZE);
+ activesize = INITIAL_ACTIVE_SIZE;
+
+ /* make sure the hash table is empty */
+ memset(ptable, 0, HASH_SIZE * sizeof(struct top_proc *));
+
+ /* all done! */
+ return 0;
+}
+
+
+void
+get_system_info(struct system_info *info)
+
+{
+ char buffer[4096+1];
+ int fd, len;
+ char *p;
+
+ /* get load averages */
+
+ if ((fd = open("loadavg", O_RDONLY)) != -1)
+ {
+ if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
+ {
+ buffer[len] = '\0';
+
+ info->load_avg[0] = strtod(buffer, &p);
+ info->load_avg[1] = strtod(p, &p);
+ info->load_avg[2] = strtod(p, &p);
+ p = skip_token(p); /* skip running/tasks */
+ p = skip_ws(p);
+ if (*p)
+ {
+ info->last_pid = atoi(p);
+ }
+ else
+ {
+ info->last_pid = -1;
+ }
+ }
+ close(fd);
+ }
+
+ /* get the cpu time info */
+ if ((fd = open("stat", O_RDONLY)) != -1)
+ {
+ if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
+ {
+ buffer[len] = '\0';
+ p = skip_token(buffer); /* "cpu" */
+ cp_time[0] = strtoul(p, &p, 0);
+ cp_time[1] = strtoul(p, &p, 0);
+ cp_time[2] = strtoul(p, &p, 0);
+ cp_time[3] = strtoul(p, &p, 0);
+
+ /* convert cp_time counts to percentages */
+ percentages(4, cpu_states, cp_time, cp_old, cp_diff);
+ }
+ close(fd);
+ }
+
+ /* get system wide memory usage */
+ if ((fd = open("meminfo", O_RDONLY)) != -1)
+ {
+ char *p;
+ int mem = 0;
+ int swap = 0;
+ unsigned long memtotal = 0;
+ unsigned long memfree = 0;
+ unsigned long swaptotal = 0;
+
+ if ((len = read(fd, buffer, sizeof(buffer)-1)) > 0)
+ {
+ buffer[len] = '\0';
+ p = buffer-1;
+
+ /* iterate thru the lines */
+ while (p != NULL)
+ {
+ p++;
+ if (p[0] == ' ' || p[0] == '\t')
+ {
+ /* skip */
+ }
+ else if (strncmp(p, "Mem:", 4) == 0)
+ {
+ p = skip_token(p); /* "Mem:" */
+ p = skip_token(p); /* total memory */
+ memory_stats[MEMUSED] = strtoul(p, &p, 10);
+ memory_stats[MEMFREE] = strtoul(p, &p, 10);
+ memory_stats[MEMSHARED] = strtoul(p, &p, 10);
+ memory_stats[MEMBUFFERS] = strtoul(p, &p, 10);
+ memory_stats[MEMCACHED] = strtoul(p, &p, 10);
+ memory_stats[MEMUSED] = bytetok(memory_stats[MEMUSED]);
+ memory_stats[MEMFREE] = bytetok(memory_stats[MEMFREE]);
+ memory_stats[MEMSHARED] = bytetok(memory_stats[MEMSHARED]);
+ memory_stats[MEMBUFFERS] = bytetok(memory_stats[MEMBUFFERS]);
+ memory_stats[MEMCACHED] = bytetok(memory_stats[MEMCACHED]);
+ mem = 1;
+ }
+ else if (strncmp(p, "Swap:", 5) == 0)
+ {
+ p = skip_token(p); /* "Swap:" */
+ p = skip_token(p); /* total swap */
+ swap_stats[SWAPUSED] = strtoul(p, &p, 10);
+ swap_stats[SWAPFREE] = strtoul(p, &p, 10);
+ swap_stats[SWAPUSED] = bytetok(swap_stats[SWAPUSED]);
+ swap_stats[SWAPFREE] = bytetok(swap_stats[SWAPFREE]);
+ swap = 1;
+ }
+ else if (!mem && strncmp(p, "MemTotal:", 9) == 0)
+ {
+ p = skip_token(p);
+ memtotal = strtoul(p, &p, 10);
+ }
+ else if (!mem && memtotal > 0 && strncmp(p, "MemFree:", 8) == 0)
+ {
+ p = skip_token(p);
+ memfree = strtoul(p, &p, 10);
+ memory_stats[MEMUSED] = memtotal - memfree;
+ memory_stats[MEMFREE] = memfree;
+ }
+ else if (!mem && strncmp(p, "MemShared:", 10) == 0)
+ {
+ p = skip_token(p);
+ memory_stats[MEMSHARED] = strtoul(p, &p, 10);
+ }
+ else if (!mem && strncmp(p, "Buffers:", 8) == 0)
+ {
+ p = skip_token(p);
+ memory_stats[MEMBUFFERS] = strtoul(p, &p, 10);
+ }
+ else if (!mem && strncmp(p, "Cached:", 7) == 0)
+ {
+ p = skip_token(p);
+ memory_stats[MEMCACHED] = strtoul(p, &p, 10);
+ }
+ else if (!swap && strncmp(p, "SwapTotal:", 10) == 0)
+ {
+ p = skip_token(p);
+ swaptotal = strtoul(p, &p, 10);
+ }
+ else if (!swap && swaptotal > 0 && strncmp(p, "SwapFree:", 9) == 0)
+ {
+ p = skip_token(p);
+ memfree = strtoul(p, &p, 10);
+ swap_stats[SWAPUSED] = swaptotal - memfree;
+ swap_stats[SWAPFREE] = memfree;
+ }
+ else if (!mem && strncmp(p, "SwapCached:", 11) == 0)
+ {
+ p = skip_token(p);
+ swap_stats[SWAPCACHED] = strtoul(p, &p, 10);
+ }
+
+ /* move to the next line */
+ p = strchr(p, '\n');
+ }
+ }
+ close(fd);
+ }
+
+ /* set arrays and strings */
+ info->cpustates = cpu_states;
+ info->memory = memory_stats;
+ info->swap = swap_stats;
+}
+
+
+static void
+read_one_proc_stat(pid_t pid, struct top_proc *proc, struct process_select *sel)
+{
+ char buffer[4096], *p, *q;
+ int fd, len;
+ int fullcmd;
+
+ /* if anything goes wrong, we return with proc->state == 0 */
+ proc->state = 0;
+
+ /* full cmd handling */
+ fullcmd = sel->fullcmd;
+ if (fullcmd)
+ {
+ sprintf(buffer, "%d/cmdline", pid);
+ if ((fd = open(buffer, O_RDONLY)) != -1)
+ {
+ /* read command line data */
+ /* (theres no sense in reading more than we can fit) */
+ if ((len = read(fd, buffer, MAX_COLS)) > 1)
+ {
+ buffer[len] = '\0';
+ xfrm_cmdline(buffer, len);
+ update_procname(proc, buffer);
+ }
+ else
+ {
+ fullcmd = 0;
+ }
+ close(fd);
+ }
+ else
+ {
+ fullcmd = 0;
+ }
+ }
+
+ /* grab the proc stat info in one go */
+ sprintf(buffer, "%d/stat", pid);
+
+ fd = open(buffer, O_RDONLY);
+ len = read(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ buffer[len] = '\0';
+
+ proc->uid = (uid_t)proc_owner((int)pid);
+
+ /* parse out the status */
+
+ /* skip pid and locate command, which is in parentheses */
+ if ((p = strchr(buffer, '(')) == NULL)
+ {
+ return;
+ }
+ if ((q = strrchr(++p, ')')) == NULL)
+ {
+ return;
+ }
+
+ /* set the procname */
+ *q = '\0';
+ if (!fullcmd)
+ {
+ update_procname(proc, p);
+ }
+
+ /* scan the rest of the line */
+ p = q+1;
+ p = skip_ws(p);
+ switch (*p++) /* state */
+ {
+ case 'R': proc->state = 1; break;
+ case 'S': proc->state = 2; break;
+ case 'D': proc->state = 3; break;
+ case 'Z': proc->state = 4; break;
+ case 'T': proc->state = 5; break;
+ case 'W': proc->state = 6; break;
+ case '\0': return;
+ }
+
+ proc->ppid = strtoul(p, &p, 10); /* ppid */
+ p = skip_token(p); /* skip pgrp */
+ p = skip_token(p); /* skip session */
+ p = skip_token(p); /* skip tty */
+ p = skip_token(p); /* skip tty pgrp */
+ p = skip_token(p); /* skip flags */
+ p = skip_token(p); /* skip min flt */
+ p = skip_token(p); /* skip cmin flt */
+ p = skip_token(p); /* skip maj flt */
+ p = skip_token(p); /* skip cmaj flt */
+
+ proc->time = strtoul(p, &p, 10); /* utime */
+ proc->time += strtoul(p, &p, 10); /* stime */
+
+ p = skip_token(p); /* skip cutime */
+ p = skip_token(p); /* skip cstime */
+
+ proc->pri = strtol(p, &p, 10); /* priority */
+ proc->nice = strtol(p, &p, 10); /* nice */
+
+ p = skip_token(p); /* skip timeout */
+ p = skip_token(p); /* skip it_real_val */
+ proc->start_time = strtoul(p, &p, 10); /* start_time */
+
+ proc->size = bytetok(strtoul(p, &p, 10)); /* vsize */
+ proc->rss = pagetok(strtoul(p, &p, 10)); /* rss */
+
+ p = skip_token(p); /* skip rlim */
+ proc->start_code = strtoul(p, &p, 10); /* start_code */
+ proc->end_code = strtoul(p, &p, 10); /* end_code */
+ proc->start_stack = strtoul(p, &p, 10); /* start_stack */
+
+ /* for the record, here are the rest of the fields */
+#if 0
+ p = skip_token(p); /* skip sp */
+ p = skip_token(p); /* skip pc */
+ p = skip_token(p); /* skip signal */
+ p = skip_token(p); /* skip sigblocked */
+ p = skip_token(p); /* skip sigignore */
+ p = skip_token(p); /* skip sigcatch */
+ p = skip_token(p); /* skip wchan */
+#endif
+}
+
+
+caddr_t
+get_process_info(struct system_info *si,
+ struct process_select *sel,
+ int compare_index)
+{
+ struct timeval thistime;
+ double timediff, alpha, beta;
+ struct top_proc *proc;
+ pid_t pid;
+ unsigned long now;
+ unsigned long elapsed;
+ int i;
+
+ /* calculate the time difference since our last check */
+ gettimeofday(&thistime, 0);
+ if (lasttime.tv_sec)
+ {
+ timediff = ((thistime.tv_sec - lasttime.tv_sec) +
+ (thistime.tv_usec - lasttime.tv_usec) * 1e-6);
+ }
+ else
+ {
+ timediff = 0;
+ }
+ lasttime = thistime;
+
+ /* round current time to a second */
+ now = (unsigned long)thistime.tv_sec;
+ if (thistime.tv_usec >= 500000)
+ {
+ now++;
+ }
+
+ /* calculate constants for the exponental average */
+ if (timediff > 0.0 && timediff < 30.0)
+ {
+ alpha = 0.5 * (timediff / 30.0);
+ beta = 1.0 - alpha;
+ }
+ else
+ alpha = beta = 0.5;
+ timediff *= HZ; /* convert to ticks */
+
+ /* mark all hash table entries as not seen */
+ for (i = 0; i < HASH_SIZE; ++i)
+ {
+ for (proc = ptable[i]; proc; proc = proc->next)
+ {
+ proc->state = 0;
+ }
+ }
+
+ /* read the process information */
+ {
+ DIR *dir = opendir(".");
+ struct dirent *ent;
+ int total_procs = 0;
+ struct top_proc **active;
+
+ int show_idle = sel->idle;
+ int show_uid = sel->uid != -1;
+
+ memset(process_states, 0, sizeof(process_states));
+
+ while ((ent = readdir(dir)) != NULL)
+ {
+ struct top_proc *pp;
+
+ if (!isdigit(ent->d_name[0]))
+ continue;
+
+ pid = atoi(ent->d_name);
+
+ /* look up hash table entry */
+ proc = pp = ptable[HASH(pid)];
+ while (proc && proc->pid != pid)
+ {
+ proc = proc->next;
+ }
+
+ /* if we came up empty, create a new entry */
+ if (proc == NULL)
+ {
+ proc = new_proc();
+ proc->pid = pid;
+ proc->next = pp;
+ ptable[HASH(pid)] = proc;
+ proc->time = proc->otime = 0;
+ }
+
+ read_one_proc_stat(pid, proc, sel);
+ proc->threads = 1;
+
+ if (proc->state == 0)
+ continue;
+
+ total_procs++;
+ process_states[proc->state]++;
+
+ /* calculate cpu percentage */
+ if (timediff > 0.0)
+ {
+ if ((proc->pcpu = (proc->time - proc->otime) / timediff) < 0.0001)
+ {
+ proc->pcpu = 0;
+ }
+ }
+ else if ((elapsed = (now - boottime)*HZ - proc->start_time) > 0)
+ {
+ if ((proc->pcpu = (double)proc->time / (double)elapsed) < 0.0001)
+ {
+ proc->pcpu;
+ }
+ }
+ else
+ {
+ proc->pcpu = 0.0;
+ }
+
+ /* remember time for next time */
+ proc->otime = proc->time;
+ }
+ closedir(dir);
+
+ /* make sure we have enough slots for the active procs */
+ if (activesize < total_procs)
+ {
+ pactive = (struct top_proc **)realloc(pactive,
+ sizeof(struct top_proc *) * total_procs);
+ activesize = total_procs;
+ }
+
+ /* set up the active procs and flush dead entries */
+ /* also coalesce threads */
+ active = pactive;
+ for (i = 0; i < HASH_SIZE; i++)
+ {
+ struct top_proc *last;
+ struct top_proc *ptmp;
+ struct top_proc *parent;
+
+ last = NULL;
+ proc = ptable[i];
+ while (proc != NULL)
+ {
+ if (proc->state == 0)
+ {
+ ptmp = proc;
+ if (last)
+ {
+ proc = last->next = proc->next;
+ }
+ else
+ {
+ proc = ptable[i] = proc->next;
+ }
+ free_proc(ptmp);
+ }
+ else
+ {
+ /* look up hash table entry for parent */
+ parent = proc;
+ do {
+ pid = parent->ppid;
+ parent = ptable[HASH(pid)];
+ while (parent && parent->pid != pid)
+ {
+ parent = parent->next;
+ }
+ } while (parent && parent->state == 0);
+
+ /* does this look like a thread of its parent? */
+ if (parent && proc->size == parent->size &&
+ proc->rss == parent->rss &&
+ proc->start_code == parent->start_code &&
+ proc->end_code == parent->end_code &&
+ proc->start_stack == parent->start_stack)
+ {
+ /* yes it does: roll up the cumulative numbers */
+ parent->threads += proc->threads;
+ parent->time += proc->time;
+ parent->pcpu += proc->pcpu;
+
+ /* mark this process as dead (undisplayable) */
+ proc->state = 0;
+ }
+ else if ((show_idle || proc->state == 1 || proc->pcpu) &&
+ (!show_uid || proc->uid == sel->uid))
+ {
+ *active++ = proc;
+ last = proc;
+ }
+ proc = proc->next;
+ }
+ }
+ }
+
+ si->p_active = active - pactive;
+ si->p_total = total_procs;
+ si->procstates = process_states;
+ }
+
+ /* if requested, sort the "active" procs */
+ if (si->p_active)
+ qsort(pactive, si->p_active, sizeof(struct top_proc *),
+ proc_compares[compare_index]);
+
+ /* don't even pretend that the return value thing here isn't bogus */
+ nextactive = pactive;
+ return (caddr_t)0;
+}
+
+
+char *
+format_header(char *uname_field)
+
+{
+ int uname_len = strlen(uname_field);
+ if (uname_len > 8)
+ uname_len = 8;
+
+ memcpy(strchr(fmt_header, 'X'), uname_field, uname_len);
+
+ return fmt_header;
+}
+
+
+char *
+format_next_process(caddr_t handle, char *(*get_userid)(int))
+
+{
+ static char fmt[MAX_COLS]; /* static area where result is built */
+ struct top_proc *p = *nextactive++;
+
+ snprintf(fmt, sizeof(fmt),
+ "%5d %-8.8s %3d %3d %4d %5s %5s %-5s %6s %5.2f%% %s",
+ p->pid,
+ (*get_userid)(p->uid),
+ p->threads,
+ p->pri < -99 ? -99 : p->pri,
+ p->nice,
+ format_k(p->size),
+ format_k(p->rss),
+ state_abbrev[p->state],
+ format_time(p->time / HZ),
+ p->pcpu * 100.0,
+ p->name);
+
+ /* return the result */
+ return (fmt);
+}
+
+/* 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 (dresult = p2->pcpu - p1->pcpu,\
+ (result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0)
+#define ORDERKEY_CPTICKS if ((result = (long)p2->time - (long)p1->time) == 0)
+#define ORDERKEY_STATE if ((result = (sort_state[p2->state] - \
+ sort_state[p1->state])) == 0)
+#define ORDERKEY_PRIO if ((result = p2->pri - p1->pri) == 0)
+#define ORDERKEY_RSSIZE if ((result = p2->rss - p1->rss) == 0)
+#define ORDERKEY_MEM if ((result = p2->size - p1->size) == 0)
+#define ORDERKEY_NAME if ((result = strcmp(p1->name, p2->name)) == 0)
+
+/* Now the array that maps process state to a weight */
+
+unsigned char sort_state[] =
+{
+ 0, /* empty */
+ 6, /* run */
+ 3, /* sleep */
+ 5, /* disk wait */
+ 1, /* zombie */
+ 2, /* stop */
+ 4 /* swap */
+};
+
+
+/* compare_cpu - the comparison function for sorting by cpu percentage */
+
+int
+compare_cpu (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+ }
+
+/* compare_size - the comparison function for sorting by total memory usage */
+
+int
+compare_size (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+ }
+
+/* compare_res - the comparison function for sorting by resident set size */
+
+int
+compare_res (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+ }
+
+/* compare_time - the comparison function for sorting by total cpu time */
+
+int
+compare_time (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 1;
+ }
+
+/* compare_cmd - the comparison function for sorting by command name */
+
+int
+compare_cmd (
+ struct top_proc **pp1,
+ struct top_proc **pp2)
+ {
+ register struct top_proc *p1;
+ register struct top_proc *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_NAME
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ;
+
+ return result == 0 ? 0 : result < 0 ? -1 : 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(int pid)
+
+{
+ struct stat sb;
+ char buffer[32];
+ sprintf(buffer, "%d", pid);
+
+ if (stat(buffer, &sb) < 0)
+ return -1;
+ else
+ return (int)sb.st_uid;
+}
--- /dev/null
+.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.
+
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+.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.
+
--- /dev/null
+/* $NetBSD: m_netbsd.c,v 1.18 2013/10/20 03:02:27 christos Exp $ */
+
+/*
+ * top - a top users display for Unix
+ *
+ * SYNOPSIS: For a NetBSD-1.5 (or later) system
+ *
+ * DESCRIPTION:
+ * Originally written for BSD4.4 system by Christos Zoulas.
+ * Based on the FreeBSD 2.0 version by Steven Wallace and Wolfram Schneider.
+ * NetBSD-1.0 port by Arne Helme. Process ordering by Luke Mewburn.
+ * NetBSD-1.3 port by Luke Mewburn, based on code by Matthew Green.
+ * NetBSD-1.4/UVM port by matthew green.
+ * NetBSD-1.5 port by Simon Burge.
+ * NetBSD-1.6/UBC port by Tomas Svensson.
+ * -
+ * This is the machine-dependent module for NetBSD-1.5 and later
+ * works for:
+ * NetBSD-1.6ZC
+ * and should work for:
+ * NetBSD-2.0 (when released)
+ * -
+ * top does not need to be installed setuid or setgid with this module.
+ *
+ * LIBS: -lkvm
+ *
+ * CFLAGS: -DHAVE_GETOPT -DORDER -DHAVE_STRERROR
+ *
+ * AUTHORS: Christos Zoulas <christos@ee.cornell.edu>
+ * Steven Wallace <swallace@freebsd.org>
+ * Wolfram Schneider <wosch@cs.tu-berlin.de>
+ * Arne Helme <arne@acm.org>
+ * Luke Mewburn <lukem@NetBSD.org>
+ * matthew green <mrg@eterna.com.au>
+ * Simon Burge <simonb@NetBSD.org>
+ * Tomas Svensson <ts@unix1.net>
+ * Andrew Doran <ad@NetBSD.org>
+ *
+ *
+ * $Id: m_netbsd.c,v 1.18 2013/10/20 03:02:27 christos Exp $
+ */
+#include <sys/cdefs.h>
+
+#ifndef lint
+__RCSID("$NetBSD: m_netbsd.c,v 1.18 2013/10/20 03:02:27 christos Exp $");
+#endif
+
+#include <sys/param.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/sched.h>
+#include <sys/swap.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <err.h>
+#include <errno.h>
+#include <kvm.h>
+#include <math.h>
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "os.h"
+#include "top.h"
+#include "machine.h"
+#include "utils.h"
+#include "display.h"
+#include "loadavg.h"
+#include "username.h"
+
+static void percentages64(int, int *, u_int64_t *, u_int64_t *,
+ u_int64_t *);
+
+/* get_process_info passes back a handle. This is what it looks like: */
+
+struct handle {
+ struct process_select *sel;
+ struct kinfo_proc2 **next_proc; /* points to next valid proc pointer */
+ int remaining; /* number of pointers remaining */
+};
+
+/* define what weighted CPU is. */
+#define weighted_cpu(pfx, pct, pp) ((pp)->pfx ## swtime == 0 ? 0.0 : \
+ ((pct) / (1.0 - exp((pp)->pfx ## swtime * logcpu))))
+
+/* what we consider to be process size: */
+/* NetBSD introduced p_vm_msize with RLIMIT_AS */
+#ifdef RLIMIT_AS
+#define PROCSIZE(pp) \
+ ((pp)->p_vm_msize)
+#else
+#define PROCSIZE(pp) \
+ ((pp)->p_vm_tsize + (pp)->p_vm_dsize + (pp)->p_vm_ssize)
+#endif
+
+
+/*
+ * These definitions control the format of the per-process area
+ */
+
+static char Proc_header[] =
+ " PID X PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND";
+/* 0123456 -- field to fill in starts at header+6 */
+#define PROC_UNAME_START 6
+#define Proc_format \
+ "%5d %-8.8s %3d %4d%7s %5s %-8.8s%7s %5.*f%% %5.*f%% %s"
+
+static char Thread_header[] =
+ " PID LID X PRI STATE TIME WCPU CPU NAME COMMAND";
+/* 0123456 -- field to fill in starts at header+6 */
+#define THREAD_UNAME_START 12
+#define Thread_format \
+ "%5d %5d %-8.8s %3d %-8.8s%7s %5.2f%% %5.2f%% %-9.9s %s"
+
+/*
+ * Process state names for the "STATE" column of the display.
+ */
+
+const char *state_abbrev[] = {
+ "", "IDLE", "RUN", "SLEEP", "STOP", "ZOMB", "DEAD", "CPU"
+};
+
+static kvm_t *kd;
+
+static char *(*userprint)(int);
+
+/* these are retrieved from the kernel in _init */
+
+static double logcpu;
+static int hz;
+static int ccpu;
+
+/* these are for calculating CPU state percentages */
+
+static int ncpu = 0;
+static u_int64_t *cp_time;
+static u_int64_t *cp_old;
+static u_int64_t *cp_diff;
+
+/* these are for detailing the process states */
+
+int process_states[8];
+const char *procstatenames[] = {
+ "", " idle, ", " runnable, ", " sleeping, ", " stopped, ",
+ " zombie, ", " dead, ", " on CPU, ",
+ NULL
+};
+
+/* these are for detailing the CPU states */
+
+int *cpu_states;
+const char *cpustatenames[] = {
+#ifndef __minix
+ "user", "nice", "system", "interrupt", "idle", NULL
+#else /* __minix */
+ "user", "nice", "system", "kernel", "idle", NULL
+#endif /* __minix */
+};
+
+/* these are for detailing the memory statistics */
+
+long memory_stats[7];
+const char *memorynames[] = {
+#ifndef __minix
+ "K Act, ", "K Inact, ", "K Wired, ", "K Exec, ", "K File, ",
+ "K Free, ",
+#else /* __minix */
+ "K Total, ", "K Free, ", "K Contig, ", "K Cached, ", "K ???, ",
+ "K ???, ",
+#endif /* __minix */
+ NULL
+};
+
+long swap_stats[4];
+const char *swapnames[] = {
+#ifndef __minix
+ "K Total, ", "K Used, ", "K Free, ",
+#endif /* __minix */
+ NULL
+};
+
+
+/* these are names given to allowed sorting orders -- first is default */
+const char *ordernames[] = {
+ "cpu",
+ "pri",
+ "res",
+ "size",
+ "state",
+ "time",
+ "pid",
+ "command",
+ "username",
+ NULL
+};
+
+/* forward definitions for comparison functions */
+static int compare_cpu(struct proc **, struct proc **);
+static int compare_prio(struct proc **, struct proc **);
+static int compare_res(struct proc **, struct proc **);
+static int compare_size(struct proc **, struct proc **);
+static int compare_state(struct proc **, struct proc **);
+static int compare_time(struct proc **, struct proc **);
+static int compare_pid(struct proc **, struct proc **);
+static int compare_command(struct proc **, struct proc **);
+static int compare_username(struct proc **, struct proc **);
+
+int (*proc_compares[])(struct proc **, struct proc **) = {
+ compare_cpu,
+ compare_prio,
+ compare_res,
+ compare_size,
+ compare_state,
+ compare_time,
+ compare_pid,
+ compare_command,
+ compare_username,
+ NULL
+};
+
+static char *format_next_lwp(caddr_t, char *(*)(int));
+static char *format_next_proc(caddr_t, char *(*)(int));
+
+static caddr_t get_proc_info(struct system_info *, struct process_select *,
+ int (*)(struct proc **, struct proc **));
+static caddr_t get_lwp_info(struct system_info *, struct process_select *,
+ int (*)(struct proc **, struct proc **));
+
+/* these are for keeping track of the proc array */
+
+static int nproc;
+static int onproc = -1;
+static int nlwp;
+static int onlwp = -1;
+static int pref_len;
+static int lref_len;
+static struct kinfo_proc2 *pbase;
+static struct kinfo_lwp *lbase;
+static struct kinfo_proc2 **pref;
+static struct kinfo_lwp **lref;
+static int maxswap;
+static void *swapp;
+static int procgen;
+static int thread_nproc;
+static int thread_onproc = -1;
+static struct kinfo_proc2 *thread_pbase;
+
+/* these are for getting the memory statistics */
+
+static int pageshift; /* log base 2 of the pagesize */
+
+int threadmode;
+
+/* define pagetok in terms of pageshift */
+
+#define pagetok(size) ((size) << pageshift)
+
+/*
+ * Print swapped processes as <pname> and
+ * system processes as [pname]
+ */
+static const char *
+get_pretty(const struct kinfo_proc2 *pp)
+{
+ if ((pp->p_flag & P_SYSTEM) != 0)
+ return "[]";
+ if ((pp->p_flag & P_INMEM) == 0)
+ return "<>";
+ return "";
+}
+
+static const char *
+get_command(const struct process_select *sel, struct kinfo_proc2 *pp)
+{
+ static char cmdbuf[128];
+ const char *pretty;
+ char **argv;
+ if (pp == NULL)
+ return "<gone>";
+ pretty = get_pretty(pp);
+
+ if (sel->fullcmd == 0 || kd == NULL || (argv = kvm_getargv2(kd, pp,
+ sizeof(cmdbuf))) == NULL) {
+ if (pretty[0] != '\0' && pp->p_comm[0] != pretty[0])
+ snprintf(cmdbuf, sizeof(cmdbuf), "%c%s%c", pretty[0],
+ printable(pp->p_comm), pretty[1]);
+ else
+ strlcpy(cmdbuf, printable(pp->p_comm), sizeof(cmdbuf));
+ } else {
+ char *d = cmdbuf;
+ if (pretty[0] != '\0' && argv[0][0] != pretty[0])
+ *d++ = pretty[0];
+ while (*argv) {
+ const char *s = printable(*argv++);
+ while (d < cmdbuf + sizeof(cmdbuf) - 2 &&
+ (*d++ = *s++) != '\0')
+ continue;
+ if (d > cmdbuf && d < cmdbuf + sizeof(cmdbuf) - 2 &&
+ d[-1] == '\0')
+ d[-1] = ' ';
+ }
+ if (pretty[0] != '\0' && pretty[0] == cmdbuf[0])
+ *d++ = pretty[1];
+ *d++ = '\0';
+ }
+ return cmdbuf;
+}
+
+int
+machine_init(statics)
+ struct statics *statics;
+{
+ int pagesize;
+ int mib[2];
+ size_t size;
+ struct clockinfo clockinfo;
+ struct timeval boottime;
+
+ if ((kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open")) == NULL)
+ return -1;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ size = sizeof(ncpu);
+ if (sysctl(mib, 2, &ncpu, &size, NULL, 0) == -1) {
+ fprintf(stderr, "top: sysctl hw.ncpu failed: %s\n",
+ strerror(errno));
+ return(-1);
+ }
+ statics->ncpu = ncpu;
+ cp_time = malloc(sizeof(cp_time[0]) * CPUSTATES * ncpu);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CP_TIME;
+ size = sizeof(cp_time[0]) * CPUSTATES * ncpu;
+ if (sysctl(mib, 2, cp_time, &size, NULL, 0) < 0) {
+ fprintf(stderr, "top: sysctl kern.cp_time failed: %s\n",
+ strerror(errno));
+ return(-1);
+ }
+
+ /* Handle old call that returned only aggregate */
+ if (size == sizeof(cp_time[0]) * CPUSTATES)
+ ncpu = 1;
+
+ cpu_states = malloc(sizeof(cpu_states[0]) * CPUSTATES * ncpu);
+ cp_old = malloc(sizeof(cp_old[0]) * CPUSTATES * ncpu);
+ cp_diff = malloc(sizeof(cp_diff[0]) * CPUSTATES * ncpu);
+ if (cpu_states == NULL || cp_time == NULL || cp_old == NULL ||
+ cp_diff == NULL) {
+ fprintf(stderr, "top: machine_init: %s\n",
+ strerror(errno));
+ return(-1);
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CCPU;
+ size = sizeof(ccpu);
+ if (sysctl(mib, 2, &ccpu, &size, NULL, 0) == -1) {
+ fprintf(stderr, "top: sysctl kern.ccpu failed: %s\n",
+ strerror(errno));
+ return(-1);
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CLOCKRATE;
+ size = sizeof(clockinfo);
+ if (sysctl(mib, 2, &clockinfo, &size, NULL, 0) == -1) {
+ fprintf(stderr, "top: sysctl kern.clockrate failed: %s\n",
+ strerror(errno));
+ return(-1);
+ }
+ hz = clockinfo.stathz;
+
+ /* this is used in calculating WCPU -- calculate it ahead of time */
+ logcpu = log(loaddouble(ccpu));
+
+ pbase = NULL;
+ lbase = NULL;
+ pref = NULL;
+ nproc = 0;
+ onproc = -1;
+ nlwp = 0;
+ onlwp = -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 */
+#ifdef notyet
+ statics->ncpu = ncpu;
+#endif
+ statics->procstate_names = procstatenames;
+ statics->cpustate_names = cpustatenames;
+ statics->memory_names = memorynames;
+ statics->swap_names = swapnames;
+ statics->order_names = ordernames;
+ statics->flags.threads = 1;
+ statics->flags.fullcmds = 1;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTTIME;
+ size = sizeof(boottime);
+ if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
+ boottime.tv_sec != 0)
+ statics->boottime = boottime.tv_sec;
+ else
+ statics->boottime = 0;
+ /* all done! */
+ return(0);
+}
+
+char *
+format_process_header(struct process_select *sel, caddr_t handle, int count)
+
+{
+ char *header;
+ char *ptr;
+ const char *uname_field = sel->usernames ? "USERNAME" : " UID ";
+
+ if (sel->threads) {
+ header = Thread_header;
+ ptr = header + THREAD_UNAME_START;
+ } else {
+ header = Proc_header;
+ ptr = header + PROC_UNAME_START;
+ }
+
+ while (*uname_field != '\0') {
+ *ptr++ = *uname_field++;
+ }
+
+ return(header);
+}
+
+char *
+format_header(char *uname_field)
+{
+ char *header = Proc_header;
+ char *ptr = header + PROC_UNAME_START;
+
+ while (*uname_field != '\0') {
+ *ptr++ = *uname_field++;
+ }
+
+ return(header);
+}
+
+void
+get_system_info(struct system_info *si)
+{
+ size_t ssize;
+ int mib[2];
+ struct uvmexp_sysctl uvmexp;
+ struct swapent *sep;
+ u_int64_t totalsize, totalinuse;
+ int size, inuse, ncounted, i;
+ int rnswap, nswap;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CP_TIME;
+ ssize = sizeof(cp_time[0]) * CPUSTATES * ncpu;
+ if (sysctl(mib, 2, cp_time, &ssize, NULL, 0) < 0) {
+ fprintf(stderr, "top: sysctl kern.cp_time failed: %s\n",
+ strerror(errno));
+ quit(23);
+ }
+
+ if (getloadavg(si->load_avg, NUM_AVERAGES) < 0) {
+ int j;
+
+ warn("can't getloadavg");
+ for (j = 0; j < NUM_AVERAGES; j++)
+ si->load_avg[j] = 0.0;
+ }
+
+ /* convert cp_time counts to percentages */
+ for (i = 0; i < ncpu; i++) {
+ int j = i * CPUSTATES;
+ percentages64(CPUSTATES, cpu_states + j, cp_time + j, cp_old + j,
+ cp_diff + j);
+ }
+
+ mib[0] = CTL_VM;
+ mib[1] = VM_UVMEXP2;
+ ssize = sizeof(uvmexp);
+ if (sysctl(mib, 2, &uvmexp, &ssize, NULL, 0) < 0) {
+ fprintf(stderr, "top: sysctl vm.uvmexp2 failed: %s\n",
+ strerror(errno));
+ quit(23);
+ }
+
+ /* convert memory stats to Kbytes */
+#ifndef __minix
+ memory_stats[0] = pagetok(uvmexp.active);
+ memory_stats[1] = pagetok(uvmexp.inactive);
+ memory_stats[2] = pagetok(uvmexp.wired);
+ memory_stats[3] = pagetok(uvmexp.execpages);
+ memory_stats[4] = pagetok(uvmexp.filepages);
+ memory_stats[5] = pagetok(uvmexp.free);
+#else /* __minix */
+ memory_stats[0] = pagetok(uvmexp.npages);
+ memory_stats[1] = pagetok(uvmexp.free);
+ memory_stats[2] = pagetok(uvmexp.unused1); /* largest phys contig */
+ memory_stats[3] = pagetok(uvmexp.filepages);
+ memory_stats[4] = 0;
+ memory_stats[5] = 0;
+#endif /* __minix */
+
+ swap_stats[0] = swap_stats[1] = swap_stats[2] = 0;
+
+ do {
+#ifndef __minix
+ nswap = swapctl(SWAP_NSWAP, 0, 0);
+#else /* __minix */
+ nswap = 0;
+#endif /* __minix */
+ if (nswap < 1)
+ break;
+ if (nswap > maxswap) {
+ if (swapp)
+ free(swapp);
+ swapp = sep = malloc(nswap * sizeof(*sep));
+ if (sep == NULL)
+ break;
+ maxswap = nswap;
+ } else
+ sep = swapp;
+#ifndef __minix
+ rnswap = swapctl(SWAP_STATS, (void *)sep, nswap);
+#else /* __minix */
+ rnswap = 0;
+#endif /* __minix */
+ if (nswap != rnswap)
+ break;
+
+ totalsize = totalinuse = ncounted = 0;
+ for (; rnswap-- > 0; sep++) {
+ ncounted++;
+ size = sep->se_nblks;
+ inuse = sep->se_inuse;
+ totalsize += size;
+ totalinuse += inuse;
+ }
+ swap_stats[0] = dbtob(totalsize) / 1024;
+ swap_stats[1] = dbtob(totalinuse) / 1024;
+ swap_stats[2] = dbtob(totalsize) / 1024 - swap_stats[1];
+ } while (0);
+
+ memory_stats[6] = -1;
+ swap_stats[3] = -1;
+
+ /* set arrays and strings */
+ si->cpustates = cpu_states;
+ si->memory = memory_stats;
+ si->swap = swap_stats;
+ si->last_pid = -1;
+
+}
+
+static struct kinfo_proc2 *
+proc_from_thread(struct kinfo_lwp *pl)
+{
+ struct kinfo_proc2 *pp = thread_pbase;
+ int i;
+
+ for (i = 0; i < thread_nproc; i++, pp++)
+ if ((pid_t)pp->p_pid == (pid_t)pl->l_pid)
+ return pp;
+ return NULL;
+}
+
+static int
+uid_from_thread(struct kinfo_lwp *pl)
+{
+ struct kinfo_proc2 *pp;
+
+ if ((pp = proc_from_thread(pl)) == NULL)
+ return -1;
+ return pp->p_ruid;
+}
+
+caddr_t
+get_process_info(struct system_info *si, struct process_select *sel, int c)
+{
+ userprint = sel->usernames ? username : itoa7;
+
+ if ((threadmode = sel->threads) != 0)
+ return get_lwp_info(si, sel, proc_compares[c]);
+ else
+ return get_proc_info(si, sel, proc_compares[c]);
+}
+
+static caddr_t
+get_proc_info(struct system_info *si, struct process_select *sel,
+ int (*compare)(struct proc **, struct proc **))
+{
+ int i;
+ int total_procs;
+ int active_procs;
+ struct kinfo_proc2 **prefp, **n;
+ struct kinfo_proc2 *pp;
+ int op, arg;
+
+ /* these are copied out of sel for speed */
+ int show_idle;
+ int show_system;
+ int show_uid;
+
+ static struct handle handle;
+
+ procgen++;
+
+ if (sel->pid == (pid_t)-1) {
+ op = KERN_PROC_ALL;
+ arg = 0;
+ } else {
+ op = KERN_PROC_PID;
+ arg = sel->pid;
+ }
+
+ pbase = kvm_getproc2(kd, op, arg, sizeof(struct kinfo_proc2), &nproc);
+ if (pbase == NULL) {
+ if (sel->pid != (pid_t)-1) {
+ nproc = 0;
+ } else {
+ (void) fprintf(stderr, "top: Out of memory.\n");
+ quit(23);
+ }
+ }
+ if (nproc > onproc) {
+ n = (struct kinfo_proc2 **) realloc(pref,
+ sizeof(struct kinfo_proc2 *) * nproc);
+ if (n == NULL) {
+ (void) fprintf(stderr, "top: Out of memory.\n");
+ quit(23);
+ }
+ pref = n;
+ onproc = nproc;
+ }
+ /* 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;
+ 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 P_SYSTEM set are system
+ * processes---these get ignored unless show_sysprocs is set.
+ */
+ if (pp->p_stat != 0 && (show_system || ((pp->p_flag & P_SYSTEM) == 0))) {
+ total_procs++;
+ process_states[(unsigned char) pp->p_stat]++;
+ if (pp->p_stat != LSZOMB &&
+ (show_idle || (pp->p_pctcpu != 0) ||
+ (pp->p_stat == LSRUN || pp->p_stat == LSONPROC)) &&
+ (!show_uid || pp->p_ruid == (uid_t)sel->uid)) {
+ *prefp++ = pp;
+ active_procs++;
+ }
+ }
+ }
+
+ /* if requested, sort the "interesting" processes */
+ if (compare != NULL) {
+ qsort((char *)pref, active_procs, sizeof(struct kinfo_proc2 *),
+ (int (*)(const void *, const void *))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;
+ handle.sel = sel;
+ return((caddr_t)&handle);
+}
+
+static caddr_t
+get_lwp_info(struct system_info *si, struct process_select *sel,
+ int (*compare)(struct proc **, struct proc **))
+{
+ int i;
+ int total_lwps;
+ int active_lwps;
+ struct kinfo_lwp **lrefp, **n;
+ struct kinfo_lwp *lp;
+ struct kinfo_proc2 *pp;
+
+ /* these are copied out of sel for speed */
+ int show_idle;
+ int show_system;
+ int show_uid;
+
+ static struct handle handle;
+
+ pp = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2),
+ &thread_nproc);
+ if (pp == NULL) {
+ (void) fprintf(stderr, "top: Out of memory.\n");
+ quit(23);
+ }
+ if (thread_pbase == NULL || thread_nproc != thread_onproc) {
+ free(thread_pbase);
+ thread_onproc = thread_nproc;
+ thread_pbase = calloc(sizeof(struct kinfo_proc2), thread_nproc);
+ if (thread_pbase == NULL) {
+ (void) fprintf(stderr, "top: Out of memory.\n");
+ quit(23);
+ }
+ }
+ memcpy(thread_pbase, pp, sizeof(struct kinfo_proc2) * thread_nproc);
+
+ lbase = kvm_getlwps(kd, -1, 0, sizeof(struct kinfo_lwp), &nlwp);
+ if (lbase == NULL) {
+#ifdef notyet
+ if (sel->pid != (pid_t)-1) {
+ nproc = 0;
+ nlwp = 0;
+ }
+ else
+#endif
+ {
+ (void) fprintf(stderr, "top: Out of memory.\n");
+ quit(23);
+ }
+ }
+ if (nlwp > onlwp) {
+ n = (struct kinfo_lwp **) realloc(lref,
+ sizeof(struct kinfo_lwp *) * nlwp);
+ if (n == NULL) {
+ (void) fprintf(stderr, "top: Out of memory.\n");
+ quit(23);
+ }
+ lref = n;
+ onlwp = nlwp;
+ }
+ /* 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 thread states and get pointers to interesting threads */
+ total_lwps = 0;
+ active_lwps = 0;
+ memset((char *)process_states, 0, sizeof(process_states));
+ lrefp = lref;
+ for (lp = lbase, i = 0; i < nlwp; lp++, i++) {
+ if (sel->pid != (pid_t)-1 && sel->pid != (pid_t)lp->l_pid)
+ continue;
+
+ /*
+ * Place pointers to each valid lwp structure in lref[].
+ * thread slots that are actually in use have a non-zero
+ * status field. threads with L_SYSTEM set are system
+ * threads---these get ignored unless show_sysprocs is set.
+ */
+ if (lp->l_stat != 0 && (show_system || ((lp->l_flag & LW_SYSTEM) == 0))) {
+ total_lwps++;
+ process_states[(unsigned char) lp->l_stat]++;
+ if (lp->l_stat != LSZOMB &&
+ (show_idle || (lp->l_pctcpu != 0) ||
+ (lp->l_stat == LSRUN || lp->l_stat == LSONPROC)) &&
+ (!show_uid || uid_from_thread(lp) == sel->uid)) {
+ *lrefp++ = lp;
+ active_lwps++;
+ }
+ }
+ }
+
+ /* if requested, sort the "interesting" threads */
+ if (compare != NULL) {
+ qsort((char *)lref, active_lwps, sizeof(struct kinfo_lwp *),
+ (int (*)(const void *, const void *))compare);
+ }
+
+ /* remember active and total counts */
+ si->p_total = total_lwps;
+ si->p_active = lref_len = active_lwps;
+
+ /* pass back a handle */
+ handle.next_proc = (struct kinfo_proc2 **)lref;
+ handle.remaining = active_lwps;
+ handle.sel = sel;
+
+ return((caddr_t)&handle);
+}
+
+char *
+format_next_process(caddr_t handle, char *(*get_userid)(int))
+{
+
+ if (threadmode)
+ return format_next_lwp(handle, get_userid);
+ else
+ return format_next_proc(handle, get_userid);
+}
+
+
+char *
+format_next_proc(caddr_t handle, char *(*get_userid)(int))
+{
+ struct kinfo_proc2 *pp;
+ long cputime;
+ double pct, wcpu, cpu;
+ struct handle *hp;
+ const char *statep;
+#ifdef KI_NOCPU
+ char state[10];
+#endif
+ char wmesg[KI_WMESGLEN + 1];
+ static char fmt[MAX_COLS]; /* static area where result is built */
+
+ /* 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 0
+ /* This does not produce the correct results */
+ cputime = pp->p_uticks + pp->p_sticks + pp->p_iticks;
+#else
+ cputime = pp->p_rtime_sec; /* This does not count interrupts */
+#endif
+
+ /* calculate the base for CPU percentages */
+ pct = pctdouble(pp->p_pctcpu);
+
+ if (pp->p_stat == LSSLEEP) {
+ strlcpy(wmesg, pp->p_wmesg, sizeof(wmesg));
+ statep = wmesg;
+ } else
+ statep = state_abbrev[(unsigned)pp->p_stat];
+
+#ifdef KI_NOCPU
+ /* Post-1.5 change: add CPU number if appropriate */
+ if (pp->p_cpuid != KI_NOCPU && ncpu > 1) {
+ switch (pp->p_stat) {
+ case LSONPROC:
+ case LSRUN:
+ case LSSLEEP:
+ case LSIDL:
+ (void)snprintf(state, sizeof(state), "%.6s/%u",
+ statep, (unsigned int)pp->p_cpuid);
+ statep = state;
+ break;
+ }
+ }
+#endif
+ wcpu = 100.0 * weighted_cpu(p_, pct, pp);
+ cpu = 100.0 * pct;
+
+ /* format this entry */
+ sprintf(fmt,
+ Proc_format,
+ pp->p_pid,
+ (*userprint)(pp->p_ruid),
+ pp->p_priority,
+ pp->p_nice - NZERO,
+ format_k(pagetok(PROCSIZE(pp))),
+ format_k(pagetok(pp->p_vm_rssize)),
+ statep,
+ format_time(cputime),
+ (wcpu >= 100.0) ? 0 : 2, wcpu,
+ (cpu >= 100.0) ? 0 : 2, cpu,
+ get_command(hp->sel, pp));
+
+ /* return the result */
+ return(fmt);
+}
+
+static char *
+format_next_lwp(caddr_t handle, char *(*get_userid)(int))
+{
+ struct kinfo_proc2 *pp;
+ struct kinfo_lwp *pl;
+ long cputime;
+ double pct;
+ struct handle *hp;
+ const char *statep;
+#ifdef KI_NOCPU
+ char state[10];
+#endif
+ char wmesg[KI_WMESGLEN + 1];
+ static char fmt[MAX_COLS]; /* static area where result is built */
+ int uid;
+
+ /* find and remember the next proc structure */
+ hp = (struct handle *)handle;
+ pl = (struct kinfo_lwp *)*(hp->next_proc++);
+ hp->remaining--;
+ pp = proc_from_thread(pl);
+
+ /* get the process's user struct and set cputime */
+ uid = pp ? pp->p_ruid : 0;
+
+ cputime = pl->l_rtime_sec;
+
+ /* calculate the base for CPU percentages */
+ pct = pctdouble(pl->l_pctcpu);
+
+ if (pl->l_stat == LSSLEEP) {
+ strlcpy(wmesg, pl->l_wmesg, sizeof(wmesg));
+ statep = wmesg;
+ } else
+ statep = state_abbrev[(unsigned)pl->l_stat];
+
+#ifdef KI_NOCPU
+ /* Post-1.5 change: add CPU number if appropriate */
+ if (pl->l_cpuid != KI_NOCPU && ncpu > 1) {
+ switch (pl->l_stat) {
+ case LSONPROC:
+ case LSRUN:
+ case LSSLEEP:
+ case LSIDL:
+ (void)snprintf(state, sizeof(state), "%.6s/%u",
+ statep, (unsigned int)pl->l_cpuid);
+ statep = state;
+ break;
+ }
+ }
+#endif
+
+ if (pl->l_name[0] == '\0') {
+ pl->l_name[0] = '-';
+ pl->l_name[1] = '\0';
+ }
+
+ /* format this entry */
+ sprintf(fmt,
+ Thread_format,
+ pl->l_pid,
+ pl->l_lid,
+ (*userprint)(uid),
+ pl->l_priority,
+ statep,
+ format_time(cputime),
+ 100.0 * weighted_cpu(l_, pct, pl),
+ 100.0 * pct,
+ printable(pl->l_name),
+ get_command(hp->sel, pp));
+
+ /* return the result */
+ return(fmt);
+}
+
+/* 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(pfx) \
+ if (lresult = (pctcpu)(p2)->pfx ## pctcpu - (pctcpu)(p1)->pfx ## pctcpu,\
+ (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
+
+#define ORDERKEY_CPTICKS(pfx) \
+ if (lresult = (pctcpu)(p2)->pfx ## rtime_sec \
+ - (pctcpu)(p1)->pfx ## rtime_sec,\
+ (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
+
+#define ORDERKEY_STATE(pfx) \
+ if ((result = sorted_state[(int)(p2)->pfx ## stat] - \
+ sorted_state[(int)(p1)->pfx ## stat] ) == 0)
+
+#define ORDERKEY_PRIO(pfx) \
+ if ((result = (p2)->pfx ## priority - (p1)->pfx ## priority) == 0)
+
+#define ORDERKEY_RSSIZE \
+ if ((result = p2->p_vm_rssize - p1->p_vm_rssize) == 0)
+
+#define ORDERKEY_MEM \
+ if ((result = (PROCSIZE(p2) - PROCSIZE(p1))) == 0)
+#define ORDERKEY_SIZE(v1, v2) \
+ if ((result = (v2 - v1)) == 0)
+
+/*
+ * Now the array that maps process state to a weight.
+ * The order of the elements should match those in state_abbrev[]
+ */
+
+static int sorted_state[] = {
+ 0, /* (not used) ? */
+ 1, /* "start" SIDL */
+ 4, /* "run" SRUN */
+ 3, /* "sleep" SSLEEP */
+ 3, /* "stop" SSTOP */
+ 2, /* "dead" SDEAD */
+ 1, /* "zomb" SZOMB */
+ 5, /* "onproc" SONPROC */
+};
+
+/* compare_cpu - the comparison function for sorting by CPU percentage */
+
+static int
+compare_cpu(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ int result;
+ pctcpu lresult;
+
+ if (threadmode) {
+ struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
+
+ ORDERKEY_PCTCPU(l_)
+ ORDERKEY_CPTICKS(l_)
+ ORDERKEY_STATE(l_)
+ ORDERKEY_PRIO(l_)
+ return result;
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+
+ ORDERKEY_PCTCPU(p_)
+ ORDERKEY_CPTICKS(p_)
+ ORDERKEY_STATE(p_)
+ ORDERKEY_PRIO(p_)
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ return result;
+ }
+
+ return (result);
+}
+
+/* compare_prio - the comparison function for sorting by process priority */
+
+static int
+compare_prio(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ int result;
+ pctcpu lresult;
+
+ if (threadmode) {
+ struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
+
+ ORDERKEY_PRIO(l_)
+ ORDERKEY_PCTCPU(l_)
+ ORDERKEY_CPTICKS(l_)
+ ORDERKEY_STATE(l_)
+ return result;
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+
+ ORDERKEY_PRIO(p_)
+ ORDERKEY_PCTCPU(p_)
+ ORDERKEY_CPTICKS(p_)
+ ORDERKEY_STATE(p_)
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ return result;
+ }
+
+ return (result);
+}
+
+/* compare_res - the comparison function for sorting by resident set size */
+
+static int
+compare_res(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ int result;
+ pctcpu lresult;
+
+ if (threadmode) {
+ struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
+
+ ORDERKEY_PCTCPU(l_)
+ ORDERKEY_CPTICKS(l_)
+ ORDERKEY_STATE(l_)
+ ORDERKEY_PRIO(l_)
+ return result;
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PCTCPU(p_)
+ ORDERKEY_CPTICKS(p_)
+ ORDERKEY_STATE(p_)
+ ORDERKEY_PRIO(p_)
+ return result;
+ }
+
+ return (result);
+}
+
+static int
+compare_pid(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ if (threadmode) {
+ struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
+ struct kinfo_proc2 *p1 = proc_from_thread(l1);
+ struct kinfo_proc2 *p2 = proc_from_thread(l2);
+ return p2->p_pid - p1->p_pid;
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+ return p2->p_pid - p1->p_pid;
+ }
+}
+
+static int
+compare_command(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ if (threadmode) {
+ struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
+ struct kinfo_proc2 *p1 = proc_from_thread(l1);
+ struct kinfo_proc2 *p2 = proc_from_thread(l2);
+ return strcmp(p2->p_comm, p1->p_comm);
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+ return strcmp(p2->p_comm, p1->p_comm);
+ }
+}
+
+static int
+compare_username(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ if (threadmode) {
+ struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
+ struct kinfo_proc2 *p1 = proc_from_thread(l1);
+ struct kinfo_proc2 *p2 = proc_from_thread(l2);
+ return strcmp(p2->p_login, p1->p_login);
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+ return strcmp(p2->p_login, p1->p_login);
+ }
+}
+/* compare_size - the comparison function for sorting by total memory usage */
+
+static int
+compare_size(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ int result;
+ pctcpu lresult;
+
+ if (threadmode) {
+ struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
+
+ ORDERKEY_PCTCPU(l_)
+ ORDERKEY_CPTICKS(l_)
+ ORDERKEY_STATE(l_)
+ ORDERKEY_PRIO(l_)
+ return result;
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ORDERKEY_PCTCPU(p_)
+ ORDERKEY_CPTICKS(p_)
+ ORDERKEY_STATE(p_)
+ ORDERKEY_PRIO(p_)
+ return result;
+ }
+
+ return (result);
+}
+
+/* compare_state - the comparison function for sorting by process state */
+
+static int
+compare_state(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ int result;
+ pctcpu lresult;
+
+ if (threadmode) {
+ struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
+
+ ORDERKEY_STATE(l_)
+ ORDERKEY_PCTCPU(l_)
+ ORDERKEY_CPTICKS(l_)
+ ORDERKEY_PRIO(l_)
+ return result;
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+
+ ORDERKEY_STATE(p_)
+ ORDERKEY_PCTCPU(p_)
+ ORDERKEY_CPTICKS(p_)
+ ORDERKEY_PRIO(p_)
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ return result;
+ }
+
+ return (result);
+}
+
+/* compare_time - the comparison function for sorting by total CPU time */
+
+static int
+compare_time(pp1, pp2)
+ struct proc **pp1, **pp2;
+{
+ int result;
+ pctcpu lresult;
+
+ if (threadmode) {
+ struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
+ struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
+
+ ORDERKEY_CPTICKS(l_)
+ ORDERKEY_PCTCPU(l_)
+ ORDERKEY_STATE(l_)
+ ORDERKEY_PRIO(l_)
+ return result;
+ } else {
+ struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
+ struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
+
+ ORDERKEY_CPTICKS(p_)
+ ORDERKEY_PCTCPU(p_)
+ ORDERKEY_STATE(p_)
+ ORDERKEY_PRIO(p_)
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ return result;
+ }
+
+ 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;
+{
+ int cnt;
+ struct kinfo_proc2 **prefp;
+ struct kinfo_proc2 *pp;
+
+ if (threadmode)
+ return(-1);
+
+ prefp = pref;
+ cnt = pref_len;
+ while (--cnt >= 0) {
+ pp = *prefp++;
+ if (pp->p_pid == (pid_t)pid)
+ return(pp->p_ruid);
+ }
+ return(-1);
+}
+
+/*
+ * 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.
+ */
+
+static void
+percentages64(cnt, out, new, old, diffs)
+ int cnt;
+ int *out;
+ u_int64_t *new;
+ u_int64_t *old;
+ u_int64_t *diffs;
+{
+ int i;
+ u_int64_t change;
+ u_int64_t total_change;
+ u_int64_t *dp;
+ u_int64_t half_total;
+
+ /* initialization */
+ total_change = 0;
+ dp = diffs;
+
+ /* calculate changes for each state and the overall change */
+ for (i = 0; i < cnt; i++) {
+ /*
+ * Don't worry about wrapping - even at hz=1GHz, a
+ * u_int64_t will last at least 544 years.
+ */
+ change = *new - *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 / 2;
+ for (i = 0; i < cnt; i++)
+ *out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
+}
--- /dev/null
+.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.
--- /dev/null
+/*
+ * 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 *)(®),
+ sizeof(struct region), "region" );
+ return ®
+}
+
+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);
+}
+
--- /dev/null
+.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().
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+.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.
--- /dev/null
+/*
+ * top - a top users display for Unix
+ *
+ * SYNOPSIS: Any Sun running SunOS 5.x (Solaris 2.x)
+ *
+ * DESCRIPTION:
+ * This is the machine-dependent module for SunOS 5.x (Solaris 2).
+ * There is some support for MP architectures.
+ * This makes top work on all revisions of SunOS 5 from 5.0
+ * through 5.9 (otherwise known as Solaris 9). It has not been
+ * tested on SunOS 5.10.
+ *
+ * AUTHORS: Torsten Kasch <torsten@techfak.uni-bielefeld.de>
+ * Robert Boucher <boucher@sofkin.ca>
+ * CONTRIBUTORS: Marc Cohen <marc@aai.com>
+ * Charles Hedrick <hedrick@geneva.rutgers.edu>
+ * William L. Jones <jones@chpc>
+ * Petri Kutvonen <kutvonen@cs.helsinki.fi>
+ * Casper Dik <casper.dik@sun.com>
+ * Tim Pugh <tpugh@oce.orst.edu>
+ */
+
+#define _KMEMUSER
+
+#include "os.h"
+#include "utils.h"
+#include "username.h"
+#include "display.h"
+
+#if (OSREV == 551)
+#undef OSREV
+#define OSREV 55
+#endif
+
+/*
+ * Starting with SunOS 5.6 the data in /proc changed along with the
+ * means by which it is accessed. In this case we define USE_NEW_PROC.
+ * Note that with USE_NEW_PROC defined the structure named "prpsinfo"
+ * is redefined to be "psinfo". This will be confusing as you read
+ * the code.
+ */
+
+#if OSREV >= 56
+#define USE_NEW_PROC
+#endif
+
+#if defined(USE_NEW_PROC)
+#define _STRUCTURED_PROC 1
+#define prpsinfo psinfo
+#include <sys/procfs.h>
+#define pr_fill pr_nlwp
+/* the "px" macros are used where the actual member could be in a substructure */
+#define px_state pr_lwp.pr_state
+#define px_nice pr_lwp.pr_nice
+#define px_pri pr_lwp.pr_pri
+#define px_onpro pr_lwp.pr_onpro
+#define ZOMBIE(p) ((p)->pr_nlwp == 0)
+#define SIZE_K(p) (long)((p)->pr_size)
+#define RSS_K(p) (long)((p)->pr_rssize)
+#else
+#define px_state pr_state
+#define px_oldpri pr_oldpri
+#define px_nice pr_nice
+#define px_pri pr_pri
+#define px_onpro pr_filler[5]
+#define ZOMBIE(p) ((p)->pr_zomb)
+#define SIZE_K(p) (long)((p)->pr_bysize/1024)
+#define RSS_K(p) (long)((p)->pr_byrssize/1024)
+#endif
+
+#include "top.h"
+#include "machine.h"
+#include <limits.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>
+#include <kvm.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/sysinfo.h>
+#include <sys/sysmacros.h>
+#include <sys/syscall.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+#include <sys/vm.h>
+#include <sys/var.h>
+#include <sys/cpuvar.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/priocntl.h>
+#include <sys/tspriocntl.h>
+#include <sys/processor.h>
+#include <sys/resource.h>
+#include <sys/swap.h>
+#include <sys/stat.h>
+#include <vm/anon.h>
+#include <math.h>
+#include <utmpx.h>
+#include "utils.h"
+#include "hash.h"
+
+#if OSREV >= 53
+#define USE_KSTAT
+#endif
+#ifdef USE_KSTAT
+#include <kstat.h>
+/*
+ * Some kstats are fixed at 32 bits, these will be specified as ui32; some
+ * are "natural" size (32 bit on 32 bit Solaris, 64 on 64 bit Solaris
+ * we'll make those unsigned long)
+ * Older Solaris doesn't define KSTAT_DATA_UINT32, those are always 32 bit.
+ */
+# ifndef KSTAT_DATA_UINT32
+# define ui32 ul
+# endif
+#endif
+
+#define UNIX "/dev/ksyms"
+#define KMEM "/dev/kmem"
+#define PROCFS "/proc"
+#define CPUSTATES 5
+#ifndef PRIO_MIN
+#define PRIO_MIN -20
+#endif
+#ifndef PRIO_MAX
+#define PRIO_MAX 20
+#endif
+
+#ifndef FSCALE
+#define FSHIFT 8 /* bits to right of fixed binary point */
+#define FSCALE (1<<FSHIFT)
+#endif /* FSCALE */
+
+#define loaddouble(la) ((double)(la) / FSCALE)
+#define dbl_align(x) (((unsigned long)(x)+(sizeof(double)-1)) & \
+ ~(sizeof(double)-1))
+
+/*
+ * SunOS 5.4 and above track pctcpu in the proc structure as pr_pctcpu.
+ * These values are weighted over one minute whereas top output prefers
+ * a near-instantaneous measure of cpu utilization. So we choose to
+ * ignore pr_pctcpu: we calculate our own cpu percentage and store it in
+ * one of the spare slots in the prinfo structure.
+ */
+
+#define percent_cpu(pp) (*(double *)dbl_align(&pp->pr_filler[0]))
+
+/* definitions for indices in the nlist array */
+#define X_V 0
+#define X_MPID 1
+#define X_ANONINFO 2
+#define X_MAXMEM 3
+#define X_FREEMEM 4
+#define X_AVENRUN 5
+#define X_CPU 6
+#define X_NPROC 7
+#define X_NCPUS 8
+
+static struct nlist nlst[] =
+{
+ {"v"}, /* 0 */ /* replaced by dynamic allocation */
+ {"mpid"}, /* 1 */
+#if OSREV >= 56
+ /* this structure really has some extra fields, but the first three match */
+ {"k_anoninfo"}, /* 2 */
+#else
+ {"anoninfo"}, /* 2 */
+#endif
+ {"maxmem"}, /* 3 */ /* use sysconf */
+ {"freemem"}, /* 4 */ /* available from kstat >= 2.5 */
+ {"avenrun"}, /* 5 */ /* available from kstat */
+ {"cpu"}, /* 6 */ /* available from kstat */
+ {"nproc"}, /* 7 */ /* available from kstat */
+ {"ncpus"}, /* 8 */ /* available from kstat */
+ {0}
+};
+
+static unsigned long avenrun_offset;
+static unsigned long mpid_offset;
+#ifdef USE_KSTAT
+static kstat_ctl_t *kc = NULL;
+static kid_t kcid = 0;
+#else
+static unsigned long *cpu_offset;
+#endif
+static unsigned long nproc_offset;
+static unsigned long freemem_offset;
+static unsigned long maxmem_offset;
+static unsigned long anoninfo_offset;
+static int maxfiles = 256;
+#define MAXFILES 2048
+static int *display_fields;
+static int show_threads = 0;
+static int show_fullcmd;
+
+/* 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 */
+};
+
+/*
+ * Structure for keeping track processes between updates.
+ * We keep these things in a hash table, which is updated at every cycle.
+ */
+struct oldproc
+{
+ pid_t pid;
+ id_t lwpid;
+ double oldtime;
+ double oldpct;
+ uid_t owner_uid;
+ int fd_psinfo;
+ int fd_lpsinfo;
+ int seen;
+};
+
+#define TIMESPEC_TO_DOUBLE(ts) ((ts).tv_sec * 1.0e9 + (ts).tv_nsec)
+
+hash_table *prochash;
+hash_table *threadhash;
+
+/*
+ * Structure for tracking per-cpu information
+ */
+struct cpustats
+{
+ unsigned int states[CPUSTATES];
+ uint_t pswitch;
+ uint_t trap;
+ uint_t intr;
+ uint_t syscall;
+ uint_t sysfork;
+ uint_t sysvfork;
+ uint_t pfault;
+ uint_t pgin;
+ uint_t pgout;
+};
+
+/*
+ * GCC assumes that all doubles are aligned. Unfortunately it
+ * doesn't round up the structure size to be a multiple of 8.
+ * Thus we'll get a coredump when going through array. The
+ * following is a size rounded up to 8.
+ */
+#define PRPSINFOSIZE dbl_align(sizeof(struct prpsinfo))
+
+/* this defines one field (or column) in the process display */
+
+struct proc_field {
+ char *name;
+ int width;
+ int rjust;
+ int min_screenwidth;
+ int (*format)(char *, int, struct prpsinfo *);
+};
+
+#define PROCSTATES 8
+/* process state names for the "STATE" column of the display */
+char *state_abbrev[] =
+{"", "sleep", "run", "zombie", "stop", "start", "cpu", "swap"};
+
+int process_states[PROCSTATES];
+char *procstatenames[] =
+{
+ "", " sleeping, ", " running, ", " zombie, ", " stopped, ",
+ " starting, ", " on cpu, ", " swapped, ",
+ NULL
+};
+
+int cpu_states[CPUSTATES];
+char *cpustatenames[] =
+{"idle", "user", "kernel", "iowait", "swap", NULL};
+#define CPUSTATE_IOWAIT 3
+#define CPUSTATE_SWAP 4
+
+
+/* these are for detailing the memory statistics */
+long memory_stats[5];
+char *memorynames[] =
+{"K phys mem, ", "K free mem, ", "K total swap, ", "K free swap", NULL};
+#define MEMORY_TOTALMEM 0
+#define MEMORY_FREEMEM 1
+#define MEMORY_TOTALSWAP 2
+#define MEMORY_FREESWAP 3
+
+/* these are for detailing kernel statistics */
+int kernel_stats[8];
+char *kernelnames[] =
+{" ctxsw, ", " trap, ", " intr, ", " syscall, ", " fork, ",
+ " flt, ", " pgin, ", " pgout, ", NULL};
+#define KERNEL_CSWITCH 0
+#define KERNEL_TRAP 1
+#define KERNEL_INTR 2
+#define KERNEL_SYSCALL 3
+#define KERNEL_FORK 4
+#define KERNEL_PFAULT 5
+#define KERNEL_PGIN 6
+#define KERNEL_PGOUT 7
+
+/* these are names given to allowed sorting orders -- first is default */
+char *ordernames[] =
+{"cpu", "size", "res", "time", "pid", NULL};
+
+/* forward definitions for comparison functions */
+int compare_cpu();
+int compare_size();
+int compare_res();
+int compare_time();
+int compare_pid();
+
+int (*proc_compares[])() = {
+ compare_cpu,
+ compare_size,
+ compare_res,
+ compare_time,
+ compare_pid,
+ NULL };
+
+kvm_t *kd;
+static DIR *procdir;
+
+/* "cpucount" is used to store the value for the kernel variable "ncpus".
+ But since <sys/cpuvar.h> actually defines a variable "ncpus" we need
+ to use a different name here. --wnl */
+static int cpucount;
+
+/* pagetok function is really a pointer to an appropriate function */
+static int pageshift;
+static long (*p_pagetok) ();
+#define pagetok(size) ((*p_pagetok)(size))
+
+/* useful externals */
+extern char *myname;
+extern void perror ();
+extern int getptable ();
+extern void quit ();
+
+/* process formatting functions and data */
+
+int
+fmt_pid(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%6d", (int)pp->pr_pid);
+}
+
+int
+fmt_username(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%-8.8s", username(pp->pr_uid));
+}
+
+int
+fmt_uid(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%6d", (int)pp->pr_uid);
+}
+
+int
+fmt_nlwp(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%4d", pp->pr_fill < 999 ? pp->pr_fill: 999);
+}
+
+int
+fmt_pri(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%3d", pp->px_pri);
+}
+
+int
+fmt_nice(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%4d", pp->px_nice - NZERO);
+}
+
+int
+fmt_size(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%5s", format_k(SIZE_K(pp)));
+}
+
+int
+fmt_res(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%5s", format_k(RSS_K(pp)));
+}
+
+int
+fmt_state(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ if (pp->px_state == SONPROC && cpucount > 1)
+ {
+ /* large #s may overflow colums */
+ if (pp->px_onpro < 100)
+ {
+ return snprintf(buf, sz, "cpu/%-2d", pp->px_onpro);
+ }
+ return snprintf(buf, sz, "cpu/**");
+ }
+
+ return snprintf(buf, sz, "%-6s", state_abbrev[(int)pp->px_state]);
+}
+
+int
+fmt_time(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%6s", format_time(pp->pr_time.tv_sec));
+}
+
+int
+fmt_cpu(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%5s%%",
+ format_percent(percent_cpu(pp) / cpucount));
+}
+
+int
+fmt_command(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%s",
+ printable(show_fullcmd ? pp->pr_psargs : pp->pr_fname));
+}
+
+int
+fmt_lwp(char *buf, int sz, struct prpsinfo *pp)
+
+{
+ return snprintf(buf, sz, "%4d", ((int)pp->pr_lwp.pr_lwpid < 10000 ?
+ (int)pp->pr_lwp.pr_lwpid : 9999));
+}
+
+struct proc_field proc_field[] = {
+ { "PID", 6, 1, 0, fmt_pid },
+ { "USERNAME", 8, 0, 0, fmt_username },
+#define FIELD_USERNAME 1
+ { "UID", 6, 1, 0, fmt_uid },
+#define FIELD_UID 2
+ { "NLWP", 4, 1, 0, fmt_nlwp },
+ { "PRI", 3, 1, 0, fmt_pri },
+ { "NICE", 4, 1, 0, fmt_nice },
+ { "SIZE", 5, 1, 0, fmt_size },
+ { "RES", 5, 1, 0, fmt_res },
+ { "STATE", 6, 0, 0, fmt_state },
+ { "TIME", 6, 1, 0, fmt_time },
+ { "CPU", 6, 1, 0, fmt_cpu },
+ { "COMMAND", 7, 0, 0, fmt_command },
+ { "LWP", 4, 1, 0, fmt_lwp },
+};
+#define MAX_FIELDS 13
+
+static int proc_display[MAX_FIELDS];
+static int thr_display[MAX_FIELDS];
+
+int
+field_index(char *col)
+
+{
+ struct proc_field *fp;
+ int i = 0;
+
+ fp = proc_field;
+ while (fp->name != NULL)
+ {
+ if (strcmp(col, fp->name) == 0)
+ {
+ return i;
+ }
+ fp++;
+ i++;
+ }
+
+ return -1;
+}
+
+void
+field_subst(int *fp, int old, int new)
+
+{
+ while (*fp != -1)
+ {
+ if (*fp == old)
+ {
+ *fp = new;
+ }
+ fp++;
+ }
+}
+
+/* p_pagetok points to one of the following, depending on which
+ direction data has to be shifted: */
+
+long pagetok_none(long size)
+
+{
+ return(size);
+}
+
+long pagetok_left(long size)
+
+{
+ return(size << pageshift);
+}
+
+long pagetok_right(long size)
+
+{
+ return(size >> pageshift);
+}
+
+/*
+ * 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)
+{
+ dprintf("getkval(%08x, %08x, %d, %s)\n", offset, ptr, size, refstr);
+
+ if (kvm_read (kd, offset, (char *) ptr, size) != size)
+ {
+ dprintf("getkval: read failed\n");
+ if (*refstr == '!')
+ {
+ return (0);
+ }
+ else
+ {
+ fprintf (stderr, "top: kvm_read for %s: %s\n", refstr, strerror(errno));
+ quit (23);
+ }
+ }
+
+ dprintf("getkval read %d (%08x)\n", *ptr);
+
+ return (1);
+
+}
+
+/* procs structure memory management */
+
+static struct prpsinfo **allprocs = NULL;
+static struct prpsinfo **nextproc = NULL;
+static int maxprocs = 0;
+static int idxprocs = 0;
+
+/*
+ * void procs_prealloc(int cnt)
+ *
+ * Preallocate "cnt" procs structures. If "cnt" is less than or equal
+ * to procs_max() then this function has no effect.
+ */
+
+void
+procs_prealloc(int max)
+
+{
+ int cnt;
+ struct prpsinfo *new;
+ struct prpsinfo **pp;
+
+ cnt = max - maxprocs;
+ if (cnt > 0)
+ {
+ dprintf("procs_prealloc: need %d, deficit %d\n", max, cnt);
+ allprocs = (struct prpsinfo **)
+ realloc((void *)allprocs, max * sizeof(struct prpsinfo *));
+ pp = nextproc = allprocs + idxprocs;
+ new = (struct prpsinfo *)malloc(cnt * PRPSINFOSIZE);
+ dprintf("procs_prealloc: idxprocs %d, allprocs %08x, nextproc %08x, new %08x\n",
+ idxprocs, allprocs, nextproc, new);
+ while (--cnt >= 0)
+ {
+ *pp++ = new;
+ new = (struct prpsinfo *) ((char *)new + PRPSINFOSIZE);
+ }
+ dprintf("procs_prealloc: done filling at %08x\n", new);
+ maxprocs = max;
+ }
+}
+
+/*
+ * struct prpsinfo *procs_next()
+ *
+ * Return the next available procs structure, allocating a new one
+ * if needed.
+ */
+
+struct prpsinfo *
+procs_next()
+
+{
+ if (idxprocs >= maxprocs)
+ {
+ /* allocate some more */
+ procs_prealloc(maxprocs + 128);
+ }
+ idxprocs++;
+ return *nextproc++;
+}
+
+struct prpsinfo *
+procs_dup(struct prpsinfo *p)
+
+{
+ struct prpsinfo *n;
+
+ n = procs_next();
+ memcpy(n, p, PRPSINFOSIZE);
+ return n;
+}
+
+/*
+ * struct prpsinfo *procs_start()
+ *
+ * Return the first procs structure.
+ */
+
+struct prpsinfo *
+procs_start()
+
+{
+ idxprocs = 0;
+ nextproc = allprocs;
+ return procs_next();
+}
+
+/*
+ * int procs_max()
+ *
+ * Return the maximum number of procs structures currently allocated.
+ */
+
+int
+procs_max()
+
+{
+ return maxprocs;
+}
+
+/*
+ * 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;
+
+ /* 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);
+}
+
+
+char *
+format_header (register char *uname_field)
+{
+ return ("");
+}
+
+#ifdef USE_KSTAT
+
+long
+kstat_data_value_l(kstat_named_t *kn)
+
+{
+#ifdef KSTAT_DATA_UINT32
+ switch(kn->data_type)
+ {
+ case KSTAT_DATA_INT32:
+ return ((long)(kn->value.i32));
+ case KSTAT_DATA_UINT32:
+ return ((long)(kn->value.ui32));
+ case KSTAT_DATA_INT64:
+ return ((long)(kn->value.i64));
+ case KSTAT_DATA_UINT64:
+ return ((long)(kn->value.ui64));
+ }
+ return 0;
+#else
+ return ((long)(kn->value.ui32));
+#endif
+}
+
+int
+kstat_safe_retrieve(kstat_t **ksp,
+ char *module, int instance, char *name, void *buf)
+
+{
+ kstat_t *ks;
+ kid_t new_kcid;
+ int changed;
+
+ dprintf("kstat_safe_retrieve(%08x -> %08x, %s, %d, %s, %08x)\n",
+ ksp, *ksp, module, instance, name, buf);
+
+ ks = *ksp;
+ do {
+ changed = 0;
+ /* if we dont already have the kstat, retrieve it */
+ if (ks == NULL)
+ {
+ if ((ks = kstat_lookup(kc, module, instance, name)) == NULL)
+ {
+ return (-1);
+ }
+ *ksp = ks;
+ }
+
+ /* attempt to read it */
+ new_kcid = kstat_read(kc, ks, buf);
+ /* chance for an infinite loop here if kstat_read keeps
+ returning -1 */
+
+ /* if the chain changed, update it */
+ if (new_kcid != kcid)
+ {
+ dprintf("kstat_safe_retrieve: chain changed to %d...updating\n",
+ new_kcid);
+ changed = 1;
+ kcid = kstat_chain_update(kc);
+ }
+ } while (changed);
+
+ return (0);
+}
+
+/*
+ * int kstat_safe_namematch(int num, kstat_t *ksp, char *name, void *buf)
+ *
+ * Safe scan of kstat chain for names starting with "name". Matches
+ * are copied in to "ksp", and kstat_read is called on each match using
+ * "buf" as a buffer of length "size". The actual number of records
+ * found is returned. Up to "num" kstats are copied in to "ksp", but
+ * no more. If any kstat_read indicates that the chain has changed, then
+ * the whole process is restarted.
+ */
+
+int
+kstat_safe_namematch(int num, kstat_t **ksparg, char *name, void *buf, int size)
+
+{
+ kstat_t *ks;
+ kstat_t **ksp;
+ kid_t new_kcid;
+ int namelen;
+ int count;
+ int changed;
+ char *cbuf;
+
+ dprintf("kstat_safe_namematch(%d, %08x, %s, %08x, %d)\n",
+ num, ksparg, name, buf, size);
+
+ namelen = strlen(name);
+
+ do {
+ /* initialize before the scan */
+ cbuf = (char *)buf;
+ ksp = ksparg;
+ count = 0;
+ changed = 0;
+
+ /* scan the chain for matching kstats */
+ for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next)
+ {
+ if (strncmp(ks->ks_name, name, namelen) == 0)
+ {
+ /* this kstat matches: save it if there is room */
+ if (count++ < num)
+ {
+ /* read the kstat */
+ new_kcid = kstat_read(kc, ks, cbuf);
+
+ /* if the chain changed, update it */
+ if (new_kcid != kcid)
+ {
+ dprintf("kstat_safe_namematch: chain changed to %d...updating\n",
+ new_kcid);
+ changed = 1;
+ kcid = kstat_chain_update(kc);
+
+ /* there's no sense in continuing the scan */
+ /* so break out of the for loop */
+ break;
+ }
+
+ /* move to the next buffers */
+ cbuf += size;
+ *ksp++ = ks;
+ }
+ }
+ }
+ } while(changed);
+
+ dprintf("kstat_safe_namematch returns %d\n", count);
+
+ return count;
+}
+
+static kstat_t *ks_system_misc = NULL;
+
+#endif /* USE_KSTAT */
+
+
+int
+get_avenrun(int avenrun[3])
+
+{
+#ifdef USE_KSTAT
+ int status;
+ kstat_named_t *kn;
+
+ dprintf("get_avenrun(%08x)\n", avenrun);
+
+ if ((status = kstat_safe_retrieve(&ks_system_misc,
+ "unix", 0, "system_misc", NULL)) == 0)
+ {
+ if ((kn = kstat_data_lookup(ks_system_misc, "avenrun_1min")) != NULL)
+ {
+ avenrun[0] = kn->value.ui32;
+ }
+ if ((kn = kstat_data_lookup(ks_system_misc, "avenrun_5min")) != NULL)
+ {
+ avenrun[1] = kn->value.ui32;
+ }
+ if ((kn = kstat_data_lookup(ks_system_misc, "avenrun_15min")) != NULL)
+ {
+ avenrun[2] = kn->value.ui32;
+ }
+ }
+ dprintf("get_avenrun returns %d\n", status);
+ return (status);
+
+#else /* !USE_KSTAT */
+
+ (void) getkval (avenrun_offset, (int *) avenrun, sizeof (int [3]), "avenrun");
+
+ return 0;
+
+#endif /* USE_KSTAT */
+}
+
+int
+get_ncpus()
+
+{
+#ifdef USE_KSTAT
+ kstat_named_t *kn;
+ int ret = -1;
+
+ if ((kn = kstat_data_lookup(ks_system_misc, "ncpus")) != NULL)
+ {
+ ret = (int)(kn->value.ui32);
+ }
+
+ return ret;
+#else
+ int ret;
+
+ (void) getkval(nlst[X_NCPUS].n_value, (int *)(&ret), sizeof(ret), "ncpus");
+ return ret;
+#endif
+}
+
+int
+get_nproc()
+
+{
+#ifdef USE_KSTAT
+ kstat_named_t *kn;
+ int ret = -1;
+
+ if ((kn = kstat_data_lookup(ks_system_misc, "nproc")) != NULL)
+ {
+ ret = (int)(kn->value.ui32);
+ }
+#else
+ int ret;
+
+ (void) getkval (nproc_offset, (int *) (&ret), sizeof (ret), "nproc");
+#endif
+
+ dprintf("get_nproc returns %d\n", ret);
+ return ret;
+}
+
+struct cpustats *
+get_cpustats(int *cnt, struct cpustats *cpustats)
+
+{
+#ifdef USE_KSTAT
+ static kstat_t **cpu_ks = NULL;
+ static cpu_stat_t *cpu_stat = NULL;
+ static unsigned int nelems = 0;
+ cpu_stat_t *cpu_stat_p;
+ int i, cpu_num;
+ struct cpustats *cpustats_p;
+
+ dprintf("get_cpustats(%d -> %d, %08x)\n", cnt, *cnt, cpustats);
+
+ while (nelems > 0 ?
+ (cpu_num = kstat_safe_namematch(nelems,
+ cpu_ks,
+ "cpu_stat",
+ cpu_stat,
+ sizeof(cpu_stat_t))) > nelems :
+ (cpu_num = get_ncpus()) > 0)
+ {
+ /* reallocate the arrays */
+ dprintf("realloc from %d to %d\n", nelems, cpu_num);
+ nelems = cpu_num;
+ if (cpu_ks != NULL)
+ {
+ free(cpu_ks);
+ }
+ cpu_ks = (kstat_t **)calloc(nelems, sizeof(kstat_t *));
+ if (cpu_stat != NULL)
+ {
+ free(cpu_stat);
+ }
+ cpu_stat = (cpu_stat_t *)malloc(nelems * sizeof(cpu_stat_t));
+ }
+
+ /* do we have more cpus than our caller? */
+ if (cpu_num > *cnt)
+ {
+ /* yes, so realloc their array, too */
+ dprintf("realloc array from %d to %d\n", *cnt, cpu_num);
+ *cnt = cpu_num;
+ cpustats = (struct cpustats *)realloc(cpustats,
+ cpu_num * sizeof(struct cpustats));
+ }
+
+ cpu_stat_p = cpu_stat;
+ cpustats_p = cpustats;
+ for (i = 0; i < cpu_num; i++)
+ {
+ dprintf("cpu %d %08x: idle %u, user %u, syscall %u\n", i, cpu_stat_p,
+ cpu_stat_p->cpu_sysinfo.cpu[0],
+ cpu_stat_p->cpu_sysinfo.cpu[1],
+ cpu_stat_p->cpu_sysinfo.syscall);
+
+ cpustats_p->states[CPU_IDLE] = cpu_stat_p->cpu_sysinfo.cpu[CPU_IDLE];
+ cpustats_p->states[CPU_USER] = cpu_stat_p->cpu_sysinfo.cpu[CPU_USER];
+ cpustats_p->states[CPU_KERNEL] = cpu_stat_p->cpu_sysinfo.cpu[CPU_KERNEL];
+ cpustats_p->states[CPUSTATE_IOWAIT] = cpu_stat_p->cpu_sysinfo.wait[W_IO] +
+ cpu_stat_p->cpu_sysinfo.wait[W_PIO];
+ cpustats_p->states[CPUSTATE_SWAP] = cpu_stat_p->cpu_sysinfo.wait[W_SWAP];
+ cpustats_p->pswitch = cpu_stat_p->cpu_sysinfo.pswitch;
+ cpustats_p->trap = cpu_stat_p->cpu_sysinfo.trap;
+ cpustats_p->intr = cpu_stat_p->cpu_sysinfo.intr;
+ cpustats_p->syscall = cpu_stat_p->cpu_sysinfo.syscall;
+ cpustats_p->sysfork = cpu_stat_p->cpu_sysinfo.sysfork;
+ cpustats_p->sysvfork = cpu_stat_p->cpu_sysinfo.sysvfork;
+ cpustats_p->pfault = cpu_stat_p->cpu_vminfo.hat_fault +
+ cpu_stat_p->cpu_vminfo.as_fault;
+ cpustats_p->pgin = cpu_stat_p->cpu_vminfo.pgin;
+ cpustats_p->pgout = cpu_stat_p->cpu_vminfo.pgout;
+ cpustats_p++;
+ cpu_stat_p++;
+ }
+
+ cpucount = cpu_num;
+
+ dprintf("get_cpustats sees %d cpus and returns %08x\n", cpucount, cpustats);
+
+ return (cpustats);
+#else /* !USE_KSTAT */
+ int i;
+ struct cpu cpu;
+ unsigned int (*cp_stats_p)[CPUSTATES];
+
+ /* do we have more cpus than our caller? */
+ if (cpucount > *cnt)
+ {
+ /* yes, so realloc their array, too */
+ dprintf("realloc array from %d to %d\n", *cnt, cpucount);
+ *cnt = cpucount;
+ cp_stats = (unsigned int (*)[CPUSTATES])realloc(cp_stats,
+ cpucount * sizeof(unsigned int) * CPUSTATES);
+ }
+
+ cp_stats_p = cp_stats;
+ for (i = 0; i < cpucount; i++)
+ {
+ if (cpu_offset[i] != 0)
+ {
+ /* get struct cpu for this processor */
+ (void) getkval (cpu_offset[i], (int *)(&cpu), sizeof (struct cpu), "cpu");
+
+ (*cp_stats_p)[CPU_IDLE] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_IDLE];
+ (*cp_stats_p)[CPU_USER] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_USER];
+ (*cp_stats_p)[CPU_KERNEL] = cpu.cpu_stat.cpu_sysinfo.cpu[CPU_KERNEL];
+ (*cp_stats_p)[CPUSTATE_IOWAIT] = cpu.cpu_stat.cpu_sysinfo.wait[W_IO] +
+ cpu.cpu_stat.cpu_sysinfo.wait[W_PIO];
+ (*cp_stats_p)[CPUSTATE_SWAP] = cpu.cpu_stat.cpu_sysinfo.wait[W_SWAP];
+ cp_stats_p++;
+ }
+ }
+
+ return (cp_stats);
+#endif /* USE_KSTAT */
+}
+
+/*
+ * void get_meminfo(long *total, long *fr)
+ *
+ * Get information about the system's physical memory. Pass back values
+ * for total available and amount of memory that is free (in kilobytes).
+ * It returns 0 on success and -1 on any kind of failure.
+ */
+
+int
+get_meminfo(long *total, long *fr)
+
+{
+ long freemem;
+ static kstat_t *ks = NULL;
+ kstat_named_t *kn;
+
+ /* total comes from sysconf */
+ *total = pagetok(sysconf(_SC_PHYS_PAGES));
+
+ /* free comes from the kernel's freemem or from kstat */
+ /* prefer kmem for this because kstat unix:0:system_pages
+ can be slow on systems with lots of memory */
+ if (kd)
+ {
+ (void) getkval(freemem_offset, (int *)(&freemem), sizeof(freemem),
+ "freemem");
+ }
+ else
+ {
+#ifdef USE_KSTAT
+ /* only need to grab kstat chain once */
+ if (ks == NULL)
+ {
+ ks = kstat_lookup(kc, "unix", 0, "system_pages");
+ }
+
+ if (ks != NULL &&
+ kstat_read(kc, ks, 0) != -1 &&
+ (kn = kstat_data_lookup(ks, "freemem")) != NULL)
+ {
+ freemem = kstat_data_value_l(kn);
+ }
+ else
+ {
+ freemem = -1;
+ }
+#else
+ freemem = -1;
+#endif
+ }
+
+ *fr = freemem == -1 ? -1 : pagetok(freemem);
+
+ return (0);
+}
+
+/*
+ * void get_swapinfo(long *total, long *fr)
+ *
+ * Get information about the system's swap. Pass back values for
+ * total swap available and amount of swap that is free (in kilobytes).
+ * It returns 0 on success and -1 on any kind of failure.
+ */
+
+int
+get_swapinfo(long *total, long *fr)
+
+{
+ register int cnt, i;
+ register long t, f;
+ struct swaptable *swt;
+ struct swapent *ste;
+ static char path[256];
+
+ /* preset values to 0 just in case we have to return early */
+ *total = 0;
+ *fr = 0;
+
+ /* get total number of swap entries */
+ if ((cnt = swapctl(SC_GETNSWP, 0)) == -1)
+ {
+ return (-1);
+ }
+
+ /* allocate enough space to hold count + n swapents */
+ swt = (struct swaptable *)malloc(sizeof(int) +
+ cnt * sizeof(struct swapent));
+ if (swt == NULL)
+ {
+ return (-1);
+ }
+ swt->swt_n = cnt;
+
+ /* fill in ste_path pointers: we don't care about the paths, so we point
+ them all to the same buffer */
+ ste = &(swt->swt_ent[0]);
+ i = cnt;
+ while (--i >= 0)
+ {
+ ste++->ste_path = path;
+ }
+
+ /* grab all swap info */
+ if (swapctl(SC_LIST, swt) == -1)
+ {
+ return (-1);
+ }
+
+ /* walk thru the structs and sum up the fields */
+ t = f = 0;
+ ste = &(swt->swt_ent[0]);
+ i = cnt;
+ while (--i >= 0)
+ {
+ /* dont count slots being deleted */
+ if (!(ste->ste_flags & ST_INDEL) &&
+ !(ste->ste_flags & ST_DOINGDEL))
+ {
+ t += ste->ste_pages;
+ f += ste->ste_free;
+ }
+ ste++;
+ }
+
+ /* fill in the results */
+ *total = pagetok(t);
+ *fr = pagetok(f);
+ free(swt);
+
+ /* good to go */
+ return (0);
+}
+
+int
+machine_init (struct statics *statics)
+{
+ struct utmpx ut;
+ struct utmpx *up;
+ struct rlimit rlim;
+ int i;
+ char *p;
+ int *ip;
+ int nproc;
+#ifndef USE_KSTAT
+ int offset;
+#endif
+
+ /* There's a buffer overflow bug in curses that can be exploited when
+ we run as root. By making sure that TERMINFO is set to something
+ this bug is avoided. This code thanks to Casper */
+ if ((p = getenv("TERMINFO")) == NULL || *p == '\0')
+ {
+ putenv("TERMINFO=/usr/share/lib/terminfo/");
+ }
+
+ /* perform the kvm_open - suppress error here */
+ if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
+ {
+ /* save the error message: we may need it later */
+ p = strerror(errno);
+ }
+ dprintf("kvm_open: fd %d\n", kd);
+
+ /*
+ * turn off super group/user privs - but beware; we might
+ * want the privs back later and we still have a fd to
+ * /dev/kmem open so we can't use setgid()/setuid() as that
+ * would allow a debugger to attach to this process. CD
+ */
+ setegid(getgid());
+ seteuid(getuid()); /* super user not needed for NEW_PROC */
+
+#ifdef USE_KSTAT
+ /* open kstat */
+ if ((kc = kstat_open()) == NULL)
+ {
+ fprintf(stderr, "Unable to open kstat.\n");
+ return(-1);
+ }
+ kcid = kc->kc_chain_id;
+ dprintf("kstat_open: chain %d\n", kcid);
+#endif
+
+ /* fill in the statics information */
+ statics->procstate_names = procstatenames;
+ statics->cpustate_names = cpustatenames;
+ statics->memory_names = memorynames;
+ statics->kernel_names = kernelnames;
+ statics->order_names = ordernames;
+ statics->flags.fullcmds = 1;
+ statics->flags.warmup = 1;
+ statics->flags.threads = 1;
+
+ /* get boot time */
+ ut.ut_type = BOOT_TIME;
+ if ((up = getutxid(&ut)) != NULL)
+ {
+ statics->boottime = up->ut_tv.tv_sec;
+ }
+ endutxent();
+
+ /* if the kvm_open succeeded, get the nlist */
+ if (kd)
+ {
+ if (kvm_nlist (kd, nlst) < 0)
+ {
+ perror ("kvm_nlist");
+ return (-1);
+ }
+ if (check_nlist (nlst) != 0)
+ return (-1);
+ }
+#ifndef USE_KSTAT
+ /* if KSTAT is not available to us and we can't open /dev/kmem,
+ this is a serious problem.
+ */
+ else
+ {
+ /* Print the error message here */
+ (void) fprintf(stderr, "kvm_open: %s\n", p);
+ return (-1);
+ }
+#endif
+
+ /* 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;
+ freemem_offset = nlst[X_FREEMEM].n_value;
+ maxmem_offset = nlst[X_MAXMEM].n_value;
+
+#ifndef USE_KSTAT
+ (void) getkval (nlst[X_NCPUS].n_value, (int *) (&cpucount),
+ sizeof (cpucount), "ncpus");
+
+ cpu_offset = (unsigned long *) malloc (cpucount * sizeof (unsigned long));
+ for (i = offset = 0; i < cpucount; offset += sizeof(unsigned long)) {
+ (void) getkval (nlst[X_CPU].n_value + offset,
+ (int *)(&cpu_offset[i]), sizeof (unsigned long),
+ nlst[X_CPU].n_name );
+ if (cpu_offset[i] != 0)
+ i++;
+ }
+#endif
+
+ /* we need to get the current nproc */
+#ifdef USE_KSTAT
+ /* get_nproc assumes that the chain has already been retrieved,
+ so we need to do that here */
+ kstat_safe_retrieve(&ks_system_misc, "unix", 0, "system_misc", NULL);
+#endif
+ nproc = get_nproc();
+ dprintf("machine_init: nproc=%d\n", nproc);
+
+ /* hash table for procs and threads sized based on current nproc*/
+ prochash = hash_create(nproc > 100 ? nproc * 2 + 1 : 521);
+ threadhash = hash_create(nproc > 100 ? nproc * 4 + 1 : 2053);
+
+ /* calculate pageshift value */
+ i = sysconf(_SC_PAGESIZE);
+ pageshift = 0;
+ while ((i >>= 1) > 0)
+ {
+ pageshift++;
+ }
+
+ /* calculate an amount to shift to K values */
+ /* remember that log base 2 of 1024 is 10 (i.e.: 2^10 = 1024) */
+ pageshift -= 10;
+
+ /* now determine which pageshift function is appropriate for the
+ result (have to because x << y is undefined for y < 0) */
+ if (pageshift > 0)
+ {
+ /* this is the most likely */
+ p_pagetok = pagetok_left;
+ }
+ else if (pageshift == 0)
+ {
+ p_pagetok = pagetok_none;
+ }
+ else
+ {
+ p_pagetok = pagetok_right;
+ pageshift = -pageshift;
+ }
+
+ /* we cache open files to improve performance, so we need to up
+ the NOFILE limit */
+ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
+ {
+ /* set a new soft limit */
+ maxfiles = (int)(rlim.rlim_max < MAXFILES ? rlim.rlim_max : MAXFILES);
+ rlim.rlim_cur = (rlim_t)maxfiles;
+ (void)setrlimit(RLIMIT_NOFILE, &rlim);
+
+ /* now leave some wiggle room above the maximum */
+ maxfiles -= 20;
+ }
+
+ /* set up the display indices */
+ ip = proc_display;
+ *ip++ = field_index("PID");
+ *ip++ = field_index("USERNAME");
+ *ip++ = field_index("NLWP");
+ *ip++ = field_index("PRI");
+ *ip++ = field_index("NICE");
+ *ip++ = field_index("SIZE");
+ *ip++ = field_index("RES");
+ *ip++ = field_index("STATE");
+ *ip++ = field_index("TIME");
+ *ip++ = field_index("CPU");
+ *ip++ = field_index("COMMAND");
+ *ip = -1;
+ ip = thr_display;
+ *ip++ = field_index("PID");
+ *ip++ = field_index("LWP");
+ *ip++ = field_index("USERNAME");
+ *ip++ = field_index("PRI");
+ *ip++ = field_index("NICE");
+ *ip++ = field_index("SIZE");
+ *ip++ = field_index("RES");
+ *ip++ = field_index("STATE");
+ *ip++ = field_index("TIME");
+ *ip++ = field_index("CPU");
+ *ip++ = field_index("COMMAND");
+ *ip = -1;
+
+ if (!(procdir = 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);
+}
+
+void
+get_system_info (struct system_info *si)
+{
+ int avenrun[3];
+
+ static long cp_time[CPUSTATES];
+ static long cp_old[CPUSTATES];
+ static long cp_diff[CPUSTATES];
+ static struct cpustats *cpustats = NULL;
+ static struct cpustats sum_current;
+ static struct cpustats sum_old;
+ static int cpus = 0;
+ register int j, i;
+
+ /* remember the old values and zero out the current */
+ memcpy(&sum_old, &sum_current, sizeof(sum_current));
+ memset(&sum_current, 0, sizeof(sum_current));
+
+ /* get important information */
+ get_avenrun(avenrun);
+
+ /* get the cpu statistics arrays */
+ cpustats = get_cpustats(&cpus, cpustats);
+
+ /* zero the cp_time array */
+ memset(cp_time, 0, sizeof(cp_time));
+
+ /* sum stats in to a single array and a single structure */
+ for (i = 0; i < cpus; i++)
+ {
+ for (j = 0; j < CPUSTATES; j++)
+ {
+ cp_time[j] += cpustats[i].states[j];
+ }
+ sum_current.pswitch += cpustats[i].pswitch;
+ sum_current.trap += cpustats[i].trap;
+ sum_current.intr += cpustats[i].intr;
+ sum_current.syscall += cpustats[i].syscall;
+ sum_current.sysfork += cpustats[i].sysfork;
+ sum_current.sysvfork += cpustats[i].sysvfork;
+ sum_current.pfault += cpustats[i].pfault;
+ sum_current.pgin += cpustats[i].pgin;
+ sum_current.pgout += cpustats[i].pgout;
+ }
+
+ /* convert cp_time counts to percentages */
+ (void) percentages (CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
+
+ /* get mpid -- process id of last process */
+ if (kd)
+ (void) getkval(mpid_offset, &(si->last_pid), sizeof (si->last_pid), "mpid");
+ else
+ si->last_pid = -1;
+
+ /* convert load averages to doubles */
+ for (i = 0; i < 3; i++)
+ si->load_avg[i] = loaddouble (avenrun[i]);
+
+ /* get physical memory data */
+ if (get_meminfo(&(memory_stats[MEMORY_TOTALMEM]),
+ &(memory_stats[MEMORY_FREEMEM])) == -1)
+ {
+ memory_stats[MEMORY_TOTALMEM] = memory_stats[MEMORY_FREEMEM] = -1;
+ }
+
+ /* get swap data */
+ if (get_swapinfo(&(memory_stats[MEMORY_TOTALSWAP]),
+ &(memory_stats[MEMORY_FREESWAP])) == -1)
+ {
+ memory_stats[MEMORY_TOTALSWAP] = memory_stats[MEMORY_FREESWAP] = -1;
+ }
+
+ /* get kernel data */
+ kernel_stats[KERNEL_CSWITCH] = diff_per_second(sum_current.pswitch, sum_old.pswitch);
+ kernel_stats[KERNEL_TRAP] = diff_per_second(sum_current.trap, sum_old.trap);
+ kernel_stats[KERNEL_INTR] = diff_per_second(sum_current.intr, sum_old.intr);
+ kernel_stats[KERNEL_SYSCALL] = diff_per_second(sum_current.syscall, sum_old.syscall);
+ kernel_stats[KERNEL_FORK] = diff_per_second(sum_current.sysfork + sum_current.sysvfork,
+ sum_old.sysfork + sum_old.sysvfork);
+ kernel_stats[KERNEL_PFAULT] = diff_per_second(sum_current.pfault, sum_old.pfault);
+ kernel_stats[KERNEL_PGIN] = pagetok(diff_per_second(sum_current.pgin, sum_old.pgin));
+ kernel_stats[KERNEL_PGOUT] = pagetok(diff_per_second(sum_current.pgout, sum_old.pgout));
+
+
+ /* set arrays and strings */
+ si->cpustates = cpu_states;
+ si->memory = memory_stats;
+ si->kernel = kernel_stats;
+
+ dprintf("get_system_info returns\n");
+}
+
+static struct handle handle;
+
+caddr_t
+get_process_info (
+ struct system_info *si,
+ struct process_select *sel,
+ int compare_index)
+{
+ register int i;
+ register int total_procs;
+ register int active_procs;
+ register struct prpsinfo **prefp;
+ register struct prpsinfo *pp;
+ int nproc;
+ int state;
+
+ /* these are copied out of sel for speed */
+ int show_idle;
+ int show_system;
+ int show_uid;
+ char *show_command;
+
+ /* these persist across calls */
+ static struct prpsinfo **pref = NULL;
+ static int pref_size = 0;
+
+ /* 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_fullcmd = sel->fullcmd;
+ show_command = sel->command;
+ show_threads = sel->threads;
+
+ /* allocate enough space for twice our current needs */
+ nproc = get_nproc();
+ if (nproc > procs_max())
+ {
+ procs_prealloc(2 * nproc);
+ }
+
+ /* read all the proc structures */
+ nproc = getptable();
+
+ /* allocate pref[] */
+ if (pref_size < nproc)
+ {
+ if (pref != NULL)
+ {
+ free(pref);
+ }
+ pref = (struct prpsinfo **)malloc(nproc * sizeof(struct prpsinfo *));
+ dprintf("get_process_info: allocated %d prinfo pointers at %08x\n",
+ nproc, pref);
+ pref_size = nproc;
+ }
+
+ /* get a pointer to the states summary array */
+ si->procstates = process_states;
+
+ /* 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 = procs_start(), i = 0; i < nproc;
+ i++, pp = procs_next())
+ {
+ dprintf("looking at #%d: %d.%d\n", i,
+ pp->pr_pid, pp->pr_lwp.pr_lwpid);
+ /*
+ * 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->px_state != 0 &&
+ (show_system || ((pp->pr_flag & SSYS) == 0)))
+ {
+ total_procs++;
+ state = (int)pp->px_state;
+ if (state > 0 && state < PROCSTATES)
+ {
+ process_states[state]++;
+ }
+ else
+ {
+ dprintf("process %d.%d: state out of bounds %d\n",
+ pp->pr_pid, pp->pr_lwp.pr_lwpid, state);
+ }
+
+ if ((!ZOMBIE(pp)) &&
+ (show_idle || percent_cpu (pp) || (pp->px_state == SRUN) || (pp->px_state == SONPROC)) &&
+ (!show_uid || pp->pr_uid == (uid_t) sel->uid) &&
+ (show_command == NULL ||
+ strstr(pp->pr_fname, show_command) != NULL))
+ {
+ *prefp++ = pp;
+ active_procs++;
+ }
+ }
+ }
+
+ dprintf("total_procs %d, active_procs %d\n", total_procs, active_procs);
+
+ /* if requested, sort the "interesting" processes */
+ qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *),
+ proc_compares[compare_index]);
+
+ /* 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);
+}
+
+static char p_header[MAX_COLS];
+
+char *
+format_process_header(struct process_select *sel, caddr_t handle, int count)
+
+{
+ int cols;
+ char *p;
+ int *fi;
+ struct proc_field *fp;
+
+ /* check for null handle */
+ if (handle == NULL)
+ {
+ return("");
+ }
+
+ /* remember how many columns there are on the display */
+ cols = display_columns();
+
+ /* mode & threads dictate format */
+ fi = display_fields = sel->threads ? thr_display : proc_display;
+
+ /* set username field correctly */
+ if (!sel->usernames)
+ {
+ /* display uids */
+ field_subst(fi, FIELD_USERNAME, FIELD_UID);
+ }
+ else
+ {
+ /* display usernames */
+ field_subst(fi, FIELD_UID, FIELD_USERNAME);
+ }
+
+ /* walk thru fields and construct header */
+ /* are we worried about overflow??? */
+ p = p_header;
+ while (*fi != -1)
+ {
+ fp = &(proc_field[*fi++]);
+ if (fp->min_screenwidth <= cols)
+ {
+ p += sprintf(p, fp->rjust ? "%*s" : "%-*s", fp->width, fp->name);
+ *p++ = ' ';
+ }
+ }
+ *--p = '\0';
+
+ return p_header;
+}
+
+static char fmt[MAX_COLS]; /* static area where result is built */
+
+char *
+format_next_process(caddr_t handle, char *(*get_userid)(int))
+
+{
+ struct prpsinfo *pp;
+ struct handle *hp;
+ struct proc_field *fp;
+ int *fi;
+ int i;
+ int cols;
+ char *p;
+ int len;
+ int x;
+
+ /* find and remember the next proc structure */
+ hp = (struct handle *)handle;
+ pp = *(hp->next_proc++);
+ hp->remaining--;
+
+ /* grab format descriptor */
+ fi = display_fields;
+
+ /* screen width is a consideration, too */
+ cols = display_columns();
+
+ /* build output by field */
+ p = fmt;
+ len = MAX_COLS;
+ while ((i = *fi++) != -1)
+ {
+ fp = &(proc_field[i]);
+ if (len > 0 && fp->min_screenwidth <= cols)
+ {
+ x = (*(fp->format))(p, len, pp);
+ if (x >= len)
+ {
+ dprintf("format_next_process: formatter overflow: x %d, len %d, p %08x => %08x, fmt %08x - %08x\n",
+ x, len, p, p + len, fmt, fmt + sizeof(fmt));
+ p += len;
+ len = 0;
+ }
+ else
+ {
+ p += x;
+ *p++ = ' ';
+ len -= x + 1;
+ }
+ }
+ }
+ *--p = '\0';
+
+ /* return the result */
+ return(fmt);
+}
+
+/* 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 (dresult = percent_cpu (p2) - percent_cpu (p1),\
+ (result = dresult > 0.0 ? 1 : dresult < 0.0 ? -1 : 0) == 0)
+#define ORDERKEY_CPTICKS if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
+#define ORDERKEY_STATE if ((result = (long) (sorted_state[(int)p2->px_state] - \
+ sorted_state[(int)p1->px_state])) == 0)
+#define ORDERKEY_PRIO if ((result = p2->px_pri - p1->px_pri) == 0)
+#define ORDERKEY_RSSIZE if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
+#define ORDERKEY_MEM if ((result = (p2->pr_size - p1->pr_size)) == 0)
+#define ORDERKEY_LWP if ((result = (p1->pr_lwp.pr_lwpid - p2->pr_lwp.pr_lwpid)) == 0)
+#define ORDERKEY_PID if ((result = (p1->pr_pid - p2->pr_pid)) == 0)
+
+/* Now the array that maps process state to a weight */
+
+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) */
+};
+
+
+/* compare_cpu - the comparison function for sorting by cpu percentage */
+
+int
+compare_cpu (struct prpsinfo **pp1, struct prpsinfo **pp2)
+
+{
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PID
+ ORDERKEY_LWP
+ ;
+
+ return (result);
+}
+
+/* compare_size - the comparison function for sorting by total memory usage */
+
+int
+compare_size (struct prpsinfo **pp1, struct prpsinfo **pp2)
+
+{
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_PID
+ ORDERKEY_LWP
+ ;
+
+ return (result);
+}
+
+/* compare_res - the comparison function for sorting by resident set size */
+
+int
+compare_res (struct prpsinfo **pp1, struct prpsinfo **pp2)
+
+{
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PCTCPU
+ ORDERKEY_CPTICKS
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_PID
+ ORDERKEY_LWP
+ ;
+
+ return (result);
+}
+
+/* compare_time - the comparison function for sorting by total cpu time */
+
+int
+compare_time (struct prpsinfo **pp1, struct prpsinfo **pp2)
+
+{
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ORDERKEY_PID
+ ORDERKEY_LWP
+ ;
+
+ return (result);
+}
+
+/* compare_pid - the comparison function for sorting by process id */
+
+int
+compare_pid (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;
+
+ ORDERKEY_PID
+ ORDERKEY_LWP
+ ;
+
+ return (result);
+}
+
+/* get process table */
+int
+getptable (struct prpsinfo *baseptr)
+{
+ struct prpsinfo *currproc; /* pointer to current proc structure */
+#ifndef USE_NEW_PROC
+ struct prstatus prstatus; /* for additional information */
+#endif
+ int numprocs = 0;
+ struct dirent *direntp;
+ struct oldproc *op;
+ hash_pos pos;
+ hash_item_pid *hi;
+ hash_item_pidthr *hip;
+ prheader_t *prp;
+ lwpsinfo_t *lwpp;
+ pidthr_t pidthr;
+ static struct timeval lasttime =
+ {0, 0};
+ struct timeval thistime;
+ struct stat st;
+ double timediff;
+
+ gettimeofday (&thistime, NULL);
+ /*
+ * 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;
+
+ /* get our first procs pointer */
+ currproc = procs_start();
+
+ /* before reading /proc files, turn on root privs */
+ /* (we don't care if this fails since it will be caught later) */
+#ifndef USE_NEW_PROC
+ seteuid(0);
+#endif
+
+ for (rewinddir (procdir); (direntp = readdir (procdir));)
+ {
+ int fd;
+ int pid;
+ char buf[40];
+
+ /* skip dot files */
+ if (direntp->d_name[0] == '.')
+ continue;
+
+ /* convert pid to a number (and make sure its valid) */
+ pid = atoi(direntp->d_name);
+ if (pid <= 0)
+ continue;
+
+ /* fetch the old proc data */
+ op = (struct oldproc *)hash_lookup_pid(prochash, pid);
+ if (op == NULL)
+ {
+ /* new proc: create an entry for it */
+ op = (struct oldproc *)malloc(sizeof(struct oldproc));
+ hash_add_pid(prochash, pid, (void *)op);
+ op->pid = pid;
+ op->fd_psinfo = -1;
+ op->fd_lpsinfo = -1;
+ op->oldtime = 0.0;
+ }
+
+ /* do we have a cached file? */
+ fd = op->fd_psinfo;
+ if (fd == -1)
+ {
+ /* no: open the psinfo file */
+ snprintf(buf, sizeof(buf), "%s/psinfo", direntp->d_name);
+ if ((fd = open(buf, O_RDONLY)) < 0)
+ {
+ /* cleanup??? */
+ continue;
+ }
+ }
+
+ /* read data from the file */
+#ifdef USE_NEW_PROC
+ if (pread(fd, currproc, sizeof(psinfo_t), 0) != sizeof(psinfo_t))
+ {
+ (void) close (fd);
+ op->fd_psinfo = -1;
+ continue;
+ }
+#else
+ if (ioctl(fd, PIOCPSINFO, currproc) < 0)
+ {
+ (void) close(fd);
+ op->fd_psinfo = -1;
+ continue;
+ }
+
+ if (ioctl(fd, PIOCSTATUS, &prstatus) < 0)
+ {
+ /* not a show stopper -- just fill in the needed values */
+ currproc->pr_fill = 0;
+ currproc->px_onpro = 0;
+ }
+ else
+ {
+ /* copy over the values we need from prstatus */
+ currproc->pr_fill = (short)prstatus.pr_nlwp;
+ currproc->px_onpro = prstatus.pr_processor;
+ }
+#endif
+
+ /*
+ * We track our own cpu% usage.
+ * We compute it based on CPU since the last update by calculating
+ * the difference in cumulative cpu time and dividing by the amount
+ * of time we measured between updates (timediff).
+ * NOTE: Solaris 2.4 and higher do maintain CPU% in psinfo,
+ * but it does not produce the kind of results we really want,
+ * so we don't use it even though its there.
+ */
+ if (lasttime.tv_sec > 0)
+ {
+ percent_cpu(currproc) =
+ (TIMESPEC_TO_DOUBLE(currproc->pr_time) - op->oldtime) / timediff;
+ }
+ else
+ {
+ /* first screen -- no difference is possible */
+ percent_cpu(currproc) = 0.0;
+ }
+
+ /* save data for next time */
+ op->pid = currproc->pr_pid;
+ op->oldtime = TIMESPEC_TO_DOUBLE(currproc->pr_time);
+ op->owner_uid = currproc->pr_uid;
+ op->seen = 1;
+
+ /* cache the file descriptor if we can */
+ if (fd < maxfiles)
+ {
+ op->fd_psinfo = fd;
+ }
+ else
+ {
+ (void) close(fd);
+ }
+
+#ifdef USE_NEW_PROC
+ /* collect up the threads */
+ /* use cached lps file if it's there */
+ fd = op->fd_lpsinfo;
+ if (fd == -1)
+ {
+ snprintf(buf, sizeof(buf), "%s/lpsinfo", direntp->d_name);
+ fd = open(buf, O_RDONLY);
+ }
+
+ /* make sure we have a valid descriptor and the file's current size */
+ if (fd >= 0 && fstat(fd, &st) != -1)
+ {
+ char *p;
+ int i;
+
+ /* read the whole file */
+ p = malloc(st.st_size);
+ (void)pread(fd, p, st.st_size, 0);
+
+ /* cache the file descriptor if we can */
+ if (fd < maxfiles)
+ {
+ op->fd_lpsinfo = fd;
+ }
+ else
+ {
+ (void)close(fd);
+ }
+
+ /* the file starts with a struct prheader */
+ prp = (prheader_t *)p;
+ p += sizeof(prheader_t);
+
+ /* there are prp->pr_nent entries in the file */
+ for (i = 0; i < prp->pr_nent; i++)
+ {
+ /* process this entry */
+ lwpp = (lwpsinfo_t *)p;
+ p += prp->pr_entsize;
+
+ /* fetch the old thread data */
+ /* this hash is indexed by both pid and lwpid */
+ pidthr.k_pid = currproc->pr_pid;
+ pidthr.k_thr = lwpp->pr_lwpid;
+ dprintf("getptable: processing %d.%d\n",
+ pidthr.k_pid, pidthr.k_thr);
+ op = (struct oldproc *)hash_lookup_pidthr(threadhash, pidthr);
+ if (op == NULL)
+ {
+ /* new thread: create an entry for it */
+ op = (struct oldproc *)malloc(sizeof(struct oldproc));
+ hash_add_pidthr(threadhash, pidthr, (void *)op);
+ op->pid = pid;
+ op->lwpid = lwpp->pr_lwpid;
+ op->oldtime = 0.0;
+ dprintf("getptable: %d.%d: new thread\n",
+ pidthr.k_pid, pidthr.k_thr);
+ }
+
+ /* are we showing individual threads? */
+ if (show_threads)
+ {
+ /* yes: if this is the first thread we reuse the proc
+ entry we have, otherwise we create a new one by
+ duping the current one */
+ if (i > 0)
+ {
+ currproc = procs_dup(currproc);
+ numprocs++;
+ }
+
+ /* yes: copy over thread-specific data */
+ currproc->pr_time = lwpp->pr_time;
+ currproc->px_state = lwpp->pr_state;
+ currproc->px_pri = lwpp->pr_pri;
+ currproc->px_onpro = lwpp->pr_onpro;
+ currproc->pr_lwp.pr_lwpid = lwpp->pr_lwpid;
+
+ /* calculate percent cpu for just this thread */
+ if (lasttime.tv_sec > 0)
+ {
+ percent_cpu(currproc) =
+ (TIMESPEC_TO_DOUBLE(lwpp->pr_time) - op->oldtime) /
+ timediff;
+ }
+ else
+ {
+ /* first screen -- no difference is possible */
+ percent_cpu(currproc) = 0.0;
+ }
+
+ dprintf("getptable: %d.%d: time %.0f, state %d, pctcpu %.2f\n",
+ currproc->pr_pid, lwpp->pr_lwpid,
+ TIMESPEC_TO_DOUBLE(currproc->pr_time),
+ currproc->px_state, percent_cpu(currproc));
+ }
+
+ /* save data for next time */
+ op->oldtime = TIMESPEC_TO_DOUBLE(lwpp->pr_time);
+ op->seen = 1;
+ }
+ free(p);
+ }
+#endif
+
+ /* move to next */
+ numprocs++;
+ currproc = procs_next();
+ }
+
+#ifndef USE_NEW_PROC
+ /* turn off root privs */
+ seteuid(getuid());
+#endif
+
+ dprintf("getptable saw %d procs\n", numprocs);
+
+ /* scan the hash tables and remove dead entries */
+ hi = hash_first_pid(prochash, &pos);
+ while (hi != NULL)
+ {
+ op = (struct oldproc *)(hi->value);
+ if (op->seen)
+ {
+ op->seen = 0;
+ }
+ else
+ {
+ dprintf("removing %d from prochash\n", op->pid);
+ if (op->fd_psinfo >= 0)
+ {
+ (void)close(op->fd_psinfo);
+ }
+ if (op->fd_lpsinfo >= 0)
+ {
+ (void)close(op->fd_lpsinfo);
+ }
+ hash_remove_pos_pid(&pos);
+ free(op);
+ }
+ hi = hash_next_pid(&pos);
+ }
+
+ hip = hash_first_pidthr(threadhash, &pos);
+ while (hip != NULL)
+ {
+ op = (struct oldproc *)(hip->value);
+ if (op->seen)
+ {
+ op->seen = 0;
+ }
+ else
+ {
+ dprintf("removing %d from threadhash\n", op->pid);
+ hash_remove_pos_pidthr(&pos);
+ free(op);
+ }
+ hip = hash_next_pidthr(&pos);
+ }
+
+ lasttime = thistime;
+
+ return numprocs;
+}
+
+/*
+ * 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 (int pid)
+{
+ struct oldproc *op;
+
+ /* we keep this information in the hash table */
+ op = (struct oldproc *)hash_lookup_pid(prochash, (pid_t)pid);
+ if (op != NULL)
+ {
+ return((int)(op->owner_uid));
+ }
+ return(-1);
+}
+
+/* older revisions don't supply a setpriority */
+#if (OSREV < 55)
+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
+
--- /dev/null
+.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>.
--- /dev/null
+/*
+ * 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++;
+ }
+}
--- /dev/null
+.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)
--- /dev/null
+/*
+ * 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: For Intel based System V Release 5 (Unixware7)
+ *
+ * DESCRIPTION:
+ * System V release 5 for i[3456]86
+ * Works for:
+ * i586-sco-sysv5uw7 i386 SCO UNIX_SVR5 (UnixWare 7)
+ *
+ * LIBS: -lelf -lmas
+ *
+ * CFLAGS: -DHAVE_GETOPT -DORDER
+ *
+ * AUTHORS: Mike Hopkirk <hops@sco.com>
+ * David Cutter <dpc@grail.com>
+ * Andrew Herbert <andrew@werple.apana.org.au>
+ * Robert Boucher <boucher@sofkin.ca>
+ */
+
+/* build config
+ * SHOW_NICE - process nice fields don't seem to be being updated so changed
+ * default to display # of threads in use instead.
+ * define this to display nice fields (values always 0)
+ * #define SHOW_NICE 1
+ */
+
+#define _KMEMUSER
+#define prpsinfo psinfo
+#include <sys/procfs.h>
+
+#define pr_state pr_lwp.pr_state
+#define pr_nice pr_lwp.pr_nice
+#define pr_pri pr_lwp.pr_pri
+#define pr_onpro pr_lwp.pr_onpro
+#define ZOMBIE(p) ((p)->pr_nlwp == 0)
+#define SIZE_K(p) pagetok((p)->pr_size)
+#define RSS_K(p) pagetok((p)->pr_rssize)
+
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <dirent.h>
+#include <nlist.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sysmacros.h>
+#include <vm/anon.h>
+#include <sys/priocntl.h>
+#include <sys/tspriocntl.h>
+#include <sys/var.h>
+
+#include "top.h"
+#include "machine.h"
+#include "utils.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 pagetok(size) ((size) * pagesz) >> LOG1024
+
+/* definitions for the index in the nlist array */
+#define X_AVENRUN 0
+#define X_V 1
+#define X_MPID 2
+
+static struct nlist nlst[] =
+{
+ {"avenrun"}, /* 0 */
+ {"v"}, /* 1 */
+ {"nextpid"}, /* 2 */
+ {NULL}
+};
+
+static unsigned long avenrun_offset;
+static unsigned long mpid_offset;
+
+static unsigned int pagesz;
+
+static void reallocproc(int n);
+static int maxprocs;
+
+/* 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[] =
+#ifdef SHOW_NICE
+" PID X PRI NICE SIZE RES STATE TIME CPU COMMAND";
+#else
+" PID X PRI THR SIZE RES STATE TIME CPU COMMAND";
+#endif
+/* 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 %8.4f%% %.16s"
+
+char *state_abbrev[] =
+{"oncpu", "run", "sleep", "stop", "idle", "zombie"};
+
+#define sZOMB 5
+int process_states[8];
+char *procstatenames[] =
+{
+ " on cpu, ", " running, ", " sleeping, ", " stopped, ",
+ " idling ", " zombie, ",
+ NULL
+};
+
+int cpu_states[CPUSTATES];
+char *cpustatenames[] =
+{"idle", "user", "kernel", "wait", NULL};
+
+
+/* these are for detailing the memory statistics */
+long memory_stats[5];
+char *memorynames[] =
+{"K phys, ", "K used, ", "K free, ", "K swapUsed, ", "K swapFree", NULL};
+
+/* these are names given to allowed sorting orders -- first is default */
+char *ordernames[] =
+{"state", "cpu", "size", "res", "time", "pid", "uid", "rpid", "ruid", NULL};
+
+/* forward definitions for comparison functions */
+int proc_compare();
+int compare_cpu();
+int compare_size();
+int compare_res();
+int compare_time();
+int compare_pid();
+int compare_uid();
+int compare_rpid();
+int compare_ruid();
+
+int (*proc_compares[])() = {
+ proc_compare,
+ compare_cpu,
+ compare_size,
+ compare_res,
+ compare_time,
+ compare_pid,
+ compare_uid,
+ compare_rpid,
+ compare_ruid,
+ NULL };
+
+
+static int kmem = -1;
+static int nproc;
+static int bytes;
+static struct prpsinfo *pbase;
+static struct prpsinfo **pref;
+static DIR *procdir;
+
+/* useful externals */
+extern int errno;
+extern char *sys_errlist[];
+extern char *myname;
+extern long percentages ();
+extern int check_nlist ();
+extern int getkval ();
+extern void perror ();
+extern void getptable ();
+extern void quit ();
+extern int nlist ();
+
+/* fwd dcls */
+static int kmet_init(void );
+static int get_cpustates(int *new);
+
+
+int
+machine_init (struct statics *statics)
+ {
+ static struct var v;
+ int i;
+
+ /* fill in the statics information */
+ statics->procstate_names = procstatenames;
+ statics->cpustate_names = cpustatenames;
+ statics->memory_names = memorynames;
+ statics->order_names = ordernames;
+
+ /* 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);
+ }
+
+ v.v_proc=200; /* arbitrary default */
+ /* 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;
+ maxprocs = nproc;
+
+ /* stash away certain offsets for later use */
+ mpid_offset = nlst[X_MPID].n_value;
+ avenrun_offset = nlst[X_AVENRUN].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 *));
+
+ pagesz = sysconf(_SC_PAGESIZE);
+
+
+ /* 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 (!(procdir = 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);
+ }
+
+
+ kmet_init();
+
+ /* 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];
+ long mem;
+ static time_t cp_old[CPUSTATES];
+ static time_t cp_diff[CPUSTATES]; /* for cpu state percentages */
+ register int i;
+ static long swap_total;
+ static long swap_free;
+ int new_states[CPUSTATES];
+
+ get_cpustates(new_states);
+
+ /* convert cp_time counts to percentages */
+ (void) percentages (CPUSTATES, cpu_states, new_states, cp_old, cp_diff);
+
+
+ si->last_pid = -1;
+ /* get mpid -- process id of last process
+ * svr5 is nextpid - next pid to be assigned (already incremented)
+ */
+ (void) getkval (mpid_offset, &(si->last_pid), sizeof (si->last_pid),
+ "nextpid");
+ (si->last_pid)--; /* so we shld decrement for display */
+
+
+ /* 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]);
+
+ mem = sysconf(_SC_TOTAL_MEMORY); /* physical mem */
+ memory_stats[0] = pagetok (mem);
+
+ mem = kmet_get_freemem(); /* free mem */
+ memory_stats[2] = pagetok (mem);
+
+ /* mem = sysconf(_SC_GENERAL_MEMORY); */
+ memory_stats[1] = memory_stats[0] - memory_stats[2]; /* active */
+
+ get_swapinfo(&swap_total, &swap_free);
+ memory_stats[3] = pagetok(swap_total - swap_free);
+ memory_stats[4] = pagetok(swap_free);
+
+
+ /* 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 idx)
+{
+ 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 */
+
+ /* 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;
+
+ nproc = kmet_get_nproc();
+
+ /* 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 PR_ISSYS set are system
+ * processes---these get ignored unless show_sysprocs is set.
+ */
+ if ((pp->pr_state >= SONPROC && pp->pr_state <= SIDL) &&
+ (show_system || ((pp->pr_flag & PR_ISSYS) == 0)))
+ {
+ total_procs++;
+ process_states[pp->pr_state]++;
+ if ((!ZOMBIE(pp)) &&
+ (show_idle || (pp->pr_state == SRUN) || (pp->pr_state == SONPROC)) &&
+ (!show_uid || pp->pr_uid == (uid_t) sel->uid))
+ {
+ *prefp++ = pp;
+ active_procs++;
+ }
+ if (ZOMBIE(pp))
+ process_states[sZOMB]++; /* invented */
+
+ }
+ }
+
+ /* if requested, sort the "interesting" processes */
+ qsort ((char *) pref, active_procs, sizeof (struct prpsinfo *),
+ proc_compares[idx]);
+
+ /* 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);
+}
+
+/*
+ * cpu percentage calculation is as fm ps.c
+ * seems to be ratio of (sys+user time used)/(elapsed time)
+ * i.e percent of cpu utilised when on cpu
+ */
+static double percent_cpu( struct prpsinfo *pp)
+{
+ static time_t tim = 0L;
+ time_t starttime;
+ time_t ctime;
+ time_t etime;
+
+ /* if (tim == 0L) */
+ tim = time((time_t *) 0);
+ starttime = pp->pr_start.tv_sec;
+ if (pp->pr_start.tv_nsec > 500000000)
+ starttime++;
+ etime = (tim - starttime);
+ ctime = pp->pr_time.tv_sec;
+ if (pp->pr_time.tv_nsec > 500000000)
+ ctime++;
+ if (etime)
+ {
+ /* return (float)(ctime * 100) / (unsigned)etime; */
+ /* this was ocasionally giving vals >100 for some
+ * unknown reason so the below normalises it
+ */
+
+ double pct;
+ pct = (float)(ctime * 100) / (unsigned)etime;
+ return (pct < 100.0) ? pct : 100.00;
+ }
+ return 0.00;
+}
+
+
+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,
+#ifdef SHOW_NICE
+ pp->pr_nice,
+#else
+ (u_short)pp->pr_nlwp < 999 ? (u_short)pp->pr_nlwp : 999,
+#endif
+ format_k(SIZE_K(pp)),
+ format_k(RSS_K(pp)),
+ (ZOMBIE(pp)) ? state_abbrev[sZOMB]
+ : state_abbrev[pp->pr_state],
+ format_time(cputime),
+ /* 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;
+
+ /* 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_value == 0)
+ {
+ /* 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)
+{
+ if (lseek (kmem, (long) offset, 0) == -1)
+ {
+ 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 routines for qsort ---------------- */
+
+/* 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 (dresult = percent_cpu (p2) - percent_cpu (p1),\
+ (result = dresult > 0.0 ? 1 : \
+ dresult < 0.0 ? -1 : 0) == 0)
+
+#define ORDERKEY_CPTICKS if ((result = p2->pr_time.tv_sec - p1->pr_time.tv_sec) == 0)
+#define ORDERKEY_STATE if ((result = (long) (sorted_state[p2->pr_state] - \
+ sorted_state[p1->pr_state])) == 0)
+
+#define ORDERKEY_PRIO if ((result = p2->pr_pri - p1->pr_pri) == 0)
+#define ORDERKEY_RSSIZE if ((result = p2->pr_rssize - p1->pr_rssize) == 0)
+#define ORDERKEY_MEM if ((result = (p2->pr_size - p1->pr_size)) == 0)
+
+#define ORDERKEY_PID if ((result = (p2->pr_pid - p1->pr_pid)) == 0)
+#define ORDERKEY_UID if ((result = (p2->pr_uid - p1->pr_uid)) == 0)
+#define ORDERKEY_RPID if ((result = (p1->pr_pid - p2->pr_pid)) == 0)
+#define ORDERKEY_RUID if ((result = (p1->pr_uid - p2->pr_uid)) == 0)
+
+/* states enum {SONPROC, SRUN, SSLEEP, SSTOP, SIDL} */
+unsigned char sorted_state[] =
+{
+ 7, /* onproc */
+ 6, /* run */
+ 5, /* sleep */
+ 4, /* stop */
+ 3, /* idle */
+ 2, /* zombie */
+ 0, /* unused */
+ 0 /* unused */
+};
+
+#if 0
+/*
+ * proc_compare - original singleton 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.
+ */
+ /* default comparison rtn */
+int
+original_proc_compare (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ /* compare percent cpu (pctcpu) */
+ dresult = percent_cpu(p2) - percent_cpu (p1);
+ result = dresult > 0.0 ? 1 :
+ dresult < 0.0 ? -1 : 0;
+ if (result)
+ {
+ /* 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_pri - p1->pr_pri) == 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);
+ }
+#endif /* original comparison rtn */
+
+/* compare_state - comparison function for sorting by state,pri,time,size */
+int
+proc_compare (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_CPTICKS
+ ORDERKEY_RSSIZE
+ ORDERKEY_MEM
+ ORDERKEY_PCTCPU
+ ;
+
+ return (result);
+ }
+
+
+/* compare_cpu - the comparison function for sorting by cpu % (deflt) */
+int
+compare_cpu (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* 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 */
+int
+compare_size (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* 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 */
+int
+compare_res (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* 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 */
+int
+compare_time (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ;
+
+ return (result);
+ }
+
+/* compare_pid - the comparison function for sorting by pid */
+int
+compare_pid (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_PID
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ;
+
+ return (result);
+ }
+
+/* compare_uid - the comparison function for sorting by user ID */
+int
+compare_uid (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_UID
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ;
+
+ return (result);
+ }
+
+/* compare_rpid - the comparison function for sorting by pid ascending */
+int
+compare_rpid (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_RPID
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ;
+
+ return (result);
+ }
+
+/* compare_uid - the comparison function for sorting by user ID ascending */
+int
+compare_ruid (
+ struct prpsinfo **pp1,
+ struct prpsinfo **pp2)
+ {
+ register struct prpsinfo *p1;
+ register struct prpsinfo *p2;
+ register long result;
+ double dresult;
+
+ /* remove one level of indirection */
+ p1 = *pp1;
+ p2 = *pp2;
+
+ ORDERKEY_RUID
+ ORDERKEY_CPTICKS
+ ORDERKEY_PCTCPU
+ ORDERKEY_STATE
+ ORDERKEY_PRIO
+ ORDERKEY_MEM
+ ORDERKEY_RSSIZE
+ ;
+
+ return (result);
+ }
+
+
+/* ---------------- helper rtns ---------------- */
+
+/*
+ * get process table
+ */
+void
+getptable (struct prpsinfo *baseptr)
+{
+ struct prpsinfo *currproc; /* pointer to current proc structure */
+ int numprocs = 0;
+ struct dirent *direntp;
+
+ currproc = baseptr;
+ for (rewinddir (procdir); direntp = readdir (procdir);)
+ {
+ int fd;
+ char buf[30];
+
+ sprintf(buf,"%s/psinfo", direntp->d_name);
+
+ if ((fd = open (buf, O_RDONLY)) < 0)
+ continue;
+
+ if (read(fd, currproc, sizeof(psinfo_t)) != sizeof(psinfo_t))
+ {
+ (void) close (fd);
+ continue;
+ }
+
+ numprocs++;
+ currproc++;
+
+ (void) close (fd);
+
+ /* Atypical place for growth */
+ if (numprocs >= maxprocs)
+ {
+ reallocproc(2 * numprocs);
+ currproc = (struct prpsinfo *)
+ ((char *)baseptr + sizeof(psinfo_t) * numprocs);
+ }
+
+ }
+
+ 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 ((int)(p->pr_uid));
+
+ return (-1);
+}
+
+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);
+}
+
+
+get_swapinfo(long *total, long *fr)
+{
+ register int cnt, i;
+ register long t, f;
+ struct swaptable *swt;
+ struct swapent *ste;
+ static char path[256];
+
+ /* get total number of swap entries */
+ cnt = swapctl(SC_GETNSWP, 0);
+
+ /* allocate enough space to hold count + n swapents */
+ swt = (struct swaptable *)malloc(sizeof(int) +
+ cnt * sizeof(struct swapent));
+ if (swt == NULL)
+ {
+ *total = 0;
+ *fr = 0;
+ return;
+ }
+ swt->swt_n = cnt;
+
+ /* fill in ste_path pointers: we don't care about the paths, so we point
+ them all to the same buffer */
+ ste = &(swt->swt_ent[0]);
+ i = cnt;
+ while (--i >= 0)
+ {
+ ste++->ste_path = path;
+ }
+
+ /* grab all swap info */
+ swapctl(SC_LIST, swt);
+
+ /* walk thru the structs and sum up the fields */
+ t = f = 0;
+ ste = &(swt->swt_ent[0]);
+ i = cnt;
+ while (--i >= 0)
+ {
+ /* dont count slots being deleted */
+ if (!(ste->ste_flags & ST_INDEL) )
+ {
+ t += ste->ste_pages;
+ f += ste->ste_free;
+ }
+ ste++;
+ }
+
+ /* fill in the results */
+ *total = t;
+ *fr = f;
+ free(swt);
+}
+
+
+/*
+ * When we reach a proc limit, we need to realloc the stuff.
+ */
+static void reallocproc(int n)
+{
+ int bytes;
+ struct oldproc *op, *endbase;
+
+ if (n < maxprocs)
+ return;
+
+ maxprocs = n;
+
+ /* allocate space for proc structure array and array of pointers */
+ bytes = maxprocs * sizeof(psinfo_t) ;
+ pbase = (struct prpsinfo *) realloc(pbase, bytes);
+ pref = (struct prpsinfo **) realloc(pref,
+ maxprocs * sizeof(struct prpsinfo *));
+
+ /* Just in case ... */
+ if (pbase == (struct prpsinfo *) NULL || pref == (struct prpsinfo **) NULL)
+ {
+ fprintf (stderr, "%s: can't allocate sufficient memory\n", myname);
+ quit(1);
+ }
+}
+
+/* ---------------------------------------------------------------- */
+/* Access kernel Metrics
+ * SVR5 uses metreg inteface to Kernel statistics (metrics)
+ * see /usr/include/mas.h, /usr/include/metreg.h
+ */
+
+#include <sys/mman.h>
+#include <sys/dl.h>
+#include <mas.h>
+#include <metreg.h>
+
+static int md; /* metric descriptor handle */
+static uint32 ncpu; /* number of processors in system */
+
+/* fwd dcls */
+static uint32 kmet_get_cpu( int type, char *desc);
+static void kmet_verify(
+ uint32 md, metid_t id, units_t units, type_t mettype,
+ uint32 metsz, uint32 nobj, uint32 nlocs, resource_t res_id,
+ uint32 ressz ) ;
+
+
+static int get_cpustates(int *new)
+{
+ new[0] = (int)kmet_get_cpu( MPC_CPU_IDLE, "idle");
+ new[1] = (int)kmet_get_cpu( MPC_CPU_USR, "usr");
+ new[2] = (int)kmet_get_cpu( MPC_CPU_SYS, "sys");
+ new[3] = (int)kmet_get_cpu( MPC_CPU_WIO, "wio");
+}
+
+
+/* initialises kernel metrics access and gets #cpus */
+static int kmet_init()
+{
+ uint32 *ncpu_p;
+
+ /* open (and map in) the metric access file and assoc data structures */
+ if( ( md = mas_open( MAS_FILE, MAS_MMAP_ACCESS ) ) < 0 )
+ {
+ (void)fprintf(stderr,"mas_open failed\n");
+ mas_perror();
+ quit(10);
+ }
+
+ /* verify the NCPU metric is everything we expect */
+ kmet_verify(md, NCPU, CPUS, CONFIGURABLE, sizeof(short),
+ 1, 1, MAS_SYSTEM, sizeof(uint32) );
+
+ /* get the number of cpu's on the system */
+ if( (ncpu_p = (uint32 *)mas_get_met( md, NCPU, 0 )) == NULL )
+ {
+ (void)fprintf(stderr,"mas_get_met of ncpu failed\n");
+ mas_perror();
+ quit(12);
+ }
+ ncpu = (uint32)(*(short *)ncpu_p);
+
+ /* check that MPC_CPU_IDLE is of the form we expect
+ * ( paranoically we should check the rest as well but ... )
+ */
+ kmet_verify( md, MPC_CPU_IDLE, TIX, PROFILE, sizeof(uint32),
+ 1, ncpu, NCPU, sizeof(short) );
+
+ kmet_verify( md, PROCUSE, PROCESSES, COUNT, sizeof(uint32),
+ 1, 1, MAS_SYSTEM, sizeof(uint32) );
+ nproc = kmet_get_nproc();
+
+ return 0;
+}
+
+/* done with kernel metrics access */
+static int
+kmet_done()
+{
+ if ( mas_close( md ) < 0 )
+ {
+ (void)fprintf(stderr,"mas_close failed\n");
+ mas_perror();
+ quit(14);
+ }
+}
+
+
+static uint32
+kmet_get_cpu( int type, char *desc)
+{
+ int i;
+ uint32 r=0, rtot=0 ;
+
+ for (i=0; i <ncpu; i++)
+ {
+ r=*(uint32 *)mas_get_met( md, (metid_t)type, 0 );
+ if ( !r)
+ {
+ (void)fprintf(stderr,"mas_get_met of %s failed\n", desc);
+ mas_perror();
+ quit(12);
+ }
+ rtot += r; /* sum them for multi cpus */
+ }
+ return rtot /* /ncpu */ ;
+}
+
+static int
+kmet_get_freemem()
+{
+ dl_t *fm_p, fm, fmc, denom;
+ time_t td1;
+ static time_t td0;
+ static dl_t fm_old;
+
+
+ td1 = time(NULL);
+ if ((fm_p = (dl_t *)mas_get_met( md, FREEMEM, 0 )) == NULL )
+ {
+ (void)fprintf(stderr,"mas_get_met of freemem failed\n");
+ mas_perror();
+ quit(12);
+ }
+ fm = *fm_p;
+
+ denom.dl_hop = 0;
+ denom.dl_lop = (long) (td1 - td0);
+ td0 = td1;
+
+ /* calculate the freemem difference divided by the time diff
+ * giving the freemem in that time sample
+ * (new - old) / (time_between_samples)
+ */
+ fmc = lsub(fm, fm_old);
+ fm_old = fm;
+
+ fmc = ldivide(fmc, denom);
+ return fmc.dl_lop;
+}
+
+/*
+ * return # of processes currently executing on system
+ */
+static int
+kmet_get_nproc()
+{
+ uint32 *p;
+ if ((p = (uint32 *)mas_get_met( md, PROCUSE, 0 )) == NULL )
+ {
+ (void)fprintf(stderr,"mas_get_met of procuse failed\n");
+ mas_perror();
+ quit(11);
+ }
+ nproc = (int)*p;
+}
+
+
+/*
+ * Function: kmet_verify
+ * renamed from mas_usrtime example verify_met() fm Doug Souders
+ *
+ * Description: Verify the registration data associated with this metric
+ * match what are expected. Cautious consumer applications
+ * should do this sort of verification before using metrics.
+ */
+static void
+kmet_verify(
+ uint32 md, /* metric descriptor */
+ metid_t id, /* metric id number */
+ units_t units, /* expected units of metric */
+ type_t mettype, /* expected type of metric */
+ uint32 metsz, /* expected object size of metric */
+ uint32 nobj, /* expected number of array elements */
+ uint32 nlocs, /* expected number of instances */
+ resource_t res_id, /* expected resource id number */
+ uint32 ressz /* expected resource object size */
+ )
+{
+
+ char *name; /* the name of the metric */
+ units_t *units_p; /* the units of the metric */
+ type_t *mettype_p; /* type field of the metric */
+ uint32 *objsz_p; /* size of each element in met */
+ uint32 *nobj_p; /* num of elements >1 then array*/
+ uint32 *nlocs_p; /* total number of instances */
+ uint32 *status_p; /* status word (update|avail) */
+ resource_t *resource_p; /* the resource list of the met */
+ uint32 *resval_p; /* pointer to resource */
+ uint32 *ressz_p; /* size of the resource met */
+
+ if (!(name = mas_get_met_name( md, id )))
+ {
+ (void)fprintf(stderr,"mas_get_met_name failed\n");
+ mas_perror();
+ quit(11);
+ }
+
+ if (!(status_p = mas_get_met_status( md, id )))
+ {
+ (void)fprintf(stderr,"mas_get_met_status of %s failed\n",
+ name );
+ mas_perror();
+ quit(11);
+ }
+ if ( *status_p != MAS_AVAILABLE )
+ {
+ (void)fprintf(stderr,"unexpected status word for %s\n"
+ "- expected %u got %u\n",
+ name, MAS_AVAILABLE, *status_p );
+ quit(11);
+ }
+ if (!(units_p = mas_get_met_units( md, id )))
+ {
+ (void)fprintf(stderr,"mas_get_met_units of %s failed\n",
+ name );
+ mas_perror();
+ quit(11);
+ }
+ if (units != *units_p )
+ {
+ (void)fprintf(stderr,"unexpected units for %s\n"
+ "- expected %u got %u\n",
+ name, units, *units_p );
+ quit(11);
+ }
+
+ if (!(mettype_p = mas_get_met_type( md, id )))
+ {
+ (void)fprintf(stderr,"mas_get_met_type of %s failed\n",
+ name );
+ mas_perror();
+ quit(11);
+ }
+ if (mettype != *mettype_p )
+ {
+ (void)fprintf(stderr,"unexpected metric type for %s\n"
+ "- expected %u got %u\n",
+ name, mettype , *mettype_p );
+ quit(11);
+ }
+
+ if (!(objsz_p = mas_get_met_objsz( md, id )))
+ {
+ (void)fprintf(stderr,"mas_get_met_objsz of %s failed\n", name );
+ mas_perror();
+ quit(11);
+ }
+ if (*objsz_p != metsz )
+ {
+ (void)fprintf(stderr,"unexpected object size for %s\n"
+ "- expected %u got %u\n",
+ name, metsz, *objsz_p );
+ quit(11);
+ }
+
+ if (!(nobj_p = mas_get_met_nobj( md, id )))
+ {
+ (void)fprintf(stderr,"mas_get_met_nobj of %s failed\n", name );
+ mas_perror();
+ quit(11);
+ }
+ if (nobj != *nobj_p )
+ {
+ (void)fprintf(stderr,"unexpected number of objects for %s\n"
+ "- expected %u got %u\n",
+ name, nobj, *nobj_p );
+ quit(11);
+ }
+
+ /* get the number of instances that libmas thinks it knows about */
+ if (!(nlocs_p = mas_get_met_nlocs( md, id )))
+ {
+ (void)fprintf(stderr,"mas_get_met_nlocs of %s failed\n", name );
+ mas_perror();
+ quit(11);
+ }
+ if (nlocs != *nlocs_p )
+ {
+ (void)fprintf(stderr,"unexpected number of instances for %s"
+ " - expected %u got %u\n",
+ name, nlocs, *nlocs_p );
+ quit(11);
+
+ }
+ /* get the resource list for the metric */
+ if (!(resource_p = mas_get_met_resources( md, id )))
+ {
+ (void)fprintf(stderr,"mas_get_met_resources of %s failed\n", name );
+ mas_perror();
+ quit(11);
+ }
+ if (*resource_p != res_id )
+ {
+ (void)fprintf(stderr,"unexpected resource id for %s\n"
+ "- expected %u got %u\n",
+ name, res_id, *resource_p);
+ quit(11);
+ }
+ /* get the size of the resource */
+ if (!(ressz_p = mas_get_met_objsz( md, (metid_t)(*resource_p) )))
+ {
+ (void)fprintf(stderr,"mas_get_met_objsz of resource failed\n");
+ mas_perror();
+ quit(11);
+ }
+ if (*ressz_p != ressz )
+ {
+ (void)fprintf(stderr,"unexpected resource size for %s\n"
+ "- expected %u got %u\n",
+ name, ressz, *ressz_p );
+ quit(11);
+ }
+/*
+ * get the address of the resource
+ */
+ if (!(resval_p = (uint32 *)mas_get_met( md, *resource_p, 0 )))
+ {
+ (void)fprintf(stderr,"mas_get_met of resource failed\n");
+ mas_perror();
+ quit(11);
+ }
+ if (ressz == sizeof( short ) )
+ {
+ if( (uint32)(*(short *)resval_p) != nlocs )
+ {
+ (void)fprintf(stderr,"unexpected resource value for %s\n"
+ "- expected %u got %u\n",
+ name, nlocs, (uint32)(*(short *)resval_p) );
+ quit(11);
+ }
+ }
+ else
+ { /* assume size of uint32 */
+ if (*resval_p != nlocs )
+ {
+ (void)fprintf(stderr,"unexpected resource value for %s\n"
+ "- expected %u got %u\n",
+ name, nlocs, *resval_p );
+ quit(11);
+ }
+ }
+ return;
+}
+
--- /dev/null
+.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
+
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+ }
+}
+
+
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+# 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");
+ }
--- /dev/null
+.\" 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/
--- /dev/null
+/*
+ * 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. */
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
SUBDIR+= grep
SUBDIR+= mined
SUBDIR+= ministat
-SUBDIR+= top
+SUBDIR+= mtop
SUBDIR+= toproto
SUBDIR+= trace
-PROG= top
+PROG= mtop
MAN=
DPADD+= ${LIBCURSES} ${LIBTERMINFO}
LDADD+= -lcurses -lterminfo
+WARNS?= 5
+
.include <bsd.prog.mk>