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