From: David van Moolenbroek Date: Sun, 8 Nov 2015 11:29:53 +0000 (+0000) Subject: Rename top(1) to mtop(1), import NetBSD top(1) X-Git-Url: http://zhaoyanbai.com/repos/%22http:/static/doc/zpipe.c?a=commitdiff_plain;h=refs%2Fchanges%2F54%2F3254%2F2;p=minix.git Rename top(1) to mtop(1), import NetBSD top(1) Due to differences in (mainly) measuring and accumulating CPU times, the two top programs end up serving different purposes: the NetBSD top is a system administration tool, while the MINIX3 top (now mtop) is a performance debugging tool. Therefore, we keep both. The newly imported BSD top has a few MINIX3-specific changes. CPU statistics separate system time from kernel time, rather than kernel time from time spent on handling interrupts. Memory statistics show numbers that are currently relevant for MINIX3. Swap statistics are disabled entirely. All of these changes effectively bring it closer to how mtop already worked as well. Change-Id: I9611917cb03e164ddf012c5def6da0e7fede826d --- diff --git a/distrib/sets/lists/minix-base/mi b/distrib/sets/lists/minix-base/mi index 58fb5e913..495ec2bdc 100644 --- a/distrib/sets/lists/minix-base/mi +++ b/distrib/sets/lists/minix-base/mi @@ -406,6 +406,7 @@ ./usr/bin/more minix-base ./usr/bin/msgc minix-base ./usr/bin/mt minix-base +./usr/bin/mtop minix-base ./usr/bin/nbperf minix-base ./usr/bin/netpgp minix-base crypto ./usr/bin/netpgpkeys minix-base crypto diff --git a/distrib/sets/lists/minix-man/mi b/distrib/sets/lists/minix-man/mi index 1756fdeeb..c49176705 100644 --- a/distrib/sets/lists/minix-man/mi +++ b/distrib/sets/lists/minix-man/mi @@ -367,6 +367,7 @@ ./usr/man/man1/tic.1 minix-man ./usr/man/man1/time.1 minix-man ./usr/man/man1/tmux.1 minix-man +./usr/man/man1/top.1 minix-man ./usr/man/man1/touch.1 minix-man ./usr/man/man1/tput.1 minix-man ./usr/man/man1/tr.1 minix-man diff --git a/external/bsd/Makefile b/external/bsd/Makefile index 95a84d8b8..224b56751 100644 --- a/external/bsd/Makefile +++ b/external/bsd/Makefile @@ -6,7 +6,7 @@ SUBDIR= byacc \ fetch file flex less \ libarchive libevent mdocml \ - tmux + tmux top .if (${MKATF} != "no") SUBDIR+= atf diff --git a/external/bsd/top/Makefile b/external/bsd/top/Makefile new file mode 100644 index 000000000..381754c91 --- /dev/null +++ b/external/bsd/top/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.2 2008/07/17 10:46:56 lukem Exp $ + +SUBDIR= bin + +.include diff --git a/external/bsd/top/bin/Makefile b/external/bsd/top/bin/Makefile new file mode 100644 index 000000000..ed4a75ac2 --- /dev/null +++ b/external/bsd/top/bin/Makefile @@ -0,0 +1,41 @@ +# $NetBSD: Makefile,v 1.9 2013/03/21 21:43:22 christos Exp $ + +.include + +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 diff --git a/external/bsd/top/bin/config.h.in b/external/bsd/top/bin/config.h.in new file mode 100644 index 000000000..02d1b3189 --- /dev/null +++ b/external/bsd/top/bin/config.h.in @@ -0,0 +1,257 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Support for debugging output */ +/* #undef DEBUG */ + +/* Default delay */ +#define DEFAULT_DELAY 5 + +/* Default number of processes to display */ +#define DEFAULT_TOPN -1 + +/* Enable color */ +#define ENABLE_COLOR 1 + +/* Enable dual architecture */ +/* #undef ENABLE_DUALARCH */ + +/* Enable kill and renice */ +#define ENABLE_KILL 1 + +/* Supports C99 style variadic macros */ +#define HAVE_C99_VARIADIC_MACROS 1 + +/* Define to 1 if you have the 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 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 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 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 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 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 header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_SYSEXITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMCAP_H 1 + +/* Define to 1 if you have the 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 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 and . */ +#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 */ diff --git a/external/bsd/top/dist/Changes b/external/bsd/top/dist/Changes new file mode 100644 index 000000000..98fc82f52 --- /dev/null +++ b/external/bsd/top/dist/Changes @@ -0,0 +1,949 @@ +Tue May 6 2008 - wnl (3.8beta1) + Main code: fixed bugs in screen_cleareol and in display code. Fixed + bug in i_swap when all data is 0. Added ^W patch (from thaquis). + Fixed bug in xdprintf. Added command line options for the "t" and + "m" commands. + SunOS 5 changes: Support for showing individual threads. Redid + allocation of prpsinfo structures. Added a pidthr hash that uses + both pid and thread id for a key. Changed format_process_header + and format_next_process to use a table-driven method for generating + the columns. Status files from /proc (psinfo and lpsinfo) are now + cached to avoid repeatedly reopening them. Column showing number of + LWPs is now called "NLWP" and column showing lwpid is "LWP". + FreeBSD changes: Runtime check to ensure binary is running on + the same machine type it was compiled for. Lots of cleanup and + changed nearly everything to use sysctl rather than kvm, and + inability to open kvm is no longer fatal. Improved thread reporting: + disabled for 7.x and lower. Added lwpid hash for proper tracking + of threads. Changed format_process_header and format_next_process + to use a table-driven method for generating the columns. + Dec Alpha: configure uses compile-time options to properly trap + and handle exceptions from the Alpha FPU (from Brian Maly). + +Tue Feb 26 2008 - wnl (3.7) + Prepare for version 3.7 release. + +Fri Feb 1 2008 - wnl (3.7beta4) + Using the $ notation in printf formats for freebsd apparently was + causing problems on 64-bit systems. All such usage has been + removed and the process line is formatted piecemeal. + +Thu Dec 27 2007 - wnl (3.7beta3) + Improved function comments in display.c for message_error functions. + Changed some of the error messages in top.c to be more succint. + +Fri Dec 7 2007 - wnl (3.7beta3) + Changes to freebsd port: moved some functions up front to + eliminate forward references. Use sysctl to get all vm stats + information, as some of this isn't updated in the struct + vmmeter under FreeBSD 7.0. Added routines to support large-scale + sysctl access. + +Wed Nov 28 2007 - wnl (3.7beta3) + Changes to documentation: FAQ, README, man page. + +Tue Nov 27 2007 - wnl (3.7beta3) + For freebsd, added page faults, pageins, pageouts, and pages + freed to the kernel display line. These numbers reflect the + values presented in vmstat. For sunos5, added page faults, + pageins and pageouts to the kernel display line. + +Fri Nov 2 2007 - wnl (3.7beta3) + Added copyright notices to the top of every source and include file. + Added copyright information to the man page. + Removed a few outdated things from the manifest. + Minor changes to sigconv.awk. + +Sat Oct 27 2007 - wnl (3.7beta3) + Added check for sys_signame at configure time and if it is + present then it is used in commands.c to translate signal names + in to numbers. + Added alternate snprintf and vsnprintf functions from apache (in + ap_snprintf.c). Added configure magic to define and compile them in + where needed. Added check to configure for variadic macros. + Preprocessor defintion of dprintf (in utils.h) now depends on + support for variadic macros. Cleaned up m_linux code. + +Wed Oct 3 2007 - wnl (3.7beta3) + Lots of changes, thanks to Mark Wong. Most changes were to + clean the code up so that it would compile cleanly with -Wall + (all warnings). Changed function names in screen.c so that + they all start with "screen_". Isolated all interaction with + termcap to screen.c by adding a real function for cursor + addressing (in the past it was just a macro). Only screen.c + now needs to worry about defining templates for the termcap + functions. Added configure and preprocessor magic to ensure + that all the termcap functions used in the code are defined + with templates. Changed names of some other functions and + global variables to avoid name conflicts with functions in + curses and other well established libraries. Changed dprintf + macro to use variadic arguments so that the preprocessor can + gobble up the entire call when compiling without debugging + (this will have to be made more portable). All include files + are surrounded by #ifndef statements to accomodate multiple + inclusions. Platform module is now compiled with + -fno-strict-aliasing as some of the modules do type punning + that can confuse the optimizer. + +Wed Sep 26 2007 - wnl (3.7beta3) + For freebsd, priority is no longer normalized by PZERO. This + contradicts the behavior used by ps when it displays priority. + But normalizing by PZERO has become a bit of an anachronism + and it actually obscures the meaning of the priority without + adding any real value. + +Wed Sep 19 2007 - wnl (3.7beta3) + Many changes to improve the display of threads. Changed + process summary line to use the word "threads" when showing + individual threads. Added the system command to toggle the + display of system processes. Fixed bug in hash.c remove_pos. + For freebsd: count threads correctly when they are being + displayed, nice column is more closely in line with ps + (nothing fancy for real time processes), add two more process + states that didn't exist in older releases of freebsd (wait + and lock). + For linux: Threads done right. Now track individual threads + of multi-threaded processes separately so that we always know + their %cpu. Switch to format_process_header so that we can + change the column headings and remove the THR column when + displaying individual threads. Switched process (and thread) + tracking over to use generic hash table functions included + with the new version of top. Process states and total now + include threads when they are being shown. Added "SHR" column + to show the amount of shared memory per process. Improved + calculation of elapsed time and percent cpu to avoid + overflows. Remove weighted cpu calculations entirely as it is + an anachronism. + For Solaris: Moved check for libelf to accomodate older systems. + +Sun Sep 9 2007 - wnl (3.7beta2) + Documentation changes. Fixes to sunos5 port. Added display of + thread count and selection by command name to linux port. Removed + the use of inline functions from hash.c as that doesn't appear to + be very portable. + +Wed Sep 5 2007 - wnl (3.7beta1) + Fixed freebsd and linux configuration bugs. Added configuration + options for tweaking program defaults. Rewrote top level code + (top.c) from scratch, including command handling so that adding + new commands is much easier. Changed message-line handling to + ensure that the message is displayed for at least 5 seconds + regardless of the update frequency. Added a "miniupdate" that + occurs one second after the initial screen on systems that don't + already delay the first screen. The mini-update shows cpu state + percentages. Added ability to select output by command name on + some systems. Fixed color toggling via the "C" command. Added + long options via getopt_long to complement the existing single + character options. Added the freebsd "m" command to chose + alternate display modes. On freebsd this gives a process i/o + display. Added the freebsd "H" command to select the display of + individual threads. Added "-a" option ("all") to set number of + displays and number of processes to infinity (equivalent to + "-d all all"). Added dual architecture compilation for Solaris + to generate both a 32-bit and a 64-bit binary. This is on by + default when compiling on a 64-bit system and can be explicitly + set via "configure --enable-dualarch". Added uniform hashing + functions that use bucket hash for uint, pid, and string. Changed + username.c and the sunos and freebsd modules to use these functions. + Added the "kernel" information line to the display to show + statistics on what the kernel is doing (context switches, forks, + traps, etc.). This requires explicit support by the platform + module, currently only freebsd, linux, and sunos. + +Wed Apr 18 2007 - wnl (3.6.1) + Fixed a few bugs in sigconv.awk that were causing incorrect + results on FreeBSD. Changed configure.ac to fix a few linux + problems: signal include file and /proc/1/stat. + +Fri Apr 13 2007 - wnl (3.6.1) + Removed the use of VPATH for compiling the system module and used + an explicit dependency in the Makefile instead. VPATH is now set + to just srcdir to ensure that top will compile correctly when + configured from a different directory. On systems without VPATH + support, top will still configure and compile, but only + from within the source directory. This fixes bug 1699526. + +Fri Feb 2 2007 - wnl (3.6.1) + Revised the way that configure figures out owner, group, and mode. + For systems that don't use the kernel, it tries to match install + settings to allow access to stuff in /proc. More importantly, if + mode is 755 then neither owner nor group are set. This fixes bug + 1631136. Added patch from haanjdj@xs4all.nl to fix an occasional + core dump in m_decosf1.c. This checks return code from task_threads. + Made sure all get_system_info functions are declared void. Fixed + string termination bug. Cleaned up documetation for sunos5. + +Tue Aug 8 2006 - wnl (3.6.1) + For Solaris, changed the tag "swap" to "total swap" to clarify + what is beign displayed. Note that the calculations are still the + same: the display is just showing total rather than total - free. + +Thu Apr 27 2006 - wnl (3.6) + Added patches for linux-style sort shortcuts and for Unixware + support in configure (patch 1474427). Fixed sunos5 to do slow start + and to ensure cpucount is set (patch 1477386). Added pagination + routines to display.c and modified show_help to use it, since the + help screen is now longer than 24 lines. Applied patch for unixware + support that adds check for mas library (patch #1474423). Solaris + cpu percent now reflects a percentage of the entire server, rather + than a single cpu (bug 1478138). + +Mon Mar 27 2006 - wnl (3.6) + The production release of version 3.6. Fixed a minor scaling + bug in the decosf1 module. Support for MacOS X is officially + withdrawn although the macosx module is still part of the + distribution. Hopefully this is a temporary situation. + Documentation updated. + + +Wed Feb 15 2006 - wnl (3.6beta5) + Minor changes to eliminate warnings from the Sun Studio compiler. + These were mostly sloppy argument declarations. I also added + message.h to provide an interface file for just the message + related functions of display.c. + +Mon Dec 26 2005 - wnl (3.6beta4) + Added new netbsd module, courtesy of Simon Burge. + Fixed a few bugs in SVR4 module and added its use to + configure.ac, thanks to Sanchet Dighe. Also ensured that the + novpath Makefile was in the distribution. + Fixed portability problem in display.c + + +Mon Oct 24 2005 - wnl (3.6beta3) + Set up a color tagging mechanism in color.c to allow for the + dynamic creation of tag names to contol color highlighting. + These names are partially derived from the tags used to label + memory and swap information on the screen, thus are driven by + the machine module itself. Added -T option to list color + highlighting information. Help screen now includes the actual + list of sort order names. Incorporated some minor fixes to + the main code from the Freebsd source tree. Fixed bug #1324582. + Freebsd 5: removed WCPU column and added THR column. Display + for freebsd 4 and earlier unchanged since they don't track + threads in the kernel. Added LICENSE file to distribution. + +Wed Oct 12 2005 - wnl (3.6beta2) + Major overhaul to display.c. All lines of the display are + directly tracked and controlled via display_write and its + companion display_fmt. Added support for complete control + of ANSI color on the screen: this will be used in the future + to allow for full use of color everywhere on the screen. + Signal handling code now uses sigaction on all systems that + support it. Restored the freebsd module and did away with + freebsd4, and upgraded freebsd module to support 5.x. + Fix bug #1306099 (wio(wait) timer ignored on OSF1). + +Fri Sep 23 2005 - wnl (3.6beta1) + Fixed bugs #1266341 (compilation errors with gcc 4.x), + #1156464 (cpu% field for sunos), #1156243 (compilation + errors on AIX). Applied patches #1217855 (Solaris 10 + xarch flag). Overhaul of sunos5 module, making code more + efficient and easier to follow. Got rid of need for MEMTYPE + type in utils.h. Changed all memory statistics data in the + module specification from an int to a long to better support + 64-bit systems with lots of memory. Moved all unused modules + out of the distribution (I will add them back in as needed). + Moved freebsd module to freebsd4 as it won't work with 5.x + (a new module will be necessary). Added support to configure + for makes that don't understand VPATH. Updated documentation: + man page, FAQ, README, INSTALL. + +Mon Jan 24 2005 - wnl (3.6alpha10) + Updated aix43 module with ANSI function declarations and fixed + declaration of get_system_info. Configure now uses irixsgi + module for irix6* systems. Updates to the following modules: + irixsgi, sunos5. Fixed null pointer bug in color.c. Removed + some useless code and definitions in display.c + + +Sun Nov 28 2004 - wnl (3.6alpha9) + Replace AIX 5 module with alternate (bug 1056565). + Fixed vulnerability in use of snprintf. + +Fri Oct 22 2004 - wnl (3.6alpha8) + Support for linux 2.6, added more stuff to memory and swap lines. + Updated linuxthr module, which is only useful on 2.4 and earlier. + Added some color support back in (feature request 930588), but + still need to add it back to the per-process display. Added + OSF 5 support (untested). + Fixed bug 1017951 (invalid process count argument not caught) + +Tue Apr 20 2004 - wnl (3.6alpha7) + Added 64 bit support for AIX. + +Thu Apr 15 2004 - wnl (3.6alpha6) + Included fixes for decosf1 pid size and updated module. Also + added osf1 to list of recognized operating systems in configure.ac. + +Tue Mar 30 2004 - wnl (3.6alpha5) + Minor bug fixes and some code rearrangement. Changes to install + rule. Added several more platforms including: aix 4.2 thru 5, + MacOS 10, Dec OSF, HPUX 7 thru 11. Fixed the core dumping bug + in linux. Code cleanup, including sigdesc.h (by changing + sigconv.awk). Startup error messages are displayed on the + first screen rather than beforehand (no more pause). Cleaned + up interrupt handling to avoid a race condition. Eliminated + top.local.h. REMOVED Configure!!! + +Mon Mar 22 2004 - wnl (3.6alpha1) + Now using gnu autoconf. Eliminated the need for CFLAGS and LIBS + tags in the module source files. Autoconf tries to figure all + that out now. Machine module interface now uses flags to determine + if module supports sorting, selective display of idle processes, + viewing full commands. Added display of uptime for modules that + support it. Added display of full command lines for modules that + support it. 3.5 modules must be changed a bit to work for 3.6: + ORDER is no longer defined, and the module must fill in the + appropriate fields in struct statics to get the extra features. + Added a extenstion interface to allow for putting extra stuff + on the screen -- this is still half baked and not documented. + +Mon Feb 23 2004 - wnl (3.5) + Turned rc1 in to version 3.5. Only changes were to the FAQ. + +Mon Feb 2 2004 - wnl (3.5rc1) + Changed format_k (utils.c) to use MEMTYPE for its parameter. + On most systems this is a long, but if the module defines + USE_SIZE_T, this is set to be a size_t. The sunos5 module + now defines it, so that it will work correctly on 64-bit + machines. New "linuxthr" module for rolling up processes + that are really threads. Configure autodetects when running + on a 64-bit Solaris machine. + +Tue Dec 16 2003 - wnl (3.5beta13) + Improved linux module. For Solaris, changed "THR" column + heading to "LWP" since that's what they really are. + +Thu Mar 30 2000 - wnl (3.5beta12) + Updated modules: m_aix41.c, m_aix43.c, m_mtxinu.c, m_sco5.c, + and m_ultrix4.c. + Included m_irixsgi.c from some source that's been floating around + SGI. Don't yet know how it compares to m_irix62. + +Fri Mar 10 2000 - wnl (3.5beta11) + top.c: avoid potential loop if stdout gets closed, use macro + for p_active to avoid collision with system macros. + m_sunos5: widened some fields to accomodate 5.8. + m_decosf1: added ordering support + m_irix62_64: provides 64-bit module based on m_irix62. + m_irix62: skip bogus files in /proc directory + m_svr42MP and m_svr5: complete replacement with updated copies + m_mtxinu: complete replacement with updated copies + m_aix43: new module for 4.3 + getans: replaced with a Bourne shell script + +Mon Mar 6 2000 - wnl (3.5beta10) + m_sunos5.c: workaround for curses bug: ensure that TERMINFO has + a value. + +Fri Jan 15 1999 - wnl (3.5beta10) + top.c: now check return code from read to avoid looping on eof. + top.c: delay of 0 now only valid for root. + decosf1.c: patches from Rainer Orth should fix most of the + problems with this module (including the display of certain + processes and runtime errors). + sunos5.c: Rainer insisted on putting the slash back in the + state field ("run/4") and widened the field to accomodate it. + aix.c: widened PID field for 6-digit pids (shortened NICE field) + module macosx added, thanks to Andrew Townley. + +Fri Dec 18 1998 - wnl (3.5beta9) + Configure checks status of "make" and complains if it fails. + +Thu Dec 17 1998 - wnl (3.5beta9) + Added module sco5 from Mike Hopkirk. + Added module netbsd132 from moto kawasaki. + +Sun Oct 25 1998 - wnl (3.5beta9) + Added Casper's patches for sunos5 for the following: + produce same results as swap -s (5.5 and higher), + don't use system_pages kstat when /dev/kmem can be opened, + skip . and .. when reading /proc, replace use of SOLARIS24 + with OSREV. + +Fri Sep 11 1998 - wnl (3.5beta9) + Added workaround to getans for the absence of $< in SCO Unix. + +Wed Jul 1 1998 - wnl (3.5beta9) + Changed structure member "errno" to "errnum" in commands.c. + Replaced hpux10 module with one from John Haxby. + +Fri Apr 17 1998 - wnl (3.5beta8) + Moved definition of _KMEMUSER earlier in m_sunos5.c. This should + fix the compilation problem with gnu 2.7.2.3, obviating the need + for the fixinc.svr4 patch, but hopefully will not affect anything + else. + Added -DORDER to m_sunos4mp.c + +Tue Nov 18 1997 - wnl (3.5beta7) + Added gcc 2.7.2.3 patch for fixinc.svr4 and changed INSTALL and + FAQ to refer to it. + Added NetBSD HP9000 fix. Hopefully it doesn't break other + NetBSD platforms. + +Fri Oct 24 1997 - wnl (3.5beta7) + Modified m_dcosx.c to change uses of procdir to xprocdir, avoiding + a name clash with an include file (Bryn Parrott) + +Sat Oct 11 1997 - wnl (3.5beta6) + Incorporated Casper's patches for Solaris 2.6 and for the multi- + processor bug ("kstat finds too many cpus"). + +Sun Jan 20 1996 - wnl (3.5beta5) + Fixed Casper's m_sunos5 module: there was a poor interaction with + his use of OSREV and SunOS 5.5.1. + +Fri Dec 20 1996 - wnl (3.5beta4) + Replaced m_sunos5 with a reworked version by Casper Dik. This one + should work under 2.6 and may not require that top be run setuid + to root under 2.5 or 2.6. This also fixed a bug in m_sunos5 that + was introduced in beta3. + Fixed calculation of OSREV in Configure. + +Wed Nov 20 1996 - wnl (3.5beta3) + Incorporated contributed fixes to: bsdos2, irix62, freebsd20, + ultrix4, sunos5. Changed calculation of swap area in sunos5 (now + uses swapctl). sunos5 now understands idled processors. Changed + Configure to determine os revision using uname (when available) + and adding it to machine.c compiliation in Makefile as -DOSREV. + Changed calls to "exit" in modules to use "quit" instead. + +Oct 20 1996 - wnl (3.5beta3) + Removed "time" from list of ordering choices: there's no easy way + to get cpu time for all processes (it's in the u area). + +Fri Oct 18 1996 - wnl (3.5beta3) + hpux10 and hpux9: using a better means for determining when a + process is idle. + decosf1 now includes utils.h. + +Fri Sep 13 1996 - wnl (3.5beta2) + Fixed Configure to build Make.desc in such a way that doesn't + require a long argument to sed. + +Thu Sep 12 1996 - wnl (3.5beta2) + Fixed bug in display.c that affected empty cpustate names. + Created hpux1010 module - a variant of hpux10 that does not use + struct proc or struct user (suitable for HP/UX 10.10). + +Wed Sep 11 1996 - wnl (3.5beta2) + Changes to sunos5 module: Removed WCPU column since it is meaningless + on a SVR4-based system. Added THR column to show number of threads + for each process. This was not straightforward: the information is + not stored in prpsinfo but rather in prstatus. + +Tue Sep 10 1996 - wnl (3.5beta1) + Added patches for sunos4mp to provide order support. + Added irix62 module. + Changed prime.c to include stdio.h for printf prototype. + Added conditional code to os.h and utils.c to handle systems + where sys_errlist is defined in stdio.h (such as NetBSD). + +Mon Sep 09 1996 - wnl (3.5beta1) + Removed tar and shar rules from Makefile.X -- don't need them anymore. + Added -v option to display version number. Updated man page. + +Thu Aug 29 1996 - wnl (3.4) + Replaced modules (from Tim Pugh): next 32, next40. + Fixed bug in username.c: hashing negative uids. + +Thu Aug 22 1996 - wnl (3.4beta3) + Patched modules: ultrix4, sunos4, sunos5, utek, decosf1, irix5. + Added modules: next40, next32. + Fixed procstates update bug in display.c. + Fixed divide by zero bug in utils.c. + Fixed bad number in layout.h + Minor fixes to Configure. + Complete overhaul of FAQ. + +Tue Feb 13 1996 - wnl (3.4beta3) + Added convex module from Warren Vosper (originally written by + William Jones). + +Tue Feb 13 1996 - wnl (3.4beta2) + Fixed format_k in utils.c to calculate K and M values correctly. + Added check for gigabyte values ('G'). Changed sumamry_format + in display.c to use format_k where appropriate. + Changed creation of distribution tar file to place everything in + a top level directory. + +Tue Jan 30 1996 - wnl (3.4beta2) + Added m_aix41 module. Added new tag type to module comments: + TERMCAP, which defined the library to use for a termcap library. + If no TERMCAP tag is found in the module's initial comment, then + Configure will default to "-ltermcap". AIX needs this since it + put all the termcap routines in libcurses(!) + + Added m_bsdos2 (found lingering in my mailbox). + Updated m_svr4 to include support for NCR multiprocessors. + Fixed small bug in utils.c + +Thu Jan 25 1996 - wnl (3.4beta1) + Fixed m_sunos5 invocation of gettimeofday to include "NULL" as + second argument. This provides compatability with the Posix- + compliant template provided with SunOS 5.5, but doesn't hurt + previous versions since they do bother with a template for that + function. + + Made changes (recommended by net users) to hpux10, ultrix4, + netbsd10, aux3 (replaced aux31). Added module for linux. + +Fri Oct 10 1995 - wnl (3.4beta1) + Added user-contributed modules for SCO Unix, IRIX 5, HP/UX 10, + Pyramid DC/OSX. Changed Configure so that it runs in environments + whose c-shells have no 'eval'(!). Added support for multiple sort + ordering methods via the -o switch. This option requires support + from the machine dependent module: such support was added to + sunos5 (thus sunos54) and sunos4. + + display.c: Changed CPU states display line to shorten the leading + tag if the data won't fit in the current width. Fixed a divide-by- + zero bug that affected ultrasparc servers (and potentially other + systems). + + m_sunos5.c: Now asks the system for the correct pagesize rather than + assuming it is 4K. + +Thu Mar 2 1995 - wnl (3.3 RELEASE) + Added module netbsd10 and renamed netbsd to netbsd08. Changed + Configure so that it does not use an initial default module name. + Made other compatability fixes to Configure. Added comments to + decosf1 concerning optimizer bug. Other documentation changes. + Added use of "prime.c" to Configure script. + +Tue Feb 7 1995 - wnl (3.3beta6) + Still one more beta.... + Fixes for sunos5 2.4 gcc core dump (it was an alignment problem). + Fixed and improvements for decosf1 (including use of format_k + for proper SIZE column formatting). Added modules freebsd20 and + ncr3000. + +Thu Feb 2 1995 - wnl (3.3beta5) + One more beta.... + Fixed a few bugs in the sunos5 port pertaining to casting and + very large memory counts. Added "ifndef HAVE_GETOPT" to getopt.c + to provide for conditional compilation of the getopt function. + Those systems that have getopt in libc can add -DHAVE_GETOPT to + the CFLAGS line in the module to prevent the function from being + compiled. Added sunos54 module to accomodate SunOS 5.4 + peculiarities. Added module for aux3.1. + +Wed Jan 4 1995 - wnl (3.3beta4) + This is really taking too long......sigh. + Fixed SIGWINCH handling once and for all. It now remembers the + number of processes you want displayed even thru window resizes. + Fixed buffer conflict in utils.c (itoa and itoa7). + Lots of small improvements to the various modules were made over + the past month: too numberous to list here. SunOS 5 module made + more secure thru use of seteuid calls (other SVR4 modules should + be modified similarly). One final MP fix to sunos5, too. Module + for decosf1 was modified to accomodate V3.0. + +Mon Apr 18 1994 - wnl (3.3beta3) + I think I finally got a sunos5 module that will work on MP + machines. Fixed cpu states figure in osmp41a so that + percentages never exceed 100%. Added shell script "install" + since Unix vendors can't seem to make up their minds on what + options they want to use for the one that comes with the OS. + Added netbsd modules from Christos. Fixed lots of other little + things over the past few months that I have long since forgotten. + +Wed Dec 15 1993 - wnl (3.3beta2) + Added module patches from various users: hpux9, sunos5. + Fixed bug with batch mode (screen_width wasn't getting set). + Changes to accomodate 64 bit machines. + Fixed some bugs in command parsing ("renice 19 " did something + unexpected). + +Mon Aug 30 1993 - wnl (3.3beta) + Added lots of little patches from various users. + Added routines to utils.c for intelligent formatting of kilobytes + and time. These are intended to be used in the modules when + formatting a process line. Added code to "summary_format" in + display.c to do intelligent formatting of memory quantities. + Redid display.c to allow for varying line widths and dynamic + reallocation of the screen buffer. + Added a SIGWINCH handler to top.c! + Added a constant, MAX_COLS, to top.h which defines the absolute + widest line we will ever allow. Changed allocations of "char fmt" + in all machine modules to use this constant rather than an abitrary + number. + +Fri Aug 13 1993 - wnl (3.3) + Changed return value definition of time-related functions in top.c, + display.c, and m_ultrix4.c to time_t (stuart@coral.cs.jcu.edu.au). + Fixed bug in display.c: line_update when start != 0. + +Wed Aug 4 1993 - wnl (3.2 release) + Changes to Configure from Paul Vixie. Added modules for hpux9 and + bsd386. + +Tue Jul 13 1993 - wnl (3.1 release) + More small changes and minor bug fixes. Brought bsd44 up to date + and added a module for svr4.2. Changed shar packaging to use Rich + Salz's cshar stuff. + +Wed Jul 7 1993 - wnl (3.1BETA) + More changes and bug fixes to Configure. Applied some other + minor bug fixes and suggestions from the beta testers. Added + the "metatop" shell script and the "installmeta" rule to the + Makefile to make handling multiple machine models and OS versions + easier. Added INSTALL and FAQ files. + +Tue May 18 1993 - wnl (3.1BETA) + Changed Configure to be compatible with most SVR4 environments + (differing output from "ls -lg"). Also changed Configure, + Makefile.X, etc., to look for module files in the subdirectory + "machine" (thanks to Christos Zoulas). + +Tue Apr 20 1993 - wnl (3.1BETA) + Changed both occurences of "ls -1" in Configure to "ls". This + SHOULD produce the same result, and has the advantage that it + doesn't produce an error on a system 5 machine. Integrated other + changes recommended in the first round of beta testing. + +Wed Mar 10 1993 - wnl (3.1BETA) + MAJOR CHANGE: I have added a required function to all machine + dependent modules, called proc_owner. It takes a pid as an argument + and returns the uid of the process's owner. Such capability is + necessary for top to run securely as a set-uid program, something + that is needed for SVR4 implementations to read /proc. I have + retrofitted all modules except dgux with this function, but was + not able to test most of them. Top should now run securely as + a setuid program. Added 386bsd and sunos5 modules. Added sunos4mp + module for MP Suns. + +Sat Feb 20 1993 - wnl (3.1ALPHA) + Modified top.c and commands.c to compile correctly on System V + derived Unixes (especially SVR4), but in a way that doesn't rely + on an oracle-like declaration (that is, I don't use "ifdef SYSV"). + Fixed some bugs in "Configure" and "getans". Added inspection of + env variable "TOP" for options, and made -I default to showing + idle processes. Added "u" command to change username restriction + on the fly. Created shell script "suntop" for poor multi-version + SunOS folks (like myself). + +Wed Jun 3 1992 - wnl (3.0) + "max_topn" wasn't being used everywhere it was supposed to be + in top.c. Many cosmetic changes, including copyright notices in + all the .c files. Version number is now handled by version.c and + reflects the current patchlevel (which is initially set to 0). + Changed Configure and Makefile to allow configurable variables for + certain commands: shell, cc, awk, install. Updated README and + Porting. Ready to release to the world! + +Mon May 18 1992 - wnl (2.9BETA) + Added modules provided by Christos Zoulas. Replaced screen.c + with one modified by Christos and that will appropriately select + and handle the sgtty, termio, or termios system. Integrated many + other changes recommended by Christos. Fixed (I hope) the "-b" + batch mode display bug. Had to change loadavg to load_avg to avoid + a conflict with 4.4BSD. + +Mon Apr 27 1992 - wnl (2.8BETA) + Added modules provided by Daniel Trinkle. Added patchlevel.h, + but the patch level is not yet reflected in the version number. + Cleaned up m_sunos4.c a little. + +Wed Apr 22 1992 - wnl (2.8BETA) + Major internal reorganization. All of the system dependent stuff + is now really and truly separated from everything else. The + system dependent functions are contained in a separate .c file + called a "module". The Configure script knows how to find and + set up these modules, but the human installer still needs to tell + Configure which module to use (no automagic determination of + machine type---sorry). Added -U option to specify one user's + processes, but there is no corresponding command...yet. Other + changes and improvements too numerous to mention here. Currently + there are only two modules: sunos4 and umax. But after this beta + release is sent around, I expect more to be written. I just hope + that the machine-dependent abstractions don't need to change in + the process. + +Thu Mar 26 1992 - wnl (2.7BETA) + Beta release with minimal architecture support. Updated README + and added a first cut at a Porting guide. Added ioctl TIOCGWINSZ + code from top2.5+ (courtesy of David MacKenzie). I didn't even + try porting the Ultrix support since I don't have access to an + Ultrix machine. + +Fri Oct 11 1991 - wnl (2.6) + This version was not widely released. It contained many changes. + Here are the major ones: + + Put in Vixie's idle process hack. + + Enhanced type field in new_message to handle delayed messages. + + Changed u_process to automatically adjust for varying lines of + output. Management of screenbuf should now be completely contained + in display.c. Removed now extraneous code from CMD_number[12] + portion of command switch in top.c. This was the stuff that dealt + with zeroing out lines in screenbuf. + + Finally made it all work correctly on a 386i. Problems I had to + overcome: kvm_nlist doesn't return 0 on success as advertised (it + returns 1 instead); the results of a kvm_nlist are different + (n_type can be zero even for a symbol that exists). + + Serious rearrangement for processor dependent stuff. All nlists + are now in separate files with the suffix ".nlist". Most machine + specific code is in "machine.c" surrounded by appropriate ifdefs--- + the goal is to eventually have all machine specific code in this + file. Managed to find a way to detect SunOS 4.x at compile-time: + this is contained in the include file "sun.h". Completely changed + the memory display line for SunOS 4.x---it now displays a far + more appropriate report. + + Created the shell script "Configure" to aid in the configuration + step. + + Fixed a bug in init_termcap: it will now tolerate an environment + which does not have TERM defined (thanks to Sam Horrocks for + pointing this out). + +Tue Aug 9 1988 - wnl (2.5) + Added changes to make top work under version 4.0 of the Sun + operating system. Changes were provided by Scott Alexander of the + University of Pennsylvania. Thanks! Compile with "-Dsunos4" to + get them. Virtual memory statistics are not readily accessible + under 4.0, so they don't show up in the output. + +Thu Jul 31 1987 - wnl (2.4) + Fixed a problem with the 4.0 Pyramid code. The label "cp_time" + doesn't exist in the 4.0 kernel anymore. I think the code Carl + sent me wants "percpu" instead. That is what I am using and it + appears to work. 375 code is still untested (at least by me). + Also picked a great deal of lint out of the source. Lint now only + complains about a very few nitpicky things (there are far too many + calls to "printf" to put a "(void)" in front of!), at least under + SunOS. + +Tue Jul 28 1987 - wnl (2.4a) + Added changes for a Symmetrics Computer Systems s/375 machine. + Changes were provided by Paul Vixie. Thanks! According to Mr. + Vixie: "These changes were not made at, by, or for SCS proper. + SCS would probably be interested in them, but so far only the + users' group has them. They were made in February, 1987, to + version 2.1 of the program, by Paul Vixie + (dual!ptsfa!vixie!paul@ucbvax.Berkeley.EDU)." His changes were + integrated into version 2.3 to make version 2.4. + + The SCS peculiarities are summarized in Changes.scs. + +Tue Jun 9 1987 - wnl (2.3 for real) + Changed the includes for the extra code Carl sent me to only + compile on Version 4.0 Pyramid machines. This makes top still + compilable on pre-4.0 Pyramids. Specifically, this code is only + compiled when both "pyr" and "CPUFOUND" are defined. + +Wed Jun 3 1987 - wnl (2.3 with Pyramid additions) + It's been a month and I still haven't done anything about + distributing this version. However, Carl Gutekunst from Pyramid + has sent me some extra patches for some of the Pyramid code. I + just added those and will make them part of 2.3. This fixes the + following Pyramid problems: adds the inclusion of , + 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. diff --git a/external/bsd/top/dist/FAQ b/external/bsd/top/dist/FAQ new file mode 100644 index 000000000..92613e427 --- /dev/null +++ b/external/bsd/top/dist/FAQ @@ -0,0 +1,340 @@ + TOP + Version 3.8beta1 + + William LeFebvre + with much help from others + + Frequently Asked Questions and their Answers + + + + GENERAL + + 1. What is top? + + Top provies the user with a regularly updated display showing + information about the system and its top cpu-using processes. Think + of it as a full-screen "ps" output that gets updated at regular + intervals. + + 2. Where do I get the latest version of top? + + The official site for top is "ftp.unixtop.org" in the directory + "/pub/top". Top is also a SourceForge project, and the most recent + releases are available on any of the SourceForge mirrors. The + SourceForge project page is at + http://sourceforge.net/projects/unixtop. + + 3. Is there a web page for top? + + Yes. Point your browser at http://www.unixtop.org. It includes all + documentation, a nice interactive display which describes the various + components of the output of top, web-based retrieval of the package, + year 2000 information, and other neat stuff. + + 4. Is there a mailing list or on-line bulletin board for top? + + There is a mailing list used for general announcements regarding top, + including new releases. This mailing list is available to sourceforge + members and can be accessed from the unixtop sourceforge project + page. Visit SourceForge and search for the project "unixtop", then + click on "mailing lists". There are also on-line forums available + through SourceForge where members can post questions and comments. + + 5. What about Year 2000 compliance? + + Top did not experience any problems with the transition to the year + 2000. A full statement concerning top and the year 2000 can be found + in the file "Y2K" included with the distribution. + + 6. Will there be another major release of top? Will there be a top + version 4? + + I have some great ideas for the next major release of top, and I very + much want to make those ideas a reality. What I don't have much of + these days is free time. But I will keep poking at it and I hope to + have top version 4.0 ready by the fall of 2006. + + 7. Does top really support multi-processor systems? + + On platforms that support multiple processors, top is able to detect + and correctly summarize the information about those processors. What + top does not do is break down the cpu states summary (the third line + of the display) by cpu. Instead it collects the cpu state information + from all processors and combines them in to a single line. Some + vendors include a modified version of top that presents this + information for each cpu. Top 3.7 may have this functionality but it + is not present in the standard top 3.6 release. + + 8. Is top under CVS control? Can I access the sources via SourceForge + CVS or Subversion? + + I maintain top using subversion, not CVS. Although I utilize my own + private subversion repository, it is regularly mirrored in to the + SourceForge Subversion repository. You can access the SourceForge + repository here: https://svn.unixtop.org/unixtop/top-3. + + + COMPILING + + 9. We just upgraded our operating system to a new version and top broke. + What should we do? + + Recompile it. Top is very sensitive to changes in internal kernel + data structures. It is not uncommon for a new version of the + operating system to include changes to kernel data structures. + + + RUNNING + +10. I just finished compiling top and it works fine for root, but when I + try to run it as a regular user it either complains about files it + can't open or it doesn't display all the information it should. Did I + do something wrong? + + Well, you're just not done. On many operating systems today, access + to many of the kernel memory devices and other system files is + restricted to either root or a particular group. The configure script + figures this out (usually) and makes sure that the "install" rule in + the Makefile will install top so that anyone can run it successfully. + However, you have to *install* it first. Do this with the command + "make install". + +11. Top is (not) displaying idle processes and I don't (do) want it to. + + This default has only changed about a dozen times, and I finally got + tired of people whining about it. Go read the manual page for the + current version and pay special attention to the description of the + "TOP" environment variable. + +12. We have so much memory in our machine that the memory status display + (the fourth line) ends up being longer than 80 characters. This + completely messes up top's output. Is there a patch? + + Most modules have been changed to use new memory formatting functions + which will display large values in terms of megabytes instead of + kilobytes. This should fix all occurences of this problem. Also note + that newer versions of top can use columns beyond 79, and understand + window resizes. So you can always make your window wider. + +13. I tried to compile top with gcc and it doesn't work. I get + compilation errors in the include files, or I get an executable that + dumps core, or top displays incorrect numbers in some of the + displays. What's wrong? + + Gnu CC likes very much to use its own include files. Not being a gcc + expert, I can't explain why it does this. But I can tell you that if + you upgrade your operating system (say from Solaris 2.6 to Solaris + 2.7) after installing gcc, then the include files that gcc uses will + be incorrect, especially those found in the "sys" directory. Your + choices are: (1) rebuild and reinstall the "standard" include files + for gcc (look for scripts in the distribution called "fixincludes" + and "fixinc.svr4"), (2) compile machine.c with + "CFLAGS=-I/usr/include" then make the rest of the object files + normally, or (3) use a different compiler. + +14. The cpu state percentages are all wrong, indicating that my machine + is using 95% system time when it is clearly idle. What's wrong? + + This can happen if you compiled with gcc using the wrong include + files. See the previous question. + + + FREEBSD PROBLEMS + +15. This version of top does not show individual threads with the "t" or + "H" commands. Instead it says "command not available." Why? + + Previous versions of top attempted to support the display of + individual threads under FreeBSD through the use of the "t" command. + However, the FreeBSD kernel does not supply sufficient or correct + information on the individual threads within a process. So the data + that was being displayed was incorrect and misleading. Therefore, top + version 3.8 disables the use of this command to prevent the display + of incorrect information. FreeBSD 8.0 will correctly report + per-thread information and top version 3.8 supports the use of the + "t" command for version 8.0. + +16. The "f" command (to display full command lines for the processes) + does not work and instead says "command not available". Why? + + The current version of top is able to use sysctl to retrieve almost + all of the information it needs without having to open /dev/kmem. The + one piece of information not available via sysctl is the full command + line of each argument. If you run top as a regular user and it cannot + open /dev/kmem (in other words, it is not installed set-gid to the + kmem group) then it will disable the "f" command. Make sure the top + binary is installed with a group ownership of "kmem" and with the + set-gid bit on if you want the "f" command to work properly. + + + MACOSX PROBLEMS + +17. I tried to configure top on my Mac OSX system and I got an error + claiming "macosx not supported". What up? + + Since I don't have full time root access to a Mac OSX system I cannot + provide effective support for the platform. MacOSX uses Mach, and it + is very difficult to extract accurate system and process information + from the system. It takes a lot of trial and error, along with root + access. I have included the most up-to-date version of the macosx + module in the distribution, but I do not claim that it works. If you + want to try to use it, you can configure with "./configure + --with-module=macosx". + + + SUNOS PROBLEMS + +18. I tried compiling top under SunOS version 4.1.x and it got compile + time errors or run time errors. Is there a patch? + + If you try compiling top in a "System V environment" under SunOS + (that is, /usr/5bin is before /usr/bin on your path) then the + compilation may fail. This is mostly due to the fact that top thinks + its being compiled on a System V machine when it really isn't. The + only solution is to put /usr/bin and /usr/ucb before /usr/5bin on + your path and try again. + + + SOLARIS PROBLEMS + + + NOTE: the most common source of problems with top under Solaris is + the result of compiling it with the wrong front end. Make sure that + /usr/ucb is not on your path before attempting to compile top under + Solaris. + +19. Is there somewhere I can get a pre-compiled package? + + Yes. Although I don't provide pre-compiled binaries, you can get a + Sun-style package from www.sunfreeware.com. + +20. Under Solaris 2, when I type "make", the system says "language + optional software package not installed." What's going on? + + You tried to compile with /usr/ucb/cc. Make sure /usr/ucb is not on + your path. Furthermore, you do not have a Sun compiler installed on + your system. You need a compiler to make top. Either Sun's C compiler + or the Gnu C compiler will work fine. + +21. Under Solaris 2, when I run top as root it only shows root processes, + or it only shows processes with a PID less than 1000. It refuses to + show anything else. What do I do? + + You probably compiled it with /usr/ucb/cc instead of the real C + compiler. /usr/ucb/cc is a cc front end that compiles programs in BSD + source-level compatability mode. You do not want that. Make sure that + /usr/ucb is not on your path and try compiling top again. + +22. Under Solaris 2, I compiled top using what I am sure is the correct + compiler but when I try to run it it complains about missing dynamic + libraries. What is wrong? + + Check to see if you have LD_LIBRARY_PATH defined in your shell. If + you do, make sure that /usr/ucblib is not on the path anywhere. Then + try compiling top again. + +23. Under Solaris 2, when I try to run top it complains that it can't + open the library "libucb.so.1". So I changed the LIBS line in + m_sunos5.c to include -R/usr/ucblib to make sure that the dynamic + linker will look there when top runs. I figured this was just an + oversight. Was I right? + + No, you were not right. As distributed, top requires no alterations + for successful compilation and operations under any release of + Solaris 2. You probably compiled top with /usr/ucb/cc instead of the + real C compiler. See FAQ 22 for more details. + +24. On my 64-bit system some processes show up with incorrect information + (such as zero memory). + + If you are running a 64-bit system, then you need to make sure that + you are running the 64-bit top binary. Top's configure script + attempts to detect 64-bit systems, and will automatically generate + both 32-bit and 64-bit binaries on such systems. If you use or + install the 32-bit binary on a 64-bit system top will still run but + will not produce the correct results. This will also happen if you + configure your distribution on a 32-bit system then compile with that + configuration on a 64-bit system. You must configure and compile on + the same system. For Sparc systems the 32-bit binary will be created + in the subdirectory "sparcv7" and the 64-bit binary will be created + in the subdirectory "sparcv9". For Intel systems the directories will + be "i386" (32-bit) and "amd64" (64-bit). In all cases a copy of + /usr/lib/isaexec is made in the main directory and called "top". This + program will choose the correct binary to run from one of these + subdirectories. See isaexec(3c) for more details. + +25. Can I install both 32-bit and 64-bit binaries on a central file + server and have machines which mount it automatically use the correct + one? + + Yes. If you configure and compile on a 64-bit system, top's configure + script and makefile will automatically create both 32-bit and 64-bit + binaries. The "install" rule in the makefile will install these + binaries in subdirectories of /usr/local/bin appropriate to the + architecture (sparcv7/sparcv9 or i386/amd64) then create a copy of + /usr/lib/isaexec named "top" in /usr/local/bin to ensure that the + appropriate is run when a user types "top". If you make sure that you + configure and compile on a 64-bit system, then "make install" will do + the right thing. + +26. This version of top show less available swap space than previous + versions. Why does it no longer match the output of the swap summary + produced with "swap -s"? + + Starting with version 3.6 of top, the amount of swap space reported + by top has been changed to reflect only disk-based swap space. The + swap summary produced with "swap -s" also includes memory-based swap + space. This changed was made for several reasons. It makes the + display under Solaris more like those of other operating systems. The + display is more what users expect (except those used to previous + versions of top). Most importantly, "swap -s" gets its data via an + undocumented system interface. Now that top no longer displays that + data it can use publically documented and maintained system + interfaces to retrieve its data. + + + SVR4-DERIVED PROBLEMS + +27. When I run top on my SVR4-derived operating system, it displays all + the system information at the top but does not display any process + information (or only displays process information for my own + processes). Yet when I run it as root, everything works fine. What's + wrong? + + Your system probably uses the pseudo file system "/proc", which is by + default only accessible by root. Top needs to be installed setuid + root on such systems if it is going to function correctly for normal + users. + + + SVR42 PROBLEMS + +28. The memory display doesn't work right. Why? + + This is a known bug with the svr42 module. The problem has been + traced down to a potential bug in the "mem" driver. The author of the + svr42 module is working on a fix. + + + STILL STUCK + +29. I'm still stuck. To whom do I report problems with top? + + The most common problems are caused by top's sensitivity to internal + kernel data structures. So make sure that you are using the right + include files, and make sure that you test out top on the same + machine where you compiled it. Sun's BSD Source Compatability Mode is + also a common culprit. Make sure you aren't using either /usr/ucb/cc + or any of the libraries in /usr/ucblib. Finally, make sure you are + using the correct module. If there does not appear to be one + appropriate for your computer, then top probably will not work on + your system. + + If after reading all of this file and checking everything you can you + are still stuck, then please use SourceForge to submit a support + request or a bug. Top is supported by the SourceForge project named + "unixtop". On SourceForge you will find defect tracking, a mailing + list, and on-line forums. You can also contact the author through + SourceForge. + diff --git a/external/bsd/top/dist/INSTALL b/external/bsd/top/dist/INSTALL new file mode 100644 index 000000000..fe99ffeec --- /dev/null +++ b/external/bsd/top/dist/INSTALL @@ -0,0 +1,54 @@ + TOP + Version 3.8beta1 + + William LeFebvre + and a cast of many + +INSTALLATION + +Configuration and installation of top is easy. Top version 3.6 +comes with a configure script generated by gnu autoconf. After +unpacking the tar file, simply run "./configure". The script will +automatically perform a series of checks on the system and determine +what settings are appropriate for the Makefile and certain include +files. Once configure completes, simply type "make install" and +top will be compiled and installed. By default, the installation +location is /usr/local/bin. You can change the destination location +with the --prefix option to configure. + +In addition to the standard options, top's configure script supports +the following: + + --with-module=name + + Force the use of a particular module. Modules are located + in the subdirectory "machine". A module's name is derived + from the file's basename without the leading "m_". + + --with-ext=name + + Compile with the extension "name", found in the subdirectory + "ext". At the present time, there are no extensions in the + standard distribution. + + --enable-debug + --disable-debug + + Default off. Include debugging output in the compilation, + which can be seen with the -D switch. + + --enable-color + --disable-color + + Default on. Include code that allows for the use of color + in the output display. Use --disable-color if you do not + want this feature compiled in to the code. The configure + script also recognizes the spelling "colour". + + --enable-kill + --disable-kill + + Default on. Include code that allows for renicing and sending + signals to processes from within top (the 'kill' and 'renice' + commands). Use --disable-kill if you do not want this feature + compiled in to the code. diff --git a/external/bsd/top/dist/LICENSE b/external/bsd/top/dist/LICENSE new file mode 100644 index 000000000..3b210dc10 --- /dev/null +++ b/external/bsd/top/dist/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 1984 through 2008, William LeFebvre +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of William LeFebvre nor the names of other +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/external/bsd/top/dist/Makefile.in b/external/bsd/top/dist/Makefile.in new file mode 100644 index 000000000..ac97b3560 --- /dev/null +++ b/external/bsd/top/dist/Makefile.in @@ -0,0 +1,92 @@ +# Makefile +# +# This makefile was generated by configure from a Makefile.in definition. + +PROGRAM=top +INC=boolean.h color.h commands.h config.h display.h globalstate.h hash.h \ + loadavg.h machine.h message.h os.h screen.h sigdesc.h top.h username.h \ + utils.h version.h +SRC=color.c commands.c display.c hash.c screen.c top.c username.c utils.c version.c @SRC@ +OBJ=color.o commands.o display.o hash.o screen.o top.o username.o utils.o version.o @OBJ@ +MANPAGE=top.1 +CLEAN_SRC=sigdesc.h +CLEAN_EXTRA=@CLEAN_EXTRA@ + +srcdir=@srcdir@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +mandir=@mandir@ +datarootdir=@datarootdir@ +VPATH=@srcdir@ + +PACKAGE_NAME=@PACKAGE_NAME@ +SIGNAL=@SIGNAL_H@ +ARCHFLAG=@ARCHFLAG@ +AWK=@AWK@ +CC=@CC@ +CFLAGS=$(DEFS) $(DEFAULT_INCLUDES) $(CFLAGSONLY) $(ARCHFLAG) +CFLAGSONLY=@CFLAGS@ +CPPFLAGS=@CPPFLAGS@ +DEBUG= +DEFS=@DEFS@ $(DEBUG) +ISAEXEC=@ISAEXEC@ +LDFLAGS=@LDFLAGS@ +LIBS=@LIBS@ +MODULE_CFLAGS=@MODULE_CFLAGS@ + +INSTALL=@INSTALL@ +INSTALL_PROGRAM=@INSTALL_PROGRAM@ +INSTALL_DATA=@INSTALL_DATA@ +INSTALL_OPTS_PROG=@INSTALL_OPTS_PROG@ +INSTALL_OPTS_DATA= + +DEFAULT_INCLUDES = -I. -I$(srcdir) + +BINARY = $@ +COMPILE = $(CC) $(CFLAGS) $(CPPFLAGS) +LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $(BINARY) + + +@FIRST_RULE@ + +$(PROGRAM): $(OBJ) + $(LINK) $(OBJ) $(LIBS) + +# explicit dependency for the module appropriate to this machine +m_@MODULE@.o: $(srcdir)/machine/m_@MODULE@.c + $(COMPILE) $(MODULE_CFLAGS) -o $@ -c $(srcdir)/machine/m_@MODULE@.c + +sigdesc.h: $(srcdir)/sigconv.awk $(SIGNAL) + $(AWK) -f $(srcdir)/sigconv.awk $(SIGNAL) >sigdesc.h + +@INSTALL_RULE@ + +install-man: $(MANPAGE) + mkdir -p $(DESTDIR)$(mandir)/man1 + $(INSTALL_DATA) $(INSTALL_OPTS_DATA) \ + $(MANPAGE) $(DESTDIR)$(mandir)/man1/$(MANPAGE) + +clean: + -rm -f $(PROGRAM) $(OBJ) $(CLEAN_SRC) $(CLEAN_EXTRA) + +distclean: clean + -rm -f Makefile config.status config.cache config.log config.h + +configure: configure.ac + autoheader + autoconf + +# Include file dependencies +color.o: os.h config.h message.h color.h +commands.o: os.h config.h sigdesc.h top.h machine.h globalstate.h \ + boolean.h commands.h display.h utils.h version.h +display.o: os.h config.h top.h machine.h screen.h layout.h display.h \ + boolean.h utils.h color.h +screen.o: os.h config.h top.h screen.h boolean.h +top.o: os.h config.h top.h machine.h globalstate.h commands.h display.h \ + screen.h boolean.h username.h utils.h version.h color.h +username.o: os.h config.h top.h utils.h hash.h +utils.o: os.h config.h top.h utils.h +version.o: config.h top.h +m_@MODULE@.o: top.h machine.h utils.h loadavg.h diff --git a/external/bsd/top/dist/Porting b/external/bsd/top/dist/Porting new file mode 100644 index 000000000..c28fd378b --- /dev/null +++ b/external/bsd/top/dist/Porting @@ -0,0 +1,229 @@ +Instructions for porting top to other architectures. + +This is still a preliminary document. Suggestions for improvement are +most welcome. + +Before you embark on a port, please send me a mail message telling me +what platform you are porting top to. There are three reasons for +this: (1) I may already have a port, (2) module naming needs to be +centralized, (3) I want to loosely track the various porting efforts. +You do not need to wait for an "okay", but I do want to know that you +are working on it. And of course, once it is finished, please send me +the module files so that I can add them to the main distribution! + +---------- + +There is one set of functions which extract all the information that +top needs for display. These functions are collected in to one file. +To make top work on a different architecture simply requires a +different implementation of these functions. The functions for a +given architecture "foo" are stored in a file called "m_foo.c". The +Configure script looks for these files and lets the configurer choose +one of them. This file is called a "module". The idea is that making +top work on a different machine only requires one additional file and +does not require changes to any existing files. + +A module template is included in the distribution, called "m-template". +To write your own module, it is a good idea to start with this template. +If you architecture is similar to one for which a module already +exists, then you can start with that module instead. If you do so, +remember to change the "AUTHOR" section at the top! + +The first comment in a module contains information which is extracted +and used by Configure. This information is marked with words in all +capitals (such as "SYNOPSIS:" and "LIBS:"). Go look at m-template: it +is fairly self-explanatory. The text after "LIBS:" (on the same line) +is extracted and included in the LIBS definition of the Makefile so +that extra libraries which may be necessary on some machines (such as +"-lkvm") can be specified in the module. The text after "CFLAGS:" +(on the same line) is extracted and included as flags in the "CFLAGS" +definition of the Makefile (thus in every compilation step). This is +used for rare circumstances only: please don't abuse this hook. + +Some operating systems have idiosyncrasies which will affect the form +and/or content of the information top displays. You may wish to +document such anomalies in the top man page. This can be done by adding +a file called m_{modulename}.man (where {modulename} is replaced with +the name of the module). Configure will automatically add this file to +the end of the man page. See m_sunos4.man for an example. + +A module is concerned with two structures: + +The statics struct is filled in by machine_init. Each item is a +pointer to a list of character pointers. The list is terminated +with a null pointer. + +struct statics +{ + char **procstate_names; /* process state names */ + char **cpustate_names; /* cpu state names */ + char **memory_names; /* memory information names */ +}; + +The system_info struct is filled in by get_system_info and +get_process_info. + +struct system_info +{ + int last_pid; /* last pid assigned (0 means non-sequential assignment) */ + double load_avg[NUM_AVERAGES]; /* see below */ + int p_total; /* total number of processes */ + int p_active; /* number of procs considered "active" */ + int *procstates; /* array of process state counters */ + int *cpustates; /* array of cpustate counters */ + int *memory; /* memory information */ +}; + +The last three pointers each point to an array of integers. The +length of the array is determined by the length of the corresponding +_names array in the statics structure. Furthermore, if an entry in a +_names array is the empty string ("") then the corresponding value in +the value array will be skipped over. The display routine displays, +for example, the string procstate_names[0] then the number +procstates[0], then procstate_names[1], procstates[1], etc. until +procstate_names[N] == NULL. This allows for a tremendous amount of +flexibility in labeling the displayed values. + +"procstates" and "memory" are displayed as straight integer values. +Values in "cpustates" are displayed as a percentage * 10. For +example, the (integer) value 105 is displayed as 10.5%. + +These routines must be defined by the machine dependent module. + +int machine_init(struct statics *) + + returns 0 on success and -1 on failure, + prints error messages + +char *format_header(char *) + + Returns a string which should be used as the header for the + process display area. The argument is a string used to label + the username column (either "USERNAME" or "UID") and is always + 8 characters in length. + +void get_system_info(struct system_info *) + +caddr_t get_process_info(struct system_info *, int, int, int (*func)()) + + returns a handle to use with format_next_process + +char *format_next_process(caddr_t, char *(*func)()) + + returns string which describes next process + +int proc_compare(caddr_t, caddr_t) + + qsort comparison function + +uid_t proc_owner(pid_t) + + Returns the uid owner of the process specified by the pid argument. + This function is VERY IMPORTANT. If it fails to do its job, then + top may pose a security risk. + + +get_process_info is called immediately after get_system_info. In +fact, the two functions could be rolled in to one. The reason they +are not is mostly historical. + +Top relies on the existence of a function called "setpriority" to +change a process's priority. This exists as a kernel call on most 4.3 +BSD derived Unixes. If neither your operating system nor your C +library supplies such a function, then you will need to add one to the +module. It is defined as follows: + + int setpriority (int dummy, int who, int niceval) + + For the purposes of top, the first argument is meaningless. + The second is the pid and the third is the new nice value. + This function should behave just like a kernel call, setting + errno and returning -1 in case of an error. This function MUST + check to make sure that a non-root user does not specify a nice + value less than the process's current value. If it detects such + a condition, it should set errno to EACCES and return -1. + Other possible ERRNO values: ESRCH when pid "who" does not exist, + EPERM when the invoker is not root and not the same as the + process owner. + +Note that top checks process ownership and should never call setpriority +when the invoker's uid is not root and not the same as the process's owner +uid. + + +The file "machine.h" contains definitions which are useful to modules +and to top.c (such as the structure definitions). You SHOULD NOT need +to change it when porting to a new platform. + +Porting to a new platform should NOT require any changes to existing +files. You should only need to add m_ files. If you feel you need a +change in one of the existing files, please contact me so that we can +discuss the details. I want to keep such changes as general as +possible. + +-------- + +Changes were made to the module interface between 3.5 and 3.6. Here are +the changes that need to be made to port a 3.5 module to 3.6: + +The array that stores memory statistics and is passed back in the system +information structure as "memory" must now be an array of (signed) longs. +This was done to more easily accomodate systems that have gigabytes of +memory. Since the numbers are supposed to be kilobytes, a long can still +represent up to 2 terabytes. Look for "int memory_stats[X]" (where "X" +is some arbitrary number) and change it to "long memory_stats[X]". If +the module support reporting swap information on a separate line, then +its "swap_stats" array also needs to be an array of longs. + +The argument to proc_owner should be an int, as in "int pid". When it is +used in proc_owner it should be cast as necessary. Many operating systems +will require it to be cast to a pid_t before being compared to the appropriate +element in the proc structure. + +In the function format_next_process, the last argument in the main call +to sprintf is the string that contains the command for the process. +Make sure that this last argument is enclosed in a call to "printable". +For example: "printable(MPP(pp, p_comm))". + +The third argument to "get_process_info" needs to be changed to an integer, +typically "int compare_index". The call to qsort in get_process_info may +be guarded by "if (compare != NULL)". If it is, remove the if statement. + +The other changes to get_process_info depends on whether or not the module +supports multiple sort orders. + +To support multiple keys: + +Create an array int (*proc_compares[])() and assign to it the list of +comparison functions, NULL terminated. For example: + +int (*proc_compares[])() = { + compare_cpu, + compare_size, + compare_res, + compare_time, + NULL }; + +In get_process_info there is a call to qsort which uses one of the +functions in proc_compares. It should be changed so that its fourth +argument is "proc_compares[compare_index]". + +If the module contains the function "proc_compare", it should be removed. + +There should also be a NULL-terminated array of strings which list the names +for the sort keys, for example: + +char *ordernames[] = +{"cpu", "size", "res", "time", NULL}; + +To indicate that this module supports multiple sort keys, add the following +line in machine_init: + + statics->order_names = ordernames; + +If there is no support for multiple keys: + +Leave statics->order_names alone and call the comparison function of +your choice in get_process_info, ignoring the third argument. + + diff --git a/external/bsd/top/dist/README b/external/bsd/top/dist/README new file mode 100644 index 000000000..e0e7cf3e0 --- /dev/null +++ b/external/bsd/top/dist/README @@ -0,0 +1,191 @@ + TOP + Version 3.8beta1 + + William LeFebvre + and a cast of dozens + + +If you do not want to read this entire file, then at least read +the section at the end entitled "KNOWN PROBLEMS". + +If you are having any problems getting top to work, please read the +file "FAQ" *before* contacting me. Thank you. + +"top" is a program that will give continual reports about the state of +the system, including a list of the top cpu using processes. Version 3 +of "top" has three primary design goals: provide an accurate snapshot of +the system and process state, not be one of the top processes itself, be +as portable as possible. + +Version 3 has many bug fixes from version 2.5, and it has also been +reorganized in a major way to make it easy to port to other platforms. +All system dependent code is now contained in one file. + +Starting with version 3.6, top includes a "configure" script generated +by Gnu's autoconf. This script MUST be run before attempting to +compile top. It will explore the system and generate approriate +contents for Makefile, config.h, and top.1. + +On some systems, top requires read access to the memory files +"/dev/kmem" and "/dev/mem" as well as the system's kernel image. Most +installations have these files protected from general access. These +sites would have to install this program in the same way that programs +such as "ps" are installed. On most systems with a /proc file system, +top will try to read everything it can from /proc, but may need extra +permissions to do so. The configure script will determine the +permissions needed by the top binary, and a "make install" as root +will get the binary installed correctly. Sometimes this requires that +the binary be installed with set-group-id privileges and, in rare +cases, set-user-id to root. + +CAVEAT: version 3 of top has internal commands that kill and renice +processes. Although I have taken steps to insure that top makes +appropriate checks with these commands, I cannot guarantee that these +internal commands are totally secure. IF YOU INSTALL top SET-USER-ID +TO ROOT, YOU DO SO AT YOUR OWN RISK! I realize that some operating +systems will require top to run setuid root, and I will do everything +I can to make sure that top is a secure setuid program. + +System support now takes the form of "modules". Adding support for a +different architecture requires only adding a module. These modules +are contained in the subdirectory "machine". The "configure" script +automatically determines which module is approproate. However, it may +not be able to determine what the correct module is. This can happen +either because it doesn't know about the system or there is no module +to support the system. In the former case, if you know which module +to use, you can force "configure" to choose a particular module with +the option "--with-module". For example, if you want to force the use +of the svr4 module (which appears as "machine/m_svr4.c") then use +"configure --with-module=svr4" to generate the correct Makefile. See +the file "Porting" for a description of how to write your own module. + +To compile and install "top", read the file "INSTALL" and follow the +directions and advice contained therein. + +If you make any kind of change to "top" that you feel would be +beneficial to others who use this program, or if you find and fix a bug, +please send me the change. + +Be sure to read the FAQ enclosed with the distrubution. It contains +answers to the most commonly asked questions about the configuration, +installation, and operation of top. + +COLOR + +Version 3.6 incorporated the idea of using ANSI color sequences to +enhance information on the screen. By default, no color is used. But +you can configure the use of color through the environment variable +TOPCOLORS (or, for compatibility, TOPCOLOURS). The interface is +identical to the one first implemented by chris@spang.uk.eu.org, but +the implementation is entirely different. The option -C can be used +to diable the feature entirely. + +Any information at the top of the screen can be enhanced with color. +However, due to implementation difficulties, the per-process area +cannot be color-enhanced. A complete description of color support can +be found in the man page. References for ANSI color codes can be +found all over the Internet, but if you want a handy reference, look +in color.h. + + +AVAILABILITY + +Note that top is now a sourceforge project! Its project name is +"unixtop" and you can access its project page here: + +http://sourceforge.net/projects/unixtop + +On the project page you can find more information and access the +official bug and feature request trackers. If you find a bug, +want to request a feature, or need help, please submit a request +to the appropriate tracker on sourceforge. Thank you. + +Subversion access is also provided by Sourceforge. If Subversion is +installed on your system you can check out the project with the +following command: + + svn co https://svn.sourceforge.net/svnroot/unixtop unixtop + +There is also a web site dedicated to the project, and it is here: + +http://www.unixtop.org + +The latest version of "top" is available as a download through +sourceforge. Start here to access the downloadable files: + +http://sourceforge.net/project/showfiles.php?group_id=72892 + + +KNOWN PROBLEMS: + +Gnu CC + +Compiling via Gnu CC continued to be the source of most of the +questions I receive. By far the most common mistake made by those +attempting to compile top with Gnu CC is out of date include files. +When the operating system is upgraded, the include files that are part +of the gcc package MUST also be updated. Gcc maintains its own +include files. Even a minor OS upgrade can involve changes to some of +the kernel's internal data structures, which are defined in include +files in "sys". Top is very sensitive to these changes. If you are +compiling with gcc and experience any sort of strange problems, please +make sure the include files you are using are up to date BEFORE +sending me a bug report. Look in the gcc source distribution for the +shell script "fixincludes". + +MacOS X + +Since I don't have full time root access to a MacOS X system I cannot +provide effective support for the platform. MacOS X uses Mach, and it +is very difficult to extract accurate system and process information +from the system. It takes a lot of trial and error, along with root +access. I have included the most up-to-date version of the macosx module +in the distribution, but I do not claim that it works. If you want to +try to use it, you can configure with "./configure --with-module=macosx". + +HP/UX 10.10 + +In their infinite wisdom, the folks at HP have decided that mere mortals +such as you and I don't need to know what the kernel's proc structure looks +like. To that end, they have removed all useful content from the include +file 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 diff --git a/external/bsd/top/dist/Y2K b/external/bsd/top/dist/Y2K new file mode 100644 index 000000000..2af998d4e --- /dev/null +++ b/external/bsd/top/dist/Y2K @@ -0,0 +1,26 @@ +Top and the Year 2000 + +The software package top will not be affected by years numbering +between 2000 and 2037. No portion of the top code stores dates on +disk. All date processing in top is performed with functions from the +Unix C library and Unix kernel. The specific functions are: time(2) +and ctime(3S). These functions deal exclusively with conventional +Unix time values (number of seconds since Midnight January 1, 1970 +GMT) and produce strings with a 4-digit year. At no point in the code +for top are the last two digits used to represent a year. + +Top and the Year 2038 + +In the year 2038 top will fail to represent the time of day correctly +on 32-bit Unix operating systems. This is due to a limitation in the +way Unix represents time. Top will only work on systems whose kernel +call "time" and C library call "ctime" have been adjusted to represent +time with a value greater than 32 bits. The exact date and time of +this failure is 3:14:08 January 19, 2038 GMT. Note that this failure +will only affect the display of the current time in the output from +top. + + +THERE IS ABSOLUTELY NO WARRANTY PROVIDED WITH THIS SOFTWARE. +Please see the contents of the file "LICENSE" for further +information. diff --git a/external/bsd/top/dist/ap_snprintf.c b/external/bsd/top/dist/ap_snprintf.c new file mode 100644 index 000000000..f9ba3500f --- /dev/null +++ b/external/bsd/top/dist/ap_snprintf.c @@ -0,0 +1,1193 @@ +/* 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 + * for xinetd. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LIMITS_H +#include +#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 % */ + + 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 % 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 % (like syslog). + * Note that we can't point s inside fmt because the + * unknown 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; +} diff --git a/external/bsd/top/dist/boolean.h b/external/bsd/top/dist/boolean.h new file mode 100644 index 000000000..c6bcf4db7 --- /dev/null +++ b/external/bsd/top/dist/boolean.h @@ -0,0 +1,5 @@ +/* My favorite names for boolean values */ +#define No 0 +#define Yes 1 +#define Maybe 2 /* tri-state boolean, actually */ + diff --git a/external/bsd/top/dist/color.c b/external/bsd/top/dist/color.c new file mode 100644 index 000000000..36e831390 --- /dev/null +++ b/external/bsd/top/dist/color.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top users/processes display for Unix + * Version 3 + */ + +/* + * This file handles color definitions and access for augmenting + * the output with ansi color sequences. + * + * The definition of a color setting is as follows, separated by + * colons: + * + * tag=minimum,maximum#code + * + * "tag" is the name of the value to display with color. + * + * "minimum" and "maximum" are positive integer values defining a range: + * when the value is within this range it will be shown with the + * specified color. A missing value indicates that no check should be + * made (i.e.: ",25" is n <= 25; "25,50" is 25 <= n <= 50; and "50," + * is 50 <= n). + * + * "code" is the ansi sequence that defines the color to use with the + * escape sequence "[m". Semi-colons are allowed in this string to + * combine attributes. + */ + +#include "os.h" +#include "display.h" +#include "message.h" +#include "color.h" +#include "utils.h" + +typedef struct color_entry { + char *tag; + int min; + int max; + char color; + struct color_entry *next; + struct color_entry *tagnext; +} color_entry; + +static color_entry *entries = NULL; + +static color_entry **bytag = NULL; +static char **bytag_names = NULL; +static int totaltags = 0; +static int tagcnt = 0; +static int color_off = 0; + +static char **color_ansi = NULL; +static int num_color_ansi = 0; +static int max_color_ansi = 0; + +static int +color_slot(const char *str) + +{ + int i; + + for (i = 0; i < num_color_ansi; i++) + { + if (strcmp(color_ansi[i], str) == 0) + { + return i; + } + } + + /* need a new slot */ + if (num_color_ansi >= max_color_ansi) + { + max_color_ansi += COLOR_ANSI_SLOTS; + color_ansi = erealloc(color_ansi, max_color_ansi * sizeof(char *)); + } + color_ansi[num_color_ansi] = estrdup(str); + return num_color_ansi++; +} + +/* + * int color_env_parse(char *env) + * + * Parse a color specification "env" (such as one found in the environment) and + * add them to the list of entries. Always returns 0. Should only be called + * once. + */ + +int +color_env_parse(char *env) + +{ + char *p; + char *min; + char *max; + char *str; + int len; + color_entry *ce; + + /* initialization */ + color_ansi = emalloc(COLOR_ANSI_SLOTS * sizeof(char *)); + max_color_ansi = COLOR_ANSI_SLOTS; + + /* color slot 0 is always "0" */ + color_slot("0"); + + if (env != NULL) + { + p = strtok(env, ":"); + while (p != NULL) + { + if ((min = strchr(p, '=')) != NULL && + (max = strchr(min, ',')) != NULL && + (str = strchr(max, '#')) != NULL) + { + ce = emalloc(sizeof(color_entry)); + len = min - p; + ce->tag = emalloc(len + 1); + strncpy(ce->tag, p, len); + ce->tag[len] = '\0'; + ce->min = atoi(++min); + ce->max = atoi(++max); + ce->color = color_slot(++str); + ce->next = entries; + entries = ce; + } + else + { + if (min != NULL) + { + len = min - p; + } + else + { + len = strlen(p); + } + message_error(" %.*s: bad color entry", len, p); + } + p = strtok(NULL, ":"); + } + } + return 0; +} + +/* + * int color_tag(char *tag) + * + * Declare "tag" as a color tag. Return a tag index to use when testing + * a value against the tests for this tag. Should not be called before + * color_env_parse. + */ + +int +color_tag(const char *tag) + +{ + color_entry *entryp; + color_entry *tp; + + /* check for absurd arguments */ + if (tag == NULL || *tag == '\0') + { + return -1; + } + + dprintf("color_tag(%s)\n", tag); + + /* initial allocation */ + if (bytag == NULL) + { + totaltags = 10; + bytag = emalloc(totaltags * sizeof(color_entry *)); + bytag_names = emalloc(totaltags * sizeof(char *)); + } + + /* if we dont have enough room then reallocate */ + if (tagcnt >= totaltags) + { + totaltags *= 2; + bytag = erealloc(bytag, totaltags * sizeof(color_entry *)); + bytag_names = erealloc(bytag_names, totaltags * sizeof(char *)); + } + + /* initialize scan */ + entryp = entries; + tp = NULL; + + /* look for tag in the list of entries */ + while (entryp != NULL) + { + if (strcmp(entryp->tag, tag) == 0) + { + entryp->tagnext = tp; + tp = entryp; + } + entryp = entryp->next; + } + + /* we track names in the array bytag */ + bytag[tagcnt] = tp; + bytag_names[tagcnt] = estrdup(tag); + + /* return this index number as a reference */ + dprintf("color_tag: returns %d\n", tagcnt); + return (tagcnt++); +} + +/* + * int color_test(int tagidx, int value) + * + * Test "value" against tests for tag "tagidx", a number previously returned + * by color_tag. Return the correct color number to use when highlighting. + * If there is no match, return 0 (color 0). + */ + +int +color_test(int tagidx, int value) + +{ + color_entry *ce; + + /* sanity check */ + if (tagidx < 0 || tagidx >= tagcnt || color_off) + { + return 0; + } + + ce = bytag[tagidx]; + + while (ce != NULL) + { + if ((!ce->min || ce->min <= value) && + (!ce->max || ce->max >= value)) + { + return ce->color; + } + ce = ce->tagnext; + } + + return 0; +} + +/* + * char *color_setstr(int color) + * + * Return ANSI string to set the terminal for color number "color". + */ + +char * +color_setstr(int color) + +{ + static char v[32]; + + v[0] = '\0'; + if (color >= 0 && color < num_color_ansi) + { + snprintf(v, sizeof(v), "\033[%sm", color_ansi[color]); + } + return v; +} + +void +color_dump(FILE *f) + +{ + color_entry *ep; + int i; + int col; + int len; + + fputs("These color tags are available:", f); + col = 81; + for (i = 0; i < tagcnt; i++) + { + len = strlen(bytag_names[i]) + 1; + if (len + col > 79) + { + fputs("\n ", f); + col = 2; + } + fprintf(f, " %s", bytag_names[i]); + col += len; + } + + fputs("\n\nTop color settings:\n", f); + + for (i = 0; i < tagcnt; i++) + { + ep = bytag[i]; + while (ep != NULL) + { + fprintf(f, " %s (%d-", ep->tag, ep->min); + if (ep->max != 0) + { + fprintf(f, "%d", ep->max); + } + fprintf(f, "): ansi color %s, %sSample Text", + color_ansi[(int)ep->color], + color_setstr(ep->color)); + fprintf(f, "%s\n", color_setstr(0)); + ep = ep -> tagnext; + } + } +} + +#ifdef notdef +void +color_debug(FILE *f) +{ + color_entry *ep; + int i; + + fprintf(f, "color debug dump\n"); + ep = entries; + while (ep != NULL) + { + fprintf(f, "%s(%d,%d): slot %d, ansi %s, %sSample Text", + ep->tag, ep->min, ep->max, ep->color, color_ansi[(int)ep->color], + color_setstr(ep->color)); + fprintf(f, "%s\n", color_setstr(0)); + ep = ep -> next; + } + + fprintf(f, "\ntags:"); + for (i = 0; i < tagcnt; i++) + { + fprintf(f, " %s", bytag_names[i]); + } + fprintf(f, "\n"); +} +#endif + +int +color_activate(int i) + +{ + if (i == -1) + { + color_off = !color_off; + } + else + { + color_off = !i; + } + return color_off; +} diff --git a/external/bsd/top/dist/color.h b/external/bsd/top/dist/color.h new file mode 100644 index 000000000..e9dfdc0f0 --- /dev/null +++ b/external/bsd/top/dist/color.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top - a top users display for Unix + * + * Definition of the color interface. + */ + +#ifndef _COLOR_H_ +#define _COLOR_H_ + +#define COLOR_ANSI_SLOTS 20 + +int color_env_parse(char *env); +int color_tag(const char *tag); +int color_test(int tagidx, int value); +char *color_setstr(int color); +void color_dump(FILE *f); +int color_activate(int i); + + +/* + * These color tag names are currently in use + * (or reserved for future use): + * + * cpu, size, res, time, 1min, 5min, 15min, host + */ + +/* + * Valid ANSI values for colors are: + * + * 0 Reset all attributes + * 1 Bright + * 2 Dim + * 4 Underscore + * 5 Blink + * 7 Reverse + * 8 Hidden + * + * Foreground Colours + * 30 Black + * 31 Red + * 32 Green + * 33 Yellow + * 34 Blue + * 35 Magenta + * 36 Cyan + * 37 White + * + * Background Colours + * 40 Black + * 41 Red + * 42 Green + * 43 Yellow + * 44 Blue + * 45 Magenta + * 46 Cyan + * 47 White + */ + +#endif /*_COLOR_H_ */ diff --git a/external/bsd/top/dist/commands.c b/external/bsd/top/dist/commands.c new file mode 100644 index 000000000..03418f184 --- /dev/null +++ b/external/bsd/top/dist/commands.c @@ -0,0 +1,1070 @@ +/* + * 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 +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#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, ""); + } + 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; +} diff --git a/external/bsd/top/dist/commands.h b/external/bsd/top/dist/commands.h new file mode 100644 index 000000000..cf98c8ddb --- /dev/null +++ b/external/bsd/top/dist/commands.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* call specifications for commands.c */ + +int command_process(globalstate *gstate, int cmd); + +/* returns from command routines */ +#define CMD_ERROR -1 +#define CMD_OK 0 +#define CMD_REFRESH 1 +#define CMD_UNKNOWN 2 +#define CMD_NA 3 diff --git a/external/bsd/top/dist/config.amd64.make b/external/bsd/top/dist/config.amd64.make new file mode 100644 index 000000000..879b6c9b1 --- /dev/null +++ b/external/bsd/top/dist/config.amd64.make @@ -0,0 +1,10 @@ +# Special rules for making 32-bit and 64-bit binaries on a sunos5 x86 box +all: i386/top amd64/top + -cp -f /usr/lib/isaexec top + +i386/top: $(SRC) $(INC) + cd i386; $(MAKE) -f ../Makefile VPATH=.. srcdir=.. \ + BINARY=./top ARCHFLAG= top + +amd64/top: $(SRC) $(INC) + cd amd64; $(MAKE) -f ../Makefile VPATH=.. srcdir=.. BINARY=./top top diff --git a/external/bsd/top/dist/config.amd64.makeinstall b/external/bsd/top/dist/config.amd64.makeinstall new file mode 100644 index 000000000..52e76609e --- /dev/null +++ b/external/bsd/top/dist/config.amd64.makeinstall @@ -0,0 +1,10 @@ +# Install rule specific to i386/amd64 for sunos5 +install: all install-man + mkdir -p $(DESTDIR)$(bindir)/i386 + mkdir -p $(DESTDIR)$(bindir)/amd64 + $(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \ + i386/$(PROGRAM) $(DESTDIR)$(bindir)/i386/$(PROGRAM) + $(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \ + amd64/$(PROGRAM) $(DESTDIR)$(bindir)/amd64/$(PROGRAM) + $(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \ + $(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM) diff --git a/external/bsd/top/dist/config.default.makeinstall b/external/bsd/top/dist/config.default.makeinstall new file mode 100644 index 000000000..e3f9475b1 --- /dev/null +++ b/external/bsd/top/dist/config.default.makeinstall @@ -0,0 +1,5 @@ +# Standard install rule +install: $(PROGRAM) install-man + mkdir -p $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \ + $(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM) diff --git a/external/bsd/top/dist/config.guess b/external/bsd/top/dist/config.guess new file mode 100755 index 000000000..0e30d56e9 --- /dev/null +++ b/external/bsd/top/dist/config.guess @@ -0,0 +1,1407 @@ +#! /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 . +# Please send patches to . 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 ." + +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 /* 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 + + 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 + #include + + 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 + 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 + #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 + #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' /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 + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # 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 < +# include +#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 + 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 +# 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 < 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: diff --git a/external/bsd/top/dist/config.h.in b/external/bsd/top/dist/config.h.in new file mode 100644 index 000000000..d095dbc9f --- /dev/null +++ b/external/bsd/top/dist/config.h.in @@ -0,0 +1,256 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Support for debugging output */ +#undef DEBUG + +/* Default delay */ +#undef DEFAULT_DELAY + +/* Default number of processes to display */ +#undef DEFAULT_TOPN + +/* Enable color */ +#undef ENABLE_COLOR + +/* Enable dual architecture */ +#undef ENABLE_DUALARCH + +/* Enable kill and renice */ +#undef ENABLE_KILL + +/* Supports C99 style variadic macros */ +#undef HAVE_C99_VARIADIC_MACROS + +/* Define to 1 if you have the 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 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 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 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 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 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 header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_SYSEXITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMCAP_H + +/* Define to 1 if you have the 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 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 and . */ +#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 diff --git a/external/bsd/top/dist/config.sparcv9.make b/external/bsd/top/dist/config.sparcv9.make new file mode 100644 index 000000000..344b99ecf --- /dev/null +++ b/external/bsd/top/dist/config.sparcv9.make @@ -0,0 +1,10 @@ +# Special rules for making 32-bit and 64-bit binaries on a sunos5 box +all: sparcv7/top sparcv9/top + -cp -f $(ISAEXEC) top + +sparcv7/top: $(SRC) $(INC) + cd sparcv7; $(MAKE) -f ../Makefile VPATH=.. srcdir=.. \ + BINARY=./top ARCHFLAG= top + +sparcv9/top: $(SRC) $(INC) + cd sparcv9; $(MAKE) -f ../Makefile VPATH=.. srcdir=.. BINARY=./top top diff --git a/external/bsd/top/dist/config.sparcv9.makeinstall b/external/bsd/top/dist/config.sparcv9.makeinstall new file mode 100644 index 000000000..a836b9bd6 --- /dev/null +++ b/external/bsd/top/dist/config.sparcv9.makeinstall @@ -0,0 +1,10 @@ +# Install rule specific to sparcv7/sparcv9 for sunos5 +install: all install-man + mkdir -p $(DESTDIR)$(bindir)/sparcv7 + mkdir -p $(DESTDIR)$(bindir)/sparcv9 + $(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \ + sparcv7/$(PROGRAM) $(DESTDIR)$(bindir)/sparcv7/$(PROGRAM) + $(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \ + sparcv9/$(PROGRAM) $(DESTDIR)$(bindir)/sparcv9/$(PROGRAM) + $(INSTALL_PROGRAM) $(INSTALL_OPTS_PROG) \ + $(PROGRAM) $(DESTDIR)$(bindir)/$(PROGRAM) diff --git a/external/bsd/top/dist/config.sub b/external/bsd/top/dist/config.sub new file mode 100755 index 000000000..9d7f73390 --- /dev/null +++ b/external/bsd/top/dist/config.sub @@ -0,0 +1,1504 @@ +#! /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 . 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 ." + +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: diff --git a/external/bsd/top/dist/configure b/external/bsd/top/dist/configure new file mode 100755 index 000000000..f2a53985f --- /dev/null +++ b/external/bsd/top/dist/configure @@ -0,0 +1,7969 @@ +#! /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 &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 +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#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 if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + 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 +#include +#include +#include +/* 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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 +#include +#include +#include + +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 + +_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 + +_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 +#include +#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 +#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 +#include +#include + +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 +/* NetBSD declares sys_siglist in unistd.h. */ +#if HAVE_UNISTD_H +# include +#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 +#include +#else +#if HAVE_TERMCAP_H +#include +#else +#if HAVE_CURSES_H +#include +#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 +#include +#else +#if HAVE_TERMCAP_H +#include +#else +#if HAVE_CURSES_H +#include +#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 +#include +#else +#if HAVE_TERMCAP_H +#include +#else +#if HAVE_CURSES_H +#include +#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 +#include +#else +#if HAVE_TERMCAP_H +#include +#else +#if HAVE_CURSES_H +#include +#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 +#include +#else +#if HAVE_TERMCAP_H +#include +#else +#if HAVE_CURSES_H +#include +#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 +#include +#else +#if HAVE_TERMCAP_H +#include +#else +#if HAVE_CURSES_H +#include +#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 +#endif +#ifdef HAVE_CURSES_H +#include +#endif +#ifdef HAVE_TERM_H +#include +#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 +#include + +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 declares $ac_func. + For example, HP-UX 11i 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 to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#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 ." + +_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 >$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 + diff --git a/external/bsd/top/dist/configure.ac b/external/bsd/top/dist/configure.ac new file mode 100644 index 000000000..c7fc28faf --- /dev/null +++ b/external/bsd/top/dist/configure.ac @@ -0,0 +1,529 @@ +# configure.ac +AC_INIT(top, 3.8beta1) + +# AX_CHECK_VARIADIC_MACROS... +# ----- +AC_DEFUN([AX_CHECK_VARIADIC_MACROS], +[AC_MSG_CHECKING([for variadic macros]) +AC_COMPILE_IFELSE(AC_LANG_PROGRAM( +[#define a(x, ...) (x, __VA_ARGS__)], []), + [AS_VAR_SET(ax_cv_c99_variadic, yes)], + [AS_VAR_SET(ax_cv_c99_variadic, no)]) +AC_COMPILE_IFELSE(AC_LANG_PROGRAM( +[#define a(x...) (x)], []), + [AS_VAR_SET(ax_cv_gnu_variadic, yes)], + [AS_VAR_SET(ax_cv_gnu_variadic, no)]) +_result="" +if test "$ax_cv_c99_variadic" = "yes"; then + _result=" c99" + AC_DEFINE(HAVE_C99_VARIADIC_MACROS, 1, [Supports C99 style variadic macros]) +fi +if test "$ax_cv_gnu_variadic" = "yes"; then + _result="$_result gnu" + AC_DEFINE(HAVE_GNU_VARIADIC_MACROS, 1, [Supports gnu style variadic macros]) +fi +if test "x$_result" = x; then + _result="no" +fi +AC_MSG_RESULT($_result) +]) + +# AC_CHECK_CFLAG... +# ----- +AC_DEFUN([AC_CHECK_CFLAG], +[AC_MSG_CHECKING([whether compiler accepts $1]) +AS_VAR_PUSHDEF([ac_Flag], [ac_cv_cflag_$1])dnl +_savedcflags=$CFLAGS +_savedwerror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +CFLAGS=$CFLAGS" $1" +AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [AS_VAR_SET(ac_Flag, yes)], + [AS_VAR_SET(ac_Flag, no)]) +AC_MSG_RESULT([AS_VAR_GET(ac_Flag)]) +CFLAGS=$_savedcflags +ac_c_werror_flag=$_savedwerror_flag +AS_IF([test AS_VAR_GET(ac_Flag) = yes], [$2], [$3])[]dnl +AS_VAR_POPDEF([ac_Flag])dnl +])# AC_CHECK_CFLAG + +echo "Configuring $PACKAGE_STRING" + +AC_CONFIG_HEADER([config.h]) +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +# options processing +AC_ARG_WITH(module, AC_HELP_STRING([--with-module=NAME], + [use the platform module NAME]), + [if test ! -f machine/m_$withval.c; + then AC_MSG_ERROR([No such module $withval]); fi]) + +AC_ARG_WITH(ext, AC_HELP_STRING([--with-ext=EXT], + [use the extension EXT]), + [if test -f ext/$withval.c; then + AC_DEFINE(WITH_EXT, 1, [Include code that utilizes extensions]) + SRC="$SRC ext/$withval.c" + OBJ="$OBJ $withval.o" + else + AC_MSG_ERROR([No such extension $withval]) + fi]) + +DEFAULT_TOPN=30 +AC_ARG_WITH(default-topn, AC_HELP_STRING([--with-default-topn=N], + [use N as the default for number of processes]), + [if test x"$with_default_topn" = xall; then + DEFAULT_TOPN="-1" + elif test x`echo $with_default_topn | tr -d '[0-9+-]'` = x; then + DEFAULT_TOPN=$with_default_topn + fi]) +AC_DEFINE_UNQUOTED(DEFAULT_TOPN, $DEFAULT_TOPN, [Default number of processes to display]) +AC_SUBST(DEFAULT_TOPN) + +NOMINAL_TOPN=40 +AC_ARG_WITH(nominal-topn, AC_HELP_STRING([--with-nominal-topn=N], + [use N as the default number of processes for non-terminals]), + [if test x"$with_nominal_topn" = xall; then + NOMINAL_TOPN="-1" + elif test x`echo $with_nominal_topn | tr -d '[0-9+-]'` = x; then + NOMINAL_TOPN=$with_nominal_topn + fi]) +AC_DEFINE_UNQUOTED(NOMINAL_TOPN, $NOMINAL_TOPN, [Default number of processes to display on non-terminals when topn is all]) +AC_SUBST(NOMINAL_TOPN) + +DEFAULT_DELAY=5 +AC_ARG_WITH(default-delay, AC_HELP_STRING([--with-default-delay=SEC], + [use a default delay of SEC seconds]), + [if test x`echo $with_default_delay | tr -d '[0-9+-]'` = x; then + DEFAULT_DELAY=$with_default_delay + fi]) +AC_DEFINE_UNQUOTED(DEFAULT_DELAY, $DEFAULT_DELAY, [Default delay]) +AC_SUBST(DEFAULT_DELAY) + +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], + [enable support for debugging output])) +if test "x$enable_debug" = xyes; then + AC_DEFINE(DEBUG, 1, [Support for debugging output]) +fi + +ENABLE_KILL=0 +AC_ARG_ENABLE(kill, AC_HELP_STRING([--disable-kill], + [disable kill and renice commands])) +if test x$enable_kill != xno; then + AC_DEFINE(ENABLE_KILL, 1, [Enable kill and renice]) + ENABLE_KILL=1 +fi +AC_SUBST(ENABLE_KILL) + + +AC_ARG_ENABLE(color, AC_HELP_STRING([--disable-color], + [disable the use of color])) +AC_ARG_ENABLE(colour, AC_HELP_STRING([--disable-colour], + [synonym for --disable-color])) +if test x$enable_color != xno -a x$enable_colour != xno; then + AC_DEFINE(ENABLE_COLOR, 1, [Enable color]) +fi + +AC_ARG_ENABLE(dualarch, AC_HELP_STRING([--enable-dualarch], + [enable or disable a dual architecture (32-bit and 64-bit) compile])) + +# check for needed programs +AC_CHECK_PROGS(MAKE, make) +AC_PROG_CC +if test "$ac_cv_c_compiler_gnu" = "yes"; then + ax_cv_c_compiler_vendor="gnu" +else + AX_COMPILER_VENDOR +fi +AC_PROG_AWK +AC_PROG_INSTALL +AC_PATH_PROGS(ISAINFO, isainfo) +AC_PATH_PROGS(ISAEXEC, isaexec, , [$PATH:/usr/lib:/lib]) +AC_PATH_PROGS(UNAME, uname) +AC_SUBST(ISAEXEC) + +# system checks require uname +if test "$UNAME"; then + # we make the version number available as a C preprocessor definition + AC_MSG_CHECKING(OS revision number) + osrev=`$UNAME -r | tr -cd ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789` + + if test "$osrev" != "unknown" ; then + AC_DEFINE_UNQUOTED(OSREV, $osrev, [Define the OS revision.]) + osmajor=`$UNAME -r | sed 's/^\([[0-9]]*\).*$/\1/'` + if test -n "$osmajor"; then + AC_DEFINE_UNQUOTED(OSMAJOR, $osmajor, [Define the major OS revision number.]) + fi + else + AC_DEFINE(OSREV, "") + fi + AC_MSG_RESULT($osrev) + + # we make the non-canonicalized hardware type available + AC_MSG_CHECKING(hardware platform) + UNAME_HARDWARE=`$UNAME -m` + if test "$UNAME_HARDWARE" != "unknown"; then + AC_DEFINE_UNQUOTED(UNAME_HARDWARE, "$UNAME_HARDWARE", [Define the system hardware platform]) + fi + AC_MSG_RESULT($UNAME_HARDWARE) +fi + +# checks for libraries +AC_CHECK_LIB(elf, elf32_getphdr) +AC_CHECK_LIB(kstat, kstat_open) +AC_CHECK_LIB(kvm, kvm_open) +# -lmld -lmach +AC_CHECK_LIB(mach, vm_statistics) +AC_SEARCH_LIBS(tgetent, termcap curses ncurses) +AC_CHECK_LIB(m, exp) + +# check for libraries required by extension +extlibs="" +if test -n "$with_ext" -a -f "${srcdir}/ext/$with_ext.libs"; then + AC_MSG_CHECKING(for libraries needed by extensions) + for lib in `cat "${srcdir}/ext/$with_ext.libs"` + do + saveLIBS=$LIBS + LIBS="$LIBS -l$lib" + AC_TRY_LINK(, [exit(0);], [extlibs="$extlibs -l$lib"], ) + LIBS=$saveLIBS + done + AC_MSG_RESULT($extlibs) + LIBS="$LIBS$extlibs" +fi + +# checks for header files +AC_HEADER_STDC +AC_CHECK_HEADERS([curses.h getopt.h limits.h math.h stdarg.h sysexits.h termcap.h unistd.h sys/resource.h sys/time.h sys/utsname.h]) +AC_CHECK_HEADERS([term.h],,, +[#if HAVE_CURSES_H +#include +#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 +/* NetBSD declares sys_siglist in unistd.h. */ +#if HAVE_UNISTD_H +# include +#endif +]) +AC_CHECK_DECLS([tputs, tgoto, tgetent, tgetflag, tgetnum, tgetstr],,, +[#if HAVE_CURSES_H && HAVE_TERM_H +#include +#include +#else +#if HAVE_TERMCAP_H +#include +#else +#if HAVE_CURSES_H +#include +#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 +#endif +#ifdef HAVE_CURSES_H +#include +#endif +#ifdef HAVE_TERM_H +#include +#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 diff --git a/external/bsd/top/dist/display.c b/external/bsd/top/dist/display.c new file mode 100644 index 000000000..fbab627ad --- /dev/null +++ b/external/bsd/top/dist/display.c @@ -0,0 +1,2021 @@ +/* + * 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 +#include +#include +#include +#include + +#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; + } + } + } + } +} diff --git a/external/bsd/top/dist/display.h b/external/bsd/top/dist/display.h new file mode 100644 index 000000000..87bbaf161 --- /dev/null +++ b/external/bsd/top/dist/display.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* interface declaration for display.c */ + +#ifndef _DISPLAY_H +#define _DISPLAY_H + +#include "globalstate.h" + +void display_clear(void); +int display_resize(void); +int display_lines(void); +int display_setmulti(int m); +int display_columns(void); +int display_init(struct statics *statics, int percpuinfo); +void i_loadave(int mpid, double *avenrun); +void u_loadave(int mpid, double *avenrun); +void i_minibar(int (*formatter)(char *, int)); +void u_minibar(int (*formatter)(char *, int)); +void i_uptime(time_t *bt, time_t *tod); +void u_uptime(time_t *bt, time_t *tod); +void i_timeofday(time_t *tod); +void i_procstates(int total, int *brkdn, int threads); +void u_procstates(int total, int *brkdn, int threads); +void i_cpustates(int *states); +void u_cpustates(int *states); +void z_cpustates(void); +void i_kernel(int *stats); +void u_kernel(int *stats); +void i_memory(long *stats); +void u_memory(long *stats); +void i_swap(long *stats); +void u_swap(long *stats); +void i_message(struct timeval *now); +void u_message(struct timeval *now); +void i_header(char *text); +void u_header(char *text); +void i_process(int line, char *thisline); +void u_process(int, char *); +void i_endscreen(void); +void u_endscreen(void); +void display_header(int t); +void new_message(const char *msgfmt, ...); +void message_error(const char *msgfmt, ...); +void message_mark(void); +void message_clear(void); +void message_expire(void); +void message_prompt(const char *msgfmt, ...); +void message_prompt_plain(const char *msgfmt, ...); +int readline(char *buffer, int size, int numeric); +void display_pagerstart(void); +void display_pagerend(void); +void display_pager(const char *fmt, ...); + +#endif diff --git a/external/bsd/top/dist/getopt.c b/external/bsd/top/dist/getopt.c new file mode 100644 index 000000000..9a4af2f4c --- /dev/null +++ b/external/bsd/top/dist/getopt.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * "getopt" routine customized for top. + */ + +/* + * Many modern-day Unix implementations already have this function + * in libc. The standard "getopt" is perfectly sufficient for top's + * needs. If such a function exists in libc then you certainly don't + * need to compile this one in. To prevent this function from being + * compiled, define "HAVE_GETOPT". This is usually done in the "CFLAGS" + * line of the corresponding machine module. + */ + +/* + * This empty declaration exists solely to placate overexhuberant C + * compilers that like to warn you about content-free files. + */ +static void __empty(); + +#ifndef HAVE_GETOPT + +/*LINTLIBRARY*/ + +#include "os.h" +#ifndef NULL +#define NULL 0 +#endif +#ifndef EOF +#define EOF (-1) +#endif +#define ERR(s, c) if(opterr){\ + extern int write();\ + char errbuf[2];\ + errbuf[0] = c; errbuf[1] = '\n';\ + (void) write(2, argv[0], strlen(argv[0]));\ + (void) write(2, s, strlen(s));\ + (void) write(2, errbuf, 2);} + + +int opterr = 1; +int optind = 1; +int optopt; +char *optarg; + +int +getopt(int argc, char **argv, char *opts) + +{ + static int sp = 1; + register int c; + register char *cp; + + if(sp == 1) + if(optind >= argc || + argv[optind][0] != '-' || argv[optind][1] == '\0') + return(EOF); + else if(strcmp(argv[optind], "--") == 0) { + optind++; + return(EOF); + } + optopt = c = argv[optind][sp]; + if(c == ':' || (cp=strchr(opts, c)) == NULL) { + ERR(": unknown option, -", c); + if(argv[optind][++sp] == '\0') { + optind++; + sp = 1; + } + return('?'); + } + if(*++cp == ':') { + if(argv[optind][sp+1] != '\0') + optarg = &argv[optind++][sp+1]; + else if(++optind >= argc) { + ERR(": argument missing for -", c); + sp = 1; + return('?'); + } else + optarg = argv[optind++]; + sp = 1; + } else { + if(argv[optind][++sp] == '\0') { + sp = 1; + optind++; + } + optarg = NULL; + } + return(c); +} +#endif /* HAVE_GETOPT */ diff --git a/external/bsd/top/dist/globalstate.h b/external/bsd/top/dist/globalstate.h new file mode 100644 index 000000000..cb75aa332 --- /dev/null +++ b/external/bsd/top/dist/globalstate.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The global state of top is described in this structure. It is passed + * to routines that may need to examine or alter it. + */ + +#ifndef _GLOBALSTATE_H_ +#define _GLOBALSTATE_H_ + +#include "machine.h" + +typedef struct globalstate { + struct timeval now; + struct timeval refresh; + int fulldraw; + int topn; + int max_topn; + double delay; + int displays; + int order_index; + int show_cpustates; + int show_tags; + int show_usernames; + int use_color; + int smart_terminal; + int interactive; + int percpustates; + char *header_text; + char *order_name; /* only used before call to machine_init */ + char *order_namelist; + char *(*get_userid)(int); + struct process_select pselect; + struct statics *statics; +} globalstate; + +#endif /* _GLOBALSTATE_H_ */ diff --git a/external/bsd/top/dist/hash.c b/external/bsd/top/dist/hash.c new file mode 100644 index 000000000..c1a2d6ee2 --- /dev/null +++ b/external/bsd/top/dist/hash.c @@ -0,0 +1,1952 @@ +/* + * 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 +#endif + +#include "hash.h" + +static int +next_prime(int x) + +{ + double i, j; + int f; + + i = x; + while (i++) + { + f=1; + for (j=2; jnum_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 diff --git a/external/bsd/top/dist/hash.h b/external/bsd/top/dist/hash.h new file mode 100644 index 000000000..44a121bc0 --- /dev/null +++ b/external/bsd/top/dist/hash.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* hash.m4h */ + +/* Interface definition for hash.c */ + +/* The file hash.h is generated from hash.m4h via the preprocessor M4 */ + +#ifndef _HASH_H +#define _HASH_H + +#include + +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 diff --git a/external/bsd/top/dist/hash.m4c b/external/bsd/top/dist/hash.m4c new file mode 100755 index 000000000..6e8a73659 --- /dev/null +++ b/external/bsd/top/dist/hash.m4c @@ -0,0 +1,666 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* hash.m4c */ + +/* The file hash.c is generated from hash.m4c via the preprocessor M4 */ + +/* + * Hash table functions: init, add, lookup, first, next, sizeinfo. + * This is a conventional "bucket hash". The key is hashed in to a number + * less than or equal to the number of buckets and the result is used + * to index in to the array of buckets. Each bucket is a linked list + * that contains all the key/value pairs which hashed to that index. + */ + +#include "config.h" + +#if STDC_HEADERS +#include +#include +#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 +#else +#ifdef HAVE_STRING_H +#include +#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 +#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; jnum_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 diff --git a/external/bsd/top/dist/hash.m4h b/external/bsd/top/dist/hash.m4h new file mode 100755 index 000000000..63a386c1f --- /dev/null +++ b/external/bsd/top/dist/hash.m4h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* hash.m4h */ + +/* Interface definition for hash.c */ + +/* The file hash.h is generated from hash.m4h via the preprocessor M4 */ + +#ifndef _HASH_H +#define _HASH_H + +#include + +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 diff --git a/external/bsd/top/dist/install-sh b/external/bsd/top/dist/install-sh new file mode 100755 index 000000000..398a88e14 --- /dev/null +++ b/external/bsd/top/dist/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + : +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=$mkdirprog + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + : + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + : + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + : + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' + ' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + : + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + : + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/external/bsd/top/dist/layout.h b/external/bsd/top/dist/layout.h new file mode 100644 index 000000000..46bf78e23 --- /dev/null +++ b/external/bsd/top/dist/layout.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top - a top users display for Unix + * + * This file defines the default locations on the screen for various parts + * of the display. These definitions are used by the routines in "display.c" + * for cursor addressing. + */ + +#define X_LASTPID 10 +#define Y_LASTPID 0 +#define X_LASTPIDWIDTH 13 +#define X_LOADAVE 27 +#define Y_LOADAVE 0 +#define X_LOADAVEWIDTH 7 +#define X_MINIBAR 50 +#define Y_MINIBAR 0 +#define X_UPTIME 48 +#define Y_UPTIME 0 +#define X_PROCSTATE 15 +#define Y_PROCSTATE 1 +#define X_BRKDN 15 +#define Y_BRKDN 1 +#define X_CPUSTATES 0 +#define Y_CPUSTATES 2 +#define X_KERNEL 8 +#define Y_KERNEL 3 +#define X_MEM 8 +#define Y_MEM 3 +#define X_SWAP 6 +#define Y_SWAP 4 +#define Y_MESSAGE 4 +#define X_HEADER 0 +#define Y_HEADER 5 +#define X_IDLECURSOR 0 +#define Y_IDLECURSOR 4 +#define Y_PROCS 6 + diff --git a/external/bsd/top/dist/loadavg.h b/external/bsd/top/dist/loadavg.h new file mode 100644 index 000000000..c73fc7d28 --- /dev/null +++ b/external/bsd/top/dist/loadavg.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top - a top users display for Berkeley Unix + * + * Defines required to access load average figures. + * + * This include file sets up everything we need to access the load average + * values in the kernel in a machine independent way. First, it sets the + * typedef "load_avg" to be either double or long (depending on what is + * needed), then it defines these macros appropriately: + * + * loaddouble(la) - convert load_avg to double. + * intload(i) - convert integer to load_avg. + */ + +/* + * We assume that if FSCALE is defined, then avenrun and ccpu are type long. + * If your machine is an exception (mips, perhaps?) then make adjustments + * here. + * + * Defined types: load_avg for load averages, pctcpu for cpu percentages. + */ +#if defined(mips) && !defined(NetBSD) +# include +# 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 diff --git a/external/bsd/top/dist/machine.h b/external/bsd/top/dist/machine.h new file mode 100644 index 000000000..f623a2fe6 --- /dev/null +++ b/external/bsd/top/dist/machine.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file defines the interface between top and the machine-dependent + * module. It is NOT machine dependent and should not need to be changed + * for any specific machine. + */ + +#ifndef _MACHINE_H_ +#define _MACHINE_H_ + +#include "top.h" + +/* + * The statics struct is filled in by machine_init. Fields marked as + * "optional" are not filled in by every module. + */ +struct statics +{ + const char **procstate_names; + const char **cpustate_names; + const char **memory_names; + const char **swap_names; /* optional */ + const char **order_names; /* optional */ + const char **top_color_names; /* optional */ + const char **kernel_names; /* optional */ + time_t boottime; /* optional */ + int modemax; /* optional */ + int ncpu; /* optional */ + struct { + unsigned int fullcmds : 1; + unsigned int idle : 1; + unsigned int warmup : 1; + unsigned int threads : 1; + } flags; +}; + +/* + * the system_info struct is filled in by a machine dependent routine. + */ + +#ifdef p_active /* uw7 define macro p_active */ +#define P_ACTIVE p_pactive +#else +#define P_ACTIVE p_active +#endif + +struct system_info +{ + pid_t last_pid; + double load_avg[NUM_AVERAGES]; + int p_total; + int P_ACTIVE; /* number of procs considered "active" */ + int *procstates; + int *cpustates; + int *kernel; + long *memory; + long *swap; +}; + +/* cpu_states is an array of percentages * 10. For example, + the (integer) value 105 is 10.5% (or .105). + */ + +/* + * the process_select struct tells get_process_info what processes we + * are interested in seeing + */ + +struct process_select +{ + int idle; /* show idle processes */ + int system; /* show system processes */ + int fullcmd; /* show full command */ + int usernames; /* show usernames */ + int uid; /* only this uid (unless uid == -1) */ + char *command; /* only this command (unless == NULL) */ + int mode; /* select display mode (0 is default) */ + int threads; /* show threads separately */ + pid_t pid; /* show only this pid (unless pid == -1) */ +}; + +/* routines defined by the machine dependent module */ +int machine_init(struct statics *); +void get_system_info(struct system_info *); +caddr_t get_process_info(struct system_info *, struct process_select *, int); +char *format_header(char *); +char *format_next_process(caddr_t, char *(*)(int)); +int proc_owner(int); +#ifdef HAVE_FORMAT_PROCESS_HEADER + +#endif /* _MACHINE_H_ */ +char *format_process_header(struct process_select *sel, caddr_t handle, int count); +#endif diff --git a/external/bsd/top/dist/machine/m_aix43.c b/external/bsd/top/dist/machine/m_aix43.c new file mode 100644 index 000000000..11ed4dbb1 --- /dev/null +++ b/external/bsd/top/dist/machine/m_aix43.c @@ -0,0 +1,729 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: PowerPC running AIX 4.2 or higher + * + * DESCRIPTION: + * This is the machine-dependent module for AIX 4.2 and higher + * It is currenlty only tested on PowerPC architectures. + * + * TERMCAP: -lcurses + * + * CFLAGS: -DORDER -DHAVE_GETOPT + * + * LIBS: -bD:0x18000000 + * + * AUTHOR: Joep Vesseur + * + * PATCHES: Antoine Tabary + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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); +} + + diff --git a/external/bsd/top/dist/machine/m_aix5.c b/external/bsd/top/dist/machine/m_aix5.c new file mode 100644 index 000000000..b5d8b08f1 --- /dev/null +++ b/external/bsd/top/dist/machine/m_aix5.c @@ -0,0 +1,793 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: PowerPC running AIX 5.1 or higher + * + * DESCRIPTION: + * This is the machine-dependent module for AIX 5.1 and higher (may work on + * older releases too). It is currently only tested on PowerPC + * architectures. + * + * TERMCAP: -lcurses + * + * CFLAGS: -DORDER -DHAVE_GETOPT -DHAVE_STRERROR -DMAXPROCS=10240 + * + * LIBS: -lperfstat + * + * AUTHOR: Joep Vesseur + * + * PATCHES: Antoine Tabary , Dan Nelson + */ + +#define MAXPROCS 10240 + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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<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); +} diff --git a/external/bsd/top/dist/machine/m_decosf1.c b/external/bsd/top/dist/machine/m_decosf1.c new file mode 100644 index 000000000..4fd0dabef --- /dev/null +++ b/external/bsd/top/dist/machine/m_decosf1.c @@ -0,0 +1,988 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: OSF/1, Digital Unix 4.0, Compaq Tru64 5.0 + * + * DESCRIPTION: + * This is the machine-dependent module for DEC OSF/1 and its descendents + * It is known to work on OSF/1 1.2, 1.3, 2.0-T3, 3.0, Digital Unix V4.0, + * Digital Unix 5.0, and Tru64 5.0. + * WARNING: if you use optimization with the standard "cc" compiler that + * . comes with V3.0 the resulting executable may core dump. If + * . this happens, recompile without optimization. + * + * LIBS: -lmld -lmach + * + * CFLAGS: -DHAVE_GETOPT -DORDER + * + * AUTHOR: Anthony Baxter, + * Derived originally from m_ultrix, by David S. Comay , + * 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 + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +/* forward declarations, needed by included from */ +struct rtentry; +struct mbuf; +#include +#include +#include +#include +#include /* 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; jp_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, + ""); + 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 + */ + 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. +Derived originally from m_ultrix, by David S. Comay , +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 + +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. diff --git a/external/bsd/top/dist/machine/m_freebsd.c b/external/bsd/top/dist/machine/m_freebsd.c new file mode 100644 index 000000000..e26bca768 --- /dev/null +++ b/external/bsd/top/dist/machine/m_freebsd.c @@ -0,0 +1,1780 @@ +/* + * 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 + * Steven Wallace + * Wolfram Schneider + */ + + +#include +#include +#include +#include + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +/* Swap */ +#include +#include + +#include /* 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); +} + diff --git a/external/bsd/top/dist/machine/m_freebsd.man b/external/bsd/top/dist/machine/m_freebsd.man new file mode 100644 index 000000000..0acafea17 --- /dev/null +++ b/external/bsd/top/dist/machine/m_freebsd.man @@ -0,0 +1,134 @@ +.SH "FreeBSD NOTES" +Priorities are shown the same as they exist in process data structures, +ranging from 0 to 255. Note that this is not the same as the ps(1) +\*(lqpri\*(rq column, which subtracts 84 from each number before displaying +it. Priority numbers fall in to priority classes as follows: +.TP 15 +0 \- 63 +Interrupt threads +.TP 15 +64 \- 127 +Top half kernel threads +.TP 15 +128 \- 159 +Realtime user threads +.TP 15 +160 \- 223 +Time sharing user threads +.TP 15 +224 \- 255 +Idle user threads + +.SH "FreeBSD THREADS" +Starting with FreeBSD 8.0 the display of individual threads can be +toggled with the synonymous commands +.B t +and +.BR H. +Information about state, flags, CPU time and percent cpu are shown +for each individual thread. Other information is identical for all +threads in the same process. + +.SH "FreeBSD ALTERNATE DISPLAY" +FreeBSD supports an alternate process display which shows i/o +information. Since this information is tracked per process and not +per thread, the per-thread display is not supported in this mode. +All fields calculate the number of operations observed since the +last update and are displayed as a per-second rate. +The fields in this display are as follows: +.TP +.B VCSW +Voluntary context switches +.TP +.B IVCSW +Involuntary context switches +.TP +.B READ +Number of blocks read +.TP +.B WRITE +Number of blocks written +.TP +.B FAULT +Number of page faults +.TP +.B TOTAL +Total number of i/o operations +.TP +.B PERCENT +Percentage of total i/o attributed to this process. If no i/o occured +then this field is 0 for all processes. + +.SH "FreeBSD KERNEL SUMMARY" +All rates are shown per-second. +.TP +.B Ctx +Number of context switches. +.TP +.B Trap +Number of kernel traps. +.TP +.B Intr +Number of device interrupts. +.TP +.B Soft +Number of software interrupts. +.TP +.B Fork +Number of forks, vforks, and rforks. +.TP +.B Flt +Total number of page faults. +.TP +.B Pgin +Number of pages paged or swapped in to physical memory. +.TP +.B Pgout +Number of pages paged or swapped out from physical memory. +.TP +.B Fr +Total number of pages freed. +.SH "FreeBSD MEMORY SUMMARY" +Memory: 10M Act 1208K Inact 3220K Wired 132K Free 25% Swap, 2924Kin 2604Kout +.TP +.B K: +Kilobyte +.TP +.B M: +Megabyte +.TP +.B G: +Gigabyte +.TP +.B %: +1/100 + +.TP +.B Act: +number of pages active +.TP +.B Inact: +number of pages inactive +.TP +.B Wired: +number of pages wired down +.TP +.B Free: +number of pages free +.TP +.B Swap: +swap usage +.TP +.B Kin: +kilobytes swap pager pages paged in (last interval) +.TP +.B Kout: +kilobytes swap pager pages paged out (last interval) +.PP + +See /usr/include/sys/vmmeter.h and /sys/vm/vm_meter.c. +.PP +Contributors: Christos Zoulas, Steven Wallace, Wolfram Schneider, +Monte Mitzelfelt. +.PP +This module was retrofitted from FreeBSD 4.6.2 sources. diff --git a/external/bsd/top/dist/machine/m_hpux10.c b/external/bsd/top/dist/machine/m_hpux10.c new file mode 100644 index 000000000..1bb8e4a1a --- /dev/null +++ b/external/bsd/top/dist/machine/m_hpux10.c @@ -0,0 +1,701 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: any hp9000 running hpux version 10.x + * + * DESCRIPTION: + * This is the machine-dependent module for HPUX 10/11 that uses pstat. + * It has been tested on HP/UX 10.01, 10.20, and 11.00. It is presumed + * to work also on 10.10. + * Idle processes are marked by being either runnable or having a %CPU + * of at least 0.1%. This fraction is defined by CPU_IDLE_THRESH and + * can be adjusted at compile time. + * + * CFLAGS: -DHAVE_GETOPT + * + * LIBS: + * + * AUTHOR: John Haxby + * AUTHOR: adapted from Rich Holland + * AUTHOR: adapted from Kevin Schmidt + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 ""; +} + +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); +} + diff --git a/external/bsd/top/dist/machine/m_hpux10.man b/external/bsd/top/dist/machine/m_hpux10.man new file mode 100644 index 000000000..626597904 --- /dev/null +++ b/external/bsd/top/dist/machine/m_hpux10.man @@ -0,0 +1,18 @@ +.SH "HPUX 10 INFORMATION" +The process information layout has changed slightly since previous +versions. The CPU percentage column reports weighted cpu as +calculated directly by the kernel. The WCPU column is no longer +present in the output and a TTY column has been added to indicate +the name of the process's controlling terminal. +The definition of an +idle process has been relaxed to include those processes that have only +just gone to sleep. + +This version of top does not display a per-cpu breakdown of processor +state. Perhaps a later version will add this sophistication across +all platforms. + +The HP/UX 10 port has greatly benefitted from the diligent efforts +of the following individuals: John Haxby , +Rich Holland , and . + diff --git a/external/bsd/top/dist/machine/m_hpux7.c b/external/bsd/top/dist/machine/m_hpux7.c new file mode 100644 index 000000000..e6c5a90d9 --- /dev/null +++ b/external/bsd/top/dist/machine/m_hpux7.c @@ -0,0 +1,881 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: any hp9000 running hpux version 7 or earlier + * + * DESCRIPTION: + * This is the machine-dependent module for Hpux 6.5 and 7.0. + * This makes top work on the following systems: + * hp9000s300 + * hp9000s700 + * hp9000s800 + * + * LIBS: + * + * AUTHOR: Christos Zoulas + */ + +#include "config.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, ""); + 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 + */ + 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); +} diff --git a/external/bsd/top/dist/machine/m_hpux8.c b/external/bsd/top/dist/machine/m_hpux8.c new file mode 100644 index 000000000..83dc9c2bd --- /dev/null +++ b/external/bsd/top/dist/machine/m_hpux8.c @@ -0,0 +1,819 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: any hp9000 running hpux version 8 (may work with 9) + * + * DESCRIPTION: + * This is the machine-dependent module for HPUX 8 and is rumored to work + * for version 9 as well. This makes top work on (at least) the + * following systems: + * hp9000s300 + * hp9000s700 + * hp9000s800 + * + * LIBS: + * + * AUTHOR: Christos Zoulas + */ + +#include "config.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +# 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, ""); + 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 + */ + 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); +} diff --git a/external/bsd/top/dist/machine/m_hpux9.c b/external/bsd/top/dist/machine/m_hpux9.c new file mode 100644 index 000000000..b0ae79129 --- /dev/null +++ b/external/bsd/top/dist/machine/m_hpux9.c @@ -0,0 +1,842 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: any hp9000 running hpux version 9 + * + * DESCRIPTION: + * This is the machine-dependent module for HPUX 9. + * This makes top work on (at least) the following systems: + * hp9000s800 + * hp9000s700 + * This may make top work on the following, but we aren't sure: + * hp9000s300 + * + * LIBS: + * + * CFLAGS: -DHAVE_GETOPT + * + * AUTHOR: Kevin Schmidt + * adapted from Christos Zoulas + */ + +#include "config.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +# 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 */ +# define PCT_NORM 9 /* log2(PCT_BASE) */ +# define PCT_BASE (1<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, ""); + 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 + */ + 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); +} diff --git a/external/bsd/top/dist/machine/m_hpux9.man b/external/bsd/top/dist/machine/m_hpux9.man new file mode 100644 index 000000000..550fe0754 --- /dev/null +++ b/external/bsd/top/dist/machine/m_hpux9.man @@ -0,0 +1,9 @@ +.SH "HPUX 9 INFORMATION" +Under HP/UX 9, the kernel symbol _ccpu was eliminated. The author +believe that _cexp is a suitable substitute, but cannot be positive. +This seems to be confirmed by the fact that information produced using +this assumption correlates well with that produced by HP's version of top. + +This port was adapted from the port for HP/UX version 8 (written by +Christos Zoulas). The adaptation was performed by Kevin Schmidt +. diff --git a/external/bsd/top/dist/machine/m_irix5.c b/external/bsd/top/dist/machine/m_irix5.c new file mode 100644 index 000000000..1009709a5 --- /dev/null +++ b/external/bsd/top/dist/machine/m_irix5.c @@ -0,0 +1,763 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: any uniprocessor, 32 bit SGI machine running IRIX 5.3 + * + * DESCRIPTION: + * This is the machine-dependent module for IRIX 5.3. + * It has been tested on Indys running 5.3 and Indigos running 5.3XFS + * + * LIBS: -lmld + * CFLAGS: -DHAVE_GETOPT + * + * AUTHOR: Sandeep Cariapa + * This is not a supported product of Silicon Graphics, Inc. + * Please do not call SGI for support. + * + */ + +#define _KMEMUSER + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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<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; + +} + diff --git a/external/bsd/top/dist/machine/m_irixsgi.c b/external/bsd/top/dist/machine/m_irixsgi.c new file mode 100644 index 000000000..cd9fa9c9f --- /dev/null +++ b/external/bsd/top/dist/machine/m_irixsgi.c @@ -0,0 +1,1109 @@ +/* + * 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 + * AUTHOR: Larry McVoy + * Sandeep did all the hard work; I ported to 6.2 and fixed up some formats. + * AUTHOR: John Schimmel + * He did the all irix merge. + * AUTHOR: Ariel Faigon + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for < 6.4 NDPHIMAX et al. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 ) + * 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); + } +} + diff --git a/external/bsd/top/dist/machine/m_linux.c b/external/bsd/top/dist/machine/m_linux.c new file mode 100644 index 000000000..480177209 --- /dev/null +++ b/external/bsd/top/dist/machine/m_linux.c @@ -0,0 +1,1355 @@ +/* + * 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 + * Order support added by Alexey Klimkin + * Ported to 2.4 by William LeFebvre + * Additions for 2.6 by William LeFebvre + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for HZ */ +#include /* for PAGE_SHIFT */ + +#if 0 +#include /* 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; +} diff --git a/external/bsd/top/dist/machine/m_linux.man b/external/bsd/top/dist/machine/m_linux.man new file mode 100644 index 000000000..3067fb1b9 --- /dev/null +++ b/external/bsd/top/dist/machine/m_linux.man @@ -0,0 +1,10 @@ +.SH "LINUX NOTES" +The Linux port was written by Richard Henderson . +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 + +Made to work under 2.4 by William LeFebvre. diff --git a/external/bsd/top/dist/machine/m_linuxthr.c b/external/bsd/top/dist/machine/m_linuxthr.c new file mode 100644 index 000000000..eb79e5b68 --- /dev/null +++ b/external/bsd/top/dist/machine/m_linuxthr.c @@ -0,0 +1,1111 @@ +/* + * 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 + * Order support added by Alexey Klimkin + * Ported to 2.4 by William LeFebvre + * Thread eliding by William LeFebvre + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for HZ */ +#include /* for PAGE_SHIFT */ + +#if 0 +#include /* 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; +} diff --git a/external/bsd/top/dist/machine/m_linuxthr.man b/external/bsd/top/dist/machine/m_linuxthr.man new file mode 100644 index 000000000..d08f98cd7 --- /dev/null +++ b/external/bsd/top/dist/machine/m_linuxthr.man @@ -0,0 +1,30 @@ +.SH "LINUX NOTES" +The Linux port was written by Richard Henderson . +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 + +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. + diff --git a/external/bsd/top/dist/machine/m_macosx.c b/external/bsd/top/dist/machine/m_macosx.c new file mode 100644 index 000000000..88e4b09e6 --- /dev/null +++ b/external/bsd/top/dist/machine/m_macosx.c @@ -0,0 +1,956 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * m_macosx.c + * + * AUTHOR: Andrew S. Townley + * based on m_bsd44.c and m_next32.c + * by Christos Zoulas and Tim Pugh + * CREATED: Tue Aug 11 01:51:35 CDT 1998 + * SYNOPSIS: MacOS X Server (Rhapsody Developer Release 2) + * DESCRIPTION: + * MacOS X Server (Rhapsody Developer Release 2) + * + * CFLAGS: -DHAVE_STRERROR + * TERMCAP: none + * MATH: none + */ + +/* + * normal stuff + */ + +#include "config.h" + +#include +#include +#include +#include "os.h" +#include "top.h" +#include "machine.h" +#include "utils.h" + +/* + * MacOS kernel stuff + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 */ + 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); +} + diff --git a/external/bsd/top/dist/machine/m_macosx.man b/external/bsd/top/dist/machine/m_macosx.man new file mode 100644 index 000000000..c92a76dfc --- /dev/null +++ b/external/bsd/top/dist/machine/m_macosx.man @@ -0,0 +1,20 @@ +.SH "MacOS X NOTES" +The display is pretty close to the recommended display and also that +of a normal 4.4 BSD system. The NICE column has been changed to be +the number of threads for each process. The SIZE column reflects the +total size of the process (resident + non-resident) while the RES +column shows only the resident size. The STATE column uses +information taken from the kinfo_proc structure p_pstat member. It +will accurately display the state of stopped and zombie processes, but +I am not really sure about the other states. Finally, the MEM column +is included which displays the percent of total memory per the ps +command. + +The MacOS X module was written by Andrew S. Townley . +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. + diff --git a/external/bsd/top/dist/machine/m_netbsd.c b/external/bsd/top/dist/machine/m_netbsd.c new file mode 100644 index 000000000..fb2d5bf5b --- /dev/null +++ b/external/bsd/top/dist/machine/m_netbsd.c @@ -0,0 +1,1366 @@ +/* $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 + * Steven Wallace + * Wolfram Schneider + * Arne Helme + * Luke Mewburn + * matthew green + * Simon Burge + * Tomas Svensson + * Andrew Doran + * + * + * $Id: m_netbsd.c,v 1.18 2013/10/20 03:02:27 christos Exp $ + */ +#include + +#ifndef lint +__RCSID("$NetBSD: m_netbsd.c,v 1.18 2013/10/20 03:02:27 christos Exp $"); +#endif + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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 ""; + 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); +} diff --git a/external/bsd/top/dist/machine/m_netbsd.man b/external/bsd/top/dist/machine/m_netbsd.man new file mode 100644 index 000000000..ca5da1569 --- /dev/null +++ b/external/bsd/top/dist/machine/m_netbsd.man @@ -0,0 +1,5 @@ +.SH "NetBSD NOTES" + +This module has been tested on NetBSD 1.6, NetBSD 2.0 and NetBSD 3.0. +It should also work on NetBSD 1.5, and probably any newer releases of +NetBSD with little or no changes. diff --git a/external/bsd/top/dist/machine/m_sco5.c b/external/bsd/top/dist/machine/m_sco5.c new file mode 100644 index 000000000..e36cd04e2 --- /dev/null +++ b/external/bsd/top/dist/machine/m_sco5.c @@ -0,0 +1,874 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: SCO UNIX OpenServer5 + * + * DESCRIPTION: + * This is the machine-dependent module for SCO OpenServer5. + * Originally written for BSD4.3 system by Christos Zoulas. + * Modified to m_sco.c (3.2v4.2) by Gregory Shilin + * Modified to m_sco5.c (3.2v5.*) by Mike Hopkirk + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, ""); + 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 */ + 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); +} + diff --git a/external/bsd/top/dist/machine/m_sco5.man b/external/bsd/top/dist/machine/m_sco5.man new file mode 100644 index 000000000..d0ed276c2 --- /dev/null +++ b/external/bsd/top/dist/machine/m_sco5.man @@ -0,0 +1,6 @@ +.SH "SCO UNIX NOTES" +The SCO OpenServer5 port is a modification of the SCO Unix port +done by Mike Hopkirk (hops@sco.com). +OpenServer5 is a more normal Unix although the proc variables are still +somewhat funky. No easy access to RSS memory and CPUTICKS. +Added support for ordering and enabled use of setpriority(). diff --git a/external/bsd/top/dist/machine/m_sunos4.c b/external/bsd/top/dist/machine/m_sunos4.c new file mode 100644 index 000000000..1202a764c --- /dev/null +++ b/external/bsd/top/dist/machine/m_sunos4.c @@ -0,0 +1,979 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: any Sun running SunOS version 4.x + * + * DESCRIPTION: + * This is the machine-dependent module for SunOS 4.x. + * This makes top work on the following systems: + * SunOS 4.0 + * SunOS 4.0.1 + * SunOS 4.0.2 (including 386i architecture) + * SunOS 4.0.3 + * SunOS 4.1 + * SunOS 4.1.1 + * SunOS 4.1.2 (including MP architectures) + * SunOS 4.1.3 (including MP architectures) + * SunOS 4.1.3_U1 (including MP architectures) + * SunOS 4.1.4 (including MP architectures) + * Solbourne OS/MP PRIOR to 4.1A + * + * LIBS: -lkvm + * + * CFLAGS: -DHAVE_GETOPT -DORDER + * + * AUTHOR: William LeFebvre + * Solbourne support by David MacKenzie + */ + +/* + * #ifdef MULTIPROCESSOR means Sun MP. + * #ifdef solbourne is for Solbourne. + */ + +#include "config.h" +#include +#include + +/* make sure param.h gets loaded with KERNEL defined to get PZERO & NZERO */ +#define KERNEL +#include +#undef KERNEL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef solbourne +#include +#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, ""); + 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); +} diff --git a/external/bsd/top/dist/machine/m_sunos4.man b/external/bsd/top/dist/machine/m_sunos4.man new file mode 100644 index 000000000..ac218ff71 --- /dev/null +++ b/external/bsd/top/dist/machine/m_sunos4.man @@ -0,0 +1,23 @@ +.SH "SUNOS 4 DIFFERENCES" +On multiprocessor machines, the amount of time the processors spend in +a spin lock is displayed along with the other processor state +percentages. The percentages shown for processor states are averages +across all processors. A process in run state also has its current +processor displayed in the STATE column, for example "run/2" indicates +running on processor 2. There is an extra column in the process +display indicating which processor each running process is assigned +to. Information about physical memory is displayed on the memory +status line, but information about virtual memory is not available. + +Due to incompatabilities in kernel data structures, a top executable +compiled on a Sun 4 multiprocessor architecture machine (sun4m) will +not run correctly on a uniprocessor architecture machine (sun4), and +vice versa. You will have to compile and maintain separate executables +for these architectures. Yeah, I don't like it either. + +Some processes may show up with a resident set size (RES column) larger +than total virtual memory size (SIZE column). This seems odd at first, +but is a consequence of shared libraries: shared memory is counted as +resident but is not counted in total size. + +The SunOS 4 port was written by William LeFebvre. diff --git a/external/bsd/top/dist/machine/m_sunos5.c b/external/bsd/top/dist/machine/m_sunos5.c new file mode 100644 index 000000000..f47a5a48c --- /dev/null +++ b/external/bsd/top/dist/machine/m_sunos5.c @@ -0,0 +1,2270 @@ +/* + * 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 + * Robert Boucher + * CONTRIBUTORS: Marc Cohen + * Charles Hedrick + * William L. Jones + * Petri Kutvonen + * Casper Dik + * Tim Pugh + */ + +#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 +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "hash.h" + +#if OSREV >= 53 +#define USE_KSTAT +#endif +#ifdef USE_KSTAT +#include +/* + * 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<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 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 + diff --git a/external/bsd/top/dist/machine/m_sunos5.man b/external/bsd/top/dist/machine/m_sunos5.man new file mode 100644 index 000000000..2b649bc08 --- /dev/null +++ b/external/bsd/top/dist/machine/m_sunos5.man @@ -0,0 +1,97 @@ +.SH "SUNOS 5 NOTES" +CPU percentage is calculated as a fraction of total available computing +resources. Hence on a multiprocessor machine a single threaded process +can never consume cpu time in excess of 1 divided by the number of processors. +For example, on a 4 processor machine, a single threaded process will +never show a cpu percentage higher than 25%. The CPU percentage column +will always total approximately 100, regardless of the number of processors. + +The kernel summary line shows the following information, all displayed +as a per-second rate: +.TP 9 +.B ctxsw +Context switches. +.TP 9 +.B trap +Number of traps. +.TP 9 +.B intr +Number of interrupts. +.TP 9 +.B syscall +Number of system calls. +.TP 9 +.B fork +Number of forks and vforks. +.TP 9 +.B flt +Number of page faults. +.TP 9 +.B pgin +Number of kilobytes paged in to physical memory. +.TP 9 +.B pgout +Number of kilobytes paged out from physical memory. +.PP +The memory summary line displays the following: +.TP 14 +.B "phys mem" +Total amount of physical memory that can be allocated for use by processes +(it does not include memory reserved for the kernel's use). +.TP 14 +.B "free mem" +The amount of unallocated physical memory. +.TP 14 +.B "total swap" +The total amount of swap area allocated on disk. +.TP 14 +.B "free swap" +The amount of swap area on disk that is still available. +.PP +Unlike previous versions of +.IR top , +the swap figures will differ from the summary output of +.IR swap (1M) +since the latter includes physical memory as well. +.PP +The column +.B NLWP +indicates the number of lightweight processes in a process. +This usually corresponds to the number of threads in that process. +.PP +The display of individual threads can be toggled with the +synonymous commands +.B t +and +.BR H. +Information about state, priority, CPU time and percent CPU are +shown for each individual thread. Other information is identical +for all threads in the same process. In this display the column +.B LWP +replaces +.B NLWP +and shows the lightweight process id. The +column names +.B LWP +and +.B NLWP +are consistent with +.IR ps (1). +.PP +In BSD Unix, process priority was represented internally as a signed +offset from a zero value with an unsigned value. The "zero" value +was usually something like 20, allowing for a range of priorities +from -20 to 20. As implemented on SunOS 5, older versions of top +continued to interpret process priority in this manner, even though +it was no longer correct. Starting with top version 3.5, this was +changed to agree with the rest of the system. +.PP +Long options are not currently available in Solaris. +.PP +The SunOS 5 (Solaris 2) port was originally written by Torsten Kasch, +. Many contributions have been +provided by Casper Dik . +Support for multi-cpu, calculation of CPU% and memory stats provided by +Robert Boucher , Marc Cohen , +Charles Hedrick , and +William L. Jones . diff --git a/external/bsd/top/dist/machine/m_svr4.c b/external/bsd/top/dist/machine/m_svr4.c new file mode 100644 index 000000000..1d1159942 --- /dev/null +++ b/external/bsd/top/dist/machine/m_svr4.c @@ -0,0 +1,757 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix + * + * SYNOPSIS: Intel based System V Release 4 + * + * DESCRIPTION: + * System V release 4.0.x for i486 + * System V release 4 for Okidata M88100 + * System V release 4 for NCR 3000 series OS Rel 1.00 to 2.02 + * System V release 4 for NCR 3000 series OS Rel 02.03.00 and above + * and probably other svr4 ports + * + * LIBS: -lelf + * + * AUTHORS: Andrew Herbert + * Robert Boucher + * Ported to System 3000 Release 2.03 by: + * Jeff Janvrin + */ + +#include "top.h" +#include "machine.h" +#include "utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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<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 + * David Cutter + * Andrew Herbert + * Robert Boucher + */ + +/* 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 + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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<> 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 +#include +#include +#include + +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 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; +} + diff --git a/external/bsd/top/dist/machine/m_svr5.man b/external/bsd/top/dist/machine/m_svr5.man new file mode 100644 index 000000000..dd363271f --- /dev/null +++ b/external/bsd/top/dist/machine/m_svr5.man @@ -0,0 +1,4 @@ +.SH "SVR5 CREDITS" +The SVR5 port was generated by Mike Hopkirk from the SVR42 port by David Cutter +with lots of help from Kurt Gollhardt and Doug Souders + diff --git a/external/bsd/top/dist/message.h b/external/bsd/top/dist/message.h new file mode 100644 index 000000000..c723dd1f8 --- /dev/null +++ b/external/bsd/top/dist/message.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* interface declaration for display messages */ +/* This is a small subset of the interface from display.c that + just contains the calls for displaying messages. Do not include + this and display.h at the same time. */ + +#ifndef _MESSAGE_H +#define _MESSAGE_H + +void error_message(const char *msgfmt, ...); +void clear_message(void); + +#endif /* _MESSAGE_H_ */ diff --git a/external/bsd/top/dist/os.h b/external/bsd/top/dist/os.h new file mode 100644 index 000000000..6a9a2cdf3 --- /dev/null +++ b/external/bsd/top/dist/os.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include + +#ifdef HAVE_LIMITS_H +#include +#endif + +#if TIME_WITH_SYS_TIME +# include +# include +#else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#ifdef __NetBSD__ +#include +#else +#define emalloc malloc +#define estrdup strdup +#define ecalloc calloc +#define erealloc realloc +#endif + +#if STDC_HEADERS +#include +#include +#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 +#else +#ifdef HAVE_STRING_H +#include +#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 +#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 +#endif + +#ifdef HAVE_SYSEXITS_H +#include +#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 diff --git a/external/bsd/top/dist/screen.c b/external/bsd/top/dist/screen.c new file mode 100644 index 000000000..fcc35d148 --- /dev/null +++ b/external/bsd/top/dist/screen.c @@ -0,0 +1,605 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top users/processes display for Unix + * Version 3 + */ + +/* This file contains the routines that interface to termcap and stty/gtty. + * + * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty. + * + * I put in code to turn on the TOSTOP bit while top was running, but I + * didn't really like the results. If you desire it, turn on the + * preprocessor variable "TOStop". --wnl + */ + +#include "os.h" +#include "top.h" + +#if HAVE_CURSES_H && HAVE_TERM_H +#include +#include +#else +#if HAVE_TERMCAP_H +#include +#else +#if HAVE_CURSES_H +#include +#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 +#ifdef CBREAK +# include +# define USE_SGTTY +#else +# ifdef TCGETA +# define USE_TERMIO +# include +# else +# define USE_TERMIOS +# include +# 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); + } +} + + diff --git a/external/bsd/top/dist/screen.h b/external/bsd/top/dist/screen.h new file mode 100644 index 000000000..fedf8d7f3 --- /dev/null +++ b/external/bsd/top/dist/screen.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * top - a top users display for Unix 4.2 + * + * This file contains all the definitions necessary to use the hand-written + * screen package in "screen.c" + */ + +#ifndef _SCREEN_H_ +#define _SCREEN_H_ + +extern char ch_erase; /* set to the user's erase character */ +extern char ch_kill; /* set to the user's kill character */ +extern char ch_werase; /* set to the user's werase character */ +extern char smart_terminal; /* set if the terminal has sufficient termcap + capabilities for normal operation */ + +/* rows and columns on the screen according to termcap */ +extern int screen_length; +extern int screen_width; + +void screen_getsize(void); +int screen_readtermcap(int interactive); +void screen_init(void); +void screen_end(void); +void screen_reinit(void); +void screen_move(int x, int y); +void screen_standout(const char *msg); +void screen_clear(void); +int screen_cte(void); +void screen_cleareol(int len); +void screen_home(void); + +#endif /* _SCREEN_H_ */ diff --git a/external/bsd/top/dist/sigconv.awk b/external/bsd/top/dist/sigconv.awk new file mode 100644 index 000000000..cab964e52 --- /dev/null +++ b/external/bsd/top/dist/sigconv.awk @@ -0,0 +1,91 @@ +# Copyright (c) 1984 through 2008, William LeFebvre +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of William LeFebvre nor the names of other +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# +# Awk script converts an include file with definitions for signal names +# in to a predefined array that associates the signal numbers to the names. +# + +BEGIN { + nsig = 0; + j = 0; + print "/* This file was automatically generated */" + print "/* by the awk script \"sigconv.awk\". */\n" + print "struct sigdesc {" + print " const char *name;" + print " int number;" + print "};\n" + print "struct sigdesc sigdesc[] = {" + } + +/^#define[ \t][ \t]*SIG[A-Z]/ { + + j = sprintf("%d", $3); + if (siglist[j] != "") next; + str = $2; + + if (nsig < j) + nsig = j; + + siglist[j] = sprintf("\"%s\",\t%2d", \ + substr(str, 4), j); + } +/^#[ \t]*define[ \t][ \t]*SIG[A-Z]/ { + + j = sprintf("%d", $4); + if (siglist[j] != "") next; + str = $3; + + if (nsig < j) + nsig = j; + + siglist[j] = sprintf("\"%s\",\t%2d", \ + substr(str, 4), j); + } +/^#[ \t]*define[ \t][ \t]*_SIG[A-Z]/ { + + j = sprintf("%d", $4); + if (siglist[j] != "") next; + str = $3; + + if (nsig < j) + nsig = j; + + siglist[j] = sprintf("\"%s\",\t%2d", \ + substr(str, 5), j); + } + +END { + for (n = 1; n <= nsig; n++) + if (siglist[n] != "") + printf(" { %s },\n", siglist[n]); + + printf(" { NULL,\t 0 }\n};\n"); + } diff --git a/external/bsd/top/dist/top.1.in b/external/bsd/top/dist/top.1.in new file mode 100644 index 000000000..c0eb4bfbe --- /dev/null +++ b/external/bsd/top/dist/top.1.in @@ -0,0 +1,477 @@ +.\" NOTE: changes to the manual page for "top" should be made in the +.\" file "top.1.in" and NOT in the file "top.1". +.nr N @DEFAULT_TOPN@ +.nr D @DEFAULT_DELAY@ +.nr L @HAVE_GETOPT_LONG@ +.nr K @ENABLE_KILL@ +.TH TOP 1 Local +.UC 4 +.SH NAME +top \- display and update information about the top cpu processes +.SH SYNOPSIS +.B top +[ +.B \-1CISTabcinqtuv +] [ +.BI \-d count +] [ +.BI \-m mode +] [ +.BI \-o field +] [ +.BI \-p pid +] [ +.BI \-s time +] [ +.BI \-U username +] [ +.I number +] +.SH DESCRIPTION +.\" This defines appropriate quote strings for nroff and troff +.ds lq \&" +.ds rq \&" +.if t .ds lq `` +.if t .ds rq '' +.\" Just in case these number registers aren't set yet... +.if \nN==0 .nr N 10 +.if \nD==0 .nr D 5 +.I Top +displays the top +.if !\nN==-1 \nN +processes on the system and periodically updates this information. +.if \nN==-1 \ +\{\ +If standard output is an intelligent terminal (see below) then +as many processes as will fit on the terminal screen are displayed +by default. Otherwise, a good number of them are shown (around 20). +.\} +Raw cpu percentage is used to rank the processes. If +.I number +is given, then the top +.I number +processes will be displayed instead of the default. +.PP +.I Top +makes a distinction between terminals that support advanced capabilities +and those that do not. This +distinction affects the choice of defaults for certain options. In the +remainder of this document, an \*(lqintelligent\*(rq terminal is one that +supports cursor addressing, clear screen, and clear to end of line. +Conversely, a \*(lqdumb\*(rq terminal is one that does not support such +features. If the output of +.I top +is redirected to a file, it acts as if it were being run on a dumb +terminal. +.SH OPTIONS +.if \nL==0 Long options are not available on this system. +.TP +.B "\-1, \-\-percpustates" +Display per-cpu states on a multi-processor machine. +.TP +.B "\-C, \-\-color" +Turn off the use of color in the display. +.TP +.B "\-I, \-\-idle-procs" +Do not display idle processes. +By default, top displays both active and idle processes. +.TP +.B "\-S, \-\-system-procs" +Show system processes in the display. Normally, system processes such as +the pager and the swapper are not shown. This option makes them visible. +.TP +.B "\-T, \-\-tag-names" +List all available color tags and the current set of tests used for +color highlighting, then exit. +.TP +.B "\-a, \-\-all" +Show all processes for as long as possible. This is shorthand for +\*(lq-d all all\*(rq. This option is especially handy in batch mode. +.TP +.B "\-b, \-n, \-\-batch" +Use \*(lqbatch\*(rq mode. In this mode, all input from the terminal is +ignored. Interrupt characters (such as ^C and ^\e) still have an effect. +This is the default on a dumb terminal, or when the output is not a terminal. +.TP +.B "\-c, \-\-full-commands" +Show the full command line for each process. Default is to show just the +command name. This option is not supported on all platforms. +.TP +.B "\-i, \-\-interactive" +Use \*(lqinteractive\*(rq mode. In this mode, any input is immediately +read for processing. See the section on \*(lqInteractive Mode\*(rq +for an explanation of +which keys perform what functions. After the command is processed, the +screen will immediately be updated, even if the command was not +understood. This mode is the default when standard output is an +intelligent terminal. +.TP +.B "\-q, \-\-quick" +Renice +.I top +to -20 so that it will run faster. This can be used when the system is +being very sluggish to improve the possibility of discovering the problem. +This option can only be used by root. +.TP +.B "\-t, \-\-threads" +Show individual threads on separate lines. By default, on systems +which support threading, each process is shown with a count of the number +of threads. This option shows each thread on a separate line. This option +is not supported on all platforms. +.TP +.B "\-u, \-\-uids" +Do not take the time to map uid numbers to usernames. Normally, +.I top +will read as much of the file \*(lq/etc/passwd\*(rq as is necessary to map +all the user id numbers it encounters into login names. This option +disables all that, while possibly decreasing execution time. The uid +numbers are displayed instead of the names. +.TP +.B "\-v, \-\-version" +Write version number information to stderr then exit immediately. +No other processing takes place when this option is used. To see current +revision information while top is running, use the help command \*(lq?\*(rq. +.TP +.B "\-d \fIcount\fP, \-\-displays \fIcount\fP" +Show only +.I count +displays, then exit. A display is considered to be one update of the +screen. This option allows the user to select the number of displays he +wants to see before +.I top +automatically exits. Any proper prefix of the words \*(lqinfinity\*(rq, +\*(lqmaximum\*(rq, +or +\*(lqall\*(rq can be used to indicate an infinite number of displays. +The default for intelligent terminals is infinity. +The default for dumb terminals is 1. +.TP +.B "\-m \fImode\fP, \-\-mode=\fImode\fP" +Start the display in an alternate mode. Some platforms support multiple +process displays to show additional process information. The value +\fImode\fP is a number indicating which mode to display. The default is +0. On platforms that do not have multiple display modes this option has +no effect. +.TP +.B "\-o \fIfield\fP, \-\-sort-order=\fIfield\fP" +Sort the process display area on the specified field. The field name is +the name of the column as seen in the output, but in lower case. Likely +values are \*(lqcpu\*(rq, \*(lqsize\*(rq, \*(lqres\*(rq, and \*(lqtime\*(rq, +but may vary on different operating systems. Note that +not all operating systems support this option. +.TP +.B "\-p \fIpid\fP, \-\-pid=\fIpid\fP" +Only display the specified pid. +.TP +.B "\-s \fItime\fP, \-\-delay=\fItime\fP" +Set the delay between screen updates to +.I time +seconds. The default delay between updates is +.af D 1 +seconds. +.TP +.B "\-U \fIusername\fP, \-\-user=\fIusername\fP" +Show only those processes owned by +.IR username . +This option currently only accepts usernames and will not understand +uid numbers. +.PP +Both +.I count +and +.I number +fields can be specified as \*(lqinfinite\*(rq, indicating that they can +stretch as far as possible. This is accomplished by using any proper +prefix of the keywords +\*(lqinfinity\*(rq, +\*(lqmaximum\*(rq, +or +\*(lqall\*(rq. +The default for +.I count +on an intelligent terminal is, in fact, +\fBinfinity\fP. +.PP +The environment variable +.B TOP +is examined for options before the command line is scanned. This enables +a user to set his or her own defaults. The number of processes to display +can also be specified in the environment variable +.BR TOP . +The options +.BR \-C , +.BR \-I , +.BR \-S , +and +.B \-u +are actually toggles. A second specification of any of these options +will negate the first. Thus a user who has the environment variable +.B TOP +set to \*(lq\-I\*(rq may use the command \*(lqtop \-I\*(rq to see idle processes. +.SH "INTERACTIVE MODE" +When +.I top +is running in \*(lqinteractive mode\*(rq, it reads commands from the +terminal and acts upon them accordingly. In this mode, the terminal is +put in \*(lqCBREAK\*(rq, so that a character will be +processed as soon as it is typed. Almost always, a key will be +pressed when +.I top +is between displays; that is, while it is waiting for +.I time +seconds to elapse. If this is the case, the command will be +processed and the display will be updated immediately thereafter +(reflecting any changes that the command may have specified). This +happens even if the command was incorrect. If a key is pressed while +.I top +is in the middle of updating the display, it will finish the update and +then process the command. Some commands require additional information, +and the user will be prompted accordingly. While typing this information +in, the user's erase and kill keys (as set up by the command +.IR stty ) +are recognized, and a newline terminates the input. Note that a control-L +(^L) always redraws the current screen and a space forces an immediate +update to the screen using new data. +.PP +These commands are currently recognized: +.TP +.I "\fBh\fP\ or\ \fB?\fP" +Display a summary of the commands (help screen). Version information +is included in this display. +.TP +.B 1 +Toggle the display of per-cpu states. +.TP +.B C +Toggle the use of color in the display. +.TP +.B c +Display only processes whose commands match the specified string. An empty +string will display all processes. This command is not supported on all +platforms. +.TP +.B d +Change the number of displays to show (prompt for new number). +Remember that the next display counts as one, so typing +.B d1 +will make +.I top +show one final display and then immediately exit. +.TP +.B f +Toggle the display of the full command line. +.TP +.B H +Toggle the display of threads on separate lines. By default, on systems +which support threading, each process is shown with a count of the number +of threads. This command shows each thread on a separate line. This command +is not supported on all platforms. +.TP +.B i +(or +.BR I ) +Toggle the display of idle processes. +.if \nK==1 \{\ +.TP +.B k +Send a signal (\*(lqkill\*(rq by default) to a list of processes. This +acts similarly to the command +.IR kill (1)). +.\} +.TP +.B M +Sort display by memory usage. Shorthand for \*(lqo size\*(rq. +.TP +.B m +Change to a different process display mode. Some systems provide multiple +display modes for the process display which shows different information. +This command toggles between the available modes. This command is not +supported on all platforms. +.TP +.B N +Sort by process id. Shorthand for \*(lqo pid\*(rq. +.TP +.B n or # +Change the number of processes to display (prompt for new number). +.TP +.B o +Change the order in which the display is sorted. This command is not +available on all systems. The sort key names vary fron system to system +but usually include: \*(lqcpu\*(rq, \*(lqres\*(rq, \*(lqsize\*(rq, +\*(lqtime\*(rq. The default is cpu. +.TP +.B P +Sort by CPU usage. Shorthand for \*(lqo cpu\*(rq. +.TP +.B q +Quit +.IR top. +.if \nK==1 \{\ +.TP +.B r +Change the priority (the \*(lqnice\*(rq) of a list of processes. +This acts similarly to the command +.IR renice (8)). +.\} +.TP +.B s +Change the number of seconds to delay between displays +(prompt for new number). +.TP +.B T +Sort by CPU time. Shorthand for \*(lqo time\*(rq. +.TP +.B U +Toggle between displaying usernames and uids. +.TP +.B u +Display only processes owned by a specific username (prompt for username). +If the username specified is simply \*(lq+\*(rq, then processes belonging +to all users will be displayed. +.SH "THE DISPLAY" +The actual display varies depending on the specific variant of Unix +that the machine is running. This description may not exactly match +what is seen by top running on this particular machine. Differences +are listed at the end of this manual entry. +.PP +The top lines of the display show general information +about the state of the system. The first line shows +(on some systems) the last process id assigned to a process, +the three load averages, +the system uptime, and the current time. +The second line displays the total number of processes followed +by a breakdown of processes per state. Examples of states common +to Unix systems are sleeping, running, starting, stopped, and zombie. +The next line displays a percentage of time spent in each of the +processor states (typically user, nice, system, idle, and iowait). +These percentages show the processor activity during the time since +the last update. For multi-processor systems, this information is +a summation of time across all processors. The next line shows +kernel-related activity (not available on all systems). The numbers +shown on this line are per-second rates sampled since the last update. +The exact +information displayed varies between systems, but some examples are: +context switches, interrupts, traps, forks, and page faults. The last +one or two lines show a summary of memory and swap activity. These lines +vary between systems. +.PP +The remainder of the screen displays information about individual +processes. This display is similar in spirit to +.IR ps (1) +but it is not exactly the same. The columns displayed by top will +differ slightly between operating systems. Generally, the following +fields are displayed: +.TP +.B PID +The process id. +.TP +.B USERNAME +Username of the process's owner (if +.B \-u +is specified, a UID column will be substituted for USERNAME). +.TP +.B THR +The number of threads in the processes (this column may also +be labeled NLWP). +.TP +.B PRI +Current priority of the process. +.TP +.B NICE +Nice amount in the range \-20 to 20, as established by the use of +the command +.IR nice . +.TP +.B SIZE +Total size of the process (text, data, and stack) given in kilobytes. +.TP +.B RES +Resident memory: current amount of process memory that resides in physical +memory, given in kilobytes. +.TP +.B STATE +Current state (typically one of \*(lqsleep\*(rq, +\*(lqrun\*(rq, \*(lqidl\*(rq, \*(lqzomb\*(rq, or \*(lqstop\*(rq). +.TP +.B TIME +Number of system and user cpu seconds that the process has used. +.TP +.B CPU +Percentage of available cpu time used by this process. +.TP +.B COMMAND +Name of the command that the process is currently running. +.SH COLOR +Top supports the use of ANSI color in its output. By default, color is +available but not used. The environment variable +.B TOPCOLORS +specifies colors to use and conditions for which they should be used. +At the present time, only numbers in the summay display area can be +colored. In a future version it will be possible to highlight numbers +in the process display area as well. The environment variable is the +only way to specify color: there is no equivalent command line option. +Note that the environment variable +.B TOPCOLOURS +is also understood. The British spelling takes precedence. The use of +color only works on terminals that understand and process ANSI color +escape sequences. +.PP +The environment variable is a sequence of color specifications, separated +by colons. Each specification takes the form tag=min,max#code where +.I tag +is the name of the value to check, +.I min +and +.I max +specify a range for the value, and +.I code +is an ANSI color code. Multiple color codes can be listed and separated +with semi-colons. A missing +.I min +implies the lowest possible value (usually 0) +and a missing +.I max +implies infinity. The comma must always be present. When specifying numbers +for load averages, they should be multiplied by 100. +For example, the specification +.B 1min=500,1000#31 +indicates that a 1 minute load average between +5 and 10 should be displayed in red. Color attributes can be combined. +For example, the specification +.B 5min=1000,#37;41 +indicates that a 5 minute load average higher than 10 should be displayed +with white characters on a red background. A special tag named +.I header +is used to control the color of the header for process display. It should +be specified with no lower and upper limits, specifically +.B header=,# +followed by the ANSI color code. +.PP +You can see a list of color codes recognized by this installation of top +with the +.B \-T +option. This will also show the current set of tests used for +color highligting, as specified in the environment. +.SH AUTHOR +William LeFebvre +.SH ENVIRONMENT +.DT +TOP user-configurable defaults for options. +TOPCOLORS color specification +.SH BUGS +As with +.IR ps (1), +things can change while +.I top +is collecting information for an update. The picture it gives is only a +close approximation to reality. +.SH "SEE ALSO" +kill(1), +ps(1), +stty(1), +mem(4), +renice(8) +@MAN_SUPPLEMENT@ +.SH COPYRIGHT +Copyright (C) 1984-2007 William LeFebvre. For additional licensing +information, see http://www.unixtop.org/license/ diff --git a/external/bsd/top/dist/top.c b/external/bsd/top/dist/top.c new file mode 100644 index 000000000..083a73f41 --- /dev/null +++ b/external/bsd/top/dist/top.c @@ -0,0 +1,996 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +const char *copyright = + "Copyright (c) 1984 through 2008, William LeFebvre"; + +/* + * Changes to other files that we can do at the same time: + * screen.c:init_termcap: get rid of the "interactive" argument and have it + * pass back something meaningful (such as success/failure/error). + */ + +#include "os.h" +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif + +#ifdef HAVE_GETOPT_H +#include +#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<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. */ +} diff --git a/external/bsd/top/dist/top.h b/external/bsd/top/dist/top.h new file mode 100644 index 000000000..24b1abbd0 --- /dev/null +++ b/external/bsd/top/dist/top.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top - a top users display for Berkeley Unix + * + * General (global) definitions + */ + +#ifndef _TOP_H_ +#define _TOP_H_ + +#include + +/* 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_ */ diff --git a/external/bsd/top/dist/username.c b/external/bsd/top/dist/username.c new file mode 100644 index 000000000..b460aa45d --- /dev/null +++ b/external/bsd/top/dist/username.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top users/processes display for Unix + * Version 3 + */ + +/* + * Username translation code for top. + * + * These routines handle uid to username mapping. They use a hash table to + * reduce reading overhead. Entries are refreshed every EXPIRETIME seconds. + * + * The old ad-hoc hash functions have been replaced with something a little + * more formal and (hopefully) more robust (found in hash.c) + */ + +#include "os.h" + +#include + +#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); +} + diff --git a/external/bsd/top/dist/username.h b/external/bsd/top/dist/username.h new file mode 100644 index 000000000..2dda037ac --- /dev/null +++ b/external/bsd/top/dist/username.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* interface for username.c */ + +#ifndef _USERNAME_H_ +#define _USERNAME_H_ + +void init_username(void); +char *username(int uid); +int userid(char *username); + +#endif /* _USERNAME_H_ */ diff --git a/external/bsd/top/dist/utils.c b/external/bsd/top/dist/utils.c new file mode 100644 index 000000000..22d3e8ccf --- /dev/null +++ b/external/bsd/top/dist/utils.c @@ -0,0 +1,752 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top users/processes display for Unix + * Version 3 + */ + +/* + * This file contains various handy utilities used by top. + */ + +#include "os.h" +#include +#ifdef HAVE_STDARG_H +#include +#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 + diff --git a/external/bsd/top/dist/utils.h b/external/bsd/top/dist/utils.h new file mode 100644 index 000000000..78320abd4 --- /dev/null +++ b/external/bsd/top/dist/utils.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top users/processes display for Unix + */ + +/* prototypes for functions found in utils.c */ + +#ifndef _UTILS_H +#define _UTILS_H + +int atoiwi(char *); +char *itoa(int); +char *itoa_w(int, int); +char *itoa7(int); +int digits(int); +char *printable(char *); +char *strcpyend(char *, const char *); +char *homogenize(const char *); +int string_index(const char *, const char **); +char **argparse(char *, int *); +long percentages(int, int *, long *, long *, long *); +const char *errmsg(int); +char *format_percent(double); +char *format_time(long); +char *format_k(long); +char *string_list(const char **); +void time_get(struct timeval *); +void time_mark(struct timeval *); +void double2tv(struct timeval *, double); +unsigned int time_elapsed(void); +unsigned int diff_per_second(unsigned int, unsigned int); +void debug_set(int); +#ifdef DEBUG +#define dprintf xdprintf +void xdprintf(char *fmt, ...); +#else +#ifdef HAVE_C99_VARIADIC_MACROS +#define dprintf(...) +#else +#ifdef HAVE_GNU_VARIADIC_MACROS +#define dprintf(x...) +#else +#define dprintf if (0) +#endif +#endif +#endif + +#endif diff --git a/external/bsd/top/dist/version.c b/external/bsd/top/dist/version.c new file mode 100644 index 000000000..3c30e3114 --- /dev/null +++ b/external/bsd/top/dist/version.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top users/processes display for Unix + * Version 3 + */ + +#include "config.h" +#include "top.h" +#include "version.h" + +const char * +version_string(void) + +{ + return(PACKAGE_VERSION); +} diff --git a/external/bsd/top/dist/version.h b/external/bsd/top/dist/version.h new file mode 100644 index 000000000..fc0771223 --- /dev/null +++ b/external/bsd/top/dist/version.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1984 through 2008, William LeFebvre + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of William LeFebvre nor the names of other + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Top users/processes display for Unix + */ + +const char *version_string(void); diff --git a/minix/usr.bin/Makefile b/minix/usr.bin/Makefile index 2ca8843be..65f9057dd 100644 --- a/minix/usr.bin/Makefile +++ b/minix/usr.bin/Makefile @@ -8,7 +8,7 @@ SUBDIR+= diff SUBDIR+= grep SUBDIR+= mined SUBDIR+= ministat -SUBDIR+= top +SUBDIR+= mtop SUBDIR+= toproto SUBDIR+= trace diff --git a/minix/usr.bin/top/Makefile b/minix/usr.bin/mtop/Makefile similarity index 81% rename from minix/usr.bin/top/Makefile rename to minix/usr.bin/mtop/Makefile index 52efde9e2..f276cb0e3 100644 --- a/minix/usr.bin/top/Makefile +++ b/minix/usr.bin/mtop/Makefile @@ -1,7 +1,9 @@ -PROG= top +PROG= mtop MAN= DPADD+= ${LIBCURSES} ${LIBTERMINFO} LDADD+= -lcurses -lterminfo +WARNS?= 5 + .include diff --git a/minix/usr.bin/top/top.c b/minix/usr.bin/mtop/mtop.c similarity index 100% rename from minix/usr.bin/top/top.c rename to minix/usr.bin/mtop/mtop.c