summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.magnum.yml9
-rw-r--r--.travis.yml9
-rw-r--r--ChangeLog1026
-rw-r--r--Makefile.in22
-rw-r--r--NEWS57
-rw-r--r--README-BUILD.rst13
-rw-r--r--README.rst86
-rw-r--r--TODO4
-rw-r--r--aclocal.m4211
-rw-r--r--config.h.in12
-rwxr-xr-xconfig/config.guess1454
-rwxr-xr-xconfig/config.sub1815
-rwxr-xr-xconfig/install-sh23
-rwxr-xr-xconfigure398
-rw-r--r--configure.ac60
-rw-r--r--debian/changelog7
-rw-r--r--debian/patches/series1
-rw-r--r--debian/patches/upstream-cross-platform-fixes284
-rw-r--r--debian/watch7
-rw-r--r--man/procenv.115
-rw-r--r--procenv.spec4
-rw-r--r--src/Makefile.am95
-rw-r--r--src/Makefile.in440
-rw-r--r--src/messages.h41
-rw-r--r--src/output.c2003
-rw-r--r--src/output.h179
-rw-r--r--src/platform-headers.h286
-rw-r--r--src/platform.h171
-rw-r--r--src/platform/README.rst79
-rw-r--r--src/platform/android/platform.c48
-rw-r--r--src/platform/darwin/platform-darwin.h27
-rw-r--r--src/platform/darwin/platform.c276
-rw-r--r--src/platform/freebsd/platform-freebsd.h43
-rw-r--r--src/platform/freebsd/platform.c532
-rw-r--r--src/platform/hurd/platform-hurd.h38
-rw-r--r--src/platform/hurd/platform.c93
-rw-r--r--src/platform/linux/platform-linux.h174
-rw-r--r--src/platform/linux/platform.c2212
-rw-r--r--src/platform/minix/platform-minix.h25
-rw-r--r--src/platform/minix/platform.c128
-rw-r--r--src/platform/netbsd/platform-netbsd.h25
-rw-r--r--src/platform/netbsd/platform.c239
-rw-r--r--src/platform/openbsd/platform-openbsd.h25
-rw-r--r--src/platform/openbsd/platform.c201
-rw-r--r--src/platform/platform-generic.c973
-rw-r--r--src/platform/platform-generic.h74
-rw-r--r--src/platform/unknown/platform-unknown.h25
-rw-r--r--src/platform/unknown/platform.c91
-rw-r--r--src/pr_list.c6
-rw-r--r--src/pr_list.h2
-rw-r--r--src/procenv.c7555
-rw-r--r--src/procenv.h915
-rw-r--r--src/pstring.c310
-rw-r--r--src/pstring.h55
-rw-r--r--src/string-util.c543
-rw-r--r--src/string-util.h60
-rwxr-xr-xsrc/tests/check_all_args.in438
-rwxr-xr-xsrc/tests/show_compiler_details4
-rwxr-xr-xsrc/tests/show_machine_details59
-rw-r--r--src/types.h34
-rw-r--r--src/util.c294
-rw-r--r--src/util.h59
62 files changed, 15134 insertions, 9260 deletions
diff --git a/.magnum.yml b/.magnum.yml
new file mode 100644
index 0000000..1f2f482
--- /dev/null
+++ b/.magnum.yml
@@ -0,0 +1,9 @@
+install:
+ - sudo apt-get update -qq
+ - sudo apt-get install -y autopoint automake expat libnuma-dev libcap-dev check
+
+script:
+ - autoreconf -fi
+ - ./configure
+ - make -j4
+ - make check
diff --git a/.travis.yml b/.travis.yml
index afff87d..d4cc30e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,9 +6,14 @@ language: c
compiler:
- gcc
- clang
+os:
+ - linux
+ - osx
before_install:
- - sudo apt-get update -qq
- - sudo apt-get install -y autopoint automake expat libnuma-dev libcap-dev check
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y autopoint automake expat libnuma-dev libcap-dev check; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install expat check perl; fi
script: autoreconf -fi && ./configure && make -j4 && make check
notifications:
email:
diff --git a/ChangeLog b/ChangeLog
index 55ba18f..e69de29 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,1026 +0,0 @@
-2015-10-19 James Hunt <jamesodhunt@ubuntu.com>
-
- * man/procenv.1: Replace hard-coded utf character with unicode
- escape equivalent to suppress warning on Fedora.
- * src/tests/check_all_args.in: Replace heuristics to remove troff
- escapes with a safer approach.
- * src/procenv.c: show_uname(): Fix incorrect check on domainname,
- identified by Coverity.
-
-2015-09-28 James Hunt <jamesodhunt@ubuntu.com>
-
- * src/procenv.c:
- - Correct output order for 'libc:' and 'misc:'.
- * src/procenv.h:
- - Bump PROCENV_FORMAT_VERSION.
- * src/tests/check_all_args.in:
- - Ensure output sections are sorted and not duplicated.
-
-2015-09-27 James Hunt <jamesodhunt@ubuntu.com>
-
- * src/Makefile.am:
- - Pass path to man page to tests.
- * src/tests/check_all_args.in:
- - Set LC_ALL to the lang value under test.
- - Actually save the original LANG value.
- - 'set -e' fix.
- - Add test to compare options documented by 'procenv --help' with
- those in the man page to ensure no discrepancies.
-
-2015-09-25 James Hunt <jamesodhunt@ubuntu.com>
-
- * src/procenv.c:
- - show_libc(): New function for new '--libc'/'-B'
- option.
- - show_compiler(): Added following features:
- - _DEFAULT_SOURCE
- - _LARGEFILE_SUPPORT
- - __STDC_VERSION__
- * configure.ac: Add '--enable-reproducible-build' option which
- suppresses the display of values that will change between
- builds:
- - __DATE__
- - __TIME__
- - __TIMESTAMP__
-
-2015-08-24 James Hunt <james.hunt@ubuntu.com>
-
- * src/tests/check_all_args.in: Actually disable tests if non-existent
- locale found.
-
-2015-08-23 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: Coverity fixes:
- - get_mtu(): Drop useless goto and explicit zero return on error.
- - get_canonical(): safer string termination.
- - Allow '--indent-char' to be UTF-8.
- * src/tests/check_all_args.in:
- - New single-character tests for:
- - '--indent-char'.
- - '--separator'.
- - New multi-character tests for:
- - '--indent-char'.
- - '--separator'.
- - '--crumb-separator'.
- - Check default locale is valid before attempting to use it.
-
-2015-08-22 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.h: Use __func__ rather than __FUNCTION__ to appease gcc 5.2.
-
-2015-08-21 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: save_locale(): Specify 2nd arg to setlocale()
- as "" since the original NULL was not only incorrect, it caused
- a UTF-8 '--separator' or '--crumb-separator' to cause a crash.
- * src/tests/check_all_args.in:
- - New tests for UTF-8 '--separator' and '--crumb-separator'.
- - Show language test being run with.
- - Ensure full command-line shown on failure.
-
-2015-07-11 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: show_security_module_context_linux():
- Don't free @mode returned by aa_gettaskcon(2) since it forms
- part of the allocation returned in @context.
-
-2015-07-08 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - Update copyright.
- - show_mounts_linux(): Don't truncate fsid.
- - show_mounts_bsd(): Don't truncate fsid.
-
-2014-09-19 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: show_security_module_linux(): check HAVE_APPARMOR,
- not HAVE_SYS_APPARMOR_H to allow building on Ubuntu Lucid (which does
- not provide aa_is_enabled()).
-
-2014-09-18 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1:
- - Bump date.
- - Highlight non-display options.
- * src/procenv.c:
- - show_capabilities_linux(): Added CAP_AUDIT_READ.
- - main(): Allow '--exec' to come at the end of the command-line
- (the only non-display option this is valid for).
- * src/procenv.h: die(): Output to stderr, not stdout.
- * src/tests/check_all_args.in:
- - New test to ensure procenv can exec itself.
- - Enable tests to ensure procenv detects illegal placement of
- non-display options after any display option.
- - Fixed check on unknown capabilities.
- - Test to ensure a non-display option is disallowed after
- a display option is now more comprehensive.
- - src/tests/check_all_args.in: Ensure an empty environment is tolerated.
-
-2014-08-19 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: Restore Coverity 0.0 defect density:
- - translate(): Cleanup on error path.
- - pstring_create(): Cleanup on error path.
- * src/tests/check_all_args.in: Warn if more capabilities found
- than procenv is unaware of.
-
-2014-08-14 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1: More examples.
- * configure.ac: Add profiling for debug mode.
-
-2014-07-04 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: Correct guard used around procenv_getcpu()
- and split_fields().
-
-2014-07-03 James Hunt <james.hunt@ubuntu.com>
-
- * src/pr_list.c:
- - New functions:
- - pr_list_append_str()
- - pr_list_appendn_str()
- - pr_list_prependn_str()
- * src/procenv.c:
- - procenv_getcpu(): A {RHEL,Centos} 5-pecific hack to fully
- resolve LP: #1333194 by working around fact that glibc on that
- platform does not provide sched_getcpu(3).
-
-2014-06-26 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Updates.
- * src/procenv.c:
- - More fixes for LP: #1333194:
- - show_capabilities_linux(): Guard PR_CAPBSET_READ.
- - cap_get_bound(): Guard PR_CAPBSET_READ.
- * src/procenv.h: Define CAP_LAST_CAP when using old versions of libcap.
-
-2014-06-26 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_numa_memory():
- - Fix for systems using old numa libraries (RHEL5). This should
- really fix LP: #1333194.
- - show_security_module():
- - Corrected SELinux checking code.
- - Added MLS detail.
- - show_shared_mem_linux():
- - Compiler appeasement.
- - Added 'swap_attempts' and 'swap_successes' (apparently now unused,
- but displayed for completeness).
- - show_msg_queues_linux(): Compiler appeasement.
- * src/procenv.h:
- - PROCENV_FORMAT_VERSION: Bumped to v8.
- - Added PROCENV_NUMA_BITMASK_ISSET() macro to handle both old and new
- libnuma API's.
-
-2014-06-25 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - get_mtu(): Ensure unsigned long used for ioctl(2) request parameter
- (caught by FreeBSD's "WARNING ioctl sign-extension ioctl" console
- message).
- - get_mac_address(): As above.
- - show_uname(): Handle unset uts.domainname without an
- assertion to cope on OpenSuSE 13.1 systems.
-
-2014-06-24 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Add header checks for selinux and apparmor (LP: #1333182).
- * procenv.spec.in: Added 'libselinux-devel' to BuildRequires.
- * src/Makefile.am: Use $(top_builddir) and $(subdir) rather than
- $(abs_builddir) since the RHEL5 / Centos 5 version of automake don't
- define the latter.
- * src/procenv.c:
- - Fix building on RHEL5 / Centos 5 by guarding undefined personality
- symbols (LP: #1333194).
- - Guard code based on CPU_ALLOC(3) availability.
- - Guard capabilities, SELinux and AppArmor code.
- - show_numa_memory(): Use entry() rather than show(), the latter of
- which could have cause invalid formatted output if the NUMA policy
- could not be queried.
- - show_sizeof(): Add missing typedefs from stdint.h.
- * src/procenv.h: SELinux and capability guards.
- * src/tests/check_all_args.in:
- - Don't die if JSON or XML checker are unavailable - just run
- what tests are possible.
- - Test using C locale and current (if different).
-
-2014-06-09 James Hunt <james.hunt@ubuntu.com>
-
- * procenv.spec.in: Fix for spec file on RHEL - thanks Dave Love
- (LP: #1327594).
-
-2014-06-07 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: sysconf and confstr cleanups.
- * src/procenv.h:
- - Removed now unecessary macros.
- - Bumped PROCENV_FORMAT_VERSION.
-
-2014-06-04 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_pathconfs(): Guard all defines.
- - show_confstrs(): Guard all defines.
- * src/procenv.h: Added _show_confstr() macro to allow name to be
- specified.
-
-2014-06-03 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - Guard extended interfaces flags (IFF_*) since as of
- kernel 3.15 they have been removed (LP: #1324256).
- - show_all_groups(): Fixed possible memory leak - thanks Coverity.
- - show_uname(): Added asserts.
- * src/tests/check_all_args.in: Temporary work-around for lp:1325494.
-
-2014-03-27 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Update.
- * src/procenv.c:
- - get_arch(): Update for Sparc 64-bit (V9).
- - show_capabilities_linux(): Move CAP_LAST_CAP out of the list and use
- it as a count to avoid it being confused for an actual capability.
-
-2014-03-20 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1: Add reference to personality(2).
- * src/procenv.c: --misc: Add Linux personality type and flags.
- * src/procenv.h: Bump PROCENV_FORMAT_VERSION to 6 for format change.
-
-2014-03-17 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1: Add reference to libcap(3).
- * procenv.spec.in: Buid-depend on libcap-devel.
- * README: Update.
-
-2014-03-14 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_mounts_linux(): Don't quote unknown canonical name.
- - get_canonical(): Return value denoting if name was known.
- - show_capabilities_linux():
- - Use cap_get_bound() rather than prctl().
- - Memory leak fix.
- * src/procenv.h: _show_capability():
- - Use cap_get_bound() rather than prctl().
- - Add "supported".
-
-2014-03-13 James Hunt <james.hunt@ubuntu.com>
-
- * NEWS: Corrected formatting.
- * TODO: Updates.
- * configure.ac: Link to libcap if available.
- * src/procenv.c:
- - get_capability_by_flag(): New function to query a capability value
- for a specified capability type.
- - show_capabilities_linux():
- - Make use of libcap calls.
- - Add missing CAP_BLOCK_SUSPEND.
- - Show "unknown" capabilities if detected (capabilities that the
- running kernel supports which procenv doesn't know about).
- * src/procenv.h:
- - PROCENV_FORMAT_VERSION: bumped to version 5 for capabilities output
- format change.
- - show_capability(): Now calls _show_capability().
- - _show_capability(): Reworking of show_capability() macro that uses
- libcap calls and works for unknowns too.
-
-2014-01-31 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Build procenv.spec from .in file to auto-update
- version number.
- * procenv.spec.in: Renamed from procenv.spec.
- * src/procenv.c: show_capabilities_bsd(): Fixes to allow
- building on FreeBSD 9.
-
-2014-01-27 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Check for FreeBSD Capsicum support.
- * man/procenv.1:
- - --fds: Update for FreeBSD to mention Capsicum capabilities.
- - --capabilities: Explain this option is for Linux capabilities only
- (a different beast to Capsicum).
- - SEE ALSO: Further references.
- - Corrected BSD comment for --semaphores, --message-queues and
- --shared-memory.
- * src/procenv.c:
- - mntopt_map: Journaled Soft Updates fix for FreeBSD 8 and older.
- - usage():
- - Typo fix.
- - show_fds_generic(): Added FreeBSD Capsicum capabilities for systems
- which support it (FreeBSD 9+, assuming kernel is appropriately
- configured).
- - show_env(): Copy environ before sorting since modification is
- disallowed.
- - show_capabilities_bsd(): New function to query Capsicum capabilities.
- - show_shared_mem_linux(): Fixed bug that incorrectly showed the
- current process name rather than the last.
- * src/procenv.h:
- - Bumped PROCENV_FORMAT_VERSION (format-version) to 3 for FreeBSD
- capabilities.
- - Capsicum macro.
- - Replaced bool typedef with stdbool.h.
-
-2014-01-23 James Hunt <james.hunt@ubuntu.com>
-
- * procenv.spec: Added RPM specfile courtesy of Dave Love and
- updated for 0.30 (LP: #1100967).
- * Makefile.am: Distribute spec file.
-
-2014-01-22 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: show_cpu_affinities(): Initialise variable to
- pacify clang on FreeBSD 10.
-
-2014-01-14 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - get_tty_locked_status(): Assume unlocked if unable to query status
- (for example on Sparc64 running 2.6.32-5 kernel).
- - show_semaphores(): Calling semctl(SEM_INFO) without semun union was
- causing subsequent call to semctl(SEM_STAT) to SIGSEGV on Sparc and
- PPC architectures (Closes: #728684).
-
-2014-01-13 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Check for numa.h.
- * src/procenv.c: Allow building on Linux systems whose
- architectures are not NUMA-capable.
-
-2014-01-10 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1: Updated dates.
- * src/pr_list.c: Added header.
- * src/pr_list.h: Added header.
- * src/procenv.c:
- - Update date.
- - show_cpu_affinities(): Fix for FreeBSD which does
- not provide dynamic cpu sets (CPU_ALLOC(3) et al).
- - get_arch(): Added PPCspe and PPC64LE.
- * src/procenv.h: Added header.
-
-2014-01-08 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_cpu_affinities(): Fix for hyper-threaded systems
- (LP: #1251209) - thanks Dave Love.
- - show_numa_memory(): Fix memory leak (calling free(3) rather than
- numa_free_nodemask()).
- - show_sizeof():
- - Added lots of missing standard types (as documented in types.h(P)).
- - Sorted list.
- - show_cgroups_linux(): Fixed memory leak caused by misuse of
- strsep(3).
-
-2013-12-06 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: AM_INIT_AUTOMAKE: Ensure automake v1.13 is
- passed 'serial-tests'.
-
-2013-12-04 James Hunt <james.hunt@ubuntu.com>
-
- * src/tests/check_all_args.in: Fix to sections regex to avoid
- matching the TERMCAP variable (which contains various nasty
- characters).
-
-2013-12-03 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac:
- - Put AC_COPYRIGHT onto one line for older automakes.
- - Removed unused AC_TYPE_* checks.
- - "Fix" to handle the automake 1.13 "serial-tests" fiasco
- and always display test verbose test output.
- - Conditionally use format-security compiler flag.
- * src/procenv.c: show_numa_memory(): Tell libnuma not to call exit(3).
- * src/tests/check_all_args.in:
- - Add debug handling.
- - Use python rather than json_pp since the latter is not available
- on older perl installations.
-
-2013-12-02 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_mounts_linux(): Always initialise locals.
- - show_compiler(): Guard __TIMESTAMP__ which isn't available
- on old compilers.
-
-2013-11-30 James Hunt <james.hunt@ubuntu.com>
-
- * src/tests/check_all_args.in: Don't run XML tests if control
- characters found in the environment (for example in $TERMCAP
- when running under GNU Screen) since XMl validation will fail
- (which is only partly reasonable given that such charactes
- cannot be reliably encoded in XML anyway).
-
-2013-11-29 Dave Love <fx@gnu.org>
-
- * Fix for building on RHEL 5 (LP: #1256415).
-
-2013-11-29 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - Use PROCENV_GNU_BSD rather than PROCENV_LINUX_BSD_KERNEL.
- - Make use of generic stubs where appropriate.
- - encode_string(): Handle non-printables for JSON and XML.
- Note that they cannot be fully handled in XML as it disallows
- encoding control characters so a validating parser will choke
- on the output in that case.
- * src/tests/check_all_args.in:
- - Explicit test for json_pp.
- - Generate more details on error.
- - Protect against silent failure when setting section.
-
-2013-11-28 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - Use PROCENV_LINUX_BSD_KERNEL rather than raw define value for
- kFreeBSD systems.
- - Tweaks to hide NUMA from BSD systems.
- - usage(): Added missing entry for --memory (as caught by new test).
- - Made os-specific function names saner.
- - Make Linux-specific functions still display a heading by using
- stubs. This fixes the tests, makes the code slightly clearer
- (hopefully not at the expense of the user).
- * src/procenv.h:
- - Added PROCENV_LINUX_BSD_KERNEL for kFreeBSD systems.
- * src/tests/check_all_args.in:
- - New test to ensure that all sections generated by default output
- have a corresponding command-line option.
-
-2013-11-27 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Check for libnuma.
- * man/procenv.1:
- - Updated date.
- - Add -Y/--memory.
- * src/procenv.c:
- - show_misc(): Memory page size moved to show_memory().
- - show_memory(): New function.
- - dump():
- - Added missing call to show_cpu().
- - Added call to show_memory().
- - show_numa_memory(): New function to display NUMA details (LP: #1251209).
- * src/procenv.h: Bumped PROCENV_FORMAT_VERSION.
- * src/tests/check_all_args.in:
- - Check explicitly for xmlwf.
- - Added test to ensure all options produce output in default output
- mode too.
-
-2013-11-22 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: show_cpu_affinities(): New function that displays basic
- CPU affinity details.
- * man/procenv.1: Correct and add additional references for '--cpu'.
-
-2013-11-13 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - Fixes for unimplemented FreeBSD output:
- - show_shared_mem_bsd()
- - show_semaphores_bsd()
- - show_msg_queues_bsd()
- * src/tests/check_all_args.in:
- - Use mktemp(1) instead of Debian/Ubuntu-specific tempfile(1).
- - Remove rogue xmlwf call in '--format=text' test.
- - Fix for the unhelpful xmlwf: unlike every other Unix utility, xmlwf
- returns 0, even on failure (!) so we have to check if output is
- produced...
-
-2013-11-07 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: get_arch(): Added PPC64.
-
-2013-11-01 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1:
- - NOTES: Escape dash in indent-char.
- - EXAMPLES: Fixed display of indent-char value.
- * src/procenv.c: get_arch(): Added missing "SuperH".
-
-2013-10-30 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_signals(): Check return from get_signal_name() in case a
- platform doesn't provide the signal in question.
- - get_kernel_bits(): Return error value rather than calling die().
- - show_bsd_mounts(): Removed unused variables.
- - Added a few extra asserts to ensure section_open() is passed a valid
- name.
- * src/procenv.h: Need to define 'semun' on Hurd too.
-
-2013-10-25 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Stuff.
- * src/procenv.c: get_arch(): Fix for AARCH64 which seemingly isn't
- considered to be "ARM" by gcc.
-
-2013-10-15 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1:
- - Fix for lintian bug: spelling-error-in-binary.
- * src/procenv.c:
- - Fixes for lintian bugs: spelling-error-in-manpage,
- hyphen-used-as-minus-sign.
-
-2013-10-14 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Add '--debug' option.
- * man/procenv.1:
- - General tidy-up.
- - OPTIONS: Added '--crumb-separator'.
- - EXAMPLES: Added a few more.
- - LIMITATIONS: Updated.
- * src/pr_list.c: Undo erroneous "fix" to pr_list_append() and
- pr_list_prepend().
- * src/procenv.c:
- - Remove "(linux)" suffix from capabilities, cgroups and oom
- output: they are not displayed on other platforms, so the
- information is redundant.
- - Added '--crumb-separator'.
- - show_network_if(): Put flags in containeris rather than dumping as a
- comma-separated list.
-
-2013-10-13 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Update.
- * man/procenv.1: ENVIRONMENT VARIABLES:
- - Added PROCENV_INDENT, PROCENV_INDENT_CHAR and PROCENV_SEPARATOR.
- * src/pr_list.c:
- - Fix issue in pr_list_append() and pr_list_prepend().
- - Added PR_LIST_FOREACH_STR() and PR_LIST_FOREACH_REV_STR() from
- pr_list.h.
- - pr_list_visitor_str(): New.
- * src/procenv.c:
- - appendf(): Simplified and plugged a memory leak.
- - appendva(): Simplified and plugged a memory leak.
- - show_fds_linux(): Fixed memory leak.
- - show_semaphores_linux(): Fixed memory leak.
- - Comments.
- - cleanup(): Check crumb_list before clearing it.
- - check_envvars(): Added PROCENV_INDENT_ENV, PROCENV_INDENT_CHAR_ENV and
- PROCENV_SEPARATOR_ENV.
-
-2013-10-12 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Add ability to disable optimisation for debugging.
- * man/procenv.1:
- - SYNOPSIS: Added '--format=crumb'
- - ENVIRONMENT VARIABLES: Added 'PROCENV_FORMAT'.
- - NOTES: More details.
- - EXAMPLES: Two examples showing how to use '--format'.
- * src/Makefile.am:
- - Remove hard-coded optimisation flag.
- - Add pr_list.[ch] sources.
- * src/procenv.c:
- - Added 'crumb' format and supporting functions.
- - Removed horrid object-handling hacks since object_open()
- and object_close() are now sensible.
- - Added calls to object_open() and object_close() in various places
- for json array handling.
- - usage():
- - Fixed '--messages-queues' and '--shared-memory' to add missing
- intra-word dash.
- - Updated notes.
- - show_meta(): Use get_output_format_name() instead of hard-coded
- list.
- - show_stat(): Removed double header().
- - check_env_vars(): Update to handle 'PROCENV_FORMAT'.
- * src/tests/check_all_args.in:
- - Test both short and long options.
- - Test 'crumb' format.
-
-2013-10-03 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_proc(): Improved grouping by adding more sections.
- - show_meta(): Show output format.
- - show_compiler(): Add "feature test macros" section.
-
-2013-10-02 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1:
- - Added new options:
- - -C/--cpu.
- - --format.
- - --indent.
- - --indent-char.
- - --separator.
- - Removed bracketed partial option names since getopt_long(3) allows
- any unique partially named option.
- * src/Makefile.am:
- - Added check_all_args test.
- - CFLAGS: Check for unused variables.
- * src/procenv.c:
- - Added ability to produce output in either highly-structured text
- (default), JSON, or XML using the --format=<format> option.
-
-2013-09-13 James Hunt <james.hunt@ubuntu.com>
-
- * src/tests/check_all_args.in: Added missing test.
- * src/procenv.c:
- - usage():
- - Clarify option usage.
- - Ensure no wrapping on 80-column devices.
- - show_rlimits():
- - Enable RLIMIT_RTTIME on Linux.
- - Check kernel version and defines for newer limits.
- * src/procenv.h: Cleanup.
-
-2013-09-12 James Hunt <james.hunt@ubuntu.com>
-
- * src/Makefile.am: Updated for new check_all_args test.
- * src/procenv.c:
- - dump(): Ensure correct output ordering.
- - Added "not implemented" stubs for FreeBSD IPC functions.
- * src/tests/show_compiler_details: Don't hard-code 'gcc' - use 'cc'
- for maximum portability.
-
-2013-09-11 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1:
- - Added -E/--semaphores option.
- - Added -M/--message-queues option.
- - Added -S/--shared-memory option.
- - Added ref to ipcs(1).
- * src/procenv.c:
- - Added support for displaying IPC resources (shared memory,
- semaphores and message queues) under Linux only at this
- stage.
- - New utility functions: format_time(), format_perms() and
- pid_to_name().
-
-2013-08-30 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_stat(): Make resilient to failures.
- - show_linux_mounts(): Show if unable to query major+minor number.
- - show_bsd_mounts(): Show if unable to query major+minor number.
- - get_major_minor(): Return a value rather than simply warning on
- error.
-
-2013-08-28 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - show_network(): Handle bionics lack of getifaddrs().
- - get_arch(): Don't identify MIPSEL as MIPS.
-
-2013-08-23 James Hunt <james.hunt@ubuntu.com>
-
- * TODO:
- * man/procenv.1:
- - Added -A/--arguments option.
- - Updated --mount to include reference to statfs.
- - Added -N/--network option.
- - Updated SEE ALSO section.
- * src/procenv.c:
- - Added support for BSD/Hurd signals: SIGEMT, SIGINFO, SIGLOST.
- - usage(): Use colon to separate output types from description for
- consistency.
- - is_console(): Enable for FreeBSD/kFreeBSD.
- - append(): Allocate space if str points to NULL.
- - appendf(): Allocate space if str points to NULL.
- - appendva(): Allocate space if str points to NULL.
- - dump():
- - Call show_network().
- - Call show_locale() *after* show_rlimits() for correct ordering.
- - show_linux_mounts(): Add block and inode details (LP: #1212728).
- - show_bsd_mounts(): Add block and inode details (LP: #1212728).
- - show_compiler():
- - Added __FILE__, __BASE_FILE__ and __TIMESTAMP__.
- - main():
- - Updates for -N/--network.
- - New functions:
- - show_arguments().
- - get_network_address().
- - decode_if_flags().
- - get_ipv6_scope_name() (unused).
- - get_mtu().
- - get_mac_address().
- - decode_extended_if_flags().
- - get_net_family_name().
- - show_network_if().
- - show_network().
-
-2013-07-19 James Hunt <james.hunt@ubuntu.com>
-
- * src/man/procenv.1: Updated date and year.
- * src/procenv.c:
- - show_bsd_proc_branch(): Fix to work in BSD jails: these entities are
- bizarre in that they have no init process, and a processes parent
- may actually be a process running *outside* of the jail... and as a
- result, all you can know about it is its PID.
- - Various hacks to work in the decidedly un-bionic Android
- environment.
- * Android.mk: Makefile for Android.
-
-2013-07-04 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1: Add a new --exec example.
-
-2013-06-28 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Force old serial test behaviour (specifically
- for automake-1.13 and above) to ensure test output is visible in
- build logs.
-
-2013-05-31 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - dump_misc(): Don't quote value if it's UNKNOWN_STR
- (for easier parsing).
- - show_stat(): Change "mode" to "permissions" since not only is the
- latter more familiar to some, the tags should be as unique as
- possible (and we have another "mode" for privileged execution).
- - show_linux_mounts(): Display UNKNOWN_STR rather than aborting if
- /proc not mounted.
- - show_linux_proc_branch: As per show_linux_mounts().
- - get_os(): Fixed regression where kFreeBSD was not being detected
- (seemingly because __linux__ is no longer defined on such systems :-)
- - get_arch(): Added missing detection for "SystemZ".
- - show_linux_cgroups(): As per show_linux_mounts().
- - dump_linux_proc_fds(): As per show_linux_mounts().
- - show_oom(): As per show_linux_mounts().
- - get_root(): As per show_linux_mounts().
-
-2013-05-17 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1: Added -P/--platform option.
- * src/procenv.c:
- - usage(): Added -P/--platform option.
- - dump_misc(): Move platforms bits to dump_platform().
- - dump_platform(): New function:
- - dump(): Call dump_platform().
- - show executable bits.
- - Call show_data_model().
- - Call get_os() and get_arch().
- - get_platform(): Removed.
- - get_os(): New function.
- - get_arch(): New function (includes support for x32).
- - show_data_model(): New function.
- - main(): Added -P/--platform option.
-
-2013-04-07 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: show_tty_attrs():
- - Clear lock status for all non-linux platforms.
- - Update calls to show_const_tty() and show_cc_tty() passing
- lock_status as a parameter.
- * src/procenv.h:
- - show_cc_tty(): Pass lock status as a parameter. Comment header.
- - show_const_tty(): Pass lock status as a parameter. Comment header.
-
-2013-04-04 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - Changed __linux__ to PROCENV_LINUX.
- - header(): Fix possible buffer overflow.
- - dump_meta(): Added a "mode" value showing if running
- privileged or non-privileged (the former showing potentially
- more information).
- - show_tty_attrs():
- - Now shows individual locked tty attributes
- when running in privileged mode.
- - Added winsize attributes.
- - get_tty_locked_status(): New function.
- * man/procenv.1: Update for --tty.
-
-2013-03-27 James Hunt <james.hunt@ubuntu.com>
-
- * Merge of lp:~mtmiller/procenv/portability-bug-fixes.
-
-2013-01-10 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Updated.
- * src/procenv.c:
- - locale_map: Protect LC_NAME for FreeBSD.
- - show_env() and show_all_groups(): sort environment
- using strcoll(3) rather than strcmp(3) to make output
- locale-aware.
-
-2012-12-15 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c: get_priorities(): Do not assert priorities
- since they may be legitimate values. We could check errno,
- but little point when only querying.
-
-2012-12-10 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Updated with an idea from Dmitrijs Ledkovs.
-
-2012-12-06 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Updated with a couple of ideas.
- * man/procenv.1: Formatting of "SEE ALSO" section.
- * src/procenv.c: show_linux_prctl(): Handle all possible
- return scenarios to avoid random output.
- Thanks Dave Love (LP: #1086771).
-
- [ Dave Love <fx@gnu.org> ]
- * src/procenv.c:
- - locale_map:
- - Guard non-POSIX locale categories for portability.
- - Remove LC_ALL.
- - show_locale(): Special-case handling for LC_ALL.
-
- [ Mike Miller <mtmiller@ieee.org> ]
- * src/procenv.c:
- - show_linux_security_module_context(): Check that Apparmor
- and SELinux are enabled before querying contexts
- (LP: #1086768).
-
-2012-12-02 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - locale_map: Add LC_ADDRESS, LC_IDENTIFICATION,
- LC_MEASUREMENT, LC_NAME, LC_PAPER and LC_TELEPHONE
- (LP: #1081628).
- - show_env(): Sort environment variables (LP: #1081629).
- - show_locale(): Added LANG and LANGUAGE for parity with
- locale(1).
- * man/procenv.1:
- - Add ref to locale(7).
- - Add ref to locale(1).
-
-2012-11-29 James Hunt <james.hunt@ubuntu.com>
-
- * General tidy-up (removing unused variables, etc).
-
- [ Dave Love <fx@gnu.org> ]
- * Makefile.am: Add man page to man1_MANS for RHEL package build.
- * src/procenv.c:
- - show_locale(): Load locale from the environment prior to
- querying, and revert at end.
- - show_linux_cpu(): Guard sched_getcpu().
- * src/procenv.h: show_capability(): Make NOP if PR_CAPBSET_READ
- not available.
- * configure.ac: Add sched_getcpu to list of AC_CHECK_FUNCS.
-
-2012-11-28 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1: Update for --threads and set date.
- * src/procenv.c: get_platform(): Correction for detecting ARMHF.
-
-2012-11-28 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - get_thread_scheduler_name(): Make visible to non-Linux platforms.
- - get_platform(): Fix for Hurd.
- - show_clocks(): Fix for Hurd.
- * src/procenv.h:
- - Fix to gross Hurd hack.
- - Make visible to non-Linux platforms.
- - show_clock_res(): Make resilient to failure.
-
-2012-11-26 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Update.
- * configure.ac: Add pthread.
- * man/procenv.1: Formatting.
- * src/procenv.c:
- - usage(): Added -T and --threads option.
- - get_misc(): Minor Hurd tweak.
- - get_user_info(): Added check around prctl.
- - init(): Call gte_uname() as early as possible to allow
- LINUX_KERNEL_*() macros to work.
- - dump(): Add show_threads().
- - show_capabilities(): Put kernel version guard around
- PR_GET_KEEPCAPS.
- - get_thread_scheduler_name(): New function.
- - show_linux_scheduler(): Disallow failure.
- - show_linux_cpu(): Disallow failure.
- - show_threads(): New function.
- - main():
- - Added --threads option.
- - Call get_uname() for '-i'.
- * src/procenv.h: Added pthread.h and minor tweak for Hurd.
-
-2012-11-22 James Hunt <james.hunt@ubuntu.com>
-
- * src/tests/show_compiler_details: New test to dump out useful info
- as an aid to debugging build failures and for general interest.
- * src/Makefile.am: Call show_compiler_details test before running
- main binary such that we can use the new tests output to diagnose
- failures with the main binary.
- * src/procenv.h:
- - Added explicit define for GNU/Hurd to ensure that platform defines
- procenv_user.proc_name.
-
-2012-11-21 James Hunt <james.hunt@ubuntu.com>
-
- * TODO: Update.
- * src/procenv.c:
- - dump_misc(): Added kernel headers version.
- - linux_kernel_version():
- - Rewrite as original logic was flawed - we now use the same
- technique as KERNEL_VERSION()/LINUX_VERSION_CODE.
- - Drop the @patch parameter: we're not using it and it is problematic
- if it contains alphabetics.
- - show_linux_prctl(): Don't allow prctl to fail, even for
- environments, such as chroots, where the libc defines the symbols,
- but the kernel outside the chroot does not implement the features.
- - get_platform(): Added alpha and m68k.
- - main(): Call get_user_info() if dumping misc details to ensure uname
- values available.
- * src/procenv.h:
- - Removed LINUX_KERNEL_MMRP() as unused.
- - Removed pdie() macro now that we handle prctl failures gracefully.
-
-2012-11-20 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1:
- - Added new locale options.
- - Updated datestamp.
- * src/procenv.c:
- - usage(): Added locale options.
- - dump_misc():
- - Now shows 'platform' and 'kernel bits' (moved from dump_meta()).
- - Added 'endianness'.
- - is_big_endian(): New function.
- - show_stat(): Fixed 1 byte memory leak.
- - dump(): Call show_locale().
- - show_locale(): New function to dump locale details.
- - get_platform():
- - Added comment header.
- - Added in ia64, sparc64, sparc, mips, armhf, armel, s390x, SuperH, Hurd.
- - Changed 'Linux (Intel)' to 'Linux (i386)'.
- - Return UNKNOWN_STR as last resort.
- - show_capabilities(): Only query certain capabilities if they are
- known to be theoretically available by comparing running kernel
- version with kernel version specified in capabilities(7) that
- introduced it.
- - main(): Updated for new locale options.
- * src/procenv.h: show_capability():
- - Added comment header.
- - Now handles failure less brutally.
-
-2012-11-19 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1: Show calls made by '--proc' and '--misc'.
- * src/procenv.c:
- - Various platform-specific fixes identified by recent Debian upload.
- - Formatting.
- - linux_kernel_version(): Replacement for inadequate KERNEL_VERSION() macro.
- - New macros that make use of linux_kernel_version():
- - LINUX_KERNEL_M()
- - LINUX_KERNEL_MM()
- - LINUX_KERNEL_MMR()
- - LINUX_KERNEL_MMRP()
- - Horrid hack for Hurd, which doesn't define PATH_MAX.
-
-2012-11-16 James Hunt <james.hunt@ubuntu.com>
-
- * man/procenv.1:
- - Remove duplicate entry for --proc.
- - Add references to system and library call man pages for each option.
- - Add note that options are processed in order.
- - Correct order of options in syslog example.
- - Added rusage options.
- * TODO: Updated.
- * src/procenv.c:
- - Added rusage.
- - Moved show_capability() to header file.
- - main(): Added missing 'u' to getopt_long() call.
- - show_sizeof(): Added types uintmax_t, imaxdiv_t, rlim_t,
- fenv_t, fexcept_t.
-
-2012-11-05 James Hunt <james.hunt@ubuntu.com>
-
- * Split show_uname() into get_uname() and dump_uname().
- * init(): Call get_uname().
- * show_linux_prctl():
- - Check for x86 before quering PR_GET_TSC.
- - Check for kernel v3.5 before querying PR_GET_NO_NEW_PRIVS.
- - Check for kernel v3.4 before querying PR_GET_CHILD_SUBREAPER.
- * New macros:
- - PROCENV_ARCH_X86.
- - KERNEL_VERSION().
-
-2012-11-04 James Hunt <james.hunt@ubuntu.com>
-
- * AUTHORS: Corrected email address.
- * man/procenv.1: Credit Kees in copyright and add in
- standard "warranty".
-
-2012-11-01 James Hunt <james.hunt@ubuntu.com>
-
- * Hide show_oom() for non-Linux platforms.
-
-2012-10-27 James Hunt <james.hunt@ubuntu.com>
-
- * src/procenv.c:
- - get_path(): New function to return path of specified program.
- - show_stat(): Ensure we can resolve argv[0] to a full
- path by using get_path().
- - check_envvars(): Made strsep() usage safe.
-
-2012-10-26 James Hunt <james.hunt@ubuntu.com>
-
- * Set EXTRA_DIST to ensure man page
- included in distribution.
- * man/procenv.1: Typos and hyphen fixes.
-
-2012-10-25 James Hunt <james.hunt@ubuntu.com>
-
- * Initial import.
diff --git a/Makefile.in b/Makefile.in
index 76cf0e5..65a270a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -85,6 +85,9 @@ POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
@@ -188,9 +191,12 @@ CSCOPE = cscope
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
$(srcdir)/procenv.spec.in $(top_srcdir)/config/compile \
+ $(top_srcdir)/config/config.guess \
+ $(top_srcdir)/config/config.sub \
$(top_srcdir)/config/install-sh $(top_srcdir)/config/missing \
AUTHORS COPYING ChangeLog INSTALL NEWS README TODO \
- config/compile config/depcomp config/install-sh config/missing
+ config/compile config/config.guess config/config.sub \
+ config/depcomp config/install-sh config/missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@@ -296,14 +302,22 @@ am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
+build = @build@
build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
+host = @host@
host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
@@ -317,13 +331,19 @@ mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
+procenv_platform = @procenv_platform@
program_transform_name = @program_transform_name@
psdir = @psdir@
+runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
+target = @target@
target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
diff --git a/NEWS b/NEWS
index 28f6161..7242e0d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,60 @@
+0.50 2017-10-16
+
+ * --compiler: Add additional feature test macros.
+ * --misc: Show if running in a virtual machine.
+
+0.49 2017-02-12
+
+ * FreeBSD 11 capsicum fixes.
+ * Fix PROCENV_EXEC_ENV harder.
+
+0.48 2017-01-31
+
+ * Fix makedev(3) compiler error (it's now in sys/sysmacros.h).
+ (thanks Dave Love).
+
+0.47 2017-01-31
+
+ * Fixed hang when using PROCENV_EXEC variable.
+ * Test improvements.
+
+0.46 2016-05-28
+
+ * Fixed --file-append behaviour.
+ * Test improvements.
+ * Added support for Apple OSX (darwin).
+
+0.45 2016-03-21
+
+ * Code restructured internally to simplify maintenance and adding
+ new platforms. See src/platform/README.rst (and README-BUILD.rst).
+
+ * Dropped support for:
+ - kFreeBSD (Debian using a FreeBSD kernel) - defunc project.
+ - Ubuntu Lucid (10.04) - no longer a supported platform.
+
+ * Added support for NetBSD, OpenBSD and Minix 3.
+
+ * --meta: Now shows details of the procenv platform driver being
+ used.
+
+ * --misc now shows "security module" rather than
+ "linux security module".
+
+ * --file-append: new option (env var is "PROCENV_FILE_APPEND")
+ to append to the --file= specified rather than overwriting.
+
+0.44 2016-02-15
+
+ * --cgroup: Handle cgroup2 (cgroups v2).
+
+ * --clocks: now also includes CLOCK_REALTIME_COURSE, CLOCK_REALTIME_HR,
+ CLOCK_MONOTONIC_COURSE, CLOCK_MONOTONIC_RAW and CLOCK_BOOTTIME.
+
+ * --cpu: added I/O priority.
+
+ * Fixed crash if non-output argument specified before "--exec".
+
0.43 2015-11-24
* Namespace fix for non-Linux platforms.
diff --git a/README-BUILD.rst b/README-BUILD.rst
new file mode 100644
index 0000000..0ed9bbc
--- /dev/null
+++ b/README-BUILD.rst
@@ -0,0 +1,13 @@
+Building on FreeBSD
+-------------------
+
+FreeBSD is awkward. This worked for me on FreeBSD 10.2::
+
+ $ gmake CC=clang-devel LD=ld.gold LDFLAGS='-v -fuse-ld=gold'
+
+Building on Minix
+------------------
+
+Try this::
+
+ $ ./configure CC=clang CFLAGS='-I/usr/pkg/include' LDFLAGS='-L/usr/pkg/lib'
diff --git a/README.rst b/README.rst
index cdee008..8aeeb48 100644
--- a/README.rst
+++ b/README.rst
@@ -7,14 +7,22 @@
:target: https://scan.coverity.com/projects/jamesodhunt-procenv
:alt: Coverity Scan Build Status
-.. image:: https://img.shields.io/badge/donate-flattr-red.svg
+.. image:: https://img.shields.io/badge/donate-flattr-blue.svg
:alt: Donate via flattr
:target: https://flattr.com/profile/jamesodhunt
+.. image:: https://img.shields.io/badge/paypal-donate-blue.svg
+ :alt: Donate via Paypal
+ :target: https://www.paypal.me/jamesodhunt
+
=======
procenv
=======
+.. raw:: html
+
+ <a href="https://asciinema.org/a/118278"><img src="https://asciinema.org/a/118278.png" width="836"/></a>
+
.. contents::
.. sectnum::
@@ -28,15 +36,25 @@ it runs, in well-structured plain ASCII, JSON (YAML), XML or CSV.
It is useful as a test tool, to understand what environment a process
runs in and for system comparison.
-``procenv`` runs on Linux, FreeBSD, kFreeBSD, GNU Hurd and Android. It
-unashamedly emulates a number of existing system utilities as it is
-attempting to be all-encompassing: I wrote it with the aim of being able
-to dump "everything" that a process may care about by simply running a
-single program (by default). Also, the line of demarcation between
-"process", "program" and "system" is slightly blurry in some aspects.
-For example ``sysconf(3)`` variables could arguably be considered system
-attributes, but procenv shows these too since they are obviously meant
-to be queryable by applications.
+``procenv`` runs on the following operating systems:
+
+- Android
+- FreeBSD
+- GNU Hurd
+- GNU Linux
+- Minix 3
+- NetBSD
+- OpenBSD
+- OSX
+
+It unashamedly emulates a number of existing system
+utilities as it is attempting to be all-encompassing: I wrote it with
+the aim of being able to dump "everything" that a process may care about
+by simply running a single program (by default). Also, the line of
+demarcation between "process", "program" and "system" is slightly
+blurry in some aspects. For example ``sysconf(3)`` variables could
+arguably be considered system attributes, but procenv shows these too
+since they are obviously meant to be queryable by applications.
.. [#] If you find anything missing, please either raise a bug or send a
patch :)
@@ -51,6 +69,12 @@ build including running itself so that the build environment gets
captured in the builds logs themselves. Select a link below and drill
down to the build log to see the ``procenv`` output:
+Semaphore-CI
+~~~~~~~~~~~~
+
+* https://semaphoreci.com/jamesodhunt/procenv
+ (Click "Passed", "Job #", then "``make check``" to see output).
+
Travis-CI
~~~~~~~~~
@@ -90,24 +114,39 @@ https://code.launchpad.net/~jamesodhunt/+recipe/procenv-daily
Ubuntu Autopkgtest (DEP-8) environment
......................................
-* https://jenkins.qa.ubuntu.com/view/Wily/view/AutoPkgTest/job/wily-adt-procenv/
-* https://jenkins.qa.ubuntu.com/view/Vivid/view/AutoPkgTest/job/vivid-adt-procenv/
-* https://jenkins.qa.ubuntu.com/view/Utopic/view/AutoPkgTest/job/utopic-adt-procenv/
-* https://jenkins.qa.ubuntu.com/view/Trusty/view/AutoPkgTest/job/trusty-adt-procenv/
+* http://autopkgtest.ubuntu.com/packages/p/procenv/
+
+* Old Jenkins system
+
+ * https://jenkins.qa.ubuntu.com/view/Wily/view/AutoPkgTest/job/wily-adt-procenv/
+
+ * https://jenkins.qa.ubuntu.com/view/Vivid/view/AutoPkgTest/job/vivid-adt-procenv/
+
+ * https://jenkins.qa.ubuntu.com/view/Utopic/view/AutoPkgTest/job/utopic-adt-procenv/
+
+ * https://jenkins.qa.ubuntu.com/view/Trusty/view/AutoPkgTest/job/trusty-adt-procenv/
The ``sbuild`` tool environment
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+...............................
``procenv`` gets run from within sbuild via a DEP-8 test:
-* https://jenkins.qa.ubuntu.com/view/Wily/view/AutoPkgTest/job/wily-adt-sbuild/
+* http://autopkgtest.ubuntu.com/packages/s/sbuild/
+
+* Old Jenkins system
+
+ * https://jenkins.qa.ubuntu.com/view/Wily/view/AutoPkgTest/job/wily-adt-sbuild/
The ``pbuilder`` tool environment
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.................................
``procenv`` gets run from within pbuilder via a DEP-8 test:
-* https://jenkins.qa.ubuntu.com/view/Wily/view/AutoPkgTest/job/wily-adt-pbuilder/
+* http://autopkgtest.ubuntu.com/packages/p/pbuilder/
+
+* Old Jenkins system
+
+ * https://jenkins.qa.ubuntu.com/view/Wily/view/AutoPkgTest/job/wily-adt-pbuilder/
Debian
~~~~~~
@@ -122,12 +161,23 @@ Debian autopkgtest (DEP-8) environment
* http://ci.debian.net/#package/procenv
+Fedora
+~~~~~~
+
+* https://admin.fedoraproject.org/pkgdb/package/rpms/procenv/
+ (click "Builds status", click a build, then click one of the "build logs" links).
+
FreeBSD
~~~~~~~
Logs used to be available, but sadly it appears pointyhat.freebsd.com has
been taken offline (any replacement?)
+Gentoo
+~~~~~~
+
+* https://packages.gentoo.org/packages/sys-process/procenv/
+
Porting
-------
diff --git a/TODO b/TODO
index 51507ce..1e0db58 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,9 @@
# TODO
+- merge --clocks into --time.
+- call clock_getime() for all clock types and show time in 3 formats for each!
+- debian license file has incorrect email address.
+
- pstring tests.
- add /proc/cmdline?
- could create a kernel category?:
diff --git a/aclocal.m4 b/aclocal.m4
index 7622189..9ecb44e 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -20,32 +20,63 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
-# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
-# serial 1 (pkg-config-0.24)
-#
-# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
-#
-# This program 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.
-
-# PKG_PROG_PKG_CONFIG([MIN-VERSION])
-# ----------------------------------
+dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+dnl serial 11 (pkg-config-0.29.1)
+dnl
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.1])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+ [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
AC_DEFUN([PKG_PROG_PKG_CONFIG],
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
@@ -67,18 +98,19 @@ if test -n "$PKG_CONFIG"; then
PKG_CONFIG=""
fi
fi[]dnl
-])# PKG_PROG_PKG_CONFIG
+])dnl PKG_PROG_PKG_CONFIG
-# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-#
-# Check to see whether a particular set of modules exists. Similar
-# to PKG_CHECK_MODULES(), but does not set variables or print errors.
-#
-# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
-# only at the first occurence in configure.ac, so if the first place
-# it's called might be skipped (such as if it is within an "if", you
-# have to call PKG_CHECK_EXISTS manually
-# --------------------------------------------------------------
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
AC_DEFUN([PKG_CHECK_EXISTS],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
if test -n "$PKG_CONFIG" && \
@@ -88,8 +120,10 @@ m4_ifvaln([$3], [else
$3])dnl
fi])
-# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
-# ---------------------------------------------
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
m4_define([_PKG_CONFIG],
[if test -n "$$1"; then
pkg_cv_[]$1="$$1"
@@ -101,10 +135,11 @@ m4_define([_PKG_CONFIG],
else
pkg_failed=untried
fi[]dnl
-])# _PKG_CONFIG
+])dnl _PKG_CONFIG
-# _PKG_SHORT_ERRORS_SUPPORTED
-# -----------------------------
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -112,19 +147,17 @@ if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
else
_pkg_short_errors_supported=no
fi[]dnl
-])# _PKG_SHORT_ERRORS_SUPPORTED
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
-# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
-# [ACTION-IF-NOT-FOUND])
-#
-#
-# Note that if there is a possibility the first call to
-# PKG_CHECK_MODULES might not happen, you should be sure to include an
-# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
-#
-#
-# --------------------------------------------------------------
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
AC_DEFUN([PKG_CHECK_MODULES],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
@@ -178,16 +211,40 @@ else
AC_MSG_RESULT([yes])
$3
fi[]dnl
-])# PKG_CHECK_MODULES
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
-# PKG_INSTALLDIR(DIRECTORY)
-# -------------------------
-# Substitutes the variable pkgconfigdir as the location where a module
-# should install pkg-config .pc files. By default the directory is
-# $libdir/pkgconfig, but the default can be changed by passing
-# DIRECTORY. The user can override through the --with-pkgconfigdir
-# parameter.
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
AC_DEFUN([PKG_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
m4_pushdef([pkg_description],
@@ -198,16 +255,18 @@ AC_ARG_WITH([pkgconfigdir],
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
-]) dnl PKG_INSTALLDIR
+])dnl PKG_INSTALLDIR
-# PKG_NOARCH_INSTALLDIR(DIRECTORY)
-# -------------------------
-# Substitutes the variable noarch_pkgconfigdir as the location where a
-# module should install arch-independent pkg-config .pc files. By
-# default the directory is $datadir/pkgconfig, but the default can be
-# changed by passing DIRECTORY. The user can override through the
-# --with-noarch-pkgconfigdir parameter.
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
m4_pushdef([pkg_description],
@@ -218,13 +277,15 @@ AC_ARG_WITH([noarch-pkgconfigdir],
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
m4_popdef([pkg_default])
m4_popdef([pkg_description])
-]) dnl PKG_NOARCH_INSTALLDIR
+])dnl PKG_NOARCH_INSTALLDIR
-# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
-# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-# -------------------------------------------
-# Retrieves the value of the pkg-config variable for the given module.
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
@@ -233,7 +294,7 @@ _PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
-])# PKG_CHECK_VAR
+])dnl PKG_CHECK_VAR
# Copyright (C) 2002-2014 Free Software Foundation, Inc.
#
diff --git a/config.h.in b/config.h.in
index 492522c..dfff307 100644
--- a/config.h.in
+++ b/config.h.in
@@ -3,9 +3,18 @@
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
+/* Define to 1 if you have the `cpuset_alloc' function. */
+#undef HAVE_CPUSET_ALLOC
+
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
+/* Define to 1 if you have the `getresgid' function. */
+#undef HAVE_GETRESGID
+
+/* Define to 1 if you have the `getresuid' function. */
+#undef HAVE_GETRESUID
+
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
@@ -66,6 +75,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
+/* Define to 1 if you have the `ttyname' function. */
+#undef HAVE_TTYNAME
+
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
diff --git a/config/config.guess b/config/config.guess
new file mode 100755
index 0000000..0967f2a
--- /dev/null
+++ b/config/config.guess
@@ -0,0 +1,1454 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2016 Free Software Foundation, Inc.
+
+timestamp='2016-04-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 3 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, see <http://www.gnu.org/licenses/>.
+#
+# 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. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2016 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 ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # 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 "$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 ; set_cc_for_build= ;'
+
+# 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
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ ;;
+esac
+
+# 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 tuples: *-*-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=`(uname -p 2>/dev/null || \
+ /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 ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-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*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ 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
+ # Determine ABI tags.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ ;;
+ 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/[-_].*//' | cut -d. -f1,2`
+ ;;
+ 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}${abi}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:Sortix:*:*)
+ echo ${UNAME_MACHINE}-unknown-sortix
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # 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 Pn.n version is a patched version.
+ # 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/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
+ 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 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ 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 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ 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 ;;
+ 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 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ 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 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # 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 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ 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 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????: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 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ 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 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ 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 ;;
+ *:AIX:*:[4567])
+ 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/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = hppa2.0w ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ 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 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ 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 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ 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 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ aarch64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ 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 -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ cris:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ crisv32:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ e2k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ frv:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ hexagon:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ k1om:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #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-${LIBC}"; exit; }
+ ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-${LIBC}
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-${LIBC}
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-${LIBC}
+ exit ;;
+ 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-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-${LIBC}
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+ exit ;;
+ x86_64:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ 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 ;;
+ 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 ;;
+ 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 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ 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 ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ 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 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ 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 i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ 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 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*: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 | S7501*:*: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; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ 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; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *: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 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ 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 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *: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 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *: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 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config/config.sub b/config/config.sub
new file mode 100755
index 0000000..8d39c4b
--- /dev/null
+++ b/config/config.sub
@@ -0,0 +1,1815 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2016 Free Software Foundation, Inc.
+
+timestamp='2016-03-30'
+
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+# 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. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# 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.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# 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 or ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2016 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 ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # 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 ;;
+
+ * )
+ 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* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
+ *)
+ 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 | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -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
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -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/'`
+ ;;
+ -sco5v6*)
+ # 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*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
+ -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 \
+ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | ba \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pyramid \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
+ | we32k \
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
+ # 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-* \
+ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | ba-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | e2k-* | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pyramid-* \
+ | riscv32-* | riscv64-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
+ | visium-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # 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
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ 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
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ 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
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ asmjs)
+ basic_machine=asmjs-unknown
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ 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
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ 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
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ 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*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
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ 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
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=-msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
+ 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
+ ;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ 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
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ 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 | ppcbe) basic_machine=powerpc-unknown
+ ;;
+ ppc-* | ppcbe-*)
+ 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
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ 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
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ 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
+ ;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ 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
+ ;;
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ 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
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-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
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ 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
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ 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.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -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* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -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* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+ | -onefs* | -tirtos*)
+ # 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* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -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
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -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
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -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
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
+ -ios)
+ ;;
+ -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
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ 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
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ 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
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-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
+ ;;
+ -cnk*|-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
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -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
+
+# 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/config/install-sh b/config/install-sh
index 0b0fdcb..59990a1 100755
--- a/config/install-sh
+++ b/config/install-sh
@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
-scriptversion=2013-12-25.23; # UTC
+scriptversion=2014-09-12.12; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -324,34 +324,41 @@ do
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
+ # $RANDOM is not portable (e.g. dash); use it when possible to
+ # lower collision chance
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
- trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
+ # As "mkdir -p" follows symlinks and we work in /tmp possibly; so
+ # create the $tmpdir first (and fail if unsuccessful) to make sure
+ # that nobody tries to guess the $tmpdir name.
if (umask $mkdir_umask &&
- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ $mkdirprog $mkdir_mode "$tmpdir" &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
- ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ test_tmpdir="$tmpdir/a"
+ ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
- $mkdirprog -m$different_mode -p -- "$tmpdir" && {
- ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
- rmdir "$tmpdir/d" "$tmpdir"
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
- rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac;;
diff --git a/configure b/configure
index eaff2c9..2eab96d 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for procenv 0.43.
+# Generated by GNU Autoconf 2.69 for procenv 0.50.
#
# Report bugs to <jamesodhunt@ubuntu.com>.
#
@@ -11,7 +11,7 @@
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
#
-# Copyright (C) 2012-2015 James Hunt <jamesodhunt@ubuntu.com> and Kees Cook <kees@ubuntu.com>
+# Copyright (C) 2012-2017 James Hunt <jamesodhunt@ubuntu.com> and Kees Cook <kees@ubuntu.com>
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
@@ -582,8 +582,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='procenv'
PACKAGE_TARNAME='procenv'
-PACKAGE_VERSION='0.43'
-PACKAGE_STRING='procenv 0.43'
+PACKAGE_VERSION='0.50'
+PACKAGE_STRING='procenv 0.50'
PACKAGE_BUGREPORT='jamesodhunt@ubuntu.com'
PACKAGE_URL='https://github.com/jamesodhunt/procenv'
@@ -628,6 +628,23 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+procenv_platform
+PROCENV_PLATFORM_GENERIC_FALSE
+PROCENV_PLATFORM_GENERIC_TRUE
+PROCENV_PLATFORM_MINIX_FALSE
+PROCENV_PLATFORM_MINIX_TRUE
+PROCENV_PLATFORM_LINUX_FALSE
+PROCENV_PLATFORM_LINUX_TRUE
+PROCENV_PLATFORM_OPENBSD_FALSE
+PROCENV_PLATFORM_OPENBSD_TRUE
+PROCENV_PLATFORM_NETBSD_FALSE
+PROCENV_PLATFORM_NETBSD_TRUE
+PROCENV_PLATFORM_HURD_FALSE
+PROCENV_PLATFORM_HURD_TRUE
+PROCENV_PLATFORM_FREEBSD_FALSE
+PROCENV_PLATFORM_FREEBSD_TRUE
+PROCENV_PLATFORM_DARWIN_FALSE
+PROCENV_PLATFORM_DARWIN_TRUE
AM_CFLAGS
AM_BACKSLASH
AM_DEFAULT_VERBOSITY
@@ -681,6 +698,18 @@ PKG_CONFIG
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
EGREP
GREP
CPP
@@ -711,6 +740,7 @@ infodir
docdir
oldincludedir
includedir
+runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -741,6 +771,7 @@ enable_compiler_optimisations
enable_linker_optimisations
enable_debug
enable_reproducible_build
+with_forced_driver
'
ac_precious_vars='build_alias
host_alias
@@ -794,6 +825,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1046,6 +1078,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1183,7 +1224,7 @@ fi
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
+ libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -1296,7 +1337,7 @@ 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 procenv 0.43 to adapt to many kinds of systems.
+\`configure' configures procenv 0.50 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1336,6 +1377,7 @@ Fine tuning of the installation directories:
--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]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -1357,12 +1399,17 @@ Program names:
--program-prefix=PREFIX prepend PREFIX to installed program names
--program-suffix=SUFFIX append SUFFIX to installed program names
--program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+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 procenv 0.43:";;
+ short | recursive ) echo "Configuration of procenv 0.50:";;
esac
cat <<\_ACEOF
@@ -1387,6 +1434,13 @@ Optional Features:
Disable display of build-time values that are
guaranteed to differ between builds
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-forced-driver=...
+ Used to force a particular platform driver. Warning:
+ These aren't the droids you're looking for...
+
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
@@ -1472,14 +1526,14 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-procenv configure 0.43
+procenv configure 0.50
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
-Copyright (C) 2012-2015 James Hunt <jamesodhunt@ubuntu.com> and Kees Cook <kees@ubuntu.com>
+Copyright (C) 2012-2017 James Hunt <jamesodhunt@ubuntu.com> and Kees Cook <kees@ubuntu.com>
_ACEOF
exit
fi
@@ -1897,7 +1951,7 @@ 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 procenv $as_me 0.43, which was
+It was created by procenv $as_me 0.50, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2248,6 +2302,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
ac_config_headers="$ac_config_headers config.h"
ac_aux_dir=
@@ -2280,7 +2336,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-PROCENV_VERSION=0.43
+PROCENV_VERSION=0.50
# Expand $ac_aux_dir to an absolute path.
@@ -3795,6 +3851,118 @@ rm -rf conftest*
fi
+# expose $target
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&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 &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+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
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&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` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+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
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if ${ac_cv_target+:} false; then :
+ $as_echo_n "(cached) " >&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` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+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}-
+
#---------------------------------------------------------------------
# Checks for programs.
ac_ext=c
@@ -4812,7 +4980,7 @@ fi
# Checks for library functions.
-for ac_func in clock_gettime getcwd localtime_r strcasecmp strchr strstr sched_getcpu
+for ac_func in clock_gettime getcwd localtime_r strcasecmp strchr strstr sched_getcpu ttyname getresuid getresgid cpuset_alloc
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -5282,6 +5450,65 @@ else
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
+$as_echo_n "checking for library containing clock_gettime... " >&6; }
+if ${ac_cv_search_clock_gettime+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* 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 clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt; 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
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_clock_gettime=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_clock_gettime+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_clock_gettime+:} false; then :
+
+else
+ ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
+$as_echo "$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ HAVE_LIBRT=yes
+else
+ HAVE_LIBRT=no
+fi
+
+
if test x$HAVE_APPARMOR = xtrue; then
HAVE_APPARMOR_TRUE=
HAVE_APPARMOR_FALSE='#'
@@ -5797,7 +6024,7 @@ fi
# Define the identity of the package.
PACKAGE='procenv'
- VERSION='0.43'
+ VERSION='0.50'
cat >>confdefs.h <<_ACEOF
@@ -6091,6 +6318,105 @@ $as_echo "#define PROCENV_REPRODUCIBLE_BUILD 1" >>confdefs.h
fi
+
+# Check whether --with-forced_driver was given.
+if test "${with_forced_driver+set}" = set; then :
+ withval=$with_forced_driver;
+fi
+
+
+target_to_consider="$target"
+
+if test "x$with_forced_driver" != "x"; then :
+
+ target_to_consider="$withval"
+
+fi
+
+#---------------------------------------------------------------------
+# Determine platform
+
+case "$target_to_consider" in
+ *darwin*) procenv_platform=darwin;;
+ *freebsd*) procenv_platform=freebsd;;
+
+ # BUG: FIXME: this test does not look reliable!
+ *hurd*|*unknown-gnu*) procenv_platform=hurd;;
+
+ *linux*) procenv_platform=linux;;
+ *minix*) procenv_platform=minix;;
+ *netbsd*) procenv_platform=netbsd;;
+ *openbsd*) procenv_platform=openbsd;;
+ *) procenv_platform=unknown;;
+esac
+
+ if test "$procenv_platform" = darwin; then
+ PROCENV_PLATFORM_DARWIN_TRUE=
+ PROCENV_PLATFORM_DARWIN_FALSE='#'
+else
+ PROCENV_PLATFORM_DARWIN_TRUE='#'
+ PROCENV_PLATFORM_DARWIN_FALSE=
+fi
+
+ if test "$procenv_platform" = freebsd; then
+ PROCENV_PLATFORM_FREEBSD_TRUE=
+ PROCENV_PLATFORM_FREEBSD_FALSE='#'
+else
+ PROCENV_PLATFORM_FREEBSD_TRUE='#'
+ PROCENV_PLATFORM_FREEBSD_FALSE=
+fi
+
+ if test "$procenv_platform" = hurd; then
+ PROCENV_PLATFORM_HURD_TRUE=
+ PROCENV_PLATFORM_HURD_FALSE='#'
+else
+ PROCENV_PLATFORM_HURD_TRUE='#'
+ PROCENV_PLATFORM_HURD_FALSE=
+fi
+
+ if test "$procenv_platform" = netbsd; then
+ PROCENV_PLATFORM_NETBSD_TRUE=
+ PROCENV_PLATFORM_NETBSD_FALSE='#'
+else
+ PROCENV_PLATFORM_NETBSD_TRUE='#'
+ PROCENV_PLATFORM_NETBSD_FALSE=
+fi
+
+ if test "$procenv_platform" = openbsd; then
+ PROCENV_PLATFORM_OPENBSD_TRUE=
+ PROCENV_PLATFORM_OPENBSD_FALSE='#'
+else
+ PROCENV_PLATFORM_OPENBSD_TRUE='#'
+ PROCENV_PLATFORM_OPENBSD_FALSE=
+fi
+
+ if test "$procenv_platform" = linux; then
+ PROCENV_PLATFORM_LINUX_TRUE=
+ PROCENV_PLATFORM_LINUX_FALSE='#'
+else
+ PROCENV_PLATFORM_LINUX_TRUE='#'
+ PROCENV_PLATFORM_LINUX_FALSE=
+fi
+
+ if test "$procenv_platform" = minix; then
+ PROCENV_PLATFORM_MINIX_TRUE=
+ PROCENV_PLATFORM_MINIX_FALSE='#'
+else
+ PROCENV_PLATFORM_MINIX_TRUE='#'
+ PROCENV_PLATFORM_MINIX_FALSE=
+fi
+
+ if test "$procenv_platform" = unknown; then
+ PROCENV_PLATFORM_GENERIC_TRUE=
+ PROCENV_PLATFORM_GENERIC_FALSE='#'
+else
+ PROCENV_PLATFORM_GENERIC_TRUE='#'
+ PROCENV_PLATFORM_GENERIC_FALSE=
+fi
+
+
+
+
#---------------------------------------------------------------------
# XXX: Dump details of the preprocess/compiler/linker *NOW* so that if
# procenv fails to build later, the build logs will show details of the
@@ -6271,6 +6597,38 @@ else
am__EXEEXT_FALSE=
fi
+if test -z "${PROCENV_PLATFORM_DARWIN_TRUE}" && test -z "${PROCENV_PLATFORM_DARWIN_FALSE}"; then
+ as_fn_error $? "conditional \"PROCENV_PLATFORM_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PROCENV_PLATFORM_FREEBSD_TRUE}" && test -z "${PROCENV_PLATFORM_FREEBSD_FALSE}"; then
+ as_fn_error $? "conditional \"PROCENV_PLATFORM_FREEBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PROCENV_PLATFORM_HURD_TRUE}" && test -z "${PROCENV_PLATFORM_HURD_FALSE}"; then
+ as_fn_error $? "conditional \"PROCENV_PLATFORM_HURD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PROCENV_PLATFORM_NETBSD_TRUE}" && test -z "${PROCENV_PLATFORM_NETBSD_FALSE}"; then
+ as_fn_error $? "conditional \"PROCENV_PLATFORM_NETBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PROCENV_PLATFORM_OPENBSD_TRUE}" && test -z "${PROCENV_PLATFORM_OPENBSD_FALSE}"; then
+ as_fn_error $? "conditional \"PROCENV_PLATFORM_OPENBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PROCENV_PLATFORM_LINUX_TRUE}" && test -z "${PROCENV_PLATFORM_LINUX_FALSE}"; then
+ as_fn_error $? "conditional \"PROCENV_PLATFORM_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PROCENV_PLATFORM_MINIX_TRUE}" && test -z "${PROCENV_PLATFORM_MINIX_FALSE}"; then
+ as_fn_error $? "conditional \"PROCENV_PLATFORM_MINIX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PROCENV_PLATFORM_GENERIC_TRUE}" && test -z "${PROCENV_PLATFORM_GENERIC_FALSE}"; then
+ as_fn_error $? "conditional \"PROCENV_PLATFORM_GENERIC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
@@ -6668,7 +7026,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by procenv $as_me 0.43, which was
+This file was extended by procenv $as_me 0.50, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6735,7 +7093,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-procenv config.status 0.43
+procenv config.status 0.50
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -7598,9 +7956,12 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result:
Configure settings for $PACKAGE_NAME version $VERSION
+ Build platform : $procenv_platform
Reproducible build : ${reproducible_build}
Debug build : ${DEBUG_BUILD}
- Check Unit Test Framework : ${HAVE_CHECK}
+ Check unit test framework : ${HAVE_CHECK}
+
+ Libraries:
libapparmor : ${HAVE_APPARMOR}
libselinux : ${HAVE_SELINUX}
@@ -7612,9 +7973,12 @@ fi
$as_echo "
Configure settings for $PACKAGE_NAME version $VERSION
+ Build platform : $procenv_platform
Reproducible build : ${reproducible_build}
Debug build : ${DEBUG_BUILD}
- Check Unit Test Framework : ${HAVE_CHECK}
+ Check unit test framework : ${HAVE_CHECK}
+
+ Libraries:
libapparmor : ${HAVE_APPARMOR}
libselinux : ${HAVE_SELINUX}
diff --git a/configure.ac b/configure.ac
index 40d6a61..0b3f3c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,12 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
-m4_define([procenv_version], 0.43)
+m4_define([procenv_version], [0.50])
+
+AC_INIT(procenv,[procenv_version],[jamesodhunt@ubuntu.com],,[https://github.com/jamesodhunt/procenv])
+
+AC_COPYRIGHT([Copyright (C) 2012-2017 James Hunt <jamesodhunt@ubuntu.com> and Kees Cook <kees@ubuntu.com>])
-AC_INIT(procenv, [procenv_version], [jamesodhunt@ubuntu.com], , https://github.com/jamesodhunt/procenv)
-AC_COPYRIGHT([Copyright (C) 2012-2015 James Hunt <jamesodhunt@ubuntu.com> and Kees Cook <kees@ubuntu.com>])
AC_CONFIG_SRCDIR([src/procenv.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@@ -15,6 +17,9 @@ AC_SUBST(PROCENV_VERSION, procenv_version)
AC_GNU_SOURCE
AC_SYS_LARGEFILE
+# expose $target
+AC_CANONICAL_TARGET
+
#---------------------------------------------------------------------
# Checks for programs.
AC_PROG_CC
@@ -38,7 +43,7 @@ AC_CHECK_HEADERS(pthread.h,, [AC_MSG_ERROR([pthread.h required])])
AC_HEADER_STDBOOL
# Checks for library functions.
-AC_CHECK_FUNCS([clock_gettime getcwd localtime_r strcasecmp strchr strstr sched_getcpu])
+AC_CHECK_FUNCS([clock_gettime getcwd localtime_r strcasecmp strchr strstr sched_getcpu ttyname getresuid getresgid cpuset_alloc])
# BSD process inspection library
AC_SEARCH_LIBS([kvm_openfiles], [kvm],
@@ -72,6 +77,10 @@ AC_SEARCH_LIBS([aa_gettaskcon], [apparmor],
[HAVE_APPARMOR=yes],
[HAVE_APPARMOR=no])
+AC_SEARCH_LIBS([clock_gettime], [rt],
+ [HAVE_LIBRT=yes],
+ [HAVE_LIBRT=no])
+
AM_CONDITIONAL([HAVE_APPARMOR], [test x$HAVE_APPARMOR = xtrue])
AC_CHECK_HEADERS([sys/apparmor.h])
@@ -144,6 +153,44 @@ if test "$reproducible_build" = yes; then
AC_DEFINE([PROCENV_REPRODUCIBLE_BUILD], [1], [Generate a reproducible build])
fi
+AC_ARG_WITH([forced_driver],
+ AS_HELP_STRING([--with-forced-driver=...],
+ [Used to force a particular platform driver. Warning: These aren't the droids you're looking for...]))
+
+target_to_consider="$target"
+
+AS_IF([test "x$with_forced_driver" != "x"], [
+ target_to_consider="$withval"
+ ])
+
+#---------------------------------------------------------------------
+# Determine platform
+
+case "$target_to_consider" in
+ *darwin*) procenv_platform=darwin;;
+ *freebsd*) procenv_platform=freebsd;;
+
+ # BUG: FIXME: this test does not look reliable!
+ *hurd*|*unknown-gnu*) procenv_platform=hurd;;
+
+ *linux*) procenv_platform=linux;;
+ *minix*) procenv_platform=minix;;
+ *netbsd*) procenv_platform=netbsd;;
+ *openbsd*) procenv_platform=openbsd;;
+ *) procenv_platform=unknown;;
+esac
+
+AM_CONDITIONAL([PROCENV_PLATFORM_DARWIN], [test "$procenv_platform" = darwin])
+AM_CONDITIONAL([PROCENV_PLATFORM_FREEBSD], [test "$procenv_platform" = freebsd])
+AM_CONDITIONAL([PROCENV_PLATFORM_HURD], [test "$procenv_platform" = hurd])
+AM_CONDITIONAL([PROCENV_PLATFORM_NETBSD], [test "$procenv_platform" = netbsd])
+AM_CONDITIONAL([PROCENV_PLATFORM_OPENBSD], [test "$procenv_platform" = openbsd])
+AM_CONDITIONAL([PROCENV_PLATFORM_LINUX], [test "$procenv_platform" = linux])
+AM_CONDITIONAL([PROCENV_PLATFORM_MINIX], [test "$procenv_platform" = minix])
+AM_CONDITIONAL([PROCENV_PLATFORM_GENERIC], [test "$procenv_platform" = unknown])
+
+AC_SUBST([procenv_platform])
+
#---------------------------------------------------------------------
# XXX: Dump details of the preprocess/compiler/linker *NOW* so that if
# procenv fails to build later, the build logs will show details of the
@@ -165,9 +212,12 @@ AC_OUTPUT(Makefile src/Makefile procenv.spec)
AC_MSG_RESULT([
Configure settings for $PACKAGE_NAME version $VERSION
+ Build platform : $procenv_platform
Reproducible build : ${reproducible_build}
Debug build : ${DEBUG_BUILD}
- Check Unit Test Framework : ${HAVE_CHECK}
+ Check unit test framework : ${HAVE_CHECK}
+
+ Libraries:
libapparmor : ${HAVE_APPARMOR}
libselinux : ${HAVE_SELINUX}
diff --git a/debian/changelog b/debian/changelog
index 94897e6..b4ed0d7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+procenv (0.50-1) unstable; urgency=medium
+
+ * New upstream release
+ * Update debian/watch file to point at github
+
+ -- Dimitri John Ledkov <xnox@ubuntu.com> Tue, 30 Jan 2018 11:35:08 +0000
+
procenv (0.43-2) unstable; urgency=medium
* debian/rules: Fix broken README sym link (Closes: #804486).
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 8b13789..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/debian/patches/upstream-cross-platform-fixes b/debian/patches/upstream-cross-platform-fixes
deleted file mode 100644
index b011710..0000000
--- a/debian/patches/upstream-cross-platform-fixes
+++ /dev/null
@@ -1,284 +0,0 @@
-Description: Upstream cross-platform fixes for non x86/AMD64 platforms.
- procenv (0.27-2) unstable; urgency=low
- .
- * Upstream sync including fixes for Hurd semaphores, and those
- platforms which don't support the complete set of standard
- Linux signals.
-Author: James Hunt <james.hunt@ubuntu.com>
-
----
-The information above should follow the Patch Tagging Guidelines, please
-checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
-are templates for supplementary fields that you might want to add:
-
-Origin: <vendor|upstream|other>, <url of original patch>
-Bug: <url in upstream bugtracker>
-Bug-Debian: http://bugs.debian.org/<bugnumber>
-Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
-Forwarded: <no|not-needed|url proving that it has been forwarded>
-Reviewed-By: <name and email of someone who approved the patch>
-Last-Update: <YYYY-MM-DD>
-
---- procenv-0.27.orig/TODO
-+++ procenv-0.27/TODO
-@@ -1,5 +1,9 @@
- # TODO
-
-+- XXX: run show_compiler_details *before* build to help diagnose
-+ failures.
-+- Add YAML output format?
-+- Sort *all* output values.
- - Introduce "value()" that can take a bare value. This will allow for
- example mount options to be displayed in a container.
- - Non-root queryable hdd attributes?
---- procenv-0.27.orig/ChangeLog
-+++ procenv-0.27/ChangeLog
-@@ -1,3 +1,28 @@
-+2013-10-30 James Hunt <james.hunt@ubuntu.com>
-+
-+ * src/procenv.c:
-+ - show_signals(): Check return from get_signal_name() in case a
-+ platform doesn't provide the signal in question.
-+ - get_kernel_bits(): Return error value rather than calling die().
-+ - show_bsd_mounts(): Removed unused variables.
-+ - Added a few extra asserts to ensure section_open() is passed a valid
-+ name.
-+ * src/procenv.h: Need to define 'semun' on Hurd too.
-+
-+2013-10-25 James Hunt <james.hunt@ubuntu.com>
-+
-+ * TODO: Stuff.
-+ * src/procenv.c: get_arch(): Fix for AARCH64 which seemingly isn't
-+ considered to be "ARM" by gcc.
-+
-+2013-10-15 James Hunt <james.hunt@ubuntu.com>
-+
-+ * man/procenv.1:
-+ - Fix for lintian bug: spelling-error-in-binary.
-+ * src/procenv.c:
-+ - Fixes for lintian bugs: spelling-error-in-manpage,
-+ hyphen-used-as-minus-sign.
-+
- 2013-10-14 James Hunt <james.hunt@ubuntu.com>
-
- * configure.ac: Add '--debug' option.
---- /dev/null
-+++ procenv-0.27/TODO.debian
-@@ -0,0 +1,5 @@
-+# Debian fixes:
-+
-+- powerpc:
-+ - semmap: -1674096
-+ - 'procenv -E' crash
---- procenv-0.27.orig/src/procenv.c
-+++ procenv-0.27/src/procenv.c
-@@ -716,7 +716,7 @@ usage (void)
- show (" - Any long option name may be shortened as long as it remains unique.");
- show (" - The 'crumb' output format is designed for easy parsing: it displays");
- show (" the data in a flattened format with each value on a separate line");
-- show (" preceeded by all appropriate headings which are separated by the");
-+ show (" preceded by all appropriate headings which are separated by the");
- show (" current separator.");
- show ("");
- }
-@@ -1461,6 +1461,9 @@ show_signals (void)
- blocked = 1;
-
- signal_name = get_signal_name (i);
-+ if (! signal_name)
-+ continue;
-+
- signal_desc = strsignal (i);
-
- object_open (FALSE);
-@@ -2403,7 +2406,7 @@ get_kernel_bits (void)
- errno = 0;
- value = sysconf (_SC_LONG_BIT);
- if (value == -1 && errno != 0)
-- die ("failed to determine kernel bits");
-+ return -1;
- return value;
- #endif
- return -1;
-@@ -2709,10 +2712,11 @@ show_linux_mounts (ShowMountType what)
- used_files = fs.f_files - fs.f_ffree;
- }
-
-- get_major_minor (mnt->mnt_dir,
-+ (void)get_major_minor (mnt->mnt_dir,
- &major,
- &minor);
-
-+ assert (mnt->mnt_dir);
- section_open (mnt->mnt_dir);
-
- entry ("filesystem", "'%s'", mnt->mnt_fsname);
-@@ -2954,6 +2958,7 @@ show_network_if (const struct ifaddrs *i
-
- family = ifa->ifa_addr->sa_family;
-
-+ assert (ifa->ifa_name);
- section_open (ifa->ifa_name);
-
- entry ("family", "%s (0x%x)", get_net_family_name (family), family);
-@@ -3276,7 +3281,6 @@ show_bsd_mounts (ShowMountType what)
- statfs_int_type bfree;
- statfs_int_type bavail;
- statfs_int_type used;
-- int ret;
-
- common_assert ();
-
-@@ -3297,9 +3301,7 @@ show_bsd_mounts (ShowMountType what)
- mnt->f_mntonname);
-
- if (what == SHOW_ALL || what == SHOW_MOUNTS) {
-- char *str = NULL;
--
-- ret = get_major_minor (mnt->f_mntonname,
-+ (void)get_major_minor (mnt->f_mntonname,
- &major,
- &minor);
-
-@@ -3309,6 +3311,7 @@ show_bsd_mounts (ShowMountType what)
- bavail = mnt->f_bavail * multiplier;
- used = blocks - bfree;
-
-+ assert (mnt->f_mntfromname);
- section_open (mnt->f_mntfromname);
-
- entry ("dir", "'%s'", mnt->f_mntonname);
-@@ -4429,9 +4432,6 @@ get_arch (void)
- {
-
- #ifdef __arm__
--#ifdef __aarch64__
-- return "ARM64";
--#endif
- #ifdef __ARM_PCS_VFP
- return "ARMhf";
- #endif
-@@ -4441,6 +4441,11 @@ get_arch (void)
- return "ARM";
- #endif
-
-+ /* not arm apparently! :) */
-+#ifdef __aarch64__
-+ return "ARM64/AARCH64";
-+#endif
-+
- #ifdef __hppa__
- return "HP/PA RISC";
- #endif
-@@ -4509,6 +4514,8 @@ libs_callback (struct dl_phdr_info *info
- return 0;
-
- path = info->dlpi_name;
-+ assert (path);
-+
- name = strrchr (path, '/');
-
- if (name) {
---- procenv-0.27.orig/src/procenv.h
-+++ procenv-0.27/src/procenv.h
-@@ -817,7 +817,7 @@ void show_semaphores_bsd (void);
- void show_msg_queues_bsd (void);
- #endif /* PROCENV_BSD + __FreeBSD_kernel__ */
-
--#if defined (PROCENV_LINUX)
-+#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- /* semctl(2) on Linux tells us _we_ must define this */
-
- union semun {
---- /dev/null
-+++ procenv-0.27/tmp/procenv_0.27-1_i386.changes
-@@ -0,0 +1,44 @@
-+-----BEGIN PGP SIGNED MESSAGE-----
-+Hash: SHA512
-+
-+Format: 1.8
-+Date: Wed, 23 Oct 2013 09:13:49 +0100
-+Source: procenv
-+Binary: procenv
-+Architecture: i386
-+Version: 0.27-1
-+Distribution: sid
-+Urgency: low
-+Maintainer: James Hunt <james.hunt@ubuntu.com>
-+Changed-By: James Hunt <james.hunt@ubuntu.com>
-+Description:
-+ procenv - Utility to show process environment
-+Changes:
-+ procenv (0.27-1) unstable; urgency=low
-+ .
-+ * New upstream release.
-+ * debian/control: Add expat and perl to Build-Depends for tests.
-+Checksums-Sha1:
-+ 4c02b5fa90eb4306c4e219287163d84cf19a14c8 50048 procenv_0.27-1_i386.deb
-+Checksums-Sha256:
-+ 23d3987be04b5bd942c471eff0f6c9639288ecfa7c9835ccfe20404495374d41 50048 procenv_0.27-1_i386.deb
-+Files:
-+ 887a1a7b03a7d0c0d5569656a279ced8 50048 utils optional procenv_0.27-1_i386.deb
-+
-+-----BEGIN PGP SIGNATURE-----
-+Version: GnuPG v1.4.14 (GNU/Linux)
-+
-+iQIcBAEBCgAGBQJSZ4miAAoJEJ1Q4UTmNXMnRcwP/1H2slCi5dX2tRCURpwVSQEH
-+GN1CKi1YdjJn/1HXcaGTaBVJLR2UpCx+8IXJZADyLEtzM4eQhXPokmKI5qipKELx
-+RESrdltkzdHuAsu0jDU9jXk9d9MNMhu7XY9lVosT5wDKKPfj793e3u/Pji1e7g0P
-+cAMuN3WJM6KP5EcXhq+V9bOjXx4KvEBiJ/fsTTydtX5ad2s5jMrQ3N87RZCoh2LB
-+/h8ifs4l+/+jzlkgryemgMKNhI5gJYT4PoDhqK8PceJub6kDVtJYq3PA/1iVd1HO
-+/GvKCgy/9dzJSif1yNyC/e6aCcfuxiCOBGNsHvISzU2sM6IlZXGy6fTJ+jLTt2ZD
-+cdpkONMeLCmt2axrJ6P5TZ+AVeA89DopLF0aiw/WS0MJ9k/LRGZWyfI84+/L4Uf4
-+Au+W2/53zO0gIXWbIOIlK5h0QORkLWzqz6EfYDx3hwrUYX0ANrRNyGNp8xYIwViG
-+VbFIoX/qs2lqg+ralaC/YQkWlsK6KJqIC38dnz+JXs3p7c8/XjM5FpKhoXn9TDM3
-+Dly0ZYVBfoygYrEncyyMH8WLNeFvUG34/zIuQtX3XF62hLfEr4ldRg8WGfFL8WPK
-+VKxKm5myaWn0wfPexP54sQES2uOzblm9iqO6iajnI7MCQ5wufBLJd6edmNI9p/1q
-+GqOjKZtm/Yd0Ed12XTdB
-+=pZiW
-+-----END PGP SIGNATURE-----
---- procenv-0.27.orig/man/procenv.1
-+++ procenv-0.27/man/procenv.1
-@@ -414,7 +414,7 @@ Any long option name may be shortened as
- The
- .I crumb
- output format is designed for easy parsing: it displays the data in a
--flattened format with each value on a separate line preceeded by all
-+flattened format with each value on a separate line preceded by all
- appropriate headings which are separated by the current separator.
- .IP \(bu
- The \fB\-\-message\-queues\fR, \fB\-\-semaphores\fR and
-@@ -431,10 +431,10 @@ the values are queryable, there is no do
- \& # Send compiler information to syslog (note the order of the options).
- \& procenv \-\-output=syslog \-\-compiler
- \&
--\& # Run a command ('mycmd --arg1 --foo=bar') without creating a new
-+\& # Run a command ('mycmd \-\-arg1 \-\-foo=bar') without creating a new
- \& # process, but have procenv run first and log its output to a
- \& # regular file.
--\& exec procenv \-\-file=/tmp/procenv.log --exec -- mycmd --arg1 --foo=bar
-+\& exec procenv \-\-file=/tmp/procenv.log \-\-exec \-\- mycmd \-\-arg1 \-\-foo=bar
- \&
- \& # The following kernel command-line snippet will cause procenv to
- \& # write output to first serial tty device and then execute init(8)
-@@ -442,16 +442,16 @@ the values are queryable, there is no do
- \& init=/usr/bin/procenv PROCENV_FILE=/dev/ttyS0 PROCENV_EXEC="/sbin/init \-\-debug"
- \&
- \& # Display all data in JSON format using an indent of 4 spaces
--\& procenv --format=json --indent=4
-+\& procenv \-\-format=json \-\-indent=4
- \&
- \& # Display all data in XML format using tabs for indents
--\& procenv --format=xml --indent-char="\t"
-+\& procenv \-\-format=xml \-\-indent-char="\t"
- \&
- \& # Display resource limits in easily-parseable format
--\& procenv --format=crumb --limits
-+\& procenv \-\-format=crumb \-\-limits
- \&
- \& # Produce output suitable for importing into a spreadsheet
--\& procenv --format=crumb --crumb-separator=\(aq,\(aq --separator=\(aq,\(aq --limits
-+\& procenv \-\-format=crumb \-\-crumb-separator=\(aq,\(aq \-\-separator=\(aq,\(aq \-\-limits
- .Ve
- .Ve
- .\"
diff --git a/debian/watch b/debian/watch
index 500290d..a1d6a3d 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,3 +1,4 @@
-version=3
-https://launchpad.net/procenv/+download https://launchpad.net/procenv/.*/procenv-(.+).tar.gz
-opts=pgpsigurlmangle=s/$/.asc/
+version=4
+opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%procenv-$1.tar.gz%" \
+ https://github.com/jamesodhunt/procenv/tags \
+ (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
diff --git a/man/procenv.1 b/man/procenv.1
index decea0f..d7f9287 100644
--- a/man/procenv.1
+++ b/man/procenv.1
@@ -1,4 +1,4 @@
-.TH PROCENV "1" "2015-10-27" "User Commands"
+.TH PROCENV "1" "2016-03-10" "User Commands"
.\"
.SH NAME
procenv \- display process environment details
@@ -111,6 +111,11 @@ See
.TP
\fB\-\-file=\fR\fIFILE\fR (*)
Send output to file \fIFILE\fR (implies \fB\-\-output=file\fR).
+.\"
+.TP
+\fB\-\-file\-append\fR (*)
+If \fB\-\-file\fR is specifed, append to it rather than
+overwriting it.
.PP
.\"
.TP
@@ -213,7 +218,7 @@ See
\fB\-N\fR, \fB\-\-network\fR
Display network details.
See
-.BR getifaddrs (3) "" ", " getnameinfo (3) "" ", and " ioctl (2) " (Linux)" .
+.BR getifaddrs (3) "" ", " getnameinfo (3) "" ", " ip (7) "" ", " netdevice (7) "" ", and " ioctl (2) " (Linux)" .
.PP
.\"
.TP
@@ -395,6 +400,10 @@ Alternative to \fB\-\-exec\fR.
.TP
\fBPROCENV_FILE\fR
Alternative to \fB\-\-file\fR.
+.\"
+.TP
+\fBPROCENV_FILE_APPEND\fR
+Alternative to \fB\-\-file\-append\fR.
.PP
.\"
.TP
@@ -519,7 +528,7 @@ Kees Cook
.RB < kees@ubuntu.com > "" "."
.\"
.SH COPYRIGHT
-Copyright \(co 2012-2014 James Hunt
+Copyright \(co 2012-2016 James Hunt
.RB < jamesodhunt@ubuntu.com >
and
Kees Cook
diff --git a/procenv.spec b/procenv.spec
index a96dcd9..166124c 100644
--- a/procenv.spec
+++ b/procenv.spec
@@ -1,12 +1,12 @@
Name: procenv
-Version: 0.43
+Version: 0.50
Release: 1%{?dist}
Summary: Utility to show process environment
Group: Applications/System
License: GPLv3+
URL: https://github.com/jamesodhunt/procenv
-Source0: https://github.com/jamesodhunt/procenv/archive/0.43.tar.gz
+Source0: https://github.com/jamesodhunt/procenv/archive/0.50.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
# fixme: should be autoconf >= 2.68, but Fedora packages or alien'ed dpkg
diff --git a/src/Makefile.am b/src/Makefile.am
index ed1df72..d6acefc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,13 +7,93 @@ AM_CFLAGS = \
-fstack-protector \
-Wformat
+
+# XXX: magic option that will remove all unused symbols
+# (defined by platform-generic.c).
+if PROCENV_PLATFORM_DARWIN
+AM_CFLAGS += -flto
+else
+AM_CFLAGS += -fdata-sections -ffunction-sections
+endif
+
+# keep it tight
+AM_CFLAGS += -Werror
+
bin_PROGRAMS = procenv
+
procenv_SOURCES = \
procenv.c procenv.h \
- pr_list.c pr_list.h
+ pr_list.c pr_list.h \
+ pstring.c pstring.h \
+ string-util.c string-util.h \
+ output.c output.h \
+ util.c util.h \
+ types.h \
+ messages.h \
+ platform.h platform-headers.h \
+ platform/platform-generic.c platform/platform-generic.h
+
+# XXX: unused symbol removal magic - part 2
+if PROCENV_PLATFORM_DARWIN
+procenv_LDFLAGS = -flto
+else
+procenv_LDFLAGS = -Wl,--gc-sections
+endif
+
+# should really do this in configure.ac
+if PROCENV_PLATFORM_MINIX
+procenv_LDADD = -lc
+endif
-procenv_LDADD = -lrt
procenv_CPPFLAGS =
+procenv_CPPFLAGS += -I $(srcdir) -I $(srcdir)/platform
+
+if PROCENV_PLATFORM_DARWIN
+procenv_SOURCES += platform/darwin/platform.c platform/darwin/platform-darwin.h
+procenv_CPPFLAGS += -I $(srcdir)/platform/darwin -D PROCENV_PLATFORM_DARWIN
+endif
+
+if PROCENV_PLATFORM_LINUX
+procenv_SOURCES += platform/linux/platform.c platform/linux/platform-linux.h
+procenv_CPPFLAGS += -I $(srcdir)/platform/linux -D PROCENV_PLATFORM_LINUX
+endif
+
+if PROCENV_PLATFORM_MINIX
+procenv_SOURCES += platform/minix/platform.c platform/minix/platform-minix.h
+procenv_CPPFLAGS += \
+ -I $(srcdir)/platform/minix -D PROCENV_PLATFORM_MINIX
+endif
+
+if PROCENV_PLATFORM_HURD
+procenv_SOURCES += platform/hurd/platform.c platform/hurd/platform-hurd.h
+procenv_CPPFLAGS += -I $(srcdir)/platform/hurd -D PROCENV_PLATFORM_HURD
+endif
+
+if PROCENV_PLATFORM_FREEBSD
+procenv_SOURCES += platform/freebsd/platform.c platform/freebsd/platform-freebsd.h
+procenv_CPPFLAGS += -I $(srcdir)/platform/freebsd \
+ -D PROCENV_PLATFORM_FREEBSD \
+ -D PROCENV_PLATFORM_BSD
+endif
+
+if PROCENV_PLATFORM_NETBSD
+procenv_SOURCES += platform/netbsd/platform.c platform/netbsd/platform-netbsd.h
+procenv_CPPFLAGS += -I $(srcdir)/platform/netbsd \
+ -D PROCENV_PLATFORM_NETBSD \
+ -D PROCENV_PLATFORM_BSD
+endif
+
+if PROCENV_PLATFORM_OPENBSD
+procenv_SOURCES += platform/openbsd/platform.c platform/openbsd/platform-openbsd.h
+procenv_CPPFLAGS += -I $(srcdir)/platform/openbsd \
+ -D PROCENV_PLATFORM_OPENBSD \
+ -D PROCENV_PLATFORM_BSD
+endif
+
+if PROCENV_PLATFORM_GENERIC
+procenv_SOURCES += platform/unknown/platform.c platform/unknown/platform-unknown.h
+procenv_CPPFLAGS += -I $(srcdir)/platform/unknown -D PROCENV_PLATFORM_GENERIC
+endif
if HAVE_SELINUX
procenv_CPPFLAGS += -DHAVE_SELINUX
@@ -27,10 +107,14 @@ if ENABLE_TESTS
TESTS =
CLEANFILES =
+TESTS += tests/show_machine_details
+
check_all_args: tests/check_all_args.in
sed -e 's|[@]builddir[@]|$(top_builddir)/$(subdir)|g' \
-e 's|[@]man_path[@]|$(top_srcdir)/man/procenv.1|g' \
-e 's|[@]package_url[@]|$(PACKAGE_URL)|g' \
+ -e 's|[@]package_url[@]|$(PACKAGE_URL)|g' \
+ -e 's|[@]procenv_platform[@]|$(procenv_platform)|g' \
$< > $@
chmod +x $@
@@ -44,16 +128,17 @@ check_pr_list_LDADD = @CHECK_LIBS@ pr_list.o
endif
+TESTS += check_all_args
+
# Run built binary to ensure we can display all values
TESTS += procenv
-TESTS += check_all_args
-
CLEANFILES += check_all_args
endif
EXTRA_DIST = \
tests/show_compiler_details \
+ tests/show_machine_details \
tests/check_all_args.in \
- tests/check_pr_list.c
+ tests/check_pr_list.c
diff --git a/src/Makefile.in b/src/Makefile.in
index bfb8385..f1d3959 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -86,12 +86,47 @@ POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+
+# XXX: magic option that will remove all unused symbols
+# (defined by platform-generic.c).
+@PROCENV_PLATFORM_DARWIN_TRUE@am__append_1 = -flto
+@PROCENV_PLATFORM_DARWIN_FALSE@am__append_2 = -fdata-sections -ffunction-sections
bin_PROGRAMS = procenv$(EXEEXT)
-@HAVE_SELINUX_TRUE@am__append_1 = -DHAVE_SELINUX
-@HAVE_APPARMOR_TRUE@am__append_2 = -DHAVE_APPARMOR
-@ENABLE_TESTS_TRUE@TESTS = $(am__EXEEXT_1) procenv$(EXEEXT) \
-@ENABLE_TESTS_TRUE@ check_all_args
-@ENABLE_TESTS_TRUE@@HAVE_CHECK_TRUE@am__append_3 = check_pr_list
+@PROCENV_PLATFORM_DARWIN_TRUE@am__append_3 = platform/darwin/platform.c platform/darwin/platform-darwin.h
+@PROCENV_PLATFORM_DARWIN_TRUE@am__append_4 = -I $(srcdir)/platform/darwin -D PROCENV_PLATFORM_DARWIN
+@PROCENV_PLATFORM_LINUX_TRUE@am__append_5 = platform/linux/platform.c platform/linux/platform-linux.h
+@PROCENV_PLATFORM_LINUX_TRUE@am__append_6 = -I $(srcdir)/platform/linux -D PROCENV_PLATFORM_LINUX
+@PROCENV_PLATFORM_MINIX_TRUE@am__append_7 = platform/minix/platform.c platform/minix/platform-minix.h
+@PROCENV_PLATFORM_MINIX_TRUE@am__append_8 = \
+@PROCENV_PLATFORM_MINIX_TRUE@ -I $(srcdir)/platform/minix -D PROCENV_PLATFORM_MINIX
+
+@PROCENV_PLATFORM_HURD_TRUE@am__append_9 = platform/hurd/platform.c platform/hurd/platform-hurd.h
+@PROCENV_PLATFORM_HURD_TRUE@am__append_10 = -I $(srcdir)/platform/hurd -D PROCENV_PLATFORM_HURD
+@PROCENV_PLATFORM_FREEBSD_TRUE@am__append_11 = platform/freebsd/platform.c platform/freebsd/platform-freebsd.h
+@PROCENV_PLATFORM_FREEBSD_TRUE@am__append_12 = -I $(srcdir)/platform/freebsd \
+@PROCENV_PLATFORM_FREEBSD_TRUE@ -D PROCENV_PLATFORM_FREEBSD \
+@PROCENV_PLATFORM_FREEBSD_TRUE@ -D PROCENV_PLATFORM_BSD
+
+@PROCENV_PLATFORM_NETBSD_TRUE@am__append_13 = platform/netbsd/platform.c platform/netbsd/platform-netbsd.h
+@PROCENV_PLATFORM_NETBSD_TRUE@am__append_14 = -I $(srcdir)/platform/netbsd \
+@PROCENV_PLATFORM_NETBSD_TRUE@ -D PROCENV_PLATFORM_NETBSD \
+@PROCENV_PLATFORM_NETBSD_TRUE@ -D PROCENV_PLATFORM_BSD
+
+@PROCENV_PLATFORM_OPENBSD_TRUE@am__append_15 = platform/openbsd/platform.c platform/openbsd/platform-openbsd.h
+@PROCENV_PLATFORM_OPENBSD_TRUE@am__append_16 = -I $(srcdir)/platform/openbsd \
+@PROCENV_PLATFORM_OPENBSD_TRUE@ -D PROCENV_PLATFORM_OPENBSD \
+@PROCENV_PLATFORM_OPENBSD_TRUE@ -D PROCENV_PLATFORM_BSD
+
+@PROCENV_PLATFORM_GENERIC_TRUE@am__append_17 = platform/unknown/platform.c platform/unknown/platform-unknown.h
+@PROCENV_PLATFORM_GENERIC_TRUE@am__append_18 = -I $(srcdir)/platform/unknown -D PROCENV_PLATFORM_GENERIC
+@HAVE_SELINUX_TRUE@am__append_19 = -DHAVE_SELINUX
+@HAVE_APPARMOR_TRUE@am__append_20 = -DHAVE_APPARMOR
+@ENABLE_TESTS_TRUE@TESTS = tests/show_machine_details $(am__EXEEXT_1) \
+@ENABLE_TESTS_TRUE@ check_all_args procenv$(EXEEXT)
+@ENABLE_TESTS_TRUE@@HAVE_CHECK_TRUE@am__append_21 = check_pr_list
@ENABLE_TESTS_TRUE@@HAVE_CHECK_TRUE@check_PROGRAMS = \
@ENABLE_TESTS_TRUE@@HAVE_CHECK_TRUE@ check_pr_list$(EXEEXT)
subdir = src
@@ -114,10 +149,40 @@ check_pr_list_OBJECTS = $(am_check_pr_list_OBJECTS)
@ENABLE_TESTS_TRUE@@HAVE_CHECK_TRUE@ pr_list.o
check_pr_list_LINK = $(CCLD) $(check_pr_list_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
+am__procenv_SOURCES_DIST = procenv.c procenv.h pr_list.c pr_list.h \
+ pstring.c pstring.h string-util.c string-util.h output.c \
+ output.h util.c util.h types.h messages.h platform.h \
+ platform-headers.h platform/platform-generic.c \
+ platform/platform-generic.h platform/darwin/platform.c \
+ platform/darwin/platform-darwin.h platform/linux/platform.c \
+ platform/linux/platform-linux.h platform/minix/platform.c \
+ platform/minix/platform-minix.h platform/hurd/platform.c \
+ platform/hurd/platform-hurd.h platform/freebsd/platform.c \
+ platform/freebsd/platform-freebsd.h platform/netbsd/platform.c \
+ platform/netbsd/platform-netbsd.h platform/openbsd/platform.c \
+ platform/openbsd/platform-openbsd.h \
+ platform/unknown/platform.c \
+ platform/unknown/platform-unknown.h
+@PROCENV_PLATFORM_DARWIN_TRUE@am__objects_1 = platform/darwin/procenv-platform.$(OBJEXT)
+@PROCENV_PLATFORM_LINUX_TRUE@am__objects_2 = platform/linux/procenv-platform.$(OBJEXT)
+@PROCENV_PLATFORM_MINIX_TRUE@am__objects_3 = platform/minix/procenv-platform.$(OBJEXT)
+@PROCENV_PLATFORM_HURD_TRUE@am__objects_4 = platform/hurd/procenv-platform.$(OBJEXT)
+@PROCENV_PLATFORM_FREEBSD_TRUE@am__objects_5 = platform/freebsd/procenv-platform.$(OBJEXT)
+@PROCENV_PLATFORM_NETBSD_TRUE@am__objects_6 = platform/netbsd/procenv-platform.$(OBJEXT)
+@PROCENV_PLATFORM_OPENBSD_TRUE@am__objects_7 = platform/openbsd/procenv-platform.$(OBJEXT)
+@PROCENV_PLATFORM_GENERIC_TRUE@am__objects_8 = platform/unknown/procenv-platform.$(OBJEXT)
am_procenv_OBJECTS = procenv-procenv.$(OBJEXT) \
- procenv-pr_list.$(OBJEXT)
+ procenv-pr_list.$(OBJEXT) procenv-pstring.$(OBJEXT) \
+ procenv-string-util.$(OBJEXT) procenv-output.$(OBJEXT) \
+ procenv-util.$(OBJEXT) \
+ platform/procenv-platform-generic.$(OBJEXT) $(am__objects_1) \
+ $(am__objects_2) $(am__objects_3) $(am__objects_4) \
+ $(am__objects_5) $(am__objects_6) $(am__objects_7) \
+ $(am__objects_8)
procenv_OBJECTS = $(am_procenv_OBJECTS)
procenv_DEPENDENCIES =
+procenv_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(procenv_LDFLAGS) \
+ $(LDFLAGS) -o $@
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
@@ -151,7 +216,8 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(check_pr_list_SOURCES) $(procenv_SOURCES)
-DIST_SOURCES = $(am__check_pr_list_SOURCES_DIST) $(procenv_SOURCES)
+DIST_SOURCES = $(am__check_pr_list_SOURCES_DIST) \
+ $(am__procenv_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -204,13 +270,10 @@ am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
-AM_CFLAGS = \
- -pedantic \
- -std=gnu99 \
- -Wall -Wunused \
- -fstack-protector \
- -Wformat
+# keep it tight
+AM_CFLAGS = -pedantic -std=gnu99 -Wall -Wunused -fstack-protector \
+ -Wformat $(am__append_1) $(am__append_2) -Werror
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -271,14 +334,22 @@ am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
+build = @build@
build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
+host = @host@
host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
@@ -292,31 +363,50 @@ mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
+procenv_platform = @procenv_platform@
program_transform_name = @program_transform_name@
psdir = @psdir@
+runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
+target = @target@
target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = subdir-objects
-procenv_SOURCES = \
- procenv.c procenv.h \
- pr_list.c pr_list.h
-
-procenv_LDADD = -lrt
-procenv_CPPFLAGS = $(am__append_1) $(am__append_2)
+procenv_SOURCES = procenv.c procenv.h pr_list.c pr_list.h pstring.c \
+ pstring.h string-util.c string-util.h output.c output.h util.c \
+ util.h types.h messages.h platform.h platform-headers.h \
+ platform/platform-generic.c platform/platform-generic.h \
+ $(am__append_3) $(am__append_5) $(am__append_7) \
+ $(am__append_9) $(am__append_11) $(am__append_13) \
+ $(am__append_15) $(am__append_17)
+@PROCENV_PLATFORM_DARWIN_FALSE@procenv_LDFLAGS = -Wl,--gc-sections
+
+# XXX: unused symbol removal magic - part 2
+@PROCENV_PLATFORM_DARWIN_TRUE@procenv_LDFLAGS = -flto
+
+# should really do this in configure.ac
+@PROCENV_PLATFORM_MINIX_TRUE@procenv_LDADD = -lc
+procenv_CPPFLAGS = -I $(srcdir) -I $(srcdir)/platform $(am__append_4) \
+ $(am__append_6) $(am__append_8) $(am__append_10) \
+ $(am__append_12) $(am__append_14) $(am__append_16) \
+ $(am__append_18) $(am__append_19) $(am__append_20)
@ENABLE_TESTS_TRUE@CLEANFILES = check_all_args
@ENABLE_TESTS_TRUE@@HAVE_CHECK_TRUE@check_pr_list_SOURCES = tests/check_pr_list.c
@ENABLE_TESTS_TRUE@@HAVE_CHECK_TRUE@check_pr_list_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/src
@ENABLE_TESTS_TRUE@@HAVE_CHECK_TRUE@check_pr_list_LDADD = @CHECK_LIBS@ pr_list.o
EXTRA_DIST = \
tests/show_compiler_details \
+ tests/show_machine_details \
tests/check_all_args.in \
- tests/check_pr_list.c
+ tests/check_pr_list.c
all: all-am
@@ -408,20 +498,122 @@ tests/check_pr_list-check_pr_list.$(OBJEXT): tests/$(am__dirstamp) \
check_pr_list$(EXEEXT): $(check_pr_list_OBJECTS) $(check_pr_list_DEPENDENCIES) $(EXTRA_check_pr_list_DEPENDENCIES)
@rm -f check_pr_list$(EXEEXT)
$(AM_V_CCLD)$(check_pr_list_LINK) $(check_pr_list_OBJECTS) $(check_pr_list_LDADD) $(LIBS)
+platform/$(am__dirstamp):
+ @$(MKDIR_P) platform
+ @: > platform/$(am__dirstamp)
+platform/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/$(DEPDIR)
+ @: > platform/$(DEPDIR)/$(am__dirstamp)
+platform/procenv-platform-generic.$(OBJEXT): platform/$(am__dirstamp) \
+ platform/$(DEPDIR)/$(am__dirstamp)
+platform/darwin/$(am__dirstamp):
+ @$(MKDIR_P) platform/darwin
+ @: > platform/darwin/$(am__dirstamp)
+platform/darwin/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/darwin/$(DEPDIR)
+ @: > platform/darwin/$(DEPDIR)/$(am__dirstamp)
+platform/darwin/procenv-platform.$(OBJEXT): \
+ platform/darwin/$(am__dirstamp) \
+ platform/darwin/$(DEPDIR)/$(am__dirstamp)
+platform/linux/$(am__dirstamp):
+ @$(MKDIR_P) platform/linux
+ @: > platform/linux/$(am__dirstamp)
+platform/linux/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/linux/$(DEPDIR)
+ @: > platform/linux/$(DEPDIR)/$(am__dirstamp)
+platform/linux/procenv-platform.$(OBJEXT): \
+ platform/linux/$(am__dirstamp) \
+ platform/linux/$(DEPDIR)/$(am__dirstamp)
+platform/minix/$(am__dirstamp):
+ @$(MKDIR_P) platform/minix
+ @: > platform/minix/$(am__dirstamp)
+platform/minix/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/minix/$(DEPDIR)
+ @: > platform/minix/$(DEPDIR)/$(am__dirstamp)
+platform/minix/procenv-platform.$(OBJEXT): \
+ platform/minix/$(am__dirstamp) \
+ platform/minix/$(DEPDIR)/$(am__dirstamp)
+platform/hurd/$(am__dirstamp):
+ @$(MKDIR_P) platform/hurd
+ @: > platform/hurd/$(am__dirstamp)
+platform/hurd/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/hurd/$(DEPDIR)
+ @: > platform/hurd/$(DEPDIR)/$(am__dirstamp)
+platform/hurd/procenv-platform.$(OBJEXT): \
+ platform/hurd/$(am__dirstamp) \
+ platform/hurd/$(DEPDIR)/$(am__dirstamp)
+platform/freebsd/$(am__dirstamp):
+ @$(MKDIR_P) platform/freebsd
+ @: > platform/freebsd/$(am__dirstamp)
+platform/freebsd/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/freebsd/$(DEPDIR)
+ @: > platform/freebsd/$(DEPDIR)/$(am__dirstamp)
+platform/freebsd/procenv-platform.$(OBJEXT): \
+ platform/freebsd/$(am__dirstamp) \
+ platform/freebsd/$(DEPDIR)/$(am__dirstamp)
+platform/netbsd/$(am__dirstamp):
+ @$(MKDIR_P) platform/netbsd
+ @: > platform/netbsd/$(am__dirstamp)
+platform/netbsd/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/netbsd/$(DEPDIR)
+ @: > platform/netbsd/$(DEPDIR)/$(am__dirstamp)
+platform/netbsd/procenv-platform.$(OBJEXT): \
+ platform/netbsd/$(am__dirstamp) \
+ platform/netbsd/$(DEPDIR)/$(am__dirstamp)
+platform/openbsd/$(am__dirstamp):
+ @$(MKDIR_P) platform/openbsd
+ @: > platform/openbsd/$(am__dirstamp)
+platform/openbsd/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/openbsd/$(DEPDIR)
+ @: > platform/openbsd/$(DEPDIR)/$(am__dirstamp)
+platform/openbsd/procenv-platform.$(OBJEXT): \
+ platform/openbsd/$(am__dirstamp) \
+ platform/openbsd/$(DEPDIR)/$(am__dirstamp)
+platform/unknown/$(am__dirstamp):
+ @$(MKDIR_P) platform/unknown
+ @: > platform/unknown/$(am__dirstamp)
+platform/unknown/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) platform/unknown/$(DEPDIR)
+ @: > platform/unknown/$(DEPDIR)/$(am__dirstamp)
+platform/unknown/procenv-platform.$(OBJEXT): \
+ platform/unknown/$(am__dirstamp) \
+ platform/unknown/$(DEPDIR)/$(am__dirstamp)
procenv$(EXEEXT): $(procenv_OBJECTS) $(procenv_DEPENDENCIES) $(EXTRA_procenv_DEPENDENCIES)
@rm -f procenv$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(procenv_OBJECTS) $(procenv_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(procenv_LINK) $(procenv_OBJECTS) $(procenv_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
+ -rm -f platform/*.$(OBJEXT)
+ -rm -f platform/darwin/*.$(OBJEXT)
+ -rm -f platform/freebsd/*.$(OBJEXT)
+ -rm -f platform/hurd/*.$(OBJEXT)
+ -rm -f platform/linux/*.$(OBJEXT)
+ -rm -f platform/minix/*.$(OBJEXT)
+ -rm -f platform/netbsd/*.$(OBJEXT)
+ -rm -f platform/openbsd/*.$(OBJEXT)
+ -rm -f platform/unknown/*.$(OBJEXT)
-rm -f tests/*.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procenv-output.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procenv-pr_list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procenv-procenv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procenv-pstring.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procenv-string-util.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/procenv-util.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/$(DEPDIR)/procenv-platform-generic.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/darwin/$(DEPDIR)/procenv-platform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/freebsd/$(DEPDIR)/procenv-platform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/hurd/$(DEPDIR)/procenv-platform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/linux/$(DEPDIR)/procenv-platform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/minix/$(DEPDIR)/procenv-platform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/netbsd/$(DEPDIR)/procenv-platform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/openbsd/$(DEPDIR)/procenv-platform.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@platform/unknown/$(DEPDIR)/procenv-platform.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/check_pr_list-check_pr_list.Po@am__quote@
.c.o:
@@ -482,6 +674,188 @@ procenv-pr_list.obj: pr_list.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-pr_list.obj `if test -f 'pr_list.c'; then $(CYGPATH_W) 'pr_list.c'; else $(CYGPATH_W) '$(srcdir)/pr_list.c'; fi`
+procenv-pstring.o: pstring.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT procenv-pstring.o -MD -MP -MF $(DEPDIR)/procenv-pstring.Tpo -c -o procenv-pstring.o `test -f 'pstring.c' || echo '$(srcdir)/'`pstring.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/procenv-pstring.Tpo $(DEPDIR)/procenv-pstring.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pstring.c' object='procenv-pstring.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-pstring.o `test -f 'pstring.c' || echo '$(srcdir)/'`pstring.c
+
+procenv-pstring.obj: pstring.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT procenv-pstring.obj -MD -MP -MF $(DEPDIR)/procenv-pstring.Tpo -c -o procenv-pstring.obj `if test -f 'pstring.c'; then $(CYGPATH_W) 'pstring.c'; else $(CYGPATH_W) '$(srcdir)/pstring.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/procenv-pstring.Tpo $(DEPDIR)/procenv-pstring.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pstring.c' object='procenv-pstring.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-pstring.obj `if test -f 'pstring.c'; then $(CYGPATH_W) 'pstring.c'; else $(CYGPATH_W) '$(srcdir)/pstring.c'; fi`
+
+procenv-string-util.o: string-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT procenv-string-util.o -MD -MP -MF $(DEPDIR)/procenv-string-util.Tpo -c -o procenv-string-util.o `test -f 'string-util.c' || echo '$(srcdir)/'`string-util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/procenv-string-util.Tpo $(DEPDIR)/procenv-string-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string-util.c' object='procenv-string-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-string-util.o `test -f 'string-util.c' || echo '$(srcdir)/'`string-util.c
+
+procenv-string-util.obj: string-util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT procenv-string-util.obj -MD -MP -MF $(DEPDIR)/procenv-string-util.Tpo -c -o procenv-string-util.obj `if test -f 'string-util.c'; then $(CYGPATH_W) 'string-util.c'; else $(CYGPATH_W) '$(srcdir)/string-util.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/procenv-string-util.Tpo $(DEPDIR)/procenv-string-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='string-util.c' object='procenv-string-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-string-util.obj `if test -f 'string-util.c'; then $(CYGPATH_W) 'string-util.c'; else $(CYGPATH_W) '$(srcdir)/string-util.c'; fi`
+
+procenv-output.o: output.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT procenv-output.o -MD -MP -MF $(DEPDIR)/procenv-output.Tpo -c -o procenv-output.o `test -f 'output.c' || echo '$(srcdir)/'`output.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/procenv-output.Tpo $(DEPDIR)/procenv-output.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='output.c' object='procenv-output.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-output.o `test -f 'output.c' || echo '$(srcdir)/'`output.c
+
+procenv-output.obj: output.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT procenv-output.obj -MD -MP -MF $(DEPDIR)/procenv-output.Tpo -c -o procenv-output.obj `if test -f 'output.c'; then $(CYGPATH_W) 'output.c'; else $(CYGPATH_W) '$(srcdir)/output.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/procenv-output.Tpo $(DEPDIR)/procenv-output.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='output.c' object='procenv-output.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-output.obj `if test -f 'output.c'; then $(CYGPATH_W) 'output.c'; else $(CYGPATH_W) '$(srcdir)/output.c'; fi`
+
+procenv-util.o: util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT procenv-util.o -MD -MP -MF $(DEPDIR)/procenv-util.Tpo -c -o procenv-util.o `test -f 'util.c' || echo '$(srcdir)/'`util.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/procenv-util.Tpo $(DEPDIR)/procenv-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='util.c' object='procenv-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-util.o `test -f 'util.c' || echo '$(srcdir)/'`util.c
+
+procenv-util.obj: util.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT procenv-util.obj -MD -MP -MF $(DEPDIR)/procenv-util.Tpo -c -o procenv-util.obj `if test -f 'util.c'; then $(CYGPATH_W) 'util.c'; else $(CYGPATH_W) '$(srcdir)/util.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/procenv-util.Tpo $(DEPDIR)/procenv-util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='util.c' object='procenv-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o procenv-util.obj `if test -f 'util.c'; then $(CYGPATH_W) 'util.c'; else $(CYGPATH_W) '$(srcdir)/util.c'; fi`
+
+platform/procenv-platform-generic.o: platform/platform-generic.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/procenv-platform-generic.o -MD -MP -MF platform/$(DEPDIR)/procenv-platform-generic.Tpo -c -o platform/procenv-platform-generic.o `test -f 'platform/platform-generic.c' || echo '$(srcdir)/'`platform/platform-generic.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/$(DEPDIR)/procenv-platform-generic.Tpo platform/$(DEPDIR)/procenv-platform-generic.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/platform-generic.c' object='platform/procenv-platform-generic.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/procenv-platform-generic.o `test -f 'platform/platform-generic.c' || echo '$(srcdir)/'`platform/platform-generic.c
+
+platform/procenv-platform-generic.obj: platform/platform-generic.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/procenv-platform-generic.obj -MD -MP -MF platform/$(DEPDIR)/procenv-platform-generic.Tpo -c -o platform/procenv-platform-generic.obj `if test -f 'platform/platform-generic.c'; then $(CYGPATH_W) 'platform/platform-generic.c'; else $(CYGPATH_W) '$(srcdir)/platform/platform-generic.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/$(DEPDIR)/procenv-platform-generic.Tpo platform/$(DEPDIR)/procenv-platform-generic.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/platform-generic.c' object='platform/procenv-platform-generic.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/procenv-platform-generic.obj `if test -f 'platform/platform-generic.c'; then $(CYGPATH_W) 'platform/platform-generic.c'; else $(CYGPATH_W) '$(srcdir)/platform/platform-generic.c'; fi`
+
+platform/darwin/procenv-platform.o: platform/darwin/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/darwin/procenv-platform.o -MD -MP -MF platform/darwin/$(DEPDIR)/procenv-platform.Tpo -c -o platform/darwin/procenv-platform.o `test -f 'platform/darwin/platform.c' || echo '$(srcdir)/'`platform/darwin/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/darwin/$(DEPDIR)/procenv-platform.Tpo platform/darwin/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/darwin/platform.c' object='platform/darwin/procenv-platform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/darwin/procenv-platform.o `test -f 'platform/darwin/platform.c' || echo '$(srcdir)/'`platform/darwin/platform.c
+
+platform/darwin/procenv-platform.obj: platform/darwin/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/darwin/procenv-platform.obj -MD -MP -MF platform/darwin/$(DEPDIR)/procenv-platform.Tpo -c -o platform/darwin/procenv-platform.obj `if test -f 'platform/darwin/platform.c'; then $(CYGPATH_W) 'platform/darwin/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/darwin/platform.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/darwin/$(DEPDIR)/procenv-platform.Tpo platform/darwin/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/darwin/platform.c' object='platform/darwin/procenv-platform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/darwin/procenv-platform.obj `if test -f 'platform/darwin/platform.c'; then $(CYGPATH_W) 'platform/darwin/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/darwin/platform.c'; fi`
+
+platform/linux/procenv-platform.o: platform/linux/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/linux/procenv-platform.o -MD -MP -MF platform/linux/$(DEPDIR)/procenv-platform.Tpo -c -o platform/linux/procenv-platform.o `test -f 'platform/linux/platform.c' || echo '$(srcdir)/'`platform/linux/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/linux/$(DEPDIR)/procenv-platform.Tpo platform/linux/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/linux/platform.c' object='platform/linux/procenv-platform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/linux/procenv-platform.o `test -f 'platform/linux/platform.c' || echo '$(srcdir)/'`platform/linux/platform.c
+
+platform/linux/procenv-platform.obj: platform/linux/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/linux/procenv-platform.obj -MD -MP -MF platform/linux/$(DEPDIR)/procenv-platform.Tpo -c -o platform/linux/procenv-platform.obj `if test -f 'platform/linux/platform.c'; then $(CYGPATH_W) 'platform/linux/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/linux/platform.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/linux/$(DEPDIR)/procenv-platform.Tpo platform/linux/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/linux/platform.c' object='platform/linux/procenv-platform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/linux/procenv-platform.obj `if test -f 'platform/linux/platform.c'; then $(CYGPATH_W) 'platform/linux/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/linux/platform.c'; fi`
+
+platform/minix/procenv-platform.o: platform/minix/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/minix/procenv-platform.o -MD -MP -MF platform/minix/$(DEPDIR)/procenv-platform.Tpo -c -o platform/minix/procenv-platform.o `test -f 'platform/minix/platform.c' || echo '$(srcdir)/'`platform/minix/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/minix/$(DEPDIR)/procenv-platform.Tpo platform/minix/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/minix/platform.c' object='platform/minix/procenv-platform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/minix/procenv-platform.o `test -f 'platform/minix/platform.c' || echo '$(srcdir)/'`platform/minix/platform.c
+
+platform/minix/procenv-platform.obj: platform/minix/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/minix/procenv-platform.obj -MD -MP -MF platform/minix/$(DEPDIR)/procenv-platform.Tpo -c -o platform/minix/procenv-platform.obj `if test -f 'platform/minix/platform.c'; then $(CYGPATH_W) 'platform/minix/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/minix/platform.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/minix/$(DEPDIR)/procenv-platform.Tpo platform/minix/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/minix/platform.c' object='platform/minix/procenv-platform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/minix/procenv-platform.obj `if test -f 'platform/minix/platform.c'; then $(CYGPATH_W) 'platform/minix/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/minix/platform.c'; fi`
+
+platform/hurd/procenv-platform.o: platform/hurd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/hurd/procenv-platform.o -MD -MP -MF platform/hurd/$(DEPDIR)/procenv-platform.Tpo -c -o platform/hurd/procenv-platform.o `test -f 'platform/hurd/platform.c' || echo '$(srcdir)/'`platform/hurd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/hurd/$(DEPDIR)/procenv-platform.Tpo platform/hurd/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/hurd/platform.c' object='platform/hurd/procenv-platform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/hurd/procenv-platform.o `test -f 'platform/hurd/platform.c' || echo '$(srcdir)/'`platform/hurd/platform.c
+
+platform/hurd/procenv-platform.obj: platform/hurd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/hurd/procenv-platform.obj -MD -MP -MF platform/hurd/$(DEPDIR)/procenv-platform.Tpo -c -o platform/hurd/procenv-platform.obj `if test -f 'platform/hurd/platform.c'; then $(CYGPATH_W) 'platform/hurd/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/hurd/platform.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/hurd/$(DEPDIR)/procenv-platform.Tpo platform/hurd/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/hurd/platform.c' object='platform/hurd/procenv-platform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/hurd/procenv-platform.obj `if test -f 'platform/hurd/platform.c'; then $(CYGPATH_W) 'platform/hurd/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/hurd/platform.c'; fi`
+
+platform/freebsd/procenv-platform.o: platform/freebsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/freebsd/procenv-platform.o -MD -MP -MF platform/freebsd/$(DEPDIR)/procenv-platform.Tpo -c -o platform/freebsd/procenv-platform.o `test -f 'platform/freebsd/platform.c' || echo '$(srcdir)/'`platform/freebsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/freebsd/$(DEPDIR)/procenv-platform.Tpo platform/freebsd/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/freebsd/platform.c' object='platform/freebsd/procenv-platform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/freebsd/procenv-platform.o `test -f 'platform/freebsd/platform.c' || echo '$(srcdir)/'`platform/freebsd/platform.c
+
+platform/freebsd/procenv-platform.obj: platform/freebsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/freebsd/procenv-platform.obj -MD -MP -MF platform/freebsd/$(DEPDIR)/procenv-platform.Tpo -c -o platform/freebsd/procenv-platform.obj `if test -f 'platform/freebsd/platform.c'; then $(CYGPATH_W) 'platform/freebsd/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/freebsd/platform.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/freebsd/$(DEPDIR)/procenv-platform.Tpo platform/freebsd/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/freebsd/platform.c' object='platform/freebsd/procenv-platform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/freebsd/procenv-platform.obj `if test -f 'platform/freebsd/platform.c'; then $(CYGPATH_W) 'platform/freebsd/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/freebsd/platform.c'; fi`
+
+platform/netbsd/procenv-platform.o: platform/netbsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/netbsd/procenv-platform.o -MD -MP -MF platform/netbsd/$(DEPDIR)/procenv-platform.Tpo -c -o platform/netbsd/procenv-platform.o `test -f 'platform/netbsd/platform.c' || echo '$(srcdir)/'`platform/netbsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/netbsd/$(DEPDIR)/procenv-platform.Tpo platform/netbsd/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/netbsd/platform.c' object='platform/netbsd/procenv-platform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/netbsd/procenv-platform.o `test -f 'platform/netbsd/platform.c' || echo '$(srcdir)/'`platform/netbsd/platform.c
+
+platform/netbsd/procenv-platform.obj: platform/netbsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/netbsd/procenv-platform.obj -MD -MP -MF platform/netbsd/$(DEPDIR)/procenv-platform.Tpo -c -o platform/netbsd/procenv-platform.obj `if test -f 'platform/netbsd/platform.c'; then $(CYGPATH_W) 'platform/netbsd/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/netbsd/platform.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/netbsd/$(DEPDIR)/procenv-platform.Tpo platform/netbsd/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/netbsd/platform.c' object='platform/netbsd/procenv-platform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/netbsd/procenv-platform.obj `if test -f 'platform/netbsd/platform.c'; then $(CYGPATH_W) 'platform/netbsd/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/netbsd/platform.c'; fi`
+
+platform/openbsd/procenv-platform.o: platform/openbsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/openbsd/procenv-platform.o -MD -MP -MF platform/openbsd/$(DEPDIR)/procenv-platform.Tpo -c -o platform/openbsd/procenv-platform.o `test -f 'platform/openbsd/platform.c' || echo '$(srcdir)/'`platform/openbsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/openbsd/$(DEPDIR)/procenv-platform.Tpo platform/openbsd/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/openbsd/platform.c' object='platform/openbsd/procenv-platform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/openbsd/procenv-platform.o `test -f 'platform/openbsd/platform.c' || echo '$(srcdir)/'`platform/openbsd/platform.c
+
+platform/openbsd/procenv-platform.obj: platform/openbsd/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/openbsd/procenv-platform.obj -MD -MP -MF platform/openbsd/$(DEPDIR)/procenv-platform.Tpo -c -o platform/openbsd/procenv-platform.obj `if test -f 'platform/openbsd/platform.c'; then $(CYGPATH_W) 'platform/openbsd/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/openbsd/platform.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/openbsd/$(DEPDIR)/procenv-platform.Tpo platform/openbsd/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/openbsd/platform.c' object='platform/openbsd/procenv-platform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/openbsd/procenv-platform.obj `if test -f 'platform/openbsd/platform.c'; then $(CYGPATH_W) 'platform/openbsd/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/openbsd/platform.c'; fi`
+
+platform/unknown/procenv-platform.o: platform/unknown/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/unknown/procenv-platform.o -MD -MP -MF platform/unknown/$(DEPDIR)/procenv-platform.Tpo -c -o platform/unknown/procenv-platform.o `test -f 'platform/unknown/platform.c' || echo '$(srcdir)/'`platform/unknown/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/unknown/$(DEPDIR)/procenv-platform.Tpo platform/unknown/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/unknown/platform.c' object='platform/unknown/procenv-platform.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/unknown/procenv-platform.o `test -f 'platform/unknown/platform.c' || echo '$(srcdir)/'`platform/unknown/platform.c
+
+platform/unknown/procenv-platform.obj: platform/unknown/platform.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT platform/unknown/procenv-platform.obj -MD -MP -MF platform/unknown/$(DEPDIR)/procenv-platform.Tpo -c -o platform/unknown/procenv-platform.obj `if test -f 'platform/unknown/platform.c'; then $(CYGPATH_W) 'platform/unknown/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/unknown/platform.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) platform/unknown/$(DEPDIR)/procenv-platform.Tpo platform/unknown/$(DEPDIR)/procenv-platform.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='platform/unknown/platform.c' object='platform/unknown/procenv-platform.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(procenv_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o platform/unknown/procenv-platform.obj `if test -f 'platform/unknown/platform.c'; then $(CYGPATH_W) 'platform/unknown/platform.c'; else $(CYGPATH_W) '$(srcdir)/platform/unknown/platform.c'; fi`
+
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
@@ -693,6 +1067,24 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f platform/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/$(am__dirstamp)
+ -rm -f platform/darwin/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/darwin/$(am__dirstamp)
+ -rm -f platform/freebsd/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/freebsd/$(am__dirstamp)
+ -rm -f platform/hurd/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/hurd/$(am__dirstamp)
+ -rm -f platform/linux/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/linux/$(am__dirstamp)
+ -rm -f platform/minix/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/minix/$(am__dirstamp)
+ -rm -f platform/netbsd/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/netbsd/$(am__dirstamp)
+ -rm -f platform/openbsd/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/openbsd/$(am__dirstamp)
+ -rm -f platform/unknown/$(DEPDIR)/$(am__dirstamp)
+ -rm -f platform/unknown/$(am__dirstamp)
-rm -f tests/$(DEPDIR)/$(am__dirstamp)
-rm -f tests/$(am__dirstamp)
@@ -705,7 +1097,7 @@ clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
mostlyclean-am
distclean: distclean-am
- -rm -rf ./$(DEPDIR) tests/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) platform/$(DEPDIR) platform/darwin/$(DEPDIR) platform/freebsd/$(DEPDIR) platform/hurd/$(DEPDIR) platform/linux/$(DEPDIR) platform/minix/$(DEPDIR) platform/netbsd/$(DEPDIR) platform/openbsd/$(DEPDIR) platform/unknown/$(DEPDIR) tests/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -751,7 +1143,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR) tests/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) platform/$(DEPDIR) platform/darwin/$(DEPDIR) platform/freebsd/$(DEPDIR) platform/hurd/$(DEPDIR) platform/linux/$(DEPDIR) platform/minix/$(DEPDIR) platform/netbsd/$(DEPDIR) platform/openbsd/$(DEPDIR) platform/unknown/$(DEPDIR) tests/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@@ -792,6 +1184,8 @@ uninstall-am: uninstall-binPROGRAMS
@ENABLE_TESTS_TRUE@ sed -e 's|[@]builddir[@]|$(top_builddir)/$(subdir)|g' \
@ENABLE_TESTS_TRUE@ -e 's|[@]man_path[@]|$(top_srcdir)/man/procenv.1|g' \
@ENABLE_TESTS_TRUE@ -e 's|[@]package_url[@]|$(PACKAGE_URL)|g' \
+@ENABLE_TESTS_TRUE@ -e 's|[@]package_url[@]|$(PACKAGE_URL)|g' \
+@ENABLE_TESTS_TRUE@ -e 's|[@]procenv_platform[@]|$(procenv_platform)|g' \
@ENABLE_TESTS_TRUE@ $< > $@
@ENABLE_TESTS_TRUE@ chmod +x $@
diff --git a/src/messages.h b/src/messages.h
new file mode 100644
index 0000000..6169c97
--- /dev/null
+++ b/src/messages.h
@@ -0,0 +1,41 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_MESSAGES_H
+#define _PROCENV_MESSAGES_H
+
+/* FIXME: gettext */
+#define _(str) str
+
+#define YES_STR _("yes")
+#define NO_STR _("no")
+#define NON_STR _("non")
+#define NA_STR _("n/a")
+#define UNKNOWN_STR _("unknown")
+#define MAX_STR _(" (max)")
+#define DEFINED_STR _("defined")
+#define NOT_DEFINED_STR _("not defined")
+#define NOT_IMPLEMENTED_STR _("[not implemented]")
+#define BIG_STR _("big")
+#define LITTLE_STR _("little")
+#define PRIVILEGED_STR _("privileged")
+#define SUPPRESSED_STR _("[suppressed]")
+#define BUILD_TYPE_STD_STR _("standard")
+#define BUILD_TYPE_REPRODUCIBLE_STR _("reproducible")
+
+#endif /* _PROCENV_MESSAGES_H */
diff --git a/src/output.c b/src/output.c
new file mode 100644
index 0000000..7cd63fa
--- /dev/null
+++ b/src/output.c
@@ -0,0 +1,2003 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include <stdbool.h>
+#include <syslog.h>
+#include <assert.h>
+
+#include "pr_list.h"
+#include "string-util.h"
+#include "output.h"
+
+/* Default character to use for indent */
+#define DEFAULT_INDENT_CHAR " "
+
+/* If an indent is required, use this many INDENT_CHARs by default */
+#define DEFAULT_INDENT_AMOUNT 2
+
+#define PROCENV_DEFAULT_CRUMB_SEPARATOR ":"
+#define PROCENV_DEFAULT_TEXT_SEPARATOR ": "
+
+/*
+ * XXX: WARNING! Gross magic number hack!
+ *
+ * - This value must equal the maximum number of entries in any particular
+ * OutputFormats translation table.
+ *
+ * - This must be updated to reflect the
+ * maximum values in any TranslateMapEntry, plus 1.
+ */
+#define TRANSLATE_MAP_ENTRIES (5+1)
+
+extern pstring *doc;
+extern struct procenv_user user;
+
+/**
+ * output:
+ *
+ * Where to send output.
+ **/
+Output output = OUTPUT_STDOUT;
+
+/**
+ * output_format:
+ *
+ * Format output will be displayed in.
+ **/
+OutputFormat output_format = OUTPUT_FORMAT_TEXT;
+
+/**
+ * output_file:
+ *
+ * Name or output file to send output to if not NULL.
+ **/
+const char *output_file = NULL;
+
+/**
+ * output_file_append:
+ *
+ * If true, append to @output_file rather than truncating.
+ **/
+static int output_file_append = false;
+
+/**
+ * text_separator:
+ *
+ * Separator used for text output format to separate a name from a
+ * value.
+ **/
+static const char *text_separator = PROCENV_DEFAULT_TEXT_SEPARATOR;
+
+/**
+ * output_fd:
+ *
+ * File descriptor associated with output_file.
+ **/
+int output_fd = -1;
+
+static struct procenv_map output_map[] = {
+ { OUTPUT_FILE , "file" },
+ { OUTPUT_STDERR , "stderr" },
+ { OUTPUT_STDOUT , "stdout" },
+ { OUTPUT_SYSLOG , "syslog" },
+ { OUTPUT_TERM , "terminal" },
+
+ { 0 , NULL }
+};
+
+static struct procenv_map output_format_map[] = {
+ { OUTPUT_FORMAT_TEXT , "text" },
+ { OUTPUT_FORMAT_CRUMB , "crumb" },
+ { OUTPUT_FORMAT_JSON , "json" },
+ { OUTPUT_FORMAT_XML , "xml" },
+
+ { 0 , NULL }
+};
+
+typedef struct translate_map_entry {
+ wchar_t from;
+ wchar_t *to;
+} TranslateMapEntry;
+
+typedef struct translate_table {
+ OutputFormat output_format;
+ TranslateMapEntry map[TRANSLATE_MAP_ENTRIES];
+} TranslateTable;
+
+/*
+ * Note the gross hack to avoid need for flexible arrays.
+ */
+static TranslateTable translate_table[] = {
+ {
+ OUTPUT_FORMAT_XML,
+ {
+ { L'\'', L"&apos;" },
+ { L'"', L"&quot;" },
+ { L'&', L"&amp;" },
+ { L'<', L"&lt;" },
+ { L'>', L"&gt;" },
+
+ /* terminator */
+ { L'\0', NULL }
+ }
+ },
+ {
+ OUTPUT_FORMAT_JSON,
+ {
+ { L'"', L"\\\"" },
+ { L'\\', L"\\\\" },
+
+ /* XXX: the hack! */
+ { L'\0', NULL },
+ { L'\0', NULL },
+ { L'\0', NULL },
+
+ /* terminator */
+ { L'\0', NULL }
+ }
+ },
+};
+
+/**
+ * last_element: Type of previous element handled.
+ **/
+ElementType last_element = ELEMENT_TYPE_NONE;
+
+/**
+ * current_element: Type of element currently being handled.
+ **/
+ElementType current_element = ELEMENT_TYPE_NONE;
+
+/**
+ * crumb_list:
+ *
+ * List used to store breadcrumbs when OUTPUT_FORMAT_CRUMB being used.
+ **/
+static PRList *crumb_list = NULL;
+
+/**
+ * indent:
+ *
+ * Current output indent value.
+ **/
+static int indent = 0;
+
+/**
+ * indent_amount:
+ *
+ * Number of INDENT_CHARs to emit for an indent.
+ **/
+static int indent_amount = DEFAULT_INDENT_AMOUNT;
+
+/**
+ * indent_char, wide_indent_char:
+ *
+ * Character to use for indenting and wide-char equivalent.
+ **/
+const char *indent_char = DEFAULT_INDENT_CHAR;
+wchar_t wide_indent_char;
+
+/**
+ * crumb_separator:
+ *
+ * Separator used for text output format to separate a name from a
+ * value.
+ **/
+const char *crumb_separator = PROCENV_DEFAULT_CRUMB_SEPARATOR;
+
+void
+header (const char *name)
+{
+ assert (name);
+ common_assert ();
+
+ section_open (name);
+}
+
+void
+footer (void)
+{
+ common_assert ();
+ section_close ();
+}
+
+/**
+ * master_footer:
+ *
+ * @doc: document to write footer to.
+ *
+ * Main footer which is displayed once.
+ **/
+void
+master_footer (pstring **doc)
+{
+ common_assert ();
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_CRUMB: /* FALL */
+ case OUTPUT_FORMAT_TEXT:
+ /* Tweak */
+ wappend (doc, L"\n");
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ object_close (false);
+
+ /* Tweak */
+ wappend (doc, L"\n");
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ /* Tweak */
+ wappend (doc, L"\n");
+ dec_indent ();
+ wappendf (doc, L"</%s>\n", PACKAGE_NAME);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+/**
+ * object_open:
+ *
+ * @retain: if true, do not disrupt the current element such that the
+ * opening of the object will be invisible to the state machine, but
+ * will still produce the required output.
+ *
+ * Note: @retain is only meaningful for OUTPUT_FORMAT_JSON.
+ *
+ * Handle opening an object.
+ **/
+void
+object_open (int retain)
+{
+ common_assert ();
+
+ if (output_format == OUTPUT_FORMAT_JSON) {
+ if (retain) {
+ format_element ();
+ } else {
+ change_element (ELEMENT_TYPE_OBJECT_OPEN);
+ }
+ } else {
+ /* Objects are only required for handling JSON. In
+ * fact, they cause problems for other output formats
+ * that do not have visible "objects" in that they cause
+ * the state table to lose track of the previous element
+ * since it is actually the previous-previous element
+ * (as the pointless object is the previous element).
+ *
+ * As such, ignore them.
+ */
+ }
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_CRUMB: /* FALL */
+ case OUTPUT_FORMAT_TEXT:
+ /* NOP */
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ wappend (&doc, L"{");
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ /* NOP */
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+/**
+ * object_close:
+ *
+ * @retain: if true, do not disrupt the current element such that the
+ * object closure will be invisible to the state machine, but will still
+ * produce @retain: if true, do not disrupt the current element.
+ *
+ * Note: @retain is only meaningful for OUTPUT_FORMAT_JSON.
+ *
+ * Handle closing an object.
+ **/
+void
+object_close (int retain)
+{
+ common_assert ();
+
+ if (output_format == OUTPUT_FORMAT_JSON) {
+ if (retain) {
+ format_element ();
+ } else {
+ change_element (ELEMENT_TYPE_OBJECT_CLOSE);
+ }
+ } else {
+ /* Objects are only required for handling JSON. In
+ * fact, they cause problems for other output formats
+ * that do not have visible "objects" in that they cause
+ * the state table to lose track of the previous element
+ * since it is actually the previous-previous element
+ * (as the pointless object is the previous element).
+ *
+ * As such, ignore them.
+ */
+ }
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_CRUMB: /* FALL */
+ case OUTPUT_FORMAT_TEXT:
+ /* NOP */
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ wappend (&doc, L"}");
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ /* NOP */
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+/**
+ * section_open:
+ *
+ * @name: name of section.
+ *
+ * Start a new section which will contain >0 entry() calls.
+ **/
+void
+section_open (const char *name)
+{
+ assert (name);
+ common_assert ();
+
+ change_element (ELEMENT_TYPE_SECTION_OPEN);
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_TEXT:
+ wappendf (&doc, L"%s:", name);
+ break;
+
+ case OUTPUT_FORMAT_CRUMB:
+ add_breadcrumb (name);
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ wappendf (&doc, L"\"%s\" : {", name);
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ wappendf (&doc, L"<section name=\"%s\">", name);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+void
+section_close (void)
+{
+ common_assert ();
+
+ change_element (ELEMENT_TYPE_SECTION_CLOSE);
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_TEXT:
+ /* NOP */
+ break;
+
+ case OUTPUT_FORMAT_CRUMB:
+ remove_breadcrumb ();
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ wappend (&doc, L"}");
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ wappend (&doc, L"</section>");
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+/**
+ * container_open:
+ *
+ * @name: name of container.
+ *
+ * Start a new container which will contain >0 entry() calls.
+ *
+ * This is primarily to handle JSON arrays.
+ **/
+void
+container_open (const char *name)
+{
+ assert (name);
+ common_assert ();
+
+ change_element (ELEMENT_TYPE_CONTAINER_OPEN);
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_TEXT:
+ wappendf (&doc, L"%s:", name);
+ break;
+
+ case OUTPUT_FORMAT_CRUMB:
+ add_breadcrumb (name);
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ wappendf (&doc, L"\"%s\" : [", name);
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ wappendf (&doc, L"<container name=\"%s\">", name);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+/**
+ * container_close:
+ *
+ * Finish with a container.
+ **/
+void
+container_close (void)
+{
+ common_assert ();
+
+ change_element (ELEMENT_TYPE_CONTAINER_CLOSE);
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_TEXT:
+ /* NOP */
+ break;
+
+ case OUTPUT_FORMAT_CRUMB:
+ remove_breadcrumb ();
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ wappend (&doc, L"]");
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ wappend (&doc, L"</container>");
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+/**
+ * _show:
+ *
+ * @prefix: string prefix to write,
+ * @indent: number of spaces to indent output to,
+ * @fmt: printf-style format with associated arguments that comprises
+ * the value part.
+ *
+ * Write output to @string, indented by @indent spaces. A trailing newline
+ * will be added.
+ *
+ * Note that error scenarios cannot call die() as by definition output
+ * may not be possible.
+ **/
+void
+_show (const char *prefix, int indent, const char *fmt, ...)
+{
+ va_list ap;
+ char *buffer = NULL;
+
+ assert (fmt);
+
+ if (indent)
+ appendf (&buffer, "%*s", indent, indent_char);
+
+ if (prefix && *prefix)
+ appendf (&buffer, "%s: ", prefix);
+
+ va_start (ap, fmt);
+ appendva (&buffer, fmt, ap);
+ va_end (ap);
+
+ append (&buffer, "\n");
+
+ _show_output (buffer);
+
+ free (buffer);
+}
+
+/**
+ * entry:
+ *
+ * @name: name of thing to display,
+ * @fmt: printf-style format with associated arguments that comprises
+ * the value part.
+ *
+ * Add name/value pair represented by @name and value comprising
+ * printf-format string to the @doc global. The value added will be
+ * indented appropriately.
+ **/
+void
+entry (const char *name, const char *fmt, ...)
+{
+ pstring *encoded_name = NULL;
+ pstring *encoded_value = NULL;
+ va_list ap;
+
+ assert (name);
+ assert (fmt);
+
+ common_assert ();
+
+ change_element (ELEMENT_TYPE_ENTRY);
+
+ encoded_name = char_to_pstring (name);
+ if (! encoded_name)
+ die ("failed to encode name");
+
+ /* annoyingly, we must encode here; we cannot simply call
+ * encode_string() once just prior to showing the output
+ * document since if the output format is XML, we'd end
+ * up encoding the XML tags themselves, not just the values
+ * within!
+ */
+ if (encode_string (&encoded_name) < 0)
+ die ("failed to encode name");
+
+ /* expand format */
+ va_start (ap, fmt);
+ wmappendva (&encoded_value, fmt, ap);
+ va_end (ap);
+
+ if (encode_string (&encoded_value) < 0)
+ die ("failed to encode value");
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_CRUMB:
+ assert (crumb_list);
+
+ /* Add the bread crumbs */
+ PR_LIST_FOREACH (crumb_list, iter) {
+ char *crumb = (char *)iter->data;
+ wappendf (&doc,
+ L"%s%s",
+ crumb,
+ crumb_separator);
+ }
+
+ wappendf (&doc,
+ L"%ls%s%ls\n",
+ encoded_name->buf,
+ text_separator,
+ encoded_value->buf);
+ break;
+
+ case OUTPUT_FORMAT_TEXT:
+ wappendf (&doc,
+ L"%ls%s%ls",
+ encoded_name->buf,
+ text_separator,
+ encoded_value->buf);
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ wappendf (&doc,
+ L"\"%ls\" : \"%ls\"",
+ encoded_name->buf,
+ encoded_value->buf);
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ wappendf (&doc,
+ L"<entry name=\"%ls\">%ls</entry>",
+ encoded_name->buf,
+ encoded_value->buf);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+
+ pstring_free (encoded_name);
+ pstring_free (encoded_value);
+}
+
+/**
+ * _show_output:
+ *
+ * @string: String to display.
+ *
+ * Write output @string to appropriate location based on Output
+ * destination.
+ **/
+void
+_show_output_pstring (const pstring *pstr)
+{
+ char *str;
+
+ assert (pstr);
+
+ str = pstring_to_char (pstr);
+
+ _show_output (str);
+
+ free (str);
+}
+
+void
+_show_output (const char *str)
+{
+ int ret;
+
+ assert (str);
+
+ switch (output) {
+ case OUTPUT_SYSLOG:
+ syslog (LOG_INFO, "%s", str);
+ ret = 0;
+ break;
+
+ case OUTPUT_STDOUT:
+ ret = fputs (str, stdout);
+ break;
+
+ case OUTPUT_STDERR:
+ ret = fputs (str, stderr);
+ break;
+
+ case OUTPUT_TERM:
+ assert (user.tty_fd != -1);
+ ret = write (user.tty_fd, str, strlen (str));
+ if (ret < 0) {
+ fprintf (stderr, "ERROR: failed to write to terminal: %s\n",
+ strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+ break;
+
+ case OUTPUT_FILE:
+ {
+ int flags = (O_WRONLY | O_CREAT);
+
+ if (output_file_append)
+ flags |= O_APPEND;
+
+ assert (output_file);
+ if (output_fd < 0) {
+ output_fd = open (output_file, flags,
+ (S_IRWXU|S_IRGRP|S_IROTH));
+ if (output_fd < 0) {
+ fprintf (stderr, "ERROR: failed to open file '%s': %s\n",
+ output_file, strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+ }
+ ret = write (output_fd, str, strlen (str));
+ if (ret < 0) {
+ fprintf (stderr, "ERROR: failed to write to file '%s': %s\n",
+ output_file, strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+ }
+ break;
+
+ default:
+ fprintf (stderr, "ERROR: invalid output type: %d\n", output);
+ exit (EXIT_FAILURE);
+ break;
+ }
+
+ if (ret < 0) {
+ fprintf (stderr, "ERROR: failed to output message\n");
+ exit (EXIT_FAILURE);
+ }
+}
+
+void
+set_indent_amount (int amount)
+{
+ indent_amount = amount;
+}
+
+int
+get_indent_amount (void)
+{
+ return indent_amount;
+}
+
+
+const char *
+get_text_separator (void)
+{
+ return text_separator;
+}
+
+void
+set_text_separator (const char *s)
+{
+ text_separator = s;
+}
+
+void
+set_indent_char (const char *c)
+{
+ if (! c)
+ return;
+
+ // FIXME: free on shutdown !
+ indent_char = strdup (c);
+}
+
+const char *
+get_indent_char (void)
+{
+ return indent_char;
+}
+
+void
+set_crumb_separator (const char *c)
+{
+ if (! c)
+ return;
+
+ crumb_separator = strdup (c);
+}
+
+void
+set_output_file (const char *f)
+{
+ if (! f)
+ return;
+
+ output_file = f;
+}
+
+void
+set_output_file_append (void)
+{
+ output_file_append = true;
+}
+
+const char *
+get_crumb_separator (void)
+{
+ return crumb_separator;
+}
+
+void
+reset_indent (void)
+{
+ indent = 0;
+}
+
+/**
+ * inc_indent:
+ *
+ * Increase indent.
+ **/
+void
+inc_indent (void)
+{
+ assert (indent >= 0);
+
+ indent += indent_amount;
+}
+
+/**
+ * dec_indent:
+ *
+ * Decrease indent.
+ **/
+void
+dec_indent (void)
+{
+ assert (indent >= 0);
+
+ indent -= indent_amount;
+
+ assert (indent >= 0);
+}
+
+/**
+ * add_indent:
+ *
+ * Insert the current indent to the output document.
+ **/
+void
+add_indent (pstring **doc)
+{
+ common_assert ();
+
+ if (! indent)
+ return;
+
+ if (! strcmp (indent_char, DEFAULT_INDENT_CHAR)) {
+ wappendf (doc, L"%*s", indent, indent_char);
+ } else {
+ pstring *buffer = NULL;
+
+ // Expand the buffer to the appropriate
+ // length by filling it with spaces and a random
+ // character.
+ wappendf (&buffer, L"%*lc", indent, wide_indent_char);
+
+
+ /* Now, replace the spaces and the random character with
+ * the chosen character. This convoluted approach is
+ * necessary as printf-type functions don't allow the
+ * padding character to be specified.
+ */
+ wmemset (buffer->buf, wide_indent_char, wcslen (buffer->buf));
+
+ pappend (doc, buffer);
+ pstring_free (buffer);
+ }
+}
+
+/**
+ * master_header:
+ *
+ * @doc: document to write footer to.
+ *
+ * Main header which is displayed once.
+ **/
+void
+master_header (pstring **doc)
+{
+ common_assert ();
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_CRUMB: /* FALL */
+ case OUTPUT_FORMAT_TEXT:
+ /* NOP */
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ object_open (false);
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ wappend (doc, L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ wappendf (doc, L"<%s version=\"%s\" package_string=\"%s\" "
+ "mode=\"%s%s\" format_version=\"%d\">\n",
+ PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_STRING,
+ user.euid ? _(NON_STR) "-" : "",
+ PRIVILEGED_STR,
+ PROCENV_FORMAT_VERSION);
+
+ inc_indent ();
+
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+void
+add_breadcrumb (const char *name)
+{
+ assert (name);
+
+ if (! crumb_list)
+ crumb_list = pr_list_new (NULL);
+
+ assert (crumb_list);
+
+ pr_list_prepend_str (crumb_list, name);
+}
+
+void
+remove_breadcrumb (void)
+{
+ PRList *entry;
+
+ assert (crumb_list);
+
+ entry = pr_list_remove (crumb_list->prev);
+ assert (entry);
+
+ free ((char *)entry->data);
+ free (entry);
+}
+
+static void
+clear_breadcrumbs (void)
+{
+ assert (crumb_list);
+
+ while (crumb_list->prev != crumb_list)
+ remove_breadcrumb ();
+}
+
+static void
+free_breadcrumbs (void)
+{
+ if (output_format == OUTPUT_FORMAT_CRUMB && crumb_list) {
+ clear_breadcrumbs ();
+ free (crumb_list);
+ }
+}
+
+/**
+ * change_element:
+ *
+ * Handle changing to a new element type. Depending on the output
+ * format, this may require separators and newlines to be emitted to
+ * produce well-formatted output.
+ **/
+void
+change_element (ElementType new)
+{
+ common_assert ();
+
+ last_element = current_element;
+
+ current_element = new;
+
+ format_element ();
+}
+
+void
+format_element (void)
+{
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_TEXT:
+ format_text_element ();
+ break;
+
+ case OUTPUT_FORMAT_CRUMB:
+ /* NOP */
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ format_json_element ();
+ break;
+
+ case OUTPUT_FORMAT_XML:
+ format_xml_element ();
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+void
+format_text_element (void)
+{
+ common_assert ();
+ switch (last_element) {
+
+ case ELEMENT_TYPE_ENTRY:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_SECTION_OPEN:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ /* NOP */
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ /* NOP */
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_NONE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+void
+format_json_element (void)
+{
+ common_assert ();
+
+ switch (last_element) {
+
+ case ELEMENT_TYPE_ENTRY:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L",\n");
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_SECTION_OPEN:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ case ELEMENT_TYPE_OBJECT_OPEN:
+ /* NOP */
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ assert_not_reached ();
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L",\n");
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_OPEN:
+ /* NOP */
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_OBJECT_OPEN:
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ assert_not_reached ();
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ /* NOP */
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L",\n");
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_OBJECT_OPEN:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN:
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ /* NOP */
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_OPEN:
+ case ELEMENT_TYPE_SECTION_OPEN:
+ wappend (&doc, L",\n");
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_NONE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+void
+format_xml_element (void)
+{
+ common_assert ();
+
+ switch (last_element) {
+
+ case ELEMENT_TYPE_ENTRY:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_SECTION_OPEN:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ assert_not_reached ();
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ assert_not_reached ();
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_OPEN:
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_OBJECT_OPEN:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN:
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_OPEN:
+ wappend (&doc, L"\n");
+ inc_indent ();
+ add_indent (&doc);
+ break;
+
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ /* NOP */
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_CLOSE:
+ /* NOP */
+ break;
+
+ case ELEMENT_TYPE_CONTAINER_CLOSE:
+ case ELEMENT_TYPE_ENTRY:
+ wappend (&doc, L"\n");
+ dec_indent ();
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ case ELEMENT_TYPE_NONE:
+ {
+ switch (current_element) {
+ case ELEMENT_TYPE_ENTRY: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
+ case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
+ case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
+ case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
+ case ELEMENT_TYPE_OBJECT_CLOSE:
+ add_indent (&doc);
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+ }
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+}
+
+void
+set_output_value (const char *name)
+{
+ struct procenv_map *p;
+
+ assert (name);
+
+ for (p = output_map; p && p->name; p++) {
+ if (! strcmp (name, p->name)) {
+ output = p->num;
+ return;
+ }
+ }
+ die ("invalid output value: '%s'", name);
+}
+
+void
+set_output_value_raw (Output o)
+{
+ output = o;
+}
+
+void
+set_output_format (const char *name)
+{
+ struct procenv_map *p;
+
+ assert (name);
+
+ for (p = output_format_map; p && p->name; p++) {
+ if (! strcmp (name, p->name)) {
+ output_format = p->num;
+ return;
+ }
+ }
+ die ("invalid output format value: '%s'", name);
+}
+
+const char *
+get_output_format_name (void)
+{
+ struct procenv_map *p;
+
+ for (p = output_format_map; p && p->name; p++) {
+ if (output_format == p->num)
+ return p->name;
+ }
+
+ bug ("invalid output format: %d", output_format);
+
+ /* compiler appeasement */
+ return NULL;
+}
+
+void
+handle_indent_char (void)
+{
+ size_t len;
+
+ const char *new = indent_char;
+
+ len = mbsrtowcs (NULL, &new, 0, NULL);
+ if (len != 1)
+ die ("invalid indent character");
+
+ if (mbsrtowcs (&wide_indent_char, &new, len, NULL) != len)
+ die ("failed to convert indent character");
+}
+
+void
+output_init (void)
+{
+ if (output == OUTPUT_SYSLOG)
+ openlog (PACKAGE_NAME, LOG_CONS | LOG_PID, LOG_USER);
+}
+
+void
+output_finalise (void)
+{
+ if (output_fd != -1)
+ close (output_fd);
+
+ free_breadcrumbs ();
+
+ if (output == OUTPUT_SYSLOG)
+ closelog ();
+}
+
+/* Performs simple substitution on the input */
+static pstring *
+output_translate (const pstring *pstr)
+{
+ pstring *result = NULL;
+ const wchar_t *start;
+ const wchar_t *p;
+ TranslateTable *table;
+ size_t i;
+ size_t len;
+ size_t extra;
+ size_t bytes;
+ size_t amount;
+ wchar_t from;
+
+ assert (pstr);
+ assert (output_format != OUTPUT_FORMAT_TEXT);
+ assert (output_format != OUTPUT_FORMAT_CRUMB);
+
+ /* Find the correct translation table for the chosen output format */
+ for (i = 0; i < sizeof (translate_table) / sizeof (translate_table[0]); i++) {
+ table = &translate_table[i];
+ if (table && table->output_format == output_format)
+ break;
+ }
+
+ if (! table)
+ return NULL;
+
+ len = pstr->len;
+ start = pstr->buf;
+
+ /* First, calculate the amount of space needed for the expanded
+ * buffer.
+ */
+ extra = 0;
+ while (start && *start) {
+ for (i = 0; i < TRANSLATE_MAP_ENTRIES; i++) {
+ from = table->map[i].from;
+ if (*start == from) {
+ /* Subtract one to take account of the
+ * pre-existing character we're going to
+ * replace.
+ */
+ extra += (wcslen (table->map[i].to) - 1);
+ }
+ }
+ start++;
+ }
+
+ if (! extra) {
+ /* No translation required.
+ *
+ * FIXME: this is inefficient - we should really have
+ * the function accept a 'pstring **' to avoid
+ * re-copying.
+ */
+ return pstring_create (pstr->buf);
+ }
+
+ len += extra;
+
+ result = pstring_new ();
+ if (! result)
+ return NULL;
+
+ /* Note that this includes the space for the terminator
+ * (since a pstring's len includes the terminator)
+ */
+ bytes = len * sizeof (wchar_t);
+
+ result->buf = malloc (bytes);
+ if (! result->buf) {
+ pstring_free (result);
+ return NULL;
+ }
+
+ /* We're using wcsncat() so we'd better make sure there is a
+ * nul for it to find!
+ *
+ * Note: we could have used calloc to do this for us, but
+ * the code is clearer using the @bytes idiom.
+ */
+ memset (result->buf, '\0', bytes);
+
+ result->size = bytes;
+
+ /* Sanity check for upcoming overrun check */
+ assert (result->buf[len-1] == L'\0');
+
+ /* Now, iterate the string again, performing the actual
+ * replacements.
+ */
+ p = start = pstr->buf;
+
+ while (p && *p) {
+ for (i = 0; i < TRANSLATE_MAP_ENTRIES; i++) {
+ wchar_t *to;
+ size_t len;
+
+ from = table->map[i].from;
+
+ if (*p != from)
+ continue;
+
+ to = table->map[i].to;
+
+ amount = p - start;
+
+ /* Copy from start to match */
+ wcsncat (result->buf + result->len, start, amount);
+
+ result->len += amount;
+
+ /* Copy replacement text */
+ len = wcslen (to);
+ wcsncat (result->buf + result->len, to, len);
+ result->len += len;
+
+ /* Jump over the matching character */
+ start = p + 1;
+
+ break;
+ }
+ p++;
+ }
+
+ /* Copy remaining non-matching chars */
+ amount = p - start;
+ wcsncat (result->buf + result->len, start, amount);
+ result->len += amount;
+
+ /* Account for terminator */
+ result->len += 1;
+
+ /* check for buffer overrun */
+ assert (result->buf[len-1] == L'\0');
+
+ return result;
+}
+
+/**
+ * encode_string:
+ *
+ * @str: string to encode.
+ *
+ * Returns: 0 on success, -1 on failure.
+ *
+ * Convert the specified string to its encoded form. If no encoding is
+ * necessary, the string will not be modified.
+ *
+ * Notes:
+ *
+ * - By encoding, we mean replacing literals with their
+ * format-langage-specific encodings. For example for XML output,
+ * '<' is converted to '&lt;'.
+ *
+ * - It is the callers responsibility to free @str iff this function
+ * is successful. any previous value of @str will be freed by
+ * encode_string().
+ *
+ * BUGS: this is just horribly, horribly gross :(
+ **/
+int
+encode_string (pstring **pstr)
+{
+ int ret = 0;
+ pstring *new = NULL;
+ wchar_t *p, *q;
+ size_t non_printables;
+ size_t len = 0;
+ size_t bytes;
+
+ assert (pstr);
+ assert (*pstr);
+
+ if ((*pstr)->len <= 1) {
+ /* Nothing to do */
+ return 0;
+ }
+
+ switch (output_format) {
+
+ case OUTPUT_FORMAT_CRUMB: /* FALL */
+ case OUTPUT_FORMAT_TEXT:
+ /* Nothing to do */
+ ret = 0;
+ break;
+
+ case OUTPUT_FORMAT_JSON: /* FALL THROUGH */
+ case OUTPUT_FORMAT_XML:
+ new = output_translate (*pstr);
+ if (new) {
+ pstring_free (*pstr);
+ *pstr = new;
+ new = NULL;
+ } else {
+ ret = -1;
+ }
+ break;
+
+ default:
+ assert_not_reached ();
+ break;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ /* Now, search for evil non-printable characters and encode those
+ * appropriately.
+ */
+ for (p = (*pstr)->buf, non_printables = 0; p && *p; p++) {
+ if (! iswprint (*p))
+ non_printables++;
+ }
+
+ if (non_printables &&
+ (output_format == OUTPUT_FORMAT_XML
+ || output_format == OUTPUT_FORMAT_JSON)) {
+
+ size_t new_size = 0;
+
+ wchar_t *json_format = L"\\u%4.4x";
+
+ /* XXX:
+ *
+ * Although this format spec _may_ produce valid XML,
+ * the rules are arcane and some(?) control characters
+ * cannot be used within an XML document, hence the
+ * "may".
+ *
+ * Aside from simply discarding non-printable characters
+ * (thus distorting the output), we are left with
+ * attempting to produce some sort of encoded
+ * representation which may well choke a validating
+ * parser.
+ *
+ * Realistically, the problem is confined to handling
+ * control characters set in environment variables when
+ * attempting to output XML. This may occur if you run
+ * GNU Screen since it sets $TERMCAP which includes
+ * binary characters.
+ *
+ * FIXME:
+ *
+ * If you hit this issue, raise a bug so we can consider
+ * simply discarding all non-printables when attempting
+ * XML output.
+ */
+ wchar_t *xml_format = L"&#x%2.2x;";
+
+ len = (*pstr)->len;
+
+ /* Calculate expanded size of string by removing
+ * count of non-printable byte and adding back the
+ * number of bytes required to encode them in expanded
+ * form.
+ */
+ switch (output_format) {
+ case OUTPUT_FORMAT_XML:
+ new_size = (len - non_printables) + (non_printables * wcslen (L"&#x..;"));
+ break;
+
+ case OUTPUT_FORMAT_JSON:
+ new_size = (len - non_printables) + (non_printables * wcslen (L"\\u...."));
+ break;
+ default:
+ break;
+ }
+
+ new = pstring_new ();
+ if (! new)
+ return -1;
+
+ bytes = (1 + new_size) * sizeof (wchar_t);
+
+ new->buf = malloc (bytes);
+ if (! new->buf) {
+ free (new);
+ return -1;
+ }
+
+ new->size = bytes;
+
+ memset (new->buf, '\0', bytes);
+
+ for (p = (*pstr)->buf, q = new->buf; p && *p; p++) {
+ if (iswprint (*p)) {
+ *q = *p;
+ q++;
+ new->len++;
+ } else {
+ ret = swprintf (q,
+ new_size,
+ output_format == OUTPUT_FORMAT_JSON
+ ? json_format : xml_format,
+ *p);
+ q += ret;
+ }
+ }
+
+ /* include terminator */
+ new->len = wcslen (new->buf) + 1;
+
+ pstring_free (*pstr);
+ *pstr = new;
+ }
+
+ return ret;
+}
diff --git a/src/output.h b/src/output.h
new file mode 100644
index 0000000..94f8229
--- /dev/null
+++ b/src/output.h
@@ -0,0 +1,179 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_OUTPUT_H
+#define _PROCENV_OUTPUT_H
+
+#include "types.h"
+#include "pstring.h"
+
+#define show(...) _show ("", get_indent_amount (), __VA_ARGS__)
+
+/**
+ * showi:
+ *
+ * @_indent: additional indent amount,
+ * @fmt: printf-style format and optional arguments.
+ *
+ * Write indented message to appropriate output location.
+ **/
+#define showi(_indent, ...) \
+ _show ("", get_indent_amount() + _indent, __VA_ARGS__)
+
+/**
+ * _message:
+ * @prefix: Fixed message prefix,
+ * @fmt: printf-style format and optional arguments.
+ *
+ * Write unindented message to appropriate output location.
+ **/
+#define _message(prefix, ...) _show (prefix, 0, __VA_ARGS__)
+
+#define warn(...) \
+{ \
+ _message ("WARNING", __VA_ARGS__); \
+}
+
+#ifdef DEBUG
+/* for when running under GDB */
+#define die_finalise() raise (SIGUSR1)
+#else
+#define die_finalise() exit (EXIT_FAILURE)
+#endif
+
+#define bug(...) \
+{ \
+ _show ("BUG", 0, __VA_ARGS__); \
+ exit (EXIT_FAILURE); \
+}
+
+#define POINTER_SIZE (sizeof (void *))
+
+#define die(...) \
+{ \
+ output = OUTPUT_STDERR; \
+ _message ("ERROR", __VA_ARGS__); \
+ cleanup (); \
+ die_finalise (); \
+}
+
+#define common_assert() \
+ assert (doc); \
+ assert (get_indent_amount() >= 0)
+
+#define assert_not_reached() \
+ do { \
+ die ("%s:%d: Not reached assertion failed in %s", \
+ __FILE__, __LINE__, __func__); \
+ } while (0)
+
+typedef enum procenv_output {
+ OUTPUT_FILE,
+ OUTPUT_STDERR,
+ OUTPUT_STDOUT,
+ OUTPUT_SYSLOG,
+ OUTPUT_TERM
+} Output;
+
+typedef enum {
+ OUTPUT_FORMAT_TEXT,
+ OUTPUT_FORMAT_CRUMB,
+ OUTPUT_FORMAT_JSON,
+ OUTPUT_FORMAT_XML
+} OutputFormat;
+
+typedef enum element_type {
+ ELEMENT_TYPE_ENTRY,
+ ELEMENT_TYPE_SECTION_OPEN,
+ ELEMENT_TYPE_SECTION_CLOSE,
+ ELEMENT_TYPE_CONTAINER_OPEN,
+ ELEMENT_TYPE_CONTAINER_CLOSE,
+ ELEMENT_TYPE_OBJECT_OPEN,
+ ELEMENT_TYPE_OBJECT_CLOSE,
+ ELEMENT_TYPE_NONE = -1
+} ElementType;
+
+/********************************************************************/
+
+extern Output output;
+extern OutputFormat output_format;
+extern wchar_t wide_indent_char;
+
+void cleanup (void);
+
+/********************************************************************/
+
+void output_init (void);
+void output_finalise (void);
+
+void header (const char *name);
+void footer (void);
+
+void master_header (pstring **doc);
+void master_footer (pstring **doc);
+
+void object_open (int retain);
+void object_close (int retain);
+
+void section_open (const char *name);
+void section_close (void);
+
+void container_open (const char *name);
+void container_close (void);
+
+void entry (const char *name, const char *fmt, ...);
+void _show (const char *prefix, int indent, const char *fmt, ...);
+void _show_output (const char *str);
+void _show_output_pstring (const pstring *pstr);
+
+void inc_indent (void);
+void dec_indent (void);
+void reset_indent (void);
+void add_indent (pstring **doc);
+
+void set_indent_amount (int amount);
+int get_indent_amount (void);
+const char *get_indent_char (void);
+
+void set_indent_char (const char *c);
+void handle_indent_char (void);
+
+void add_breadcrumb (const char *name);
+void remove_breadcrumb (void);
+void set_crumb_separator (const char *c);
+const char *get_crumb_separator (void);
+
+void set_output_file (const char *f);
+void set_output_file_append (void);
+
+void change_element (ElementType new);
+void format_element (void);
+
+void format_text_element (void);
+void format_json_element (void);
+void format_xml_element (void);
+
+void set_output_value (const char *name);
+void set_output_value_raw (Output o);
+void set_output_format (const char *name);
+const char *get_output_format_name (void);
+
+const char *get_text_separator (void);
+void set_text_separator (const char *s);
+
+#endif /* _PROCENV_OUTPUT_H */
diff --git a/src/platform-headers.h b/src/platform-headers.h
new file mode 100644
index 0000000..dc3a4ba
--- /dev/null
+++ b/src/platform-headers.h
@@ -0,0 +1,286 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+/*--------------------------------------------------------------------
+ * Description: This file contains platform-specific system includes
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_HEADERS_H
+#define _PROCENV_PLATFORM_HEADERS_H
+
+/*------------------------------------------------------------------*/
+
+#if defined (PROCENV_PLATFORM_DARWIN)
+
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/statvfs.h>
+#include <sys/ucred.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <mach/clock.h>
+#include <mach/mach.h>
+#include <sys/sysctl.h>
+
+#define PROCENV_LINK_LEVEL_FAMILY AF_LINK
+#define PROCENV_CPU_TYPE int
+
+/* XXX: fake value as cpu set are not available on darwin */
+#define PROCENV_CPU_SET_TYPE void
+
+#define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flags
+#define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsid.val
+
+#define PROCENV_STATFS_INT_TYPE uint64_t
+#define PROCENV_STATFS_INT_FMT PRIu64
+
+typedef struct statfs procenv_mnt_type;
+
+#endif /* PROCENV_PLATFORM_DARWIN*/
+
+/*------------------------------------------------------------------*/
+
+/* XXX: for now, let's assume "unknown" is similar to Linux :-) */
+#if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_GENERIC)
+
+#include <sys/statvfs.h>
+#include <sys/vfs.h>
+#include <mntent.h>
+#include <sched.h>
+#include <link.h>
+
+#include <linux/if.h>
+
+#include <sys/inotify.h>
+#include <sys/prctl.h>
+#include <sys/personality.h>
+#include <sys/syscall.h>
+
+#ifndef _SYS_PRCTL_H
+#include <linux/prctl.h>
+#endif
+
+#include <linux/version.h>
+
+/* Lucid provides prctl.h, but not securebits.h */
+#if defined (PR_GET_SECUREBITS) && defined (HAVE_LINUX_SECUREBITS_H)
+#include <linux/securebits.h>
+#endif
+
+#include <linux/capability.h>
+#include <linux/vt.h>
+
+#if defined (HAVE_SYS_APPARMOR_H)
+#include <sys/apparmor.h>
+#endif
+
+#if defined (HAVE_SELINUX_SELINUX_H)
+#include <selinux/selinux.h>
+#endif
+
+#if defined (HAVE_SYS_CAPABILITY_H)
+#include <sys/capability.h>
+#endif
+
+#if defined (__GLIBC__)
+#include <sys/sysmacros.h>
+#endif
+
+/* Network family for entries containing link-level interface
+ * details. These entries will be cached to allow MAC addresses
+ * to be extracted from them when displaying the corresponding
+ * higher-level network family entries for the interface in
+ * question.
+ */
+#define PROCENV_LINK_LEVEL_FAMILY AF_PACKET
+#define PROCENV_PTHREAD_GUARD_SIZE_TYPE size_t
+#define PROCENV_PTHREAD_GUARD_SIZE_FMT "%lu"
+
+#define PROCENV_CPU_SET_TYPE cpu_set_t
+#define PROCENV_CPU_TYPE int
+
+#endif /* PROCENV_PLATFORM_LINUX || PROCENV_PLATFORM_GENERIC */
+
+/*------------------------------------------------------------------*/
+
+#if defined (PROCENV_PLATFORM_MINIX)
+
+#include <sched.h>
+#include <sys/mount.h>
+#include <sys/fstypes.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/statvfs.h>
+#include <sys/ucred.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <kvm.h>
+#include <link.h>
+
+#define PROCENV_LINK_LEVEL_FAMILY AF_LINK
+#define PROCENV_PTHREAD_GUARD_SIZE_TYPE int
+#define PROCENV_PTHREAD_GUARD_SIZE_FMT "%u"
+#define PROCENV_CPU_TYPE cpuid_t
+#define PROCENV_CPU_SET_TYPE cpuset_t
+#define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flag
+#define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsidx.__fsid_val
+
+#define PROCENV_STATFS_INT_TYPE uint64_t
+#define PROCENV_STATFS_INT_FMT PRIu64
+
+typedef struct statvfs procenv_mnt_type;
+
+#endif /* PROCENV_PLATFORM_MINIX */
+
+/*------------------------------------------------------------------*/
+
+#if defined (PROCENV_PLATFORM_FREEBSD)
+
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/statvfs.h>
+#include <sys/ucred.h>
+#include <sys/consio.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <kvm.h>
+#include <pthread_np.h>
+#include <link.h>
+
+#define PROCENV_LINK_LEVEL_FAMILY AF_LINK
+#define PROCENV_CPU_TYPE int
+#define PROCENV_CPU_SET_TYPE cpuset_t
+#define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flags
+#define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsid.val
+
+#define PROCENV_STATFS_INT_TYPE uint64_t
+#define PROCENV_STATFS_INT_FMT PRIu64
+
+typedef struct statfs procenv_mnt_type;
+
+#endif /* PROCENV_PLATFORM_FREEBSD*/
+
+/*------------------------------------------------------------------*/
+
+#if defined (PROCENV_PLATFORM_NETBSD)
+
+/* Required to access "struct kinfo_proc" (from sys/sysctl.h) */
+#ifndef _KMEMUSER
+#define _KMEMUSER
+#endif
+
+#include <sched.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/statvfs.h>
+#include <sys/ucred.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <kvm.h>
+#include <dev/wscons/wsdisplay_usl_io.h>
+#include <link.h>
+
+#define PROCENV_LINK_LEVEL_FAMILY AF_LINK
+#define PROCENV_CPU_TYPE cpuid_t
+#define PROCENV_CPU_SET_TYPE cpuset_t
+#define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flag
+#define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsidx.__fsid_val
+
+#define PROCENV_STATFS_INT_TYPE uint64_t
+#define PROCENV_STATFS_INT_FMT PRIu64
+
+typedef struct statvfs procenv_mnt_type;
+
+#endif /* PROCENV_PLATFORM_NETBSD */
+
+/*------------------------------------------------------------------*/
+
+#if defined (PROCENV_PLATFORM_OPENBSD)
+
+#include <sched.h>
+#include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+
+#include <sys/statvfs.h>
+#include <sys/ucred.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <kvm.h>
+#include <dev/wscons/wsdisplay_usl_io.h>
+#include <link.h>
+
+#define PROCENV_LINK_LEVEL_FAMILY AF_LINK
+#define PROCENV_CPU_TYPE cpuid_t
+#define PROCENV_CPU_SET_TYPE struct cpuset
+#define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flags
+#define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsid.val
+
+#define PROCENV_STATFS_INT_TYPE uint64_t
+#define PROCENV_STATFS_INT_FMT PRIu64
+
+typedef struct statfs procenv_mnt_type;
+
+#endif /* PROCENV_PLATFORM_OPENBSD */
+
+/*------------------------------------------------------------------*/
+
+#if defined (PROCENV_PLATFORM_HURD)
+
+#include <mntent.h>
+#include <sys/vfs.h>
+#include <sys/statvfs.h>
+#include <net/if.h>
+#include <link.h>
+
+#if defined (HAVE_SYS_CAPABILITY_H)
+#include <sys/capability.h>
+#endif
+
+#define PROCENV_CPU_TYPE int
+#define PROCENV_CPU_SET_TYPE cpu_set_t
+
+#endif /* PROCENV_PLATFORM_HURD */
+
+/*------------------------------------------------------------------*/
+
+#if defined (PROCENV_PLATFORM_GENERIC)
+
+/* XXX: see above */
+
+#endif /* PROCENV_PLATFORM_GENERIC */
+
+/*------------------------------------------------------------------*/
+
+#endif /* _PROCENV_PLATFORM_HEADERS_H */
+
+/*------------------------------------------------------------------*/
diff --git a/src/platform.h b/src/platform.h
new file mode 100644
index 0000000..4be6cd7
--- /dev/null
+++ b/src/platform.h
@@ -0,0 +1,171 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_H
+#define _PROCENV_PLATFORM_H
+
+#include <stdio.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <pwd.h>
+
+#ifndef PATH_MAX
+/* Hurd. Grrrr.... */
+#define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+#define PROCENV_SET_DRIVER(_name) \
+ { .name = #_name, .file = __FILE__, }
+
+#if defined (PROCENV_PLATFORM_FREEBSD)
+#include <sys/user.h>
+#define PROCENV_PR_GET_NAME_LEN (COMMLEN+1)
+#else
+#define PROCENV_PR_GET_NAME_LEN 16
+#endif
+
+extern struct procenv_user user;
+extern struct procenv_misc misc;
+extern struct procenv_priority priority_io;
+extern struct utsname uts;
+
+typedef enum {
+ SHOW_ALL,
+ SHOW_MOUNTS,
+ SHOW_PATHCONF
+} ShowMountType;
+
+#include <procenv.h>
+#include "platform-generic.h"
+#include "platform-headers.h"
+
+struct procenv_priority {
+ int process;
+ int pgrp;
+ int user;
+};
+
+struct procenv_user {
+ pid_t pid;
+ pid_t ppid;
+ pid_t sid;
+
+ char proc_name[PROCENV_PR_GET_NAME_LEN];
+
+ pid_t pgroup;
+ pid_t fg_pgroup;
+ char ctrl_terminal[L_ctermid];
+ int tty_fd;
+
+ uid_t uid;
+ uid_t euid;
+ uid_t suid;
+
+ char *login;
+
+ gid_t gid;
+ gid_t egid;
+ gid_t sgid;
+
+ struct passwd passwd;
+};
+
+struct procenv_misc {
+ char cwd[PATH_MAX];
+ char root[PATH_MAX];
+ mode_t umask_value;
+ int cpu;
+#if defined (PROCENV_PLATFORM_FREEBSD)
+ int in_jail;
+#endif
+};
+
+struct procenv_driver
+{
+ const char *name;
+ const char *file;
+};
+
+/*
+ * - get_*() functions obtain information.
+ * - show_*() functions display entries for a particular category of
+ * information.
+ * - handle_*() fuctions are similar to show_*() ones, except that they
+ * also emit the appropriate heading/section/container entries and
+ * corresponding footers.
+ */
+struct procenv_ops
+{
+ struct procenv_driver driver;
+
+ void (*init) (void);
+ void (*cleanup) (void);
+
+ const struct procenv_map *signal_map;
+ const struct procenv_map *if_flag_map;
+ const struct procenv_map *personality_map;
+ const struct procenv_map *personality_flag_map;
+
+ void (*get_user_misc) (struct procenv_user *user,
+ struct procenv_misc *misc);
+
+ void (*get_proc_name) (struct procenv_user *user);
+
+ void (*get_io_priorities) (struct procenv_priority *iop);
+ void (*get_tty_locked_status) (struct termios *lock_status);
+
+ long (*get_kernel_bits) (void);
+ int (*get_mtu) (const struct ifaddrs *ifaddr);
+ bool (*get_time) (struct timespec *ts);
+
+ void (*show_capabilities) (void);
+ void (*show_cgroups) (void);
+ void (*show_clocks) (void);
+ void (*show_confstrs) (void);
+ void (*show_cpu_affinities) (void);
+ void (*show_cpu) (void);
+ void (*show_extended_if_flags) (const char *interface,
+ unsigned short *flags);
+ void (*show_fd_capabilities) (int fd);
+ void (*show_fds) (void);
+ void (*show_io_priorities) (void);
+ void (*show_mounts) (ShowMountType what);
+ void (*show_msg_queues) (void);
+ void (*show_namespaces) (void);
+ void (*show_oom) (void);
+ void (*show_prctl) (void);
+ void (*show_rlimits) (void);
+ void (*show_security_module) (void);
+ void (*show_semaphores) (void);
+ void (*show_shared_mem) (void);
+ void (*show_timezone) (void);
+
+ void (*handle_numa_memory) (void);
+ void (*handle_proc_branch) (void);
+ void (*handle_scheduler_type) (void);
+
+ PROCENV_CPU_SET_TYPE *(*get_cpuset) (void);
+ void (*free_cpuset) (PROCENV_CPU_SET_TYPE *cs);
+ bool (*cpuset_has_cpu) (const PROCENV_CPU_SET_TYPE *cs,
+ PROCENV_CPU_TYPE cpu);
+
+ bool (*in_vm) (void);
+};
+
+#endif /* _PROCENV_PLATFORM_H */
diff --git a/src/platform/README.rst b/src/platform/README.rst
new file mode 100644
index 0000000..2470c92
--- /dev/null
+++ b/src/platform/README.rst
@@ -0,0 +1,79 @@
+===============
+procenv drivers
+===============
+
+.. contents::
+.. sectnum::
+
+Overview
+--------
+
+``procenv`` now supports platform drivers. These are simply translation
+units that are compiled only for a particular platform. They were
+introduced to combat the "``#ifdef`` hell" of previous releases.
+
+Build Stategy
+-------------
+
+``configure.ac``
+~~~~~~~~~~~~~~~~
+
+Used to identify the platform the build is run on, exporting
+"``PROCENV_PLATFORM_<name>``" and ``$procenv_platform"`` to
+"``src/Makefile.am``".
+
+``src/Makefile.am``
+~~~~~~~~~~~~~~~~~~~
+
+- Defines "``PROCENV_PLATFORM_<name>``" as a symbol to the compiler.
+
+- Adds platform driver (platform-specific) source files to the list of
+ files to be built.
+
+To simplify the include policy, all platform-specific headers are added
+to the appropriate section in ``platform-headers.h``.
+
+Additionally, one other object get built on *all* platforms:
+
+- ``platform-generic``
+
+ Provides generic Unix/Linux implementations of particular methods.
+
+Drivers are free to reference the functions from this translation unit.
+See below for details.
+
+The build uses some magic options so that although all possible
+implementations get built, *only those symbols actually referenced
+become part of the final binary* (meaning you don't end up with lots of
+generic functions linked into your binary if your driver doesn't use them :-)
+
+Implementing a new driver
+-------------------------
+
+- ``configure.ac``:
+ - Update the ``$target_to_consider`` case logic for your platform.
+ - Add an ``AM_CONDITIONAL(PROCENV_PLATFORM_*, ...)``.
+
+- Create ``src/platform/${platform}/platform.c`` with an implementation of
+ the global "``struct procenv_ops platform_ops``".
+
+ For each ``struct procenv_ops`` function pointer,
+
+ - If it doesn't make sense to define a particular function for the
+ platform, simply omit specifying a function pointer.
+
+ (Note that you could set the function pointer to ``NULL``, but that
+ isn't necessary given that the ``platform_ops`` symbol is global, and
+ thus effectively all pointers not specified are already implicitly set
+ to ``NULL``).
+
+ - If one of the generic implementations is suitable, set the function
+ pointer to the corresponding ``*_generic()`` function in
+ ``platform-generic.c``.
+
+ - If neither of the above options is suitable, define a static
+ implementation in your ``platform.c`` (with the function name
+ ``*_<platform>``) file and set the corresponding function pointer to
+ that function.
+
+- Create ``src/platform/${platform}/platform-${platform}.h``.
diff --git a/src/platform/android/platform.c b/src/platform/android/platform.c
new file mode 100644
index 0000000..745fef0
--- /dev/null
+++ b/src/platform/android/platform.c
@@ -0,0 +1,48 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform.h"
+
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (android),
+
+ // FIXME
+#if 0
+ .init = NULL,
+ .signal_map = &signal_map_linux,
+ .get_time = get_time_generic,
+
+ .show_clocks = show_clocks_generic,
+ .show_fds = show_fds_linux,
+ .show_namespaces = show_namespaces_linux,
+ .show_cgroups = show_cgroups_linux,
+ .show_oom = show_oom_linux,
+ .show_timezone = show_timezone_linux,
+ .show_capabilities = show_capabilities_linux,
+ .show_security_module = show_security_module_linux,
+ .show_security_module_context = show_security_module_context_linux,
+ .show_prctl = show_prctl_linux,
+ .show_cpu = show_cpu_linux,
+ .show_proc_branch = show_proc_branch_linux,
+ .show_shared_mem = show_shared_mem_linux,
+ .show_semaphores = show_semaphores_linux,
+ .show_msg_queues = show_msg_queues_linux,
+ .show_io_priorities = show_io_priorities_linux,
+#endif
+};
diff --git a/src/platform/darwin/platform-darwin.h b/src/platform/darwin/platform-darwin.h
new file mode 100644
index 0000000..8ce7c98
--- /dev/null
+++ b/src/platform/darwin/platform-darwin.h
@@ -0,0 +1,27 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_DARWIN_H
+#define _PROCENV_PLATFORM_DARWIN_H
+
+#include "platform.h"
+#include "util.h"
+
+#define mib_len(mib) ((sizeof (mib) / sizeof(*mib)) - 1)
+
+#endif /* _PROCENV_PLATFORM_DARWIN_H */
diff --git a/src/platform/darwin/platform.c b/src/platform/darwin/platform.c
new file mode 100644
index 0000000..4a2ed70
--- /dev/null
+++ b/src/platform/darwin/platform.c
@@ -0,0 +1,276 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-darwin.h"
+
+static struct procenv_map signal_map_darwin[] = {
+
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+ mk_map_entry (SIGCONT),
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+ mk_map_entry (SIGINT),
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGTTOU),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+ mk_map_entry (SIGIOT),
+ mk_map_entry (SIGPROF),
+ mk_map_entry (SIGSYS),
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGVTALRM),
+
+#if defined (SIGIO)
+ mk_map_entry (SIGIO),
+#endif
+
+#if defined (SIGWINCH)
+ mk_map_entry (SIGWINCH),
+#endif
+
+#if defined (SIGINFO)
+ mk_map_entry (SIGINFO),
+#endif
+
+#if defined (SIGPOLL)
+ { SIGPOLL, "SIGPOLL|SIGEMT" },
+#elif defined (SIGEMT)
+ { SIGEMT, "SIGPOLL|SIGEMT" },
+#endif
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+ { SIGABRT, "SIGABRT|SIGIOT" },
+
+ { 0, NULL },
+};
+
+static struct procenv_map64 mntopt_map_darwin[] = {
+
+ { MNT_ASYNC , "asynchronous" },
+ { MNT_EXPORTED , "NFS-exported" },
+ { MNT_LOCAL , "local" },
+ { MNT_MULTILABEL , "multilabel" },
+ { MNT_NOATIME , "noatime" },
+ { MNT_NOEXEC , "noexec" },
+ { MNT_NOSUID , "nosuid" },
+ { MNT_QUOTA , "with quotas" },
+ { MNT_RDONLY , "read-only" },
+ { MNT_SYNCHRONOUS , "synchronous" },
+ { MNT_UNION , "union" },
+
+ { 0, NULL }
+};
+
+static struct procenv_map if_flag_map_darwin[] = {
+ mk_map_entry (IFF_UP),
+ mk_map_entry (IFF_BROADCAST),
+ mk_map_entry (IFF_DEBUG),
+ mk_map_entry (IFF_LOOPBACK),
+ mk_map_entry (IFF_POINTOPOINT),
+ mk_map_entry (IFF_RUNNING),
+ mk_map_entry (IFF_NOARP),
+ mk_map_entry (IFF_PROMISC),
+ mk_map_entry (IFF_ALLMULTI),
+ mk_map_entry (IFF_SIMPLEX),
+ mk_map_entry (IFF_MULTICAST),
+
+ { 0, NULL }
+};
+
+static void
+show_cpu_darwin (void)
+{
+ long max;
+
+ max = get_sysconf (_SC_NPROCESSORS_ONLN);
+
+ /* XXX: possible to determine current cpu? */
+ entry ("number", "%s of %lu", UNKNOWN_STR, max);
+}
+
+static bool
+get_time_darwin (struct timespec *ts)
+{
+ clock_serv_t cs;
+ mach_timespec_t mts;
+
+ // FIXME: can this fail?
+ host_get_clock_service (mach_host_self(), CALENDAR_CLOCK, &cs);
+
+ // FIXME: can this fail?
+ clock_get_time (cs, &mts);
+
+ // FIXME: can this fail?
+ mach_port_deallocate (mach_task_self(), cs);
+
+ ts->tv_sec = mts.tv_sec;
+ ts->tv_nsec = mts.tv_nsec;
+
+ return 0;
+}
+
+static void
+handle_proc_branch_darwin (void)
+{
+ struct kinfo_proc *procs = NULL;
+ struct kinfo_proc *p;
+ static const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
+ int ret;
+ int done = false;
+ size_t bytes;
+ size_t count;
+ size_t i;
+ pid_t current;
+ pid_t ultimate_parent = 0;
+ char *str = NULL;
+
+ /* arbitrary */
+ int attempts = 20;
+
+ current = getpid ();
+
+ /* XXX: This system interface seems horribly racy - what if the numbe of pids
+ * XXX: changes between the 1st and 2nd call to sysctl() ???
+ */
+ while (! done) {
+ attempts--;
+ if (! attempts)
+ return;
+
+ /* determine how much space required to store details of all
+ * processes.
+ */
+ ret = sysctl ((int *)mib, mib_len (mib), NULL, &bytes, NULL, 0);
+ if (ret < 0)
+ return;
+
+ count = bytes / sizeof (struct kinfo_proc);
+
+ /* allocate space */
+ procs = calloc (count, sizeof (struct kinfo_proc));
+ if (! procs)
+ return;
+
+ /* request the details of the processes */
+ ret = sysctl ((int *)mib, mib_len (mib), procs, &bytes, NULL, 0);
+ if (ret < 0) {
+ free (procs);
+ procs = NULL;
+ if (errno != ENOMEM) {
+ /* unknown error, so give up */
+ return;
+ }
+ } else {
+ done = true;
+ }
+ }
+
+ if (! done)
+ goto out;
+
+ /* reset */
+ done = false;
+
+ /* Calculate the lowest PID number which gives us the ultimate
+ * parent of all processes.
+ */
+ p = &procs[0];
+ ultimate_parent = p->kp_proc.p_pid;
+
+ for (i = 1; i < count; i++) {
+ p = &procs[i];
+ if (p->kp_proc.p_pid < ultimate_parent)
+ ultimate_parent = p->kp_proc.p_pid;
+ }
+
+ while (! done) {
+ for (i = 0; i < count && !done; i++) {
+ p = &procs[i];
+
+ if (p->kp_proc.p_pid == current) {
+
+ if (! ultimate_parent && current == ultimate_parent) {
+
+ /* Found the "last" PID so record it and hop out */
+ appendf (&str, "%d ('%s')",
+ (int)current, p->kp_proc.p_comm);
+
+ done = true;
+ break;
+ } else {
+ /* Found a valid parent pid */
+ appendf (&str, "%d ('%s'), ",
+ (int)current, p->kp_proc.p_comm);
+ }
+
+ /* Move on */
+ current = p->kp_eproc.e_ppid;
+ }
+ }
+ }
+
+ entry ("ancestry", "%s", str);
+
+out:
+ free_if_set (str);
+ free_if_set (procs);
+}
+
+
+static void
+show_mounts_darwin (ShowMountType what)
+{
+ show_mounts_generic_bsd (what, mntopt_map_darwin);
+}
+
+/* Darwin lacks:
+ *
+ * - cpusets and cpu affinities.
+ *
+ */
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (darwin),
+
+ .signal_map = signal_map_darwin,
+ .if_flag_map = if_flag_map_darwin,
+
+ .get_time = get_time_darwin,
+ .get_kernel_bits = get_kernel_bits_generic,
+ .get_mtu = get_mtu_generic,
+
+ .handle_proc_branch = handle_proc_branch_darwin,
+
+ .show_confstrs = show_confstrs_generic,
+ .show_cpu = show_cpu_darwin,
+ .show_fds = show_fds_generic,
+ .show_mounts = show_mounts_darwin,
+ .show_rlimits = show_rlimits_generic,
+};
diff --git a/src/platform/freebsd/platform-freebsd.h b/src/platform/freebsd/platform-freebsd.h
new file mode 100644
index 0000000..07cb5c3
--- /dev/null
+++ b/src/platform/freebsd/platform-freebsd.h
@@ -0,0 +1,43 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_FREEBSD_H
+#define _PROCENV_PLATFORM_FREEBSD_H
+
+#include "platform.h"
+#include "util.h"
+
+#if defined (HAVE_SYS_CAPABILITY_H)
+#include <sys/capability.h>
+
+#if __FreeBSD__ == 9
+
+/* FreeBSD 9 introduced optional capabilities. FreeBSD enabled them by
+ * default, changing some of the system calls in the process, so handle
+ * the name changes.
+ */
+#define cap_rights_get(fd, rightsp) cap_getrights (fd, (rightsp))
+#define cap_rights_is_set(rightsp, cap) ((*rightsp) & (cap))
+
+#endif /* __FreeBSD__ == 9 */
+
+#define show_capsicum_cap(rights, cap) \
+ entry (#cap, "%s", cap_rights_is_set ((&rights), cap) ? YES_STR : NO_STR)
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+#endif /* _PROCENV_PLATFORM_FREEBSD_H */
diff --git a/src/platform/freebsd/platform.c b/src/platform/freebsd/platform.c
new file mode 100644
index 0000000..927777d
--- /dev/null
+++ b/src/platform/freebsd/platform.c
@@ -0,0 +1,532 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-freebsd.h"
+
+static struct procenv_map signal_map_freebsd[] = {
+
+ mk_map_entry (SIGABRT),
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+
+ mk_map_entry (SIGCONT),
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+ mk_map_entry (SIGINT),
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGTTOU),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGIO),
+ mk_map_entry (SIGPROF),
+ mk_map_entry (SIGSYS),
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGVTALRM),
+ mk_map_entry (SIGWINCH),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+ mk_map_entry (SIGEMT),
+ mk_map_entry (SIGINFO),
+ mk_map_entry (SIGTHR),
+ mk_map_entry (SIGLIBRT),
+
+ { 0, NULL },
+};
+
+static struct procenv_map64 mntopt_map_freebsd[] = {
+
+ { MNT_ACLS , "acls" },
+ { MNT_ASYNC , "asynchronous" },
+ { MNT_EXPORTED , "NFS-exported" },
+ { MNT_GJOURNAL , "gjournal" },
+ { MNT_LOCAL , "local" },
+ { MNT_MULTILABEL , "multilabel" },
+ { MNT_NFS4ACLS , "nfsv4acls" },
+ { MNT_NOATIME , "noatime" },
+ { MNT_NOCLUSTERR , "noclusterr" },
+ { MNT_NOCLUSTERW , "noclusterw" },
+ { MNT_NOEXEC , "noexec" },
+ { MNT_NOSUID , "nosuid" },
+ { MNT_NOSYMFOLLOW , "nosymfollow" },
+ { MNT_QUOTA , "with quotas" },
+ { MNT_RDONLY , "read-only" },
+ { MNT_SOFTDEP , "soft-updates" },
+ { MNT_SUIDDIR , "suiddir" },
+#if defined (MNT_SUJ)
+ { MNT_SUJ , "journaled soft-updates" },
+#endif
+ { MNT_SYNCHRONOUS , "synchronous" },
+ { MNT_UNION , "union" },
+
+ { 0, NULL }
+};
+
+static struct procenv_map if_flag_map_freebsd[] = {
+ mk_map_entry (IFF_UP),
+ mk_map_entry (IFF_BROADCAST),
+ mk_map_entry (IFF_DEBUG),
+ mk_map_entry (IFF_LOOPBACK),
+ mk_map_entry (IFF_POINTOPOINT),
+ mk_map_entry (IFF_RUNNING),
+ mk_map_entry (IFF_NOARP),
+ mk_map_entry (IFF_PROMISC),
+ mk_map_entry (IFF_ALLMULTI),
+ mk_map_entry (IFF_SIMPLEX),
+ mk_map_entry (IFF_MULTICAST),
+
+ { 0, NULL }
+};
+
+static void
+get_user_misc_freebsd (struct procenv_user *user,
+ struct procenv_misc *misc)
+{
+ char errors[_POSIX2_LINE_MAX];
+ kvm_t *kvm;
+ struct kinfo_proc *proc;
+ int ignored;
+
+ assert (user);
+ assert (misc);
+
+ kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
+ if (! kvm)
+ die ("unable to open kvm");
+
+ proc = kvm_getprocs (kvm, KERN_PROC_PID, user->pid, &ignored);
+ if (! proc)
+ die ("failed to get process info");
+
+ misc->in_jail = (proc->ki_flag & P_JAILED) ? true : false;
+ strcpy (user->proc_name, proc->ki_comm);
+
+ if (kvm_close (kvm) < 0)
+ die ("failed to close kvm");
+}
+
+static void
+show_fd_capabilities_freebsd (int fd)
+{
+ int ret;
+ u_int mode;
+ cap_rights_t rights;
+
+ ret = cap_getmode (&mode);
+ if (ret < 0) {
+ /* No Capsicum support */
+ goto out;
+ }
+
+ ret = cap_rights_get (fd, &rights);
+ if (ret < 0) {
+ /* Cannot query capabilities */
+ goto out;
+ }
+
+ show_capsicum_cap (rights, CAP_ACCEPT);
+ show_capsicum_cap (rights, CAP_ACL_CHECK);
+ show_capsicum_cap (rights, CAP_ACL_DELETE);
+ show_capsicum_cap (rights, CAP_ACL_GET);
+ show_capsicum_cap (rights, CAP_ACL_SET);
+ show_capsicum_cap (rights, CAP_BIND);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_BINDAT);
+ show_capsicum_cap (rights, CAP_CHFLAGSAT);
+#endif
+ show_capsicum_cap (rights, CAP_CONNECT);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_CONNECTAT);
+#endif
+ show_capsicum_cap (rights, CAP_CREATE);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_EVENT);
+#endif
+ show_capsicum_cap (rights, CAP_EXTATTR_DELETE);
+ show_capsicum_cap (rights, CAP_EXTATTR_GET);
+ show_capsicum_cap (rights, CAP_EXTATTR_LIST);
+ show_capsicum_cap (rights, CAP_EXTATTR_SET);
+ show_capsicum_cap (rights, CAP_FCHDIR);
+ show_capsicum_cap (rights, CAP_FCHFLAGS);
+ show_capsicum_cap (rights, CAP_FCHMOD);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_FCHMODAT);
+#endif
+ show_capsicum_cap (rights, CAP_FCHOWN);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_FCHOWNAT);
+#endif
+ show_capsicum_cap (rights, CAP_FCNTL);
+ show_capsicum_cap (rights, CAP_FEXECVE);
+ show_capsicum_cap (rights, CAP_FLOCK);
+ show_capsicum_cap (rights, CAP_FPATHCONF);
+ show_capsicum_cap (rights, CAP_FSCK);
+ show_capsicum_cap (rights, CAP_FSTAT);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_FSTATAT);
+#endif
+ show_capsicum_cap (rights, CAP_FSTATFS);
+ show_capsicum_cap (rights, CAP_FSYNC);
+ show_capsicum_cap (rights, CAP_FTRUNCATE);
+ show_capsicum_cap (rights, CAP_FUTIMES);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_FUTIMESAT);
+#endif
+ show_capsicum_cap (rights, CAP_GETPEERNAME);
+ show_capsicum_cap (rights, CAP_GETSOCKNAME);
+ show_capsicum_cap (rights, CAP_GETSOCKOPT);
+ show_capsicum_cap (rights, CAP_IOCTL);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_KQUEUE);
+ show_capsicum_cap (rights, CAP_KQUEUE_CHANGE);
+ show_capsicum_cap (rights, CAP_KQUEUE_EVENT);
+#if defined (CAP_LINKAT)
+ show_capsicum_cap (rights, CAP_LINKAT);
+#endif
+#if defined (CAP_LINKAT_SOURCE)
+ show_capsicum_cap (rights, CAP_LINKAT_SOURCE);
+#endif
+#if defined (CAP_LINKAT_TARGET)
+ show_capsicum_cap (rights, CAP_LINKAT_TARGET);
+#endif
+
+#endif
+ show_capsicum_cap (rights, CAP_LISTEN);
+ show_capsicum_cap (rights, CAP_LOOKUP);
+ show_capsicum_cap (rights, CAP_MAC_GET);
+ show_capsicum_cap (rights, CAP_MAC_SET);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_MKDIRAT);
+ show_capsicum_cap (rights, CAP_MKFIFOAT);
+ show_capsicum_cap (rights, CAP_MKNODAT);
+ show_capsicum_cap (rights, CAP_MMAP);
+ show_capsicum_cap (rights, CAP_MMAP_R);
+ show_capsicum_cap (rights, CAP_MMAP_RW);
+ show_capsicum_cap (rights, CAP_MMAP_RWX);
+ show_capsicum_cap (rights, CAP_MMAP_RX);
+ show_capsicum_cap (rights, CAP_MMAP_W);
+ show_capsicum_cap (rights, CAP_MMAP_WX);
+ show_capsicum_cap (rights, CAP_MMAP_X);
+#endif
+ show_capsicum_cap (rights, CAP_PDGETPID);
+ show_capsicum_cap (rights, CAP_PDKILL);
+ show_capsicum_cap (rights, CAP_PDWAIT);
+ show_capsicum_cap (rights, CAP_PEELOFF);
+ show_capsicum_cap (rights, CAP_POLL_EVENT);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_PREAD);
+ show_capsicum_cap (rights, CAP_PWRITE);
+#endif
+ show_capsicum_cap (rights, CAP_READ);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_RECV);
+#if defined (CAP_RENAMEAT)
+ show_capsicum_cap (rights, CAP_RENAMEAT);
+#endif
+#if defined (CAP_RENAMEAT_SOURCE)
+ show_capsicum_cap (rights, CAP_RENAMEAT_SOURCE);
+#endif
+#if defined (CAP_RENAMEAT_TARGET)
+ show_capsicum_cap (rights, CAP_RENAMEAT_TARGET);
+#endif
+#endif
+ show_capsicum_cap (rights, CAP_SEEK);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_SEEK_TELL);
+#endif
+ show_capsicum_cap (rights, CAP_SEM_GETVALUE);
+ show_capsicum_cap (rights, CAP_SEM_POST);
+ show_capsicum_cap (rights, CAP_SEM_WAIT);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_SEND);
+#endif
+ show_capsicum_cap (rights, CAP_SETSOCKOPT);
+ show_capsicum_cap (rights, CAP_SHUTDOWN);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_SOCK_CLIENT);
+ show_capsicum_cap (rights, CAP_SOCK_SERVER);
+ show_capsicum_cap (rights, CAP_SYMLINKAT);
+#endif
+ show_capsicum_cap (rights, CAP_TTYHOOK);
+#if __FreeBSD__ > 9
+ show_capsicum_cap (rights, CAP_UNLINKAT);
+#endif
+ show_capsicum_cap (rights, CAP_WRITE);
+
+out:
+ /* clang requires this */
+ return;
+}
+
+static void
+show_mounts_freebsd (ShowMountType what)
+{
+ show_mounts_generic_bsd (what, mntopt_map_freebsd);
+}
+
+static void
+show_cpu_freebsd (void)
+{
+ long max;
+ kvm_t *kvm;
+ struct kinfo_proc *proc;
+ int ignored;
+ int cpu;
+ char errors[_POSIX2_LINE_MAX];
+
+ assert (user.pid > 0);
+
+ max = get_sysconf (_SC_NPROCESSORS_ONLN);
+
+ kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
+ if (! kvm)
+ die ("unable to open kvm");
+
+ proc = kvm_getprocs (kvm, KERN_PROC_PID, user.pid, &ignored);
+ if (! proc)
+ die ("failed to get process info");
+
+ /* cpu values are zero-based */
+ cpu = 1 + proc->ki_oncpu;
+
+ if (kvm_close (kvm) < 0)
+ die ("failed to close kvm");
+
+ entry ("number", "%u of %lu", cpu, max);
+}
+
+/* Who would have thought handling PIDs was so tricky? */
+static void
+handle_proc_branch_freebsd (void)
+{
+ int count = 0;
+ int i;
+ char errors[_POSIX2_LINE_MAX];
+ kvm_t *kvm;
+ struct kinfo_proc *procs;
+ struct kinfo_proc *p;
+ pid_t current;
+ int done = false;
+ char *str = NULL;
+ pid_t ultimate_parent = 0;
+
+ common_assert ();
+
+ current = getpid ();
+
+ kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
+ if (! kvm)
+ die ("unable to open kvm");
+
+ procs = kvm_getprocs (kvm, KERN_PROC_PROC, 0, &count);
+ if (! procs)
+ die ("failed to get process info");
+
+ /* Calculate the lowest PID number which gives us the ultimate
+ * parent of all processes.
+ *
+ * On FreeBSD systems, PID 0 ('[kernel]') is the ultimate
+ * parent rather than PID 1 ('init').
+ *
+ * However, this doesn't work in a FreeBSD jail since in that
+ * environment:
+ *
+ * - there is no init process visible.
+ * - there is no kernel thread visible.
+ * - the ultimate parent PID will either by 1 (the "invisible"
+ * init process) or 'n' where 'n' is a PID>1 which is also
+ * "invisible" (since it lives outside the jail in the host
+ * environment).
+ *
+ * Confused yet?
+ */
+
+ p = &procs[0];
+ ultimate_parent = p->ki_pid;
+
+ for (i = 1; i < count; i++) {
+ p = &procs[i];
+ if (p->ki_pid < ultimate_parent)
+ ultimate_parent = p->ki_pid;
+ }
+
+ while (! done) {
+ for (i = 0; i < count && !done; i++) {
+ p = &procs[i];
+
+ if (p->ki_pid == current) {
+ if (misc.in_jail) {
+ struct kinfo_proc *p2;
+ int ppid_found = false;
+ int j;
+
+ /* Determine if the parent PID
+ * actually exists within the
+ * jail.
+ */
+ for (j = 0; j < count; j++) {
+ p2 = &procs[j];
+
+ if (p2->ki_pid == p->ki_ppid) {
+ ppid_found = true;
+ break;
+ }
+ }
+
+ if (p->ki_ppid == 1 || (p->ki_ppid && ! ppid_found)) {
+ /* Found the "last" PID (whose parent is either
+ * the "invisible init" or which exists outside the jail)
+ * so record it and hop out.
+ */
+ appendf (&str, "%d ('%s') %d (%s)",
+ (int)current, p->ki_comm,
+ p->ki_ppid, UNKNOWN_STR);
+ done = true;
+ break;
+ } else {
+ /* Found a valid parent pid */
+ appendf (&str, "%d ('%s'), ",
+ (int)current, p->ki_comm);
+ }
+
+ } else if (! ultimate_parent && current == ultimate_parent) {
+
+ /* Found the "last" PID so record it and hop out */
+ appendf (&str, "%d ('%s')",
+ (int)current, p->ki_comm);
+ done = true;
+ break;
+ } else {
+ /* Found a valid parent pid */
+ appendf (&str, "%d ('%s'), ",
+ (int)current, p->ki_comm);
+ }
+
+ /* Move on */
+ current = p->ki_ppid;
+ }
+ }
+ }
+
+ if (kvm_close (kvm) < 0)
+ die ("failed to close kvm");
+
+ entry ("ancestry", "%s", str);
+ free (str);
+}
+
+static PROCENV_CPU_SET_TYPE *
+get_cpuset_freebsd (void)
+{
+ static PROCENV_CPU_SET_TYPE cpu_set_real;
+ PROCENV_CPU_SET_TYPE *cs = NULL;
+ size_t size;
+
+ CPU_ZERO (&cpu_set_real);
+ cs = &cpu_set_real;
+
+ size = sizeof (PROCENV_CPU_SET_TYPE);
+
+ if (pthread_getaffinity_np (pthread_self (), size, cs))
+ return NULL;
+
+ return cs;
+}
+
+static void
+free_cpuset_freebsd (PROCENV_CPU_SET_TYPE *cs)
+{
+ (void) cs;
+}
+
+static bool cpuset_has_cpu_freebsd (const PROCENV_CPU_SET_TYPE *cs,
+ PROCENV_CPU_TYPE cpu)
+{
+ return CPU_ISSET (cpu, cs);
+}
+
+static void
+show_clocks_freebsd (void)
+{
+ show_clock_res (CLOCK_REALTIME);
+
+#if defined CLOCK_REALTIME_COARSE
+ show_clock_res (CLOCK_REALTIME_COARSE);
+#endif
+
+#if defined CLOCK_REALTIME_HR
+ show_clock_res (CLOCK_REALTIME_HR);
+#endif
+
+ show_clock_res (CLOCK_REALTIME_PRECISE);
+ show_clock_res (CLOCK_REALTIME_FAST);
+ show_clock_res (CLOCK_MONOTONIC);
+
+#if defined CLOCK_MONOTONIC_COARSE
+ show_clock_res (CLOCK_MONOTONIC_COARSE);
+#endif
+
+#if defined CLOCK_MONOTONIC_RAW
+ show_clock_res (CLOCK_MONOTONIC_RAW);
+#endif
+
+ show_clock_res (CLOCK_MONOTONIC_PRECISE);
+ show_clock_res (CLOCK_MONOTONIC_FAST);
+ show_clock_res (CLOCK_UPTIME);
+ show_clock_res (CLOCK_UPTIME_PRECISE);
+ show_clock_res (CLOCK_UPTIME_FAST);
+ show_clock_res (CLOCK_VIRTUAL);
+ show_clock_res (CLOCK_PROF);
+}
+
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (freebsd),
+
+ .get_user_misc = get_user_misc_freebsd,
+ .get_kernel_bits = get_kernel_bits_generic,
+ .get_cpuset = get_cpuset_freebsd,
+ .get_mtu = get_mtu_generic,
+ .get_time = get_time_generic,
+ .free_cpuset = free_cpuset_freebsd,
+ .cpuset_has_cpu = cpuset_has_cpu_freebsd,
+
+ .signal_map = signal_map_freebsd,
+ .if_flag_map = if_flag_map_freebsd,
+
+ .show_confstrs = show_confstrs_generic,
+ .show_cpu = show_cpu_freebsd,
+ .show_clocks = show_clocks_freebsd,
+ .show_cpu_affinities = show_cpu_affinities_generic,
+ .show_fd_capabilities = show_fd_capabilities_freebsd,
+ .show_fds = show_fds_generic,
+ .show_mounts = show_mounts_freebsd,
+ .show_rlimits = show_rlimits_generic,
+
+ .handle_proc_branch = handle_proc_branch_freebsd,
+};
diff --git a/src/platform/hurd/platform-hurd.h b/src/platform/hurd/platform-hurd.h
new file mode 100644
index 0000000..62258be
--- /dev/null
+++ b/src/platform/hurd/platform-hurd.h
@@ -0,0 +1,38 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_HURD_H
+#define _PROCENV_PLATFORM_HURD_H
+
+#include "platform.h"
+#include "util.h"
+
+/* Seriously? */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+/* semctl(2) states that POSIX.1-2001 requires the caller define this! */
+union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short int *array;
+ struct seminfo *__buf;
+};
+
+#endif /* _PROCENV_PLATFORM_HURD_H */
diff --git a/src/platform/hurd/platform.c b/src/platform/hurd/platform.c
new file mode 100644
index 0000000..74874ed
--- /dev/null
+++ b/src/platform/hurd/platform.c
@@ -0,0 +1,93 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-hurd.h"
+
+static struct procenv_map signal_map_hurd[] = {
+
+ mk_map_entry (SIGABRT),
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+
+ mk_map_entry (SIGCONT),
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+ mk_map_entry (SIGINT),
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGTTOU),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGIO),
+ mk_map_entry (SIGPROF),
+ mk_map_entry (SIGSYS),
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGVTALRM),
+ mk_map_entry (SIGWINCH),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+ mk_map_entry (SIGEMT),
+ mk_map_entry (SIGINFO),
+ mk_map_entry (SIGLOST),
+
+ { 0, NULL },
+};
+
+static struct procenv_map if_flag_map_hurd[] = {
+ mk_map_entry (IFF_UP),
+ mk_map_entry (IFF_BROADCAST),
+ mk_map_entry (IFF_DEBUG),
+ mk_map_entry (IFF_LOOPBACK),
+ mk_map_entry (IFF_POINTOPOINT),
+ mk_map_entry (IFF_RUNNING),
+ mk_map_entry (IFF_NOARP),
+ mk_map_entry (IFF_PROMISC),
+ mk_map_entry (IFF_ALLMULTI),
+ mk_map_entry (IFF_MULTICAST),
+
+ { 0, NULL }
+};
+
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (hurd),
+
+ .get_kernel_bits = get_kernel_bits_generic,
+ .get_mtu = get_mtu_generic,
+ .get_time = get_time_generic,
+
+ .signal_map = signal_map_hurd,
+ .if_flag_map = if_flag_map_hurd,
+
+ .show_clocks = show_clocks_generic,
+ .show_confstrs = show_confstrs_generic,
+ .show_cpu_affinities = show_cpu_affinities_generic,
+ .show_fds = show_fds_generic,
+ .show_mounts = show_mounts_generic_linux,
+ .show_rlimits = show_rlimits_generic,
+};
diff --git a/src/platform/linux/platform-linux.h b/src/platform/linux/platform-linux.h
new file mode 100644
index 0000000..978daf1
--- /dev/null
+++ b/src/platform/linux/platform-linux.h
@@ -0,0 +1,174 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_LINUX_H
+#define _PROCENV_PLATFORM_LINUX_H
+
+/* required for sched_getcpu() (from sched.h) */
+#define _GNU_SOURCE
+
+#include "platform.h"
+#include "util.h"
+
+#define ROOT_PATH "/proc/self/root"
+
+#if defined (HAVE_NUMA_H)
+
+#include <numa.h>
+#include <numaif.h>
+
+#if LIBNUMA_API_VERSION == 2
+#define PROCENV_NUMA_BITMASK_ISSET(mask, node) numa_bitmask_isbitset ((mask), (node))
+#else
+#define PROCENV_NUMA_BITMASK_ISSET(mask, node) nodemask_isset (&(mask), (node))
+#endif
+#endif /* HAVE_NUMA_H */
+
+/**
+ * LINUX_KERNEL_M:
+ * @major: Linux major kernel version number.
+ *
+ * Returns: true if running Linux kernel is atleast at version
+ * specified by @major else false.
+ **/
+#define LINUX_KERNEL_M(major) \
+ (linux_kernel_version (major, -1, -1))
+
+/**
+ * LINUX_KERNEL_MM:
+ * @major: Linux major kernel version number,
+ * @minor: Linux minor kernel version number.
+ *
+ * Returns: true if running Linux kernel is atleast at version
+ * specified by (@major, @minor) else false.
+ **/
+#define LINUX_KERNEL_MM(major, minor) \
+ (linux_kernel_version (major, minor, -1))
+
+/**
+ * LINUX_KERNEL_MMR:
+ * @major: Linux major kernel version number,
+ * @minor: Linux minor kernel version number,
+ * @revision: kernel revision version.
+ *
+ * Returns: true if running Linux kernel is atleast at version
+ * specified by (@major, @minor, @revision) else false.
+ **/
+#define LINUX_KERNEL_MMR(major, minor, revision) \
+ (linux_kernel_version (major, minor, revision))
+
+/**
+ * show_capability:
+ * @caps: cap_t,
+ * @cap: capability.
+ *
+ * Display specified capability, or NOT_DEFINED_STR if value is
+ * unknown.
+ **/
+#ifdef PR_CAPBSET_READ
+#define show_capability(caps, cap) \
+ _show_capability (caps, cap, #cap)
+
+#define _show_capability(caps, cap, name) \
+{ \
+ int bound; \
+ int effective; \
+ int inheritable; \
+ int permitted; \
+ \
+ bound = cap_get_bound (cap); \
+ \
+ effective = get_capability_by_flag_type (caps, CAP_EFFECTIVE, cap); \
+ inheritable = get_capability_by_flag_type (caps, CAP_INHERITABLE, cap); \
+ permitted = get_capability_by_flag_type (caps, CAP_PERMITTED, cap); \
+ \
+ section_open (name); \
+ \
+ entry ("number", "%d", cap); \
+ \
+ entry ("supported", "%s", \
+ CAP_IS_SUPPORTED (cap) \
+ ? YES_STR : NO_STR); \
+ \
+ entry ("in bounding set", "%s", \
+ bound < 0 \
+ ? UNKNOWN_STR \
+ : bound \
+ ? YES_STR \
+ : NO_STR); \
+ \
+ entry ("effective", "%s", \
+ effective < 0 \
+ ? NOT_DEFINED_STR \
+ : effective == CAP_SET \
+ ? YES_STR \
+ : NO_STR); \
+ \
+ entry ("inheritable", "%s", \
+ inheritable < 0 \
+ ? NOT_DEFINED_STR \
+ : inheritable == CAP_SET \
+ ? YES_STR \
+ : NO_STR); \
+ \
+ entry ("permitted", "%s", \
+ permitted < 0 \
+ ? NOT_DEFINED_STR \
+ : permitted == CAP_SET \
+ ? YES_STR \
+ : NO_STR); \
+ \
+ section_close (); \
+}
+#else
+#define show_capability(caps, cap)
+#endif
+
+#if defined (HAVE_SYS_CAPABILITY_H)
+
+#ifndef CAP_IS_SUPPORTED
+
+static int cap_get_bound (cap_value_t cap)
+ __attribute__((unused));
+
+#define CAP_IS_SUPPORTED(cap) (cap_get_bound (cap) >= 0)
+#define PROCENV_NEED_LOCAL_CAP_GET_BOUND
+
+#endif /* CAP_IS_SUPPORTED */
+
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+/* semctl(2) states that POSIX.1-2001 requires the caller define this! */
+union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short int *array;
+ struct seminfo *__buf;
+};
+
+static bool linux_kernel_version (int major, int minor, int revision);
+
+static int get_capability_by_flag_type (cap_t cap_p, cap_flag_t type, cap_value_t cap)
+ __attribute__((unused));
+
+#if defined (HAVE_SYS_CAPABILITY_H)
+int get_capability_by_flag_type (cap_t cap_p, cap_flag_t type, cap_value_t cap);
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+
+#endif /* _PROCENV_PLATFORM_LINUX_H */
diff --git a/src/platform/linux/platform.c b/src/platform/linux/platform.c
new file mode 100644
index 0000000..8b3e2a4
--- /dev/null
+++ b/src/platform/linux/platform.c
@@ -0,0 +1,2212 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-linux.h"
+
+static struct procenv_map scheduler_map[] = {
+
+ mk_map_entry (SCHED_OTHER),
+ mk_map_entry (SCHED_FIFO),
+ mk_map_entry (SCHED_RR),
+ mk_map_entry (SCHED_BATCH),
+
+#ifdef SCHED_IDLE
+ mk_map_entry (SCHED_IDLE),
+#endif
+
+ { 0, NULL }
+};
+
+static struct procenv_map signal_map_linux[] = {
+
+ mk_map_entry (SIGABRT),
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+
+ mk_map_entry (SIGCONT),
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+ mk_map_entry (SIGINT),
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGTTOU),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGIO),
+ mk_map_entry (SIGIOT),
+
+ {SIGPOLL, "SIGPOLL|SIGIO" },
+
+ mk_map_entry (SIGPROF),
+
+ mk_map_entry (SIGPWR),
+#ifdef SIGSTKFLT
+ mk_map_entry (SIGSTKFLT),
+#endif
+
+ mk_map_entry (SIGSYS),
+
+#ifdef SIGUNUSED
+ mk_map_entry (SIGUNUSED),
+#endif
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGVTALRM),
+ mk_map_entry (SIGWINCH),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+
+ { 0, NULL },
+};
+
+static struct procenv_map if_flag_map_linux[] = {
+ mk_map_entry (IFF_UP),
+ mk_map_entry (IFF_BROADCAST),
+ mk_map_entry (IFF_DEBUG),
+ mk_map_entry (IFF_LOOPBACK),
+ mk_map_entry (IFF_POINTOPOINT),
+ mk_map_entry (IFF_RUNNING),
+ mk_map_entry (IFF_NOARP),
+ mk_map_entry (IFF_PROMISC),
+ mk_map_entry (IFF_NOTRAILERS),
+ mk_map_entry (IFF_ALLMULTI),
+ mk_map_entry (IFF_MASTER),
+ mk_map_entry (IFF_SLAVE),
+ mk_map_entry (IFF_MULTICAST),
+ mk_map_entry (IFF_PORTSEL),
+ mk_map_entry (IFF_AUTOMEDIA),
+ mk_map_entry (IFF_DYNAMIC),
+ mk_map_entry (IFF_LOWER_UP),
+ mk_map_entry (IFF_DORMANT),
+#ifdef IFF_ECHO
+ mk_map_entry (IFF_ECHO),
+#endif
+
+ { 0, NULL }
+};
+
+static struct procenv_map if_extended_flag_map_linux[] = {
+#if defined (IFF_802_1Q_VLAN)
+ mk_map_entry (IFF_802_1Q_VLAN),
+#endif
+#if defined (IFF_EBRIDGE)
+ mk_map_entry (IFF_EBRIDGE),
+#endif
+#if defined (IFF_SLAVE_INACTIVE)
+ mk_map_entry (IFF_SLAVE_INACTIVE),
+#endif
+#if defined (IFF_MASTER_8023AD)
+ mk_map_entry (IFF_MASTER_8023AD),
+#endif
+#if defined (IFF_MASTER_ALB)
+ mk_map_entry (IFF_MASTER_ALB),
+#endif
+#if defined (IFF_BONDING)
+ mk_map_entry (IFF_BONDING),
+#endif
+#if defined (IFF_SLAVE_NEEDARP)
+ mk_map_entry (IFF_SLAVE_NEEDARP),
+#endif
+#if defined (IFF_ISATAP)
+ mk_map_entry (IFF_ISATAP),
+#endif
+ { 0, NULL }
+};
+
+static struct procenv_map personality_map_linux[] = {
+ mk_map_entry (PER_LINUX),
+ mk_map_entry (PER_LINUX_32BIT),
+ mk_map_entry (PER_SVR4),
+ mk_map_entry (PER_SVR3),
+ mk_map_entry (PER_SCOSVR3),
+ mk_map_entry (PER_OSR5),
+ mk_map_entry (PER_WYSEV386),
+ mk_map_entry (PER_ISCR4),
+ mk_map_entry (PER_BSD),
+ mk_map_entry (PER_SUNOS),
+ mk_map_entry (PER_XENIX),
+#if defined (PER_LINUX32)
+ mk_map_entry (PER_LINUX32),
+#endif
+#if defined (PER_LINUX32_3GB)
+ mk_map_entry (PER_LINUX32_3GB),
+#endif
+ mk_map_entry (PER_IRIX32),
+ mk_map_entry (PER_IRIXN32),
+ mk_map_entry (PER_IRIX64),
+ mk_map_entry (PER_RISCOS),
+ mk_map_entry (PER_SOLARIS),
+ mk_map_entry (PER_UW7),
+ mk_map_entry (PER_OSF4),
+ mk_map_entry (PER_HPUX),
+
+ { 0, NULL }
+};
+
+static struct procenv_map personality_flag_map_linux[] = {
+#if defined (ADDR_COMPAT_LAYOUT)
+ mk_map_entry (ADDR_COMPAT_LAYOUT),
+#endif
+#if defined (ADDR_LIMIT_32BIT)
+ mk_map_entry (ADDR_LIMIT_32BIT),
+#endif
+#if defined (ADDR_LIMIT_3GB)
+ mk_map_entry (ADDR_LIMIT_3GB),
+#endif
+#if defined (ADDR_NO_RANDOMIZE)
+ mk_map_entry (ADDR_NO_RANDOMIZE),
+#endif
+#if defined (MMAP_PAGE_ZERO)
+ mk_map_entry (MMAP_PAGE_ZERO),
+#endif
+#if defined (READ_IMPLIES_EXEC)
+ mk_map_entry (READ_IMPLIES_EXEC),
+#endif
+#if defined (SHORT_INODE)
+ mk_map_entry (SHORT_INODE),
+#endif
+#if defined (STICKY_TIMEOUTS)
+ mk_map_entry (STICKY_TIMEOUTS),
+#endif
+#if defined (WHOLE_SECONDS)
+ mk_map_entry (WHOLE_SECONDS),
+#endif
+
+ { 0, NULL }
+};
+
+/* lifted from include/linux/ioprio.h since not available in libc */
+#define IOPRIO_CLASS_SHIFT (13)
+#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
+#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
+#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
+
+enum {
+ IOPRIO_WHO_PROCESS = 1,
+ IOPRIO_WHO_PGRP,
+ IOPRIO_WHO_USER,
+};
+
+enum {
+ IOPRIO_CLASS_NONE, /* FIXME: is this valid? */
+ IOPRIO_CLASS_RT,
+ IOPRIO_CLASS_BE,
+ IOPRIO_CLASS_IDLE,
+ IOPRIO_CLASS_NORMAL,
+};
+
+static struct procenv_map io_priorities_class_map[] = {
+ mk_map_entry (IOPRIO_CLASS_NONE),
+ mk_map_entry (IOPRIO_CLASS_RT),
+ mk_map_entry (IOPRIO_CLASS_BE),
+ mk_map_entry (IOPRIO_CLASS_IDLE),
+ mk_map_entry (IOPRIO_CLASS_NORMAL),
+
+ { 0, NULL }
+};
+
+static char *
+pid_to_name (pid_t pid)
+{
+ char path[PATH_MAX];
+ char *name = NULL;
+ FILE *f = NULL;
+
+ sprintf (path, "/proc/%d/cmdline", (int)pid);
+
+ f = fopen (path, "r");
+ if (! f)
+ goto out;
+
+ /* Reuse buffer */
+ if (! fgets (path, sizeof (path), f))
+ goto out;
+
+ /* Nul delimiting within /proc file will ensure we only get the
+ * program name.
+ */
+ append (&name, path);
+
+out:
+ if (f)
+ fclose (f);
+
+ return name;
+}
+
+static void
+get_user_misc_linux (struct procenv_user *user,
+ struct procenv_misc *misc)
+{
+ assert (user);
+ assert (misc);
+ get_canonical_generic_linux (ROOT_PATH, misc->root, sizeof (misc->root));
+}
+
+static void
+show_capabilities_linux (void)
+{
+#if defined (HAVE_SYS_CAPABILITY_H)
+ int last_known;
+ cap_t caps;
+
+ /* Most recently-added capability that procenv knew about at
+ * compile time.
+ */
+ last_known = CAP_LAST_CAP;
+#endif
+
+#if defined (HAVE_SYS_CAPABILITY_H)
+ caps = cap_get_proc ();
+
+ entry ("count (CAP_LAST_CAP+1)", "%d", CAP_LAST_CAP+1);
+
+ if (! caps)
+ goto out;
+
+ section_open ("known");
+
+ show_capability (caps, CAP_CHOWN);
+ show_capability (caps, CAP_DAC_OVERRIDE);
+ show_capability (caps, CAP_DAC_READ_SEARCH);
+ show_capability (caps, CAP_FOWNER);
+ show_capability (caps, CAP_FSETID);
+ show_capability (caps, CAP_KILL);
+ show_capability (caps, CAP_SETGID);
+ show_capability (caps, CAP_SETUID);
+ show_capability (caps, CAP_SETPCAP);
+ show_capability (caps, CAP_LINUX_IMMUTABLE);
+ show_capability (caps, CAP_NET_BIND_SERVICE);
+ show_capability (caps, CAP_NET_BROADCAST);
+ show_capability (caps, CAP_NET_ADMIN);
+ show_capability (caps, CAP_NET_RAW);
+ show_capability (caps, CAP_IPC_LOCK);
+ show_capability (caps, CAP_IPC_OWNER);
+ show_capability (caps, CAP_SYS_MODULE);
+ show_capability (caps, CAP_SYS_RAWIO);
+ show_capability (caps, CAP_SYS_CHROOT);
+ show_capability (caps, CAP_SYS_PTRACE);
+ show_capability (caps, CAP_SYS_PACCT);
+ show_capability (caps, CAP_SYS_ADMIN);
+ show_capability (caps, CAP_SYS_BOOT);
+ show_capability (caps, CAP_SYS_NICE);
+ show_capability (caps, CAP_SYS_RESOURCE);
+ show_capability (caps, CAP_SYS_TIME);
+ show_capability (caps, CAP_SYS_TTY_CONFIG);
+
+ if (LINUX_KERNEL_MM (2, 4)) {
+ show_capability (caps, CAP_MKNOD);
+ show_capability (caps, CAP_LEASE);
+ }
+
+ if (LINUX_KERNEL_MMR (2, 6, 11)) {
+ show_capability (caps, CAP_AUDIT_WRITE);
+ show_capability (caps, CAP_AUDIT_CONTROL);
+ }
+ if (LINUX_KERNEL_MMR (2, 6, 24))
+ show_capability (caps, CAP_SETFCAP);
+ if (LINUX_KERNEL_MMR (2, 6, 25)) {
+ show_capability (caps, CAP_MAC_OVERRIDE);
+ show_capability (caps, CAP_MAC_ADMIN);
+ }
+
+#ifdef CAP_SYSLOG
+ if (LINUX_KERNEL_MMR (2, 6, 37))
+ show_capability (caps, CAP_SYSLOG);
+#endif /* CAP_SYSLOG */
+
+#ifdef CAP_WAKE_ALARM
+ if (LINUX_KERNEL_MM (3, 0))
+ show_capability (caps, CAP_WAKE_ALARM);
+#endif /* CAP_WAKE_ALARM */
+
+#ifdef CAP_BLOCK_SUSPEND
+ if (LINUX_KERNEL_MM (3, 5))
+ show_capability (caps, CAP_BLOCK_SUSPEND);
+#endif /* CAP_BLOCK_SUSPEND */
+
+#ifdef CAP_AUDIT_READ
+ if (LINUX_KERNEL_MM (3, 16)) {
+ show_capability (caps, CAP_AUDIT_READ);
+ }
+#endif /* CAP_AUDIT_READ */
+
+ section_close ();
+
+ /* It's possible that procenv is running on a system which has
+ * more capabilities that the system it was built on (for
+ * example, it might be running in a chroot with a newer kernel
+ * than the chroot environment). So display any unknown
+ * capabilities. We don't have their names, but it's useful to
+ * see that there are additional capabilities in available in
+ * the environment.
+ */
+ section_open ("unknown");
+
+#if defined (PR_CAPBSET_READ)
+ for (int i = 1+last_known; ; i++) {
+ int ret;
+ char *name = NULL;
+
+ ret = cap_get_bound (i);
+ if (ret < 0)
+ break;
+
+ /* Found an "unknown" */
+
+ appendf (&name, "CAP_LAST_CAP+%d", i);
+
+ _show_capability (caps, i, name);
+
+ free (name);
+ }
+#endif
+
+ cap_free (caps);
+
+ section_close ();
+
+#ifdef PR_GET_KEEPCAPS
+ if (LINUX_KERNEL_MMR (2, 2, 18)) {
+ int ret;
+ ret = prctl (PR_GET_KEEPCAPS, 0, 0, 0, 0);
+ if (ret < 0)
+ entry ("keep", "%s", UNKNOWN_STR);
+ else
+ entry ("keep", "%s", ret ? YES_STR : NO_STR);
+ }
+#endif
+
+
+#if defined (PR_GET_SECUREBITS) && defined (HAVE_LINUX_SECUREBITS_H)
+ if (LINUX_KERNEL_MMR (2, 6, 26)) {
+ int ret;
+
+ ret = prctl (PR_GET_SECUREBITS, 0, 0, 0, 0);
+ if (ret < 0)
+ entry ("securebits", "%s", UNKNOWN_STR);
+ else {
+ struct securebits_t {
+ unsigned int securebits;
+ } flags;
+ flags.securebits = (unsigned int)ret;
+
+ section_open ("securebits");
+
+ entry ("value", "0x%x", flags.securebits);
+
+ container_open ("fields");
+
+ show_const (flags, securebits, SECBIT_KEEP_CAPS);
+ show_const (flags, securebits, SECBIT_NO_SETUID_FIXUP);
+ show_const (flags, securebits, SECBIT_NOROOT);
+
+ container_close ();
+
+ section_close ();
+ }
+ }
+#endif
+
+out:
+ /* compiler appeasement */
+ return;
+#endif
+}
+
+static void
+show_cgroups_linux (void)
+{
+ const char *delim = ":";
+ char *file = "/proc/self/cgroup";
+ FILE *f;
+ char buffer[1024];
+ size_t len;
+
+ f = fopen (file, "r");
+
+ if (! f)
+ goto out;
+
+ while (fgets (buffer, sizeof (buffer), f)) {
+ char *buf, *b;
+ char *hierarchy;
+ char *subsystems = NULL;
+ char *path;
+
+ len = strlen (buffer);
+ /* Remove NL */
+ buffer[len-1] = '\0';
+
+ buf = b = strdup (buffer);
+ if (! buf)
+ die ("failed to alloate storage");
+
+ hierarchy = strsep (&b, delim);
+ if (! hierarchy)
+ goto next;
+
+ /* don't fail if this returns '\0' to tolerate cgroup2 where the
+ * subsystem is always empty.
+ */
+ subsystems = strsep (&b, delim);
+
+ path = strsep (&b, delim);
+ if (! path)
+ goto next;
+
+ /* FIXME: should sort by hierarchy */
+ container_open (hierarchy);
+
+ object_open (false);
+
+ /* FIXME: should split this on comma */
+ if (subsystems && *subsystems)
+ entry ("subsystems", "%s", subsystems);
+
+ entry ("path", "%s", path);
+
+ object_close (false);
+
+ container_close ();
+
+next:
+ free (buf);
+ }
+
+ fclose (f);
+
+out:
+
+ /* compiler appeasement */
+ return;
+}
+
+static void
+show_fds_linux (void)
+{
+ DIR *dir;
+ struct dirent *ent;
+ char *prefix_path = "/proc/self/fd";
+ struct stat st;
+ char path[MAXPATHLEN];
+ char link[MAXPATHLEN];
+ ssize_t len;
+
+ dir = opendir (prefix_path);
+ if (! dir)
+ return;
+
+ while ((ent=readdir (dir)) != NULL) {
+ int fd;
+ char *num = NULL;
+
+ if (! strcmp (ent->d_name, ".") || ! strcmp (ent->d_name, ".."))
+ continue;
+
+ sprintf (path, "%s/%s", prefix_path, ent->d_name);
+ fd = atoi (ent->d_name);
+
+ len = readlink (path, link, sizeof (link)-1);
+ if (len < 0)
+ /* ignore errors */
+ continue;
+
+ appendf (&num, "%d", fd);
+
+ assert (len);
+ link[len] = '\0';
+
+ if (link[0] == '/') {
+
+ if (stat (link, &st) < 0) {
+ free (num);
+ continue;
+ }
+
+ /* Ignore the last (invalid) entry */
+ if (S_ISDIR (st.st_mode)) {
+ free (num);
+ continue;
+ }
+ }
+
+ object_open (false);
+
+ section_open (num);
+ free (num);
+
+ entry ("terminal", "%s", isatty (fd) ? YES_STR : NO_STR);
+ entry ("valid", "%s", fd_valid (fd) ? YES_STR : NO_STR);
+ entry ("device", "%s", link);
+
+ section_close ();
+
+ object_close (false);
+ }
+
+ closedir (dir);
+}
+
+static void
+show_namespaces_linux (void)
+{
+ DIR *dir;
+ struct dirent *ent;
+ char *prefix_path = "/proc/self/ns";
+ char path[MAXPATHLEN];
+ char link[MAXPATHLEN];
+ ssize_t len;
+ PRList *list = NULL;
+
+ dir = opendir (prefix_path);
+ if (! dir)
+ goto end;
+
+ list = pr_list_new (NULL);
+ assert (list);
+
+ while ((ent=readdir (dir)) != NULL) {
+ PRList *entry;
+
+ if (! strcmp (ent->d_name, ".") || ! strcmp (ent->d_name, ".."))
+ continue;
+
+ sprintf (path, "%s/%s", prefix_path, ent->d_name);
+
+ len = readlink (path, link, sizeof (link)-1);
+ if (len < 0)
+ /* ignore errors */
+ continue;
+
+ assert (len);
+ link[len] = '\0';
+
+ entry = pr_list_new (strdup (link));
+ assert (entry);
+
+ assert (pr_list_prepend_str_sorted (list, entry));
+ }
+
+ closedir (dir);
+
+ PR_LIST_FOREACH_SAFE (list, iter) {
+ char *tmp;
+ char *name;
+ char *value;
+
+ pr_list_remove (iter);
+
+ tmp = iter->data;
+
+ name = strsep (&tmp, ":");
+ if (! name)
+ goto give_up;
+
+ value = strsep (&tmp, "]");
+ if (! value)
+ goto give_up;
+
+ if (*value == '[' && *(value+1)) {
+ value++;
+ }
+
+ object_open (false);
+ entry (name, "%s", value);
+ object_close (false);
+
+give_up:
+ free ((char *)iter->data);
+ free(iter);
+ }
+
+ free_if_set (list);
+
+end:
+ /* compiler appeasement */
+ return;
+}
+
+static void
+show_oom_linux (void)
+{
+ char *dir = "/proc/self";
+ char *files[] = { "oom_score", "oom_adj", "oom_score_adj", NULL };
+ char **file;
+ FILE *f;
+ char buffer[PROCENV_BUFFER];
+ char path[PATH_MAX];
+ size_t len;
+ int ret;
+ int seen = false;
+
+ for (file = files; file && *file; file++) {
+ ret = sprintf (path, "%s/%s", dir, *file);
+ if (ret < 0)
+ continue;
+
+ f = fopen (path, "r");
+ if (! f)
+ continue;
+
+ seen = true;
+
+ while (fgets (buffer, sizeof (buffer), f)) {
+ len = strlen (buffer);
+ buffer[len-1] = '\0';
+ entry (*file, "%s", buffer);
+ }
+
+ fclose (f);
+ }
+
+ if (! seen)
+ entry ("%s", UNKNOWN_STR);
+}
+
+#if ! defined (HAVE_SCHED_GETCPU)
+
+/* Crutch function for RHEL 5 */
+static int
+procenv_getcpu (void)
+{
+ int cpu = -1;
+ FILE *f;
+ char **fields;
+ const char *field;
+ char buffer[1024];
+ size_t len;
+ size_t count;
+
+ f = fopen ("/proc/self/stat", "r");
+ if (! f)
+ goto out;
+
+ if (! fgets (buffer, sizeof (buffer), f))
+ goto out;
+
+ fclose (f);
+
+ len = strlen (buffer);
+ buffer[len-1] = '\0';
+
+ count = split_fields (buffer, ' ', true, &fields);
+
+ if (! count)
+ return -1;
+
+ if (count != 42)
+ goto cleanup;
+
+ field = fields[41];
+ assert (field);
+
+ cpu = atoi (field);
+
+cleanup:
+
+ for (len = 0; len < count; len++)
+ free (fields[len]);
+ free (fields);
+
+out:
+ return cpu;
+}
+
+#endif
+
+static void
+show_cpu_linux (void)
+{
+ int cpu = -1;
+ long max;
+
+ max = get_sysconf (_SC_NPROCESSORS_ONLN);
+
+#if HAVE_SCHED_GETCPU
+ cpu = sched_getcpu ();
+ if (cpu < 0)
+ goto unknown_sched_cpu;
+
+#else
+ cpu = procenv_getcpu ();
+ if (cpu < 0)
+ goto unknown_sched_cpu;
+#endif
+
+ /* adjust to make 1-based */
+ cpu++;
+
+ entry ("number", "%u of %ld", cpu, max);
+ return;
+
+unknown_sched_cpu:
+
+ entry ("number", "%s of %ld", UNKNOWN_STR, max);
+}
+
+static void
+show_msg_queues_linux (void)
+{
+ int i;
+ int id;
+ int max;
+ struct msginfo info;
+ struct msqid_ds msqid_ds;
+ struct ipc_perm *perm;
+ char formatted_stime[CTIME_BUFFER];
+ char formatted_rtime[CTIME_BUFFER];
+ char formatted_ctime[CTIME_BUFFER];
+ char *modestr = NULL;
+ char *lspid = NULL;
+ char *lrpid = NULL;
+
+ max = msgctl (0, MSG_INFO, (void *)&info);
+ if (max < 0)
+ goto out;
+
+ section_open ("info");
+
+ entry ("msgpool", "%d", info.msgpool);
+ entry ("msgmap", "%d", info.msgmap);
+ entry ("msgmax", "%d", info.msgmax);
+ entry ("msgmnb", "%d", info.msgmnb);
+ entry ("msgmni", "%d", info.msgmni);
+ entry ("msgssz", "%d", info.msgssz);
+ entry ("msgtql", "%d", info.msgtql);
+ entry ("msgseg", "%d", info.msgseg);
+
+ section_close ();
+
+ container_open ("sets");
+
+ object_open (false);
+
+ for (i = 0; i <= max; i++) {
+ char *id_str = NULL;
+
+ id = msgctl (i, MSG_STAT, &msqid_ds);
+ if (id < 0) {
+ /* found an unused slot, so ignore it */
+ continue;
+ }
+
+ perm = &msqid_ds.msg_perm;
+
+ modestr = format_perms (perm->mode);
+ if (! modestr)
+ die ("failed to allocate space for permissions string");
+
+ /* May not have been set */
+ if (msqid_ds.msg_stime)
+ format_time (&msqid_ds.msg_stime, formatted_stime, sizeof (formatted_stime));
+ else
+ sprintf (formatted_stime, "%s", NA_STR);
+
+ /* May not have been set */
+ if (msqid_ds.msg_rtime)
+ format_time (&msqid_ds.msg_rtime, formatted_rtime, sizeof (formatted_rtime));
+ else
+ sprintf (formatted_rtime, "%s", NA_STR);
+
+ /* May not have been set */
+ if (msqid_ds.msg_ctime)
+ format_time (&msqid_ds.msg_ctime, formatted_ctime, sizeof (formatted_ctime));
+ else
+ sprintf (formatted_ctime, "%s", NA_STR);
+
+ lspid = pid_to_name (msqid_ds.msg_lspid);
+ lrpid = pid_to_name (msqid_ds.msg_lrpid);
+
+ appendf (&id_str, "%d", id);
+
+ container_open (id_str);
+ free (id_str);
+
+ object_open (false);
+
+ /* pad out to max pointer size represented in hex */
+ entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
+ entry ("sequence", "%u", perm->__seq);
+
+ section_open ("permissions");
+ entry ("octal", "%4.4o", perm->mode);
+ entry ("symbolic", "%s", modestr);
+ section_close ();
+
+ section_open ("creator");
+ entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
+ entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
+ section_close ();
+
+ section_open ("owner");
+ entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
+ entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
+ section_close ();
+
+ section_open ("times");
+ entry ("last send (stime)", "%lu (%s)", msqid_ds.msg_stime, formatted_stime);
+ entry ("last receive (rtime)", "%lu (%s)", msqid_ds.msg_rtime, formatted_rtime);
+ entry ("last change (ctime)", "%lu (%s)", msqid_ds.msg_ctime, formatted_ctime);
+ section_close ();
+
+ entry ("queue_bytes", "%lu", msqid_ds.__msg_cbytes);
+
+ entry ("msg_qnum", "%lu", msqid_ds.msg_qnum);
+ entry ("msg_qbytes", "%lu", msqid_ds.msg_qbytes);
+
+ entry ("last msgsnd pid", "%d (%s)", msqid_ds.msg_lspid,
+ lspid ? lspid : UNKNOWN_STR);
+
+ entry ("last msgrcv pid", "%d (%s)", msqid_ds.msg_lrpid,
+ lrpid ? lrpid : UNKNOWN_STR);
+
+ object_close (false);
+
+ container_close ();
+
+ free (modestr);
+ if (lspid)
+ free (lspid);
+ if (lrpid)
+ free (lrpid);
+ }
+
+ object_close (false);
+
+ container_close ();
+
+out:
+ /* compiler appeasement */
+ return;
+}
+
+static void
+show_prctl_linux (void)
+{
+ int rc;
+ int arg2;
+ char name[17] = { 0 };
+
+#ifdef PR_GET_ENDIAN
+ if (LINUX_KERNEL_MMR (2, 6, 18)) {
+ const char *value;
+
+ rc = prctl (PR_GET_ENDIAN, &arg2, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (arg2) {
+ case PR_ENDIAN_BIG:
+ value = BIG_STR;
+ break;
+ case PR_ENDIAN_LITTLE:
+ value = LITTLE_STR;
+ break;
+ case PR_ENDIAN_PPC_LITTLE:
+ value = "PowerPC pseudo little endian";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("process endian", "%s", value);
+ }
+#endif
+
+#ifdef PR_GET_DUMPABLE
+ if (LINUX_KERNEL_MMR (2, 3, 20)) {
+ const char *value;
+ rc = prctl (PR_GET_DUMPABLE, 0, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (rc) {
+ case 0:
+ value = NO_STR;
+ break;
+ case 1:
+ value = YES_STR;
+ break;
+ case 2:
+ value = "root-only";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("dumpable", "%s", value);
+ }
+#endif
+
+#ifdef PR_GET_FPEMU
+ /* Use the earliest version where this option was introduced
+ * (for some architectures).
+ */
+ if (LINUX_KERNEL_MMR (2, 4, 18)) {
+ const char *value;
+
+ rc = prctl (PR_GET_FPEMU, &arg2, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (arg2) {
+ case PR_FPEMU_NOPRINT:
+ value = YES_STR;
+ break;
+ case PR_FPEMU_SIGFPE:
+ value = "send SIGFPE";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("floating point emulation", "%s", value);
+ }
+#endif
+
+#ifdef PR_GET_FPEXC
+ /* Use the earliest version where this option was introduced
+ * (for some architectures).
+ */
+ if (LINUX_KERNEL_MMR (2, 4, 21)) {
+ const char *value;
+
+ rc = prctl (PR_GET_FPEXC, &arg2, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (arg2) {
+ case PR_FP_EXC_SW_ENABLE:
+ value = "software";
+ break;
+ case PR_FP_EXC_DISABLED:
+ value = "disabled";
+ break;
+ case PR_FP_EXC_NONRECOV:
+ value = "non-recoverable";
+ break;
+ case PR_FP_EXC_ASYNC:
+ value = "asynchronous";
+ break;
+ case PR_FP_EXC_PRECISE:
+ value = "precise";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("floating point exceptions", "%s", value);
+ }
+#endif
+
+#ifdef PR_GET_NAME
+ if (LINUX_KERNEL_MMR (2, 6, 11)) {
+ rc = prctl (PR_GET_NAME, name, 0, 0, 0);
+ if (rc < 0)
+ entry ("process name", "%s", UNKNOWN_STR);
+ else
+ entry ("process name", "%s", name);
+ }
+
+#endif
+
+#ifdef PR_GET_PDEATHSIG
+ if (LINUX_KERNEL_MMR (2, 3, 15)) {
+ rc = prctl (PR_GET_PDEATHSIG, &arg2, 0, 0, 0);
+ if (rc < 0)
+ entry ("parent death signal", "%s", UNKNOWN_STR);
+ else if (rc == 0)
+ entry ("parent death signal", "disabled");
+ else
+ entry ("parent death signal", "%d", arg2);
+ }
+#endif
+
+#ifdef PR_GET_SECCOMP
+ if (LINUX_KERNEL_MMR (2, 6, 23)) {
+ const char *value;
+
+ rc = prctl (PR_GET_SECCOMP, 0, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (rc) {
+ case 0:
+ value = "disabled";
+ break;
+ case 1:
+ value = "read/write/exit (mode 1)";
+ break;
+ case 2:
+ value = "BPF (mode 2)";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("secure computing", "%s", value);
+ }
+#endif
+
+#ifdef PR_GET_TIMING
+ /* Not 100% accurate - this option was actually
+ * introduced in 2.6.0-test4
+ */
+ if (LINUX_KERNEL_MMR (2, 6, 1)) {
+ const char *value;
+ rc = prctl (PR_GET_TIMING, 0, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (rc) {
+ case PR_TIMING_STATISTICAL:
+ value = "statistical";
+ break;
+ case PR_TIMING_TIMESTAMP:
+ value = "time-stamp";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("process timing", "%s", value);
+ }
+#endif
+
+#if defined (PR_GET_TSC)
+ if (LINUX_KERNEL_MMR (2, 6, 26)) {
+ const char *value;
+
+ rc = prctl (PR_GET_TSC, &arg2, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (arg2) {
+ case PR_TSC_ENABLE:
+ value = "enabled";
+ break;
+ case PR_TSC_SIGSEGV:
+ value = "segmentation fault";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("timestamp counter read", "%s", value);
+ }
+#endif
+
+#ifdef PR_GET_UNALIGNED
+ if (LINUX_KERNEL_MMR (2, 3, 48)) {
+ const char *value;
+
+ rc = prctl (PR_GET_UNALIGNED, &arg2, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (arg2) {
+ case PR_UNALIGN_NOPRINT:
+ value = "fix-up";
+ break;
+ case PR_UNALIGN_SIGBUS:
+ value = "send SIGBUS";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("unaligned access", "%s", value);
+ }
+#endif
+
+#ifdef PR_MCE_KILL_GET
+ if (LINUX_KERNEL_MMR (2, 6, 32)) {
+ const char *value;
+
+ rc = prctl (PR_MCE_KILL_GET, 0, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (rc) {
+ case PR_MCE_KILL_DEFAULT:
+ value = "system default";
+ break;
+ case PR_MCE_KILL_EARLY:
+ value = "early kill";
+ break;
+ case PR_MCE_KILL_LATE:
+ value = "late kill";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("machine-check exception", "%s", value);
+ }
+#endif
+
+#ifdef PR_GET_NO_NEW_PRIVS
+ if (LINUX_KERNEL_MM (3, 5)) {
+ const char *value;
+
+ rc = prctl (PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
+ if (rc < 0)
+ value = UNKNOWN_STR;
+ else {
+ switch (rc) {
+ case 0:
+ value = "normal execve";
+ break;
+ case 1:
+ value = "enabled";
+ break;
+ default:
+ value = UNKNOWN_STR;
+ break;
+ }
+ }
+ entry ("no new privileges", "%s", value);
+ }
+#endif
+
+#ifdef PR_GET_TIMERSLACK
+ if (LINUX_KERNEL_MMR (2, 6, 28)) {
+ rc = prctl (PR_GET_TIMERSLACK, 0, 0, 0, 0);
+ if (rc < 0)
+ entry ("timer slack", "%s", UNKNOWN_STR);
+ else
+ entry ("timer slack", "%dns", rc);
+ }
+#endif
+
+#ifdef PR_GET_CHILD_SUBREAPER
+ if (LINUX_KERNEL_MM (3, 4)) {
+ rc = prctl (PR_GET_CHILD_SUBREAPER, &arg2, 0, 0, 0);
+ if (rc < 0)
+ entry ("child subreaper", "%s", UNKNOWN_STR);
+ else
+ entry ("child subreaper", "%s", arg2 ? YES_STR : NO_STR);
+ }
+#endif
+
+#ifdef PR_GET_TID_ADDRESS
+ rc = prctl (PR_GET_TID_ADDRESS, &arg2, 0, 0, 0);
+ if (rc < 0)
+ entry ("clear child tid address", "%s", UNKNOWN_STR);
+ else
+ entry ("clear child tid address", "%p", arg2);
+#endif
+}
+
+static void
+handle_proc_branch_linux (void)
+{
+ char buffer[1024];
+ char path[PATH_MAX];
+ char name[16];
+ char pid[16];
+ char ppid[16];
+ size_t len;
+ char *p;
+ FILE *f;
+ char *str = NULL;
+
+ sprintf (pid, "%d", (int)getpid ());
+
+ /* This is one God-awful interface */
+ while (true) {
+ sprintf (path, "/proc/%s/status", pid);
+
+ f = fopen (path, "r");
+ if (! f) {
+ appendf (&str, "%s", UNKNOWN_STR);
+ goto out;
+ }
+
+ while (fgets (buffer, sizeof (buffer), f)) {
+ len = strlen (buffer);
+ buffer[len-1] = '\0';
+
+ if ((p=strstr (buffer, "Name:")) == buffer) {
+ p += 1+strlen ("Name:"); /* jump over tab char */
+ sprintf (name, "%s", p);
+ }
+
+ if ((p=strstr (buffer, "PPid:")) == buffer) {
+ p += 1+strlen ("PPid:"); /* jump over tab char */
+ sprintf (ppid, "%s", p);
+
+ /* got all we need now */
+ break;
+ }
+ }
+
+ fclose (f);
+
+ /* ultimate parent == PID 1 == '/sbin/init' */
+ if (! strcmp (pid, "1")) {
+ appendf (&str, "%s ('%s')", pid, name);
+ break;
+ } else {
+ appendf (&str, "%s ('%s'), ", pid, name);
+ }
+
+ /* parent is now the pid to search for */
+ sprintf (pid, "%s", ppid);
+ }
+out:
+
+ entry ("ancestry", "%s", str);
+ free (str);
+}
+
+static void
+show_security_module_context_linux (void)
+{
+ char *context = NULL;
+ char *mode = NULL;
+
+#if defined (HAVE_APPARMOR)
+ if (aa_is_enabled ()) {
+ /* XXX: The mode string is *NOT* be freed since it forms
+ * part of the allocation returned in context.
+ *
+ * See aa_gettaskcon(2) for details.
+ */
+ if (aa_gettaskcon (user.pid, &context, &mode) < 0)
+ die ("failed to query AppArmor context");
+ }
+#endif
+
+#if defined (HAVE_SELINUX_SELINUX_H)
+ if (is_selinux_enabled ()) {
+ if (getpidcon (user.pid, &context) < 0)
+ die ("failed to query SELinux context");
+ }
+#endif
+ if (context) {
+ if (mode) {
+ entry ("context", "%s (%s)", context, mode);
+ } else {
+ entry ("context", "%s", context);
+ }
+ } else {
+ entry ("context", "%s", UNKNOWN_STR);
+ }
+
+ free (context);
+}
+
+static void
+show_security_module_linux (void)
+{
+ char *lsm = UNKNOWN_STR;
+
+#if defined (HAVE_APPARMOR)
+ if (aa_is_enabled ())
+ lsm = "AppArmor";
+#endif
+
+#if defined (HAVE_SELINUX_SELINUX_H)
+ if (is_selinux_enabled () == 1) {
+
+ if (is_selinux_mls_enabled () == 1)
+ lsm = "SELinux (MLS)";
+ else
+ lsm = "SELinux";
+ }
+#endif
+
+ entry ("name", "%s", lsm);
+
+ show_security_module_context_linux ();
+}
+
+static void
+show_semaphores_linux (void)
+{
+ int i;
+ int id;
+ int max;
+ struct semid_ds semid_ds;
+ struct seminfo info;
+ struct ipc_perm *perm;
+ char formatted_otime[CTIME_BUFFER];
+ char formatted_ctime[CTIME_BUFFER];
+ char *modestr = NULL;
+ union semun arg;
+
+ arg.array = (unsigned short int *)(void *)&info;
+ max = semctl (0, 0, SEM_INFO, arg);
+ if (max < 0)
+ goto out;
+
+ section_open ("info");
+
+ entry ("semmap", "%d", info.semmap);
+ entry ("semmni", "%d", info.semmni);
+ entry ("semmns", "%d", info.semmns);
+ entry ("semmnu", "%d", info.semmnu);
+ entry ("semmsl", "%d", info.semmsl);
+ entry ("semopm", "%d", info.semopm);
+ entry ("semume", "%d", info.semume);
+ entry ("semusz", "%d", info.semusz);
+ entry ("semvmx", "%d", info.semvmx);
+ entry ("semaem", "%d", info.semaem);
+
+ section_close ();
+
+ container_open ("set");
+
+ object_open (false);
+
+ for (i = 0; i <= max; i++) {
+ char *id_str = NULL;
+
+ /* see semctl(2) */
+ arg.buf = (struct semid_ds *)&semid_ds;
+
+ id = semctl (i, 0, SEM_STAT, arg);
+ if (id < 0) {
+ /* found an unused slot, so ignore it */
+ continue;
+ }
+
+ perm = &semid_ds.sem_perm;
+
+ modestr = format_perms (perm->mode);
+ if (! modestr)
+ die ("failed to allocate space for permissions string");
+
+ /* May not have been set */
+ if (semid_ds.sem_otime)
+ format_time (&semid_ds.sem_otime, formatted_otime, sizeof (formatted_otime));
+ else
+ sprintf (formatted_otime, "%s", NA_STR);
+
+ format_time (&semid_ds.sem_ctime, formatted_ctime, sizeof (formatted_ctime));
+
+ appendf (&id_str, "%d", id);
+
+ container_open (id_str);
+ free (id_str);
+
+ object_open (false);
+
+ /* pad out to max pointer size represented in hex.
+ */
+ entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
+ entry ("sequence", "%u", perm->__seq);
+
+ entry ("number in set", "%lu", semid_ds.sem_nsems);
+
+ section_open ("permissions");
+ entry ("octal", "%4.4o", perm->mode);
+ entry ("symbolic", "%s", modestr);
+ free (modestr);
+ section_close ();
+
+ section_open ("creator");
+ entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
+ entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
+ section_close ();
+
+ section_open ("owner");
+ entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
+ entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
+ section_close ();
+
+ section_open ("times");
+ entry ("last semop (otime)", "%lu (%s)", semid_ds.sem_otime, formatted_otime);
+ entry ("last change (ctime)", "%lu (%s)", semid_ds.sem_ctime, formatted_ctime);
+ section_close ();
+
+ object_close (false);
+
+ container_close ();
+ }
+
+ object_close (false);
+
+ container_close ();
+
+out:
+ /* compiler appeasement */
+ return;
+}
+
+static void
+show_shared_mem_linux (void)
+{
+ int i;
+ int id;
+ int max;
+ struct shm_info info;
+ struct shmid_ds shmid_ds;
+ struct ipc_perm *perm;
+ char formatted_atime[CTIME_BUFFER];
+ char formatted_ctime[CTIME_BUFFER];
+ char formatted_dtime[CTIME_BUFFER];
+ char *modestr = NULL;
+ int locked = -1;
+ int destroy = -1;
+ char *cpid = NULL;
+ char *lpid = NULL;
+
+ max = shmctl (0, SHM_INFO, (void *)&info);
+ if (max < 0)
+ goto out;
+
+ /* Display summary details */
+
+ section_open ("info");
+
+ entry ("segments", "%u", info.used_ids);
+ entry ("pages", "%lu", info.shm_tot);
+ entry ("shm_rss", "%lu", info.shm_rss);
+ entry ("shm_swp", "%lu", info.shm_swp);
+
+ /* Apparently unused */
+ entry ("swap_attempts", "%lu", info.swap_attempts);
+ entry ("swap_successes", "%lu", info.swap_successes);
+
+ section_close ();
+
+ container_open ("segments");
+
+ object_open (false);
+
+ for (i = 0; i <= max; i++) {
+ char *id_str = NULL;
+
+ id = shmctl (i, SHM_STAT, &shmid_ds);
+ if (id < 0) {
+ /* found an unused slot, so ignore it */
+ continue;
+ }
+
+ perm = &shmid_ds.shm_perm;
+
+ modestr = format_perms (perm->mode);
+ if (! modestr)
+ die ("failed to allocate space for permissions string");
+
+ locked = (perm->mode & SHM_LOCKED);
+ destroy = (perm->mode & SHM_DEST);
+
+ format_time (&shmid_ds.shm_atime, formatted_atime, sizeof (formatted_atime));
+ format_time (&shmid_ds.shm_ctime, formatted_ctime, sizeof (formatted_ctime));
+ format_time (&shmid_ds.shm_dtime, formatted_dtime, sizeof (formatted_dtime));
+
+ cpid = pid_to_name (shmid_ds.shm_cpid);
+ lpid = pid_to_name (shmid_ds.shm_lpid);
+
+ appendf (&id_str, "%d", id);
+
+ container_open (id_str);
+ free (id_str);
+
+ object_open (false);
+
+ /* pad out to max pointer size represented in hex.
+ */
+ entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
+ entry ("sequence", "%u", perm->__seq);
+
+ section_open ("permissions");
+ entry ("octal", "%4.4o", perm->mode);
+ entry ("symbolic", "%s", modestr);
+ section_close ();
+
+ section_open ("pids");
+ entry ("create", "%d (%s)", shmid_ds.shm_cpid, cpid ? cpid : UNKNOWN_STR);
+ entry ("last", "%d (%s)", shmid_ds.shm_lpid, lpid ? lpid : UNKNOWN_STR);
+ section_close ();
+
+ entry ("attachers", "%lu", shmid_ds.shm_nattch);
+
+ section_open ("creator");
+ entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
+ entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
+ section_close ();
+
+ section_open ("owner");
+ entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
+ entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
+ section_close ();
+
+ entry ("segment size", "%lu", shmid_ds.shm_segsz);
+
+ section_open ("times");
+ entry ("last attach (atime)", "%lu (%s)", shmid_ds.shm_atime, formatted_atime);
+ entry ("last detach (dtime)", "%lu (%s)", shmid_ds.shm_dtime, formatted_dtime);
+ entry ("last change (ctime)", "%lu (%s)", shmid_ds.shm_ctime, formatted_ctime);
+ section_close ();
+
+ entry ("locked", "%s", locked == 0 ? NO_STR
+ : locked > 0 ? YES_STR
+ : NA_STR);
+ entry ("destroy", "%s", destroy == 0 ? NO_STR
+ : destroy > 0 ? YES_STR
+ : NA_STR);
+
+ object_close (false);
+
+ container_close ();
+
+ free (modestr);
+ if (cpid)
+ free (cpid);
+ if (lpid)
+ free (lpid);
+ }
+
+ object_close (false);
+
+ container_close ();
+
+out:
+ /* compiler appeasement */
+ return;
+}
+
+static void
+show_timezone_linux (void)
+{
+ tzset ();
+
+ entry ("tzname[0]", "'%s'", tzname[0]);
+ entry ("tzname[1]", "'%s'", tzname[1]);
+ entry ("timezone", "%ld", timezone);
+ entry ("daylight", "%d", daylight);
+}
+
+static const char *
+get_ioprio_class_name (int ioprio)
+{
+ struct procenv_map *p;
+
+ for (p = io_priorities_class_map; p && p->name; p++) {
+ if (ioprio == p->num)
+ return p->name;
+ }
+
+ return NULL;
+}
+
+/* No GLib wrapper, so create one */
+static int
+io_prio_get (int which, int who)
+{
+ return syscall(SYS_ioprio_get, which, who);
+}
+
+static void
+get_io_priorities_linux (struct procenv_priority *iop)
+{
+ iop->process = io_prio_get (IOPRIO_WHO_PROCESS, 0);
+ iop->pgrp = io_prio_get (IOPRIO_WHO_PGRP , 0);
+ iop->user = io_prio_get (IOPRIO_WHO_USER , 0);
+}
+
+static void
+show_io_priorities_linux (void)
+{
+ section_open ("process");
+ entry ("class", "%s", get_ioprio_class_name (IOPRIO_PRIO_CLASS (priority_io.process)));
+ entry ("priority", "%d", IOPRIO_PRIO_DATA (priority_io.process));
+ section_close ();
+
+ section_open ("group");
+ entry ("class", "%s", get_ioprio_class_name (IOPRIO_PRIO_CLASS (priority_io.pgrp)));
+ entry ("priority", "%d", IOPRIO_PRIO_DATA (priority_io.pgrp));
+ section_close ();
+
+ section_open ("user");
+ entry ("class", "%s", get_ioprio_class_name (IOPRIO_PRIO_CLASS (priority_io.user)));
+ entry ("priority", "%d", IOPRIO_PRIO_DATA (priority_io.user));
+ section_close ();
+}
+
+static void
+show_rlimits_linux (void)
+{
+ show_limit (RLIMIT_AS);
+ show_limit (RLIMIT_CORE);
+ show_limit (RLIMIT_CPU);
+ show_limit (RLIMIT_DATA);
+ show_limit (RLIMIT_FSIZE);
+
+#if defined (RLIMIT_RTTIME)
+ if (LINUX_KERNEL_MMR (2, 6, 25)) {
+ show_limit (RLIMIT_RTTIME);
+ }
+#endif
+
+ show_limit (RLIMIT_LOCKS);
+ show_limit (RLIMIT_MEMLOCK);
+
+#if defined (RLIMIT_MSGQUEUE)
+ if (LINUX_KERNEL_MMR (2, 6, 8)) {
+ show_limit (RLIMIT_MSGQUEUE);
+ }
+#endif
+
+#if defined RLIMIT_NICE
+ if (LINUX_KERNEL_MMR (2, 6, 12)) {
+ show_limit (RLIMIT_NICE);
+ }
+#endif
+
+ show_limit (RLIMIT_NOFILE);
+ show_limit (RLIMIT_NPROC);
+ show_limit (RLIMIT_RSS);
+ show_limit (RLIMIT_RTPRIO);
+
+#if defined (RLIMIT_SIGPENDING)
+ if (LINUX_KERNEL_MMR (2, 6, 8)) {
+ show_limit (RLIMIT_SIGPENDING);
+ }
+#endif
+
+ show_limit (RLIMIT_STACK);
+}
+
+static void
+get_proc_name_linux (struct procenv_user *user)
+{
+ assert (user);
+
+ if (LINUX_KERNEL_MMR (2, 6, 11)) {
+ if (prctl (PR_GET_NAME, user->proc_name, 0, 0, 0) < 0)
+ strcpy (user->proc_name, UNKNOWN_STR);
+ }
+}
+
+#if defined (HAVE_NUMA_H)
+
+static struct procenv_map numa_mempolicy_map[] = {
+ mk_map_entry (MPOL_DEFAULT),
+ mk_map_entry (MPOL_PREFERRED),
+ mk_map_entry (MPOL_BIND),
+ mk_map_entry (MPOL_INTERLEAVE),
+};
+
+static const char *
+get_numa_policy (int policy)
+{
+ struct procenv_map *p;
+
+ for (p = numa_mempolicy_map; p && p->name; p++) {
+ if (p->num == policy)
+ return p->name;
+ }
+
+ return NULL;
+}
+#endif /* HAVE_NUMA_H */
+
+static void
+handle_numa_memory_linux (void)
+{
+#if defined (HAVE_NUMA_H)
+ int policy;
+ const char *policy_name;
+ char *allowed_list = NULL;
+ int ret;
+ unsigned long node;
+ unsigned long allowed_size;
+
+#if defined (HAVE_NUMA_H)
+#if LIBNUMA_API_VERSION == 2
+ struct bitmask *allowed;
+#else
+ nodemask_t allowed;
+#endif
+#endif
+
+ /* part of the libnuma public API - stop the library calling
+ * exit(3) on error.
+ */
+ numa_exit_on_error = 0;
+
+ /* true if any numa nodes have been displayed yet */
+ int displayed = false;
+
+ /* Number of numa nodes in *current* range */
+ size_t count = 0;
+
+ /* Only valid to read these when count is >0 */
+ size_t last = 0;
+ size_t first = 0;
+#endif /* HAVE_NUMA_H */
+
+ header ("numa");
+
+#if defined (HAVE_NUMA_H)
+ if (numa_available () < 0)
+ /* NUMA not supported on this system */
+ goto out;
+
+#if LIBNUMA_API_VERSION == 2
+ entry ("api version", "%d", 2);
+#else
+ entry ("api version", "%d", 1);
+#endif
+
+ ret = get_mempolicy (&policy, NULL, 0, 0, 0);
+
+ if (ret < 0) {
+ entry ("policy", "%s", UNKNOWN_STR);
+ goto out;
+ }
+
+ policy_name = get_numa_policy (policy);
+
+ entry ("policy", "%s", policy_name ? policy_name : UNKNOWN_STR);
+
+#if LIBNUMA_API_VERSION == 2
+ entry ("maximum nodes", "%d", numa_num_possible_nodes ());
+ entry ("configured nodes", "%d", numa_num_configured_nodes ());
+
+ allowed = numa_get_mems_allowed ();
+ if (! allowed)
+ die ("failed to query NUMA allowed list");
+
+ allowed_size = allowed->size;
+
+#else
+ entry ("maximum nodes", "%s", UNKNOWN_STR);
+ entry ("configured nodes", "%d", numa_max_node ());
+
+ allowed = numa_get_run_node_mask ();
+ allowed_size = NUMA_NUM_NODES;
+#endif
+
+ for (node = 0; node < allowed_size; node++) {
+ if (PROCENV_NUMA_BITMASK_ISSET (allowed, node)) {
+ /* Record first entry in the range */
+ if (! count)
+ first = node;
+
+ last = node;
+ count++;
+ } else {
+ if (count) {
+ if (first == last) {
+ appendf (&allowed_list, "%s%d",
+ displayed ? "," : "",
+ first);
+ } else {
+ appendf (&allowed_list, "%s%d-%d",
+ displayed ? "," : "",
+ first, last);
+ }
+ displayed = true;
+ }
+
+ /* Reset */
+ count = 0;
+ }
+ }
+
+ if (count) {
+ if (first == last) {
+ appendf (&allowed_list, "%s%d",
+ displayed ? "," : "",
+ first);
+ } else {
+ appendf (&allowed_list, "%s%d-%d",
+ displayed ? "," : "",
+ first, last);
+ }
+ }
+
+ entry ("allowed list", "%s", allowed_list);
+
+#if LIBNUMA_API_VERSION == 2
+ numa_free_nodemask (allowed);
+#endif
+
+ free (allowed_list);
+
+out:
+#endif /* HAVE_NUMA_H */
+ footer ();
+}
+
+/**
+ * linux_kernel_version:
+ *
+ * @major: major kernel version number,
+ * @minor: minor kernel version number,
+ * @revision: kernel revision version,
+ *
+ * @minor and @revision may be -1 to denote that those version
+ * elements are not important to the caller. Once a parameter
+ * has been specified as -1, subsequent parameters are ignored
+ * (treated as -1 too).
+ *
+ * Returns: true if running Linux kernel is atleast at version
+ * specified by (@major, @minor, @revision), else false.
+ **/
+static bool
+linux_kernel_version (int major, int minor, int revision)
+{
+ int actual_version = 0x000000;
+ int requested_version = 0x000000;
+ int actual_major = -1;
+ int actual_minor = -1;
+ int actual_revision = -1;
+ int ret;
+
+ assert (uts.release);
+ assert (sizeof (int) >= 4);
+
+ /* We need something to work with */
+ assert (major > 0);
+
+ ret = sscanf (uts.release, "%d.%d.%d",
+ &actual_major, &actual_minor,
+ &actual_revision);
+
+ /* We need something to compare against */
+ assert (ret && actual_major != -1);
+
+ requested_version |= (0xFF0000 & (major << 16));
+
+ if (minor != -1) {
+ requested_version |= (0x00FF00 & (minor << 8));
+
+ if (revision != -1)
+ requested_version |= (0x0000FF & revision);
+ }
+
+ if (actual_revision != -1) {
+ actual_version |= (0x0000FF & actual_revision);
+ }
+
+ if (actual_minor != -1)
+ actual_version |= (0x00FF00 & (actual_minor << 8));
+
+ if (actual_major != -1)
+ actual_version |= (0xFF0000 & (actual_major << 16));
+
+
+ if (actual_version >= requested_version)
+ return true;
+
+ return false;
+}
+
+#if defined (HAVE_SYS_CAPABILITY_H)
+static int
+get_capability_by_flag_type (cap_t cap_p, cap_flag_t type, cap_value_t cap)
+{
+ int ret;
+ cap_flag_value_t result;
+
+ assert (cap_p);
+
+ ret = cap_get_flag (cap_p, cap, type, &result);
+
+ return ret < 0 ? ret : result;
+}
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+#if defined (HAVE_SYS_CAPABILITY_H)
+#ifdef PROCENV_NEED_LOCAL_CAP_GET_BOUND
+
+static int
+cap_get_bound (cap_value_t cap)
+{
+#if defined (PR_CAPBSET_READ)
+ return prctl (PR_CAPBSET_READ, cap);
+#else
+ return -1;
+#endif
+}
+
+#endif /* PROCENV_NEED_LOCAL_CAP_GET_BOUND */
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+static const char *
+get_scheduler_name (int sched)
+{
+ struct procenv_map *p;
+
+ for (p = scheduler_map; p && p->name; p++) {
+ if (p->num == sched)
+ return p->name;
+ }
+
+ return NULL;
+}
+
+static void
+get_tty_locked_status_linux (struct termios *lock_status)
+{
+ assert (lock_status);
+ assert (user.tty_fd != -1);
+
+ if (ioctl (user.tty_fd, TIOCGLCKTRMIOS, lock_status) < 0) {
+ /* Set to unlocked */
+ memset (lock_status, '\0', sizeof (struct termios));
+ }
+}
+
+static void
+handle_scheduler_type_linux (void)
+{
+ int sched;
+
+ sched = sched_getscheduler (0);
+
+ entry ("type", "%s",
+ sched < 0 ? UNKNOWN_STR :
+ get_scheduler_name (sched));
+}
+
+static void
+show_extended_if_flags_linux (const char *interface, unsigned short *flags)
+{
+ int sock;
+ struct ifreq ifr;
+ const struct procenv_map *p;
+
+ assert (interface);
+ assert (flags);
+
+ /* We need to create a socket to query an interfaces mac
+ * address. Don't ask me why...
+ */
+ sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
+
+ if (sock < 0)
+ return;
+
+ memset (&ifr, 0, sizeof (struct ifreq));
+ strncpy (ifr.ifr_name, interface, IFNAMSIZ-1);
+
+ if (ioctl (sock, SIOCGIFPFLAGS, &ifr) < 0)
+ goto out;
+
+ *flags = ifr.ifr_flags;
+
+ for (p = if_extended_flag_map_linux; p && p->name; p++) {
+ if (*flags & p->num) {
+ object_open (false);
+ entry (p->name, "0x%x", p->num);
+ object_close (false);
+ }
+ }
+out:
+ close (sock);
+}
+
+static PROCENV_CPU_SET_TYPE *
+get_cpuset_linux (void)
+{
+ int ret = 0;
+
+#if ! defined (CPU_ALLOC)
+ /* RHEL 5 */
+ static PROCENV_CPU_SET_TYPE cpu_set_real;
+#else
+ long max;
+#endif
+
+ size_t size;
+ PROCENV_CPU_SET_TYPE *cs = NULL;
+
+#if defined (CPU_ALLOC)
+
+ max = get_sysconf (_SC_NPROCESSORS_ONLN);
+ if (max < 0)
+ return NULL;
+
+ cs = CPU_ALLOC (max);
+ if (! cs)
+ return NULL;
+
+ size = CPU_ALLOC_SIZE (max);
+ CPU_ZERO_S (size, cs);
+
+#else /* ! CPU_ALLOC */
+
+ size = sizeof (PROCENV_CPU_SET_TYPE);
+
+ CPU_ZERO (&cpu_set_real);
+ cs = &cpu_set_real;
+
+#endif /* CPU_ALLOC */
+
+ /* We could use sched_getaffinity(2) rather than
+ * sched_getaffinity() on Linux (2.5.8+) but
+ * pthread_getaffinity_np() provides the same information...
+ * Except it is missing on kFreeBSD systems (!) so we have to
+ * use sched_getaffinity() there. :(
+ */
+#if ! defined (CPU_ALLOC)
+ ret = sched_getaffinity (0, size, cs);
+#else
+
+ /* On a hyperthreaded system, "size" as above may not actually
+ * be big enough, and we get EINVAL (hwloc has a similar
+ * workaround).
+ */
+ {
+ int mult = 0;
+ while ((ret = pthread_getaffinity_np (pthread_self (), size, cs))
+ == EINVAL) {
+ CPU_FREE (cs);
+ /* Bail out at an arbitrary value. */
+ if (mult > 128) break;
+ mult += 2;
+ cs = CPU_ALLOC (mult * max);
+ size = CPU_ALLOC_SIZE (mult * max);
+ CPU_ZERO_S (size, cs);
+ }
+ }
+#endif
+ if (ret)
+ goto err;
+
+ return cs;
+err:
+#if defined (CPU_ALLOC)
+ CPU_FREE (cs);
+#endif
+ return NULL;
+}
+
+static void
+free_cpuset_linux (PROCENV_CPU_SET_TYPE *cs)
+{
+#if defined (CPU_ALLOC)
+ CPU_FREE (cs);
+#endif
+}
+
+static bool
+cpuset_has_cpu_linux (const PROCENV_CPU_SET_TYPE *cs,
+ PROCENV_CPU_TYPE cpu)
+{
+ return CPU_ISSET (cpu, cs);
+}
+
+static bool
+in_vm_linux (void)
+{
+ bool result = false;
+ const char *cpuinfo = "/proc/cpuinfo";
+ FILE *f = NULL;
+ char buffer[1024];
+
+ f = fopen (cpuinfo, "r");
+ if (! f) {
+ return false;
+ }
+
+ while (fgets (buffer, sizeof (buffer), f)) {
+ if (strstr (buffer, "flags") != buffer) {
+ continue;
+ }
+
+ if (strstr (buffer, "hypervisor") != NULL) {
+ result = true;
+ }
+
+ /* only test the first CPU */
+ goto out;
+ }
+
+out:
+ fclose (f);
+
+ return result;
+}
+
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (linux),
+
+ .get_cpuset = get_cpuset_linux,
+ .free_cpuset = free_cpuset_linux,
+ .cpuset_has_cpu = cpuset_has_cpu_linux,
+ .get_user_misc = get_user_misc_linux,
+ .get_proc_name = get_proc_name_linux,
+ .get_io_priorities = get_io_priorities_linux,
+ .get_mtu = get_mtu_generic,
+ .get_time = get_time_generic,
+
+ .get_tty_locked_status = get_tty_locked_status_linux,
+ .get_kernel_bits = get_kernel_bits_generic,
+
+ .signal_map = signal_map_linux,
+ .if_flag_map = if_flag_map_linux,
+ .in_vm = in_vm_linux,
+ .personality_map = personality_map_linux,
+ .personality_flag_map = personality_flag_map_linux,
+
+ .show_capabilities = show_capabilities_linux,
+ .show_cgroups = show_cgroups_linux,
+ .show_confstrs = show_confstrs_generic,
+
+ .show_cpu_affinities = show_cpu_affinities_generic,
+
+ .show_cpu = show_cpu_linux,
+ .show_clocks = show_clocks_generic,
+ .show_extended_if_flags = show_extended_if_flags_linux,
+ .show_fds = show_fds_linux,
+ .show_io_priorities = show_io_priorities_linux,
+ .show_mounts = show_mounts_generic_linux,
+ .show_msg_queues = show_msg_queues_linux,
+ .show_namespaces = show_namespaces_linux,
+ .show_oom = show_oom_linux,
+ .show_prctl = show_prctl_linux,
+ .show_rlimits = show_rlimits_linux,
+ .show_security_module = show_security_module_linux,
+ .show_semaphores = show_semaphores_linux,
+ .show_shared_mem = show_shared_mem_linux,
+ .show_timezone = show_timezone_linux,
+
+ .handle_numa_memory = handle_numa_memory_linux,
+ .handle_proc_branch = handle_proc_branch_linux,
+ .handle_scheduler_type = handle_scheduler_type_linux,
+
+};
diff --git a/src/platform/minix/platform-minix.h b/src/platform/minix/platform-minix.h
new file mode 100644
index 0000000..5604190
--- /dev/null
+++ b/src/platform/minix/platform-minix.h
@@ -0,0 +1,25 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_MINIX_H
+#define _PROCENV_PLATFORM_MINIX_H
+
+#include "platform.h"
+#include "util.h"
+
+#endif /* _PROCENV_PLATFORM_MINIX_H */
diff --git a/src/platform/minix/platform.c b/src/platform/minix/platform.c
new file mode 100644
index 0000000..ef00562
--- /dev/null
+++ b/src/platform/minix/platform.c
@@ -0,0 +1,128 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-minix.h"
+
+static struct procenv_map signal_map_minix[] = {
+
+ mk_map_entry (SIGABRT),
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+
+ mk_map_entry (SIGCONT),
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+ mk_map_entry (SIGINT),
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGTTOU),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGIO),
+ mk_map_entry (SIGPROF),
+ mk_map_entry (SIGSYS),
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGVTALRM),
+ mk_map_entry (SIGWINCH),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+ mk_map_entry (SIGEMT),
+ mk_map_entry (SIGINFO),
+ mk_map_entry (SIGKMEM),
+ mk_map_entry (SIGKMESS),
+ mk_map_entry (SIGKSIG),
+ mk_map_entry (SIGKSIGSM),
+ mk_map_entry (SIGPWR),
+ mk_map_entry (SIGSNDELAY),
+
+ { 0, NULL },
+};
+
+static struct procenv_map64 mntopt_map_minix[] = {
+
+ { MNT_ASYNC , "async" },
+ //{ MNT_AUTO , "auto" },
+ { MNT_DISCARD , "discard" },
+ { MNT_EXTATTR , "extattr" },
+ { MNT_FORCE , "force" },
+ { MNT_GETARGS , "getargs" },
+ //{ MNT_GROUPQUOTA , "groupquota" },
+ { MNT_IGNORE , "hidden" },
+ { MNT_LOG , "log" },
+ { MNT_NOATIME , "atime" },
+ { MNT_NOCOREDUMP , "coredump" },
+ { MNT_NODEV , "dev" },
+ { MNT_NODEVMTIME , "devmtime" },
+ { MNT_NOEXEC , "exec" },
+ { MNT_NOSUID , "suid" },
+ { MNT_RDONLY , "rdonly" },
+ { MNT_RELOAD , "reload" },
+ //{ MNT_RO , "ro" },
+ //{ MNT_RUMP , "rump" },
+ //{ MNT_RW , "rw" },
+ { MNT_SOFTDEP , "softdep" },
+ { MNT_SYMPERM , "symperm" },
+ //{ MNT_SYNC , "sync" },
+ { MNT_UNION , "union" },
+ { MNT_UPDATE , "update" },
+ //{ MNT_USERQUOTA , "userquota" },
+
+ { 0, NULL }
+};
+
+static void
+show_mounts_minix (ShowMountType what)
+{
+ show_mounts_generic_bsd (what, mntopt_map_minix);
+}
+
+static void
+handle_proc_branch_minix (void)
+{
+ /* FIXME */
+}
+
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (minix),
+
+ .get_kernel_bits = get_kernel_bits_generic,
+ .get_time = get_time_generic,
+
+ .signal_map = signal_map_minix,
+
+ // FIXME: add show_sysconf (which will do sysctl!)
+
+ .handle_proc_branch = handle_proc_branch_minix,
+
+ .show_clocks = show_clocks_generic,
+ .show_fds = show_fds_generic,
+
+ .show_mounts = show_mounts_minix,
+ .show_rlimits = show_rlimits_generic,
+};
diff --git a/src/platform/netbsd/platform-netbsd.h b/src/platform/netbsd/platform-netbsd.h
new file mode 100644
index 0000000..9cd080b
--- /dev/null
+++ b/src/platform/netbsd/platform-netbsd.h
@@ -0,0 +1,25 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_NETBSD_H
+#define _PROCENV_PLATFORM_NETBSD_H
+
+#include "platform.h"
+#include "util.h"
+
+#endif /* _PROCENV_PLATFORM_NETBSD_H */
diff --git a/src/platform/netbsd/platform.c b/src/platform/netbsd/platform.c
new file mode 100644
index 0000000..97b071f
--- /dev/null
+++ b/src/platform/netbsd/platform.c
@@ -0,0 +1,239 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-netbsd.h"
+
+static struct procenv_map signal_map_netbsd[] = {
+
+ mk_map_entry (SIGABRT),
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+
+ mk_map_entry (SIGCONT),
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+ mk_map_entry (SIGINT),
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGIO),
+ mk_map_entry (SIGPROF),
+ mk_map_entry (SIGSYS),
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGVTALRM),
+ mk_map_entry (SIGWINCH),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+ mk_map_entry (SIGEMT),
+ mk_map_entry (SIGINFO),
+ mk_map_entry (SIGPWR),
+
+ { 0, NULL },
+};
+
+static struct procenv_map64 mntopt_map[] = {
+
+ { MNT_ASYNC , "asynchronous" },
+ { MNT_EXPORTED , "NFS-exported" },
+ { MNT_LOCAL , "local" },
+ { MNT_NOATIME , "noatime" },
+ { MNT_NOEXEC , "noexec" },
+ { MNT_NOSUID , "nosuid" },
+ { MNT_QUOTA , "with quotas" },
+ { MNT_RDONLY , "read-only" },
+ { MNT_SOFTDEP , "soft-updates" },
+#if defined (MNT_SUJ)
+ { MNT_SUJ , "journaled soft-updates" },
+#endif
+ { MNT_SYNCHRONOUS , "synchronous" },
+ { MNT_UNION , "union" },
+
+ { 0, NULL }
+};
+
+static struct procenv_map if_flag_map_netbsd[] = {
+ mk_map_entry (IFF_UP),
+ mk_map_entry (IFF_BROADCAST),
+ mk_map_entry (IFF_DEBUG),
+ mk_map_entry (IFF_LOOPBACK),
+ mk_map_entry (IFF_POINTOPOINT),
+ mk_map_entry (IFF_RUNNING),
+ mk_map_entry (IFF_NOARP),
+ mk_map_entry (IFF_PROMISC),
+ mk_map_entry (IFF_ALLMULTI),
+ mk_map_entry (IFF_SIMPLEX),
+ mk_map_entry (IFF_MULTICAST),
+
+ { 0, NULL }
+};
+
+static void
+show_mounts_netbsd (ShowMountType what)
+{
+ show_mounts_generic_bsd (what, mntopt_map);
+}
+
+/* Who would have thought handling PIDs was so tricky? */
+static void
+handle_proc_branch_netbsd (void)
+{
+ int count = 0;
+ int i;
+ char errors[_POSIX2_LINE_MAX];
+ kvm_t *kvm;
+ struct kinfo_proc2 *procs;
+ struct kinfo_proc2 *p;
+ pid_t current;
+ int done = false;
+ char *str = NULL;
+ pid_t ultimate_parent = 0;
+
+ common_assert ();
+
+ current = getpid ();
+
+ kvm = kvm_openfiles (NULL, NULL, NULL, KVM_NO_FILES, errors);
+ if (! kvm)
+ die ("unable to open kvm");
+
+ procs = kvm_getproc2 (kvm, KERN_PROC_ALL, 0, sizeof (struct kinfo_proc2), &count);
+ if (! procs)
+ die ("failed to get process info");
+
+ /* Calculate the lowest PID number which gives us the ultimate
+ * parent of all processes.
+ *
+ * On NetBSD systems, PID 0 ('[system]') is the ultimate
+ * parent rather than PID 1 ('init').
+ */
+
+ p = &procs[0];
+ ultimate_parent = p->p_pid;
+
+ for (i = 1; i < count; i++) {
+ p = &procs[i];
+ if (p->p_pid< ultimate_parent)
+ ultimate_parent = p->p_pid;
+ }
+
+ while (! done) {
+ for (i = 0; i < count && !done; i++) {
+ p = &procs[i];
+
+ if (p->p_pid == current) {
+ if (! ultimate_parent && current == ultimate_parent) {
+
+ /* Found the "last" PID so record it and hop out */
+ appendf (&str, "%d ('%*s')",
+ (int)current,
+ KI_MAXCOMLEN,
+ p->p_comm);
+ done = true;
+ break;
+ } else {
+ /* Found a valid parent pid */
+ appendf (&str, "%d ('%*s'), ",
+ (int)current,
+ KI_MAXCOMLEN,
+ p->p_comm);
+ }
+
+ /* Move on */
+ current = p->p_ppid;
+ }
+ }
+ }
+
+ if (kvm_close (kvm) < 0)
+ die ("failed to close kvm");
+
+ entry ("ancestry", "%s", str);
+ free (str);
+}
+
+static PROCENV_CPU_SET_TYPE *
+get_cpuset_netbsd (void)
+{
+ PROCENV_CPU_SET_TYPE *cs = NULL;
+ int ret;
+
+ cs = cpuset_create ();
+ if (! cs)
+ return NULL;
+
+ ret = pthread_getaffinity_np (pthread_self (), cpuset_size (cs), cs);
+ if (ret) {
+ cpuset_destroy (cs);
+ return NULL;
+ }
+
+ return cs;
+}
+
+static void
+free_cpuset_netbsd (PROCENV_CPU_SET_TYPE *cs)
+{
+ cpuset_destroy (cs);
+}
+
+bool cpuset_has_cpu_netbsd (const PROCENV_CPU_SET_TYPE *cs,
+ PROCENV_CPU_TYPE cpu)
+{
+ return cpuset_isset (cpu, cs);
+}
+
+/* XXX:Notes:
+ *
+ * - show_cpu : it doesn't appear you can query the CPU of the
+ * current process on NetBSD :-(
+ */
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (netbsd),
+
+ .get_kernel_bits = get_kernel_bits_generic,
+ .get_mtu = get_mtu_generic,
+ .get_time = get_time_generic,
+
+ .get_cpuset = get_cpuset_netbsd,
+ .free_cpuset = free_cpuset_netbsd,
+ .cpuset_has_cpu = cpuset_has_cpu_netbsd,
+
+ .signal_map = signal_map_netbsd,
+ .if_flag_map = if_flag_map_netbsd,
+
+ .show_clocks = show_clocks_generic,
+ .show_confstrs = show_confstrs_generic,
+ .show_cpu_affinities = show_cpu_affinities_generic,
+ .show_fds = show_fds_generic,
+ .show_mounts = show_mounts_netbsd,
+ .show_rlimits = show_rlimits_generic,
+
+ .handle_proc_branch = handle_proc_branch_netbsd,
+};
diff --git a/src/platform/openbsd/platform-openbsd.h b/src/platform/openbsd/platform-openbsd.h
new file mode 100644
index 0000000..c0374da
--- /dev/null
+++ b/src/platform/openbsd/platform-openbsd.h
@@ -0,0 +1,25 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_OPENBSD_H
+#define _PROCENV_PLATFORM_OPENBSD_H
+
+#include "platform.h"
+#include "util.h"
+
+#endif /* _PROCENV_PLATFORM_OPENBSD_H */
diff --git a/src/platform/openbsd/platform.c b/src/platform/openbsd/platform.c
new file mode 100644
index 0000000..b4955d7
--- /dev/null
+++ b/src/platform/openbsd/platform.c
@@ -0,0 +1,201 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-openbsd.h"
+
+static struct procenv_map signal_map_openbsd[] = {
+
+ { SIGABRT, "SIGABRT|SIGIOT" },
+
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+
+ mk_map_entry (SIGCONT),
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+ mk_map_entry (SIGINT),
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGIO),
+ mk_map_entry (SIGPROF),
+ mk_map_entry (SIGSYS),
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGVTALRM),
+ mk_map_entry (SIGWINCH),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+ mk_map_entry (SIGEMT),
+ mk_map_entry (SIGINFO),
+ mk_map_entry (SIGTHR),
+ mk_map_entry (SIGTTOU),
+
+ { 0, NULL },
+};
+
+static struct procenv_map64 mntopt_map[] = {
+
+ { MNT_ASYNC , "asynchronous" },
+ { MNT_EXPORTED , "NFS-exported" },
+ { MNT_LOCAL , "local" },
+ { MNT_NOATIME , "noatime" },
+ { MNT_NOEXEC , "noexec" },
+ { MNT_NOSUID , "nosuid" },
+ { MNT_QUOTA , "with quotas" },
+ { MNT_RDONLY , "read-only" },
+ { MNT_SOFTDEP , "soft-updates" },
+#if defined (MNT_SUJ)
+ { MNT_SUJ , "journaled soft-updates" },
+#endif
+ { MNT_SYNCHRONOUS , "synchronous" },
+
+ { 0, NULL }
+};
+
+static struct procenv_map if_flag_map_openbsd[] = {
+ mk_map_entry (IFF_UP),
+ mk_map_entry (IFF_BROADCAST),
+ mk_map_entry (IFF_DEBUG),
+ mk_map_entry (IFF_LOOPBACK),
+ mk_map_entry (IFF_POINTOPOINT),
+ mk_map_entry (IFF_RUNNING),
+ mk_map_entry (IFF_NOARP),
+ mk_map_entry (IFF_PROMISC),
+ mk_map_entry (IFF_ALLMULTI),
+ mk_map_entry (IFF_SIMPLEX),
+ mk_map_entry (IFF_MULTICAST),
+
+ { 0, NULL }
+};
+
+static void
+show_mounts_openbsd (ShowMountType what)
+{
+ show_mounts_generic_bsd (what, mntopt_map);
+}
+
+/* Who would have thought handling PIDs was so tricky? */
+static void
+handle_proc_branch_openbsd (void)
+{
+ int count = 0;
+ int i;
+ char errors[_POSIX2_LINE_MAX];
+ kvm_t *kvm;
+ struct kinfo_proc *procs;
+ struct kinfo_proc *p;
+ pid_t current;
+ int done = false;
+ char *str = NULL;
+ pid_t ultimate_parent = 0;
+
+ common_assert ();
+
+ current = getpid ();
+
+ kvm = kvm_openfiles (NULL, NULL, NULL, KVM_NO_FILES, errors);
+ if (! kvm)
+ die ("unable to open kvm");
+
+ procs = kvm_getprocs (kvm, KERN_PROC_ALL, 0, sizeof (struct kinfo_proc), &count);
+ if (! procs)
+ die ("failed to get process info");
+
+ /* Calculate the lowest PID number which gives us the ultimate
+ * parent of all processes.
+ *
+ * OpenBSD has init as PID 1.
+ */
+
+ p = &procs[0];
+ ultimate_parent = p->p_pid;
+
+ for (i = 1; i < count; i++) {
+ p = &procs[i];
+ if (p->p_pid< ultimate_parent)
+ ultimate_parent = p->p_pid;
+ }
+
+ while (! done) {
+ for (i = 0; i < count && !done; i++) {
+ p = &procs[i];
+
+ if (p->p_pid == current) {
+ if (ultimate_parent == 1 && current == ultimate_parent) {
+ /* Found the "last" PID so record it and hop out */
+ appendf (&str, "%d ('%s')",
+ (int)current,
+ p->p_comm);
+ done = true;
+ break;
+ } else {
+ /* Found a valid parent pid */
+ appendf (&str, "%d ('%s'), ",
+ (int)current,
+ p->p_comm);
+ }
+
+ /* Move on */
+ current = p->p_ppid;
+ }
+ }
+ }
+
+ if (kvm_close (kvm) < 0)
+ die ("failed to close kvm");
+
+ entry ("ancestry", "%s", str);
+ free (str);
+}
+
+/* XXX:Notes:
+ *
+ * - show_cpu : it doesn't appear you can query the CPU of the
+ * current process on NetBSD :-(
+ */
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (openbsd),
+
+ .get_kernel_bits = get_kernel_bits_generic,
+ .get_mtu = get_mtu_generic,
+ .get_time = get_time_generic,
+
+ .signal_map = signal_map_openbsd,
+ .if_flag_map = if_flag_map_openbsd,
+
+ .show_clocks = show_clocks_generic,
+ .show_confstrs = show_confstrs_generic,
+ .show_cpu_affinities = show_cpu_affinities_generic,
+ .show_fds = show_fds_generic,
+ .show_mounts = show_mounts_openbsd,
+ .show_rlimits = show_rlimits_generic,
+
+ .handle_proc_branch = handle_proc_branch_openbsd,
+};
diff --git a/src/platform/platform-generic.c b/src/platform/platform-generic.c
new file mode 100644
index 0000000..de34382
--- /dev/null
+++ b/src/platform/platform-generic.c
@@ -0,0 +1,973 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "procenv.h"
+
+#include "platform-generic.h"
+#include "messages.h"
+
+extern struct procenv_ops *ops;
+
+void
+show_rlimits_generic (void)
+{
+#if defined (RLIMIT_AS)
+ show_limit (RLIMIT_AS);
+#endif
+
+ show_limit (RLIMIT_CORE);
+ show_limit (RLIMIT_CPU);
+ show_limit (RLIMIT_DATA);
+ show_limit (RLIMIT_FSIZE);
+ show_limit (RLIMIT_MEMLOCK);
+ show_limit (RLIMIT_NOFILE);
+ show_limit (RLIMIT_NPROC);
+ show_limit (RLIMIT_RSS);
+ show_limit (RLIMIT_STACK);
+}
+
+#if !defined (PROCENV_PLATFORM_DARWIN)
+
+void
+show_clocks_generic (void)
+{
+ show_clock_res (CLOCK_REALTIME);
+
+#if defined CLOCK_REALTIME_COARSE
+ show_clock_res (CLOCK_REALTIME_COARSE);
+#endif
+
+#if defined CLOCK_REALTIME_HR
+ show_clock_res (CLOCK_REALTIME_HR);
+#endif
+
+ show_clock_res (CLOCK_MONOTONIC);
+
+#if defined CLOCK_MONOTONIC_COARSE
+ show_clock_res (CLOCK_MONOTONIC_COARSE);
+#endif
+
+#if defined CLOCK_MONOTONIC_RAW
+ show_clock_res (CLOCK_MONOTONIC_RAW);
+#endif
+
+#if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_HURD)
+
+#ifdef CLOCK_MONOTONIC_RAW
+ show_clock_res (CLOCK_MONOTONIC_RAW);
+#endif
+ show_clock_res (CLOCK_PROCESS_CPUTIME_ID);
+ show_clock_res (CLOCK_THREAD_CPUTIME_ID);
+#if defined CLOCK_BOOTTIME
+ show_clock_res (CLOCK_BOOTTIME);
+#endif
+
+#endif
+}
+
+#endif
+
+long
+get_kernel_bits_generic (void)
+{
+ long value;
+
+ errno = 0;
+#if defined (_SC_LONG_BIT)
+ value = get_sysconf (_SC_LONG_BIT);
+ if (value == -1 && errno != 0)
+ return -1;
+#else
+ value = sizeof (long) * CHAR_BIT;
+#endif
+ return value;
+}
+
+#if !defined (PROCENV_PLATFORM_MINIX)
+int
+get_mtu_generic (const struct ifaddrs *ifaddr)
+{
+ int sock;
+ struct ifreq ifr;
+ unsigned long request = SIOCGIFMTU;
+
+ assert (ifaddr);
+
+ /* We need to create a socket to query an interfaces MAC
+ * address.
+ */
+ sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
+
+ if (sock < 0)
+ return -1;
+
+ memset (&ifr, 0, sizeof (struct ifreq));
+ strncpy (ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ-1);
+
+ if (ioctl (sock, request, &ifr) < 0)
+ ifr.ifr_mtu = 0;
+
+ close (sock);
+
+ return ifr.ifr_mtu;
+}
+#endif
+
+#if !defined (PROCENV_PLATFORM_DARWIN)
+
+bool
+get_time_generic (struct timespec *ts)
+{
+ return clock_gettime (CLOCK_REALTIME, ts);
+}
+
+#endif
+
+void
+show_fds_generic (void)
+{
+ int fd;
+ int max;
+
+ max = get_sysconf (_SC_OPEN_MAX);
+
+ for (fd = 0; fd < max; fd++) {
+ int is_tty = isatty (fd);
+ char *name = NULL;
+ char *num = NULL;
+
+ if (! fd_valid (fd))
+ continue;
+
+#if defined HAVE_TTYNAME
+ name = ttyname (fd);
+#endif
+ appendf (&num, "%d", fd);
+
+ object_open (false);
+
+ section_open (num);
+
+ entry ("terminal", "%s", is_tty ? YES_STR : NO_STR);
+ entry ("valid", "%s", fd_valid (fd) ? YES_STR : NO_STR);
+ entry ("device", "%s", name ? name : NA_STR);
+
+ section_open ("capabilities");
+
+ if (ops->show_fd_capabilities)
+ ops->show_fd_capabilities (fd);
+
+ section_close ();
+
+ section_close ();
+
+ object_close (false);
+
+ free (num);
+ }
+}
+
+void
+show_confstrs_generic (void)
+{
+#if defined (_CS_GNU_LIBC_VERSION)
+ show_confstr (_CS_GNU_LIBC_VERSION);
+#endif
+
+#if defined (_CS_GNU_LIBPTHREAD_VERSION)
+ show_confstr (_CS_GNU_LIBPTHREAD_VERSION);
+#endif
+
+#if defined (_CS_LFS64_CFLAGS)
+ show_confstr (_CS_LFS64_CFLAGS);
+#endif
+
+#if defined (_CS_LFS64_LDFLAGS)
+ show_confstr (_CS_LFS64_LDFLAGS);
+#endif
+
+#if defined (_CS_LFS64_LIBS)
+ show_confstr (_CS_LFS64_LIBS);
+#endif
+
+#if defined (_CS_LFS64_LINTFLAGS)
+ show_confstr (_CS_LFS64_LINTFLAGS);
+#endif
+
+#if defined (_CS_LFS_CFLAGS)
+ show_confstr (_CS_LFS_CFLAGS);
+#endif
+
+#if defined (_CS_LFS_LDFLAGS)
+ show_confstr (_CS_LFS_LDFLAGS);
+#endif
+
+#if defined (_CS_LFS_LIBS)
+ show_confstr (_CS_LFS_LIBS);
+#endif
+
+#if defined (_CS_LFS_LINTFLAGS)
+ show_confstr (_CS_LFS_LINTFLAGS);
+#endif
+
+#if defined (_CS_PATH)
+ show_confstr (_CS_PATH);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFF32)
+ show_confstr (_CS_POSIX_V6_ILP32_OFF32);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFF32_CFLAGS)
+ show_confstr (_CS_POSIX_V6_ILP32_OFF32_CFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFF32_LDFLAGS)
+ show_confstr (_CS_POSIX_V6_ILP32_OFF32_LDFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFF32_LIBS)
+ show_confstr (_CS_POSIX_V6_ILP32_OFF32_LIBS);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFF32_LINTFLAGS)
+ show_confstr (_CS_POSIX_V6_ILP32_OFF32_LINTFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS)
+ show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS)
+ show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LIBS)
+ show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LIBS);
+#endif
+
+#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS)
+ show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_LP64_OFF64_CFLAGS)
+ show_confstr (_CS_POSIX_V6_LP64_OFF64_CFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_LP64_OFF64_LDFLAGS)
+ show_confstr (_CS_POSIX_V6_LP64_OFF64_LDFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_LP64_OFF64_LIBS)
+ show_confstr (_CS_POSIX_V6_LP64_OFF64_LIBS);
+#endif
+
+#if defined (_CS_POSIX_V6_LP64_OFF64_LINTFLAGS)
+ show_confstr (_CS_POSIX_V6_LP64_OFF64_LINTFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS)
+ show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS)
+ show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LIBS)
+ show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LIBS);
+#endif
+
+#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS)
+ show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_ILP32_OFF32_CFLAGS)
+ show_confstr (_CS_POSIX_V7_ILP32_OFF32_CFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_ILP32_OFF32_LDFLAGS)
+ show_confstr (_CS_POSIX_V7_ILP32_OFF32_LDFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_ILP32_OFF32_LIBS)
+ show_confstr (_CS_POSIX_V7_ILP32_OFF32_LIBS);
+#endif
+
+#if defined (_CS_POSIX_V7_ILP32_OFF32_LINTFLAGS)
+ show_confstr (_CS_POSIX_V7_ILP32_OFF32_LINTFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS)
+ show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS)
+ show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LIBS)
+ show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LIBS);
+#endif
+
+#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS)
+ show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_LP64_OFF64_CFLAGS)
+ show_confstr (_CS_POSIX_V7_LP64_OFF64_CFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_LP64_OFF64_LDFLAGS)
+ show_confstr (_CS_POSIX_V7_LP64_OFF64_LDFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_LP64_OFF64_LIBS)
+ show_confstr (_CS_POSIX_V7_LP64_OFF64_LIBS);
+#endif
+
+#if defined (_CS_POSIX_V7_LP64_OFF64_LINTFLAGS)
+ show_confstr (_CS_POSIX_V7_LP64_OFF64_LINTFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS)
+ show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS)
+ show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS);
+#endif
+
+#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LIBS)
+ show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LIBS);
+#endif
+
+#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS)
+ show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS);
+#endif
+
+#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
+ show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS);
+#endif
+
+#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
+ _show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS, "_XBS5_WIDTH_RESTRICTED_ENVS");
+#endif
+
+#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
+ _show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS, "XBS5_WIDTH_RESTRICTED_ENVS");
+#endif
+
+#if defined (_CS_V6_WIDTH_RESTRICTED_ENVS)
+ show_confstr (_CS_V6_WIDTH_RESTRICTED_ENVS);
+#endif
+
+#if defined (_CS_V6_WIDTH_RESTRICTED_ENVS)
+ _show_confstr (_CS_V6_WIDTH_RESTRICTED_ENVS, "POSIX_V6_WIDTH_RESTRICTED_ENVS,_POSIX_V6_WIDTH_RESTRICTED_ENVS");
+#endif
+
+#if defined (_CS_V7_WIDTH_RESTRICTED_ENVS)
+ show_confstr (_CS_V7_WIDTH_RESTRICTED_ENVS);
+#endif
+
+#if defined (_CS_XBS5_ILP32_OFF32_CFLAGS)
+ show_confstr (_CS_XBS5_ILP32_OFF32_CFLAGS);
+#endif
+
+#if defined (_CS_XBS5_ILP32_OFF32_LDFLAGS)
+ show_confstr (_CS_XBS5_ILP32_OFF32_LDFLAGS);
+#endif
+
+#if defined (_CS_XBS5_ILP32_OFF32_LIBS)
+ show_confstr (_CS_XBS5_ILP32_OFF32_LIBS);
+#endif
+
+#if defined (_CS_XBS5_ILP32_OFF32_LINTFLAGS)
+ show_confstr (_CS_XBS5_ILP32_OFF32_LINTFLAGS);
+#endif
+
+#if defined (_CS_XBS5_ILP32_OFFBIG_CFLAGS)
+ show_confstr (_CS_XBS5_ILP32_OFFBIG_CFLAGS);
+#endif
+
+#if defined (_CS_XBS5_ILP32_OFFBIG_LDFLAGS)
+ show_confstr (_CS_XBS5_ILP32_OFFBIG_LDFLAGS);
+#endif
+
+#if defined (_CS_XBS5_ILP32_OFFBIG_LIBS)
+ show_confstr (_CS_XBS5_ILP32_OFFBIG_LIBS);
+#endif
+
+#if defined (_CS_XBS5_ILP32_OFFBIG_LINTFLAGS)
+ show_confstr (_CS_XBS5_ILP32_OFFBIG_LINTFLAGS);
+#endif
+
+#if defined (_CS_XBS5_LP64_OFF64_CFLAGS)
+ show_confstr (_CS_XBS5_LP64_OFF64_CFLAGS);
+#endif
+
+#if defined (_CS_XBS5_LP64_OFF64_LDFLAGS)
+ show_confstr (_CS_XBS5_LP64_OFF64_LDFLAGS);
+#endif
+
+#if defined (_CS_XBS5_LP64_OFF64_LIBS)
+ show_confstr (_CS_XBS5_LP64_OFF64_LIBS);
+#endif
+
+#if defined (_CS_XBS5_LP64_OFF64_LINTFLAGS)
+ show_confstr (_CS_XBS5_LP64_OFF64_LINTFLAGS);
+#endif
+
+#if defined (_CS_XBS5_LPBIG_OFFBIG_CFLAGS)
+ show_confstr (_CS_XBS5_LPBIG_OFFBIG_CFLAGS);
+#endif
+
+#if defined (_CS_XBS5_LPBIG_OFFBIG_LDFLAGS)
+ show_confstr (_CS_XBS5_LPBIG_OFFBIG_LDFLAGS);
+#endif
+
+#if defined (_CS_XBS5_LPBIG_OFFBIG_LIBS)
+ show_confstr (_CS_XBS5_LPBIG_OFFBIG_LIBS);
+#endif
+
+#if defined (_CS_XBS5_LPBIG_OFFBIG_LINTFLAGS)
+ show_confstr (_CS_XBS5_LPBIG_OFFBIG_LINTFLAGS);
+#endif
+}
+
+#if defined (PROCENV_PLATFORM_LINUX) || \
+ defined (PROCENV_PLATFORM_BSD) || \
+ defined (PROCENV_PLATFORM_HURD)
+
+/* Display cpu affinities in the same compressed but reasonably
+ * human-readable fashion as /proc/self/status:Cpus_allowed_list under Linux.
+ */
+void
+show_cpu_affinities_generic (void)
+{
+ PROCENV_CPU_SET_TYPE *cpu_set;
+ char *cpu_list = NULL;
+ PROCENV_CPU_TYPE cpu;
+ PROCENV_CPU_TYPE max;
+
+ /* true if any enabled cpus have been displayed yet */
+ int displayed = false;
+
+ /* Number of cpu's in *current* range */
+ size_t count = 0;
+
+ /* Only valid to read these when count is >0 */
+ size_t last = 0;
+ size_t first = 0;
+
+ if (! ops->get_cpuset)
+ return;
+
+ if (! ops->cpuset_has_cpu)
+ return;
+
+ cpu_set = ops->get_cpuset();
+ if (! cpu_set)
+ return;
+
+ // FIXME: should be handled by get_cpuset()!!
+ max = get_sysconf (_SC_NPROCESSORS_ONLN);
+
+ for (cpu = 0; cpu < max; cpu++) {
+
+ if (ops->cpuset_has_cpu (cpu_set, cpu)) {
+ /* Record first entry in the range */
+ if (! count)
+ first = cpu;
+
+ last = cpu;
+ count++;
+ } else {
+ if (count) {
+ if (first == last) {
+ appendf (&cpu_list, "%s%d",
+ displayed ? "," : "",
+ first);
+ } else {
+ appendf (&cpu_list, "%s%d-%d",
+ displayed ? "," : "",
+ first, last);
+ }
+ displayed = true;
+ }
+
+ /* Reset */
+ count = 0;
+ }
+ }
+
+ if (count) {
+ if (first == last) {
+ appendf (&cpu_list, "%s%d",
+ displayed ? "," : "",
+ first);
+ } else {
+ appendf (&cpu_list, "%s%d-%d",
+ displayed ? "," : "",
+ first, last);
+ }
+ }
+
+ entry ("affinity list", "%s", cpu_list ? cpu_list : "-1");
+
+ if (ops->free_cpuset)
+ ops->free_cpuset (cpu_set);
+
+ free (cpu_list);
+}
+
+#endif /* PROCENV_PLATFORM_LINUX || PROCENV_PLATFORM_FREEBSD || PROCENV_PLATFORM_HURD */
+
+#if defined (PROCENV_PLATFORM_LINUX) || \
+ defined (PROCENV_PLATFORM_BSD) || \
+ defined (PROCENV_PLATFORM_HURD) || \
+ defined (PROCENV_PLATFORM_MINIX) || \
+ defined (PROCENV_PLATFORM_DARWIN)
+
+void
+show_pathconfs (ShowMountType what,
+ const char *dir)
+{
+ assert (dir);
+
+ if (what == SHOW_PATHCONF) {
+ header (dir);
+ } else {
+ header ("pathconf");
+ }
+
+#if defined (_PC_ALLOC_SIZE_MIN)
+ show_pathconf (what, dir, _PC_ALLOC_SIZE_MIN);
+#endif
+
+#if defined (_PC_ASYNC_IO)
+ show_pathconf (what, dir, _PC_ASYNC_IO);
+#endif
+
+#if defined (_PC_CHOWN_RESTRICTED)
+ show_pathconf (what, dir, _PC_CHOWN_RESTRICTED);
+#endif
+
+#if defined (_PC_FILESIZEBITS)
+ show_pathconf (what, dir, _PC_FILESIZEBITS);
+#endif
+
+#if defined (_PC_LINK_MAX)
+ show_pathconf (what, dir, _PC_LINK_MAX);
+#endif
+
+#if defined (_PC_MAX_CANON)
+ show_pathconf (what, dir, _PC_MAX_CANON);
+#endif
+
+#if defined (_PC_MAX_INPUT)
+ show_pathconf (what, dir, _PC_MAX_INPUT);
+#endif
+
+#if defined (_PC_NAME_MAX)
+ show_pathconf (what, dir, _PC_NAME_MAX);
+#endif
+
+#if defined (_PC_NO_TRUNC)
+ show_pathconf (what, dir, _PC_NO_TRUNC);
+#endif
+
+#if defined (_PC_PATH_MAX)
+ show_pathconf (what, dir, _PC_PATH_MAX);
+#endif
+
+#if defined (_PC_PIPE_BUF)
+ show_pathconf (what, dir, _PC_PIPE_BUF);
+#endif
+
+#if defined (_PC_PRIO_IO)
+ show_pathconf (what, dir, _PC_PRIO_IO);
+#endif
+
+#if defined (_PC_REC_INCR_XFER_SIZE)
+ show_pathconf (what, dir, _PC_REC_INCR_XFER_SIZE);
+#endif
+
+#if defined (_PC_REC_MAX_XFER_SIZE)
+ show_pathconf (what, dir, _PC_REC_MAX_XFER_SIZE);
+#endif
+
+#if defined (_PC_REC_MIN_XFER_SIZE)
+ show_pathconf (what, dir, _PC_REC_MIN_XFER_SIZE);
+#endif
+
+#if defined (_PC_REC_XFER_ALIGN)
+ show_pathconf (what, dir, _PC_REC_XFER_ALIGN);
+#endif
+
+#if defined (_PC_SOCK_MAXBUF)
+ show_pathconf (what, dir, _PC_SOCK_MAXBUF);
+#endif
+
+#if defined (_PC_SYMLINK_MAX)
+ show_pathconf (what, dir, _PC_SYMLINK_MAX);
+#endif
+
+#if defined (_PC_2_SYMLINKS)
+ show_pathconf (what, dir, _PC_2_SYMLINKS);
+#endif
+
+#if defined (_PC_SYNC_IO)
+ show_pathconf (what, dir, _PC_SYNC_IO);
+#endif
+
+#if defined (_PC_VDISABLE)
+ show_pathconf (what, dir, _PC_VDISABLE);
+#endif
+
+ footer ();
+}
+
+#endif
+
+#if defined (PROCENV_PLATFORM_BSD) || \
+ defined (PROCENV_PLATFORM_MINIX) || \
+ defined (PROCENV_PLATFORM_DARWIN)
+
+char *
+get_mount_opts_generic_bsd (const struct procenv_map64 *opts, uint64_t flags)
+{
+ const struct procenv_map64 *opt;
+ char *str = NULL;
+ size_t len = 0;
+ size_t total = 0;
+ int count = 0;
+
+ if (! flags)
+ return strdup ("");
+
+ /* Calculate how much space we need to allocate by iterating
+ * array for the first time.
+ */
+ for (opt = opts; opt && opt->name; opt++) {
+ if (flags & opt->num) {
+ count++;
+ len += strlen (opt->name);
+ }
+ }
+
+ if (count > 1) {
+ /* we need space for the option value themselves, plus a
+ * ", " separator between each option (except the first),
+ * and finally space for the nul terminator */
+ total = len + (count-1) + 1;
+ } else {
+ total = len + 1;
+ }
+
+ str = calloc (total, sizeof (char));
+ if (! str)
+ die ("failed to allocate space for mount options");
+
+ /* Re-iterate to construct the string. This is still going to be
+ * a lot quicker than calling malloc a stack of times.
+ */
+ for (opt = opts; opt && opt->name; opt++) {
+ if (flags & opt->num) {
+ strcat (str, opt->name);
+ if (count > 1)
+ strcat (str, ",");
+ count--;
+ }
+ }
+
+ return str;
+}
+
+void
+show_mounts_generic_bsd (ShowMountType what,
+ const struct procenv_map64 *mntopt_map)
+{
+ procenv_mnt_type *mounts;
+ procenv_mnt_type *mnt;
+ int count;
+ unsigned int major = 0;
+ unsigned int minor = 0;
+ int i;
+ unsigned multiplier = 0;
+ PROCENV_STATFS_INT_TYPE blocks;
+ PROCENV_STATFS_INT_TYPE bfree;
+ PROCENV_STATFS_INT_TYPE bavail;
+ PROCENV_STATFS_INT_TYPE used;
+
+ common_assert ();
+ assert (mntopt_map);
+
+ /* Note that returned memory cannot be freed (by us) */
+ count = getmntinfo (&mounts, MNT_WAIT);
+
+ if (! count)
+ die ("unable to query mount info");
+
+ mnt = mounts;
+
+ for (i = 0; i < count; i++) {
+ char *opts = NULL;
+
+ opts = get_mount_opts_generic_bsd (mntopt_map,
+ PROCENV_MNT_GET_FLAGS (mnt));
+ if (! opts)
+ die ("cannot determine FS flags for mountpoint '%s'",
+ mnt->f_mntonname);
+
+ if (what == SHOW_ALL || what == SHOW_MOUNTS) {
+ (void)get_major_minor (mnt->f_mntonname,
+ &major,
+ &minor);
+
+ multiplier = mnt->f_bsize / DF_BLOCK_SIZE;
+ blocks = mnt->f_blocks * multiplier;
+ bfree = mnt->f_bfree * multiplier;
+ bavail = mnt->f_bavail * multiplier;
+ used = blocks - bfree;
+
+ assert (mnt->f_mntfromname);
+ section_open (mnt->f_mntfromname);
+
+ entry ("dir", "'%s'", mnt->f_mntonname);
+ entry ("type", "%s", mnt->f_fstypename);
+ entry ("options", "'%s'", opts);
+
+ section_open ("device");
+ entry ("major", "%u", major);
+ entry ("minor", "%u", minor);
+ section_close ();
+
+ entry ("fsid", "%.*x%.*x",
+ 2 * sizeof (PROCENV_MNT_GET_FSID (mnt)[0]),
+ PROCENV_MNT_GET_FSID (mnt)[0],
+ 2 * sizeof (PROCENV_MNT_GET_FSID (mnt)[1]),
+ PROCENV_MNT_GET_FSID (mnt)[1]);
+
+ entry ("optimal block size", "%" PROCENV_STATFS_INT_FMT,
+ mnt->f_bsize);
+
+ section_open ("blocks");
+
+ entry ("size", "%lu bytes", DF_BLOCK_SIZE);
+
+ entry ("total", "%" PROCENV_STATFS_INT_FMT, blocks);
+ entry ("used", "%"PROCENV_STATFS_INT_FMT, used);
+ entry ("free", "%" PROCENV_STATFS_INT_FMT, bfree);
+ entry ("available", "%" PROCENV_STATFS_INT_FMT, bavail);
+
+ section_close ();
+
+ section_open ("files/inodes");
+
+ entry ("total", "%" PROCENV_STATFS_INT_FMT, mnt->f_files);
+ entry ("used", "%" PROCENV_STATFS_INT_FMT,
+ mnt->f_files - mnt->f_ffree);
+ entry ("free", "%" PROCENV_STATFS_INT_FMT, mnt->f_ffree);
+
+ section_close ();
+
+ section_close ();
+ }
+
+ if (what == SHOW_ALL || what == SHOW_PATHCONF)
+ show_pathconfs (what, mnt->f_mntonname);
+ mnt++;
+
+ free (opts);
+ }
+}
+
+#endif /* PROCENV_PLATFORM_BSD || PROCENV_PLATFORM_MINIX || PROCENV_PLATFORM_DARWIN */
+
+#if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_HURD)
+
+#define MOUNTS "/proc/mounts"
+
+/**
+ * get_canonical:
+ *
+ * @path: path to convert to canonical form,
+ * @canonical [out]: canonical version of @path,
+ * @len: Size of @canonical (should be atleast PATH_MAX).
+ *
+ * FIXME: this should fully resolve not just sym links but replace all
+ * occurences of '../' by the appropriate direcotry!
+ **/
+int
+get_canonical_generic_linux (const char *path, char *canonical, size_t len)
+{
+ ssize_t bytes;
+ int ret = true;
+
+ assert (path);
+ assert (canonical);
+ assert (len);
+
+ bytes = readlink (path, canonical, len);
+ if (bytes < 0) {
+ sprintf (canonical, UNKNOWN_STR);
+ ret = false;
+ } else {
+ canonical[bytes <= len ? bytes : len] = '\0';
+ }
+
+ return ret;
+}
+
+void
+show_mounts_generic_linux (ShowMountType what)
+{
+ FILE *mtab;
+ struct mntent *mnt;
+ struct statvfs fs;
+ unsigned int major = 0;
+ unsigned int minor = 0;
+ int have_stats;
+ char canonical[PATH_MAX];
+
+ mtab = fopen (MOUNTS, "r");
+
+ if (! mtab)
+ return;
+
+ while ((mnt = getmntent (mtab))) {
+ have_stats = true;
+
+ if (what == SHOW_ALL || what == SHOW_MOUNTS) {
+ unsigned multiplier = 0;
+ fsblkcnt_t blocks = 0;
+ fsblkcnt_t bfree = 0;
+ fsblkcnt_t bavail = 0;
+ fsblkcnt_t used_blocks = 0;
+ fsblkcnt_t used_files = 0;
+ int ret;
+
+ if (statvfs (mnt->mnt_dir, &fs) < 0) {
+ have_stats = false;
+ } else {
+ multiplier = fs.f_bsize / DF_BLOCK_SIZE;
+
+ blocks = fs.f_blocks * multiplier;
+ bfree = fs.f_bfree * multiplier;
+ bavail = fs.f_bavail * multiplier;
+ used_blocks = blocks - bfree;
+ used_files = fs.f_files - fs.f_ffree;
+ }
+
+ (void)get_major_minor (mnt->mnt_dir,
+ &major,
+ &minor);
+
+ assert (mnt->mnt_dir);
+ section_open (mnt->mnt_dir);
+
+ entry ("filesystem", "'%s'", mnt->mnt_fsname);
+
+ ret = get_canonical_generic_linux (mnt->mnt_fsname, canonical, sizeof (canonical));
+ entry ("canonical", "%s%s%s",
+ ret ? "'" : "",
+ canonical,
+ ret ? "'" : "");
+
+ entry ("type", "'%s'", mnt->mnt_type);
+ entry ("options", "'%s'", mnt->mnt_opts);
+
+ show_pathconfs (what, mnt->mnt_dir);
+
+ section_open ("device");
+ entry ("major", "%u", major);
+ entry ("minor", "%u", minor);
+ section_close ();
+
+ entry ("dump frequency", "%d", mnt->mnt_freq);
+ entry ("fsck pass number", "%d", mnt->mnt_passno);
+
+ if (have_stats) {
+ union fsid_u {
+ unsigned long int fsid;
+ unsigned int val[2];
+ } fsid_val;
+
+ memset (&fsid_val, 0, sizeof (fsid_val));
+
+ fsid_val.fsid = fs.f_fsid;
+
+ entry ("fsid", "%.*x%.*x",
+ 2 * sizeof (fsid_val.val[0]),
+ fsid_val.val[0],
+ 2 * sizeof (fsid_val.val[1]),
+ fsid_val.val[1]);
+
+ entry ("optimal block size", "%lu", fs.f_bsize);
+
+ section_open ("blocks");
+
+ entry ("size", "%lu bytes", DF_BLOCK_SIZE);
+ entry ("total", "%lu", blocks);
+ entry ("used", "%lu", used_blocks);
+ entry ("free", "%lu", bfree);
+ entry ("available", "%lu", bavail);
+
+ section_close ();
+
+ section_open ("files/inodes");
+
+ entry ("total", "%lu", fs.f_files);
+ entry ("used", "%lu", used_files);
+ entry ("free", "%lu", fs.f_ffree);
+
+ section_close ();
+ } else {
+ entry ("fsid", "%s", UNKNOWN_STR);
+ entry ("optimal block size", "%s", UNKNOWN_STR);
+
+ section_open ("blocks");
+
+ entry ("size", "%lu bytes", DF_BLOCK_SIZE);
+ entry ("total", "%s", UNKNOWN_STR);
+ entry ("used", "%s", UNKNOWN_STR);
+ entry ("free", "%s", UNKNOWN_STR);
+ entry ("available", "%s", UNKNOWN_STR);
+
+ section_close ();
+
+ section_open ("files/inodes");
+
+ entry ("total", "%s", UNKNOWN_STR);
+ entry ("used", "%s", UNKNOWN_STR);
+ entry ("free", "%s", UNKNOWN_STR);
+
+ section_close ();
+ }
+
+ section_close ();
+ } else {
+ show_pathconfs (what, mnt->mnt_dir);
+ }
+ }
+
+ fclose (mtab);
+}
+
+#endif /* PROCENV_PLATFORM_LINUX || PROCENV_PLATFORM_HURD */
diff --git a/src/platform/platform-generic.h b/src/platform/platform-generic.h
new file mode 100644
index 0000000..a8eab6b
--- /dev/null
+++ b/src/platform/platform-generic.h
@@ -0,0 +1,74 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_GENERIC_H
+#define _PROCENV_PLATFORM_GENERIC_H
+
+#include "types.h"
+
+void show_fds_generic (void);
+void show_rlimits_generic (void);
+void show_confstrs_generic (void);
+long get_kernel_bits_generic (void);
+
+#if !defined (PROCENV_PLATFORM_MINIX)
+int get_mtu_generic (const struct ifaddrs *ifaddr);
+#endif
+
+#if defined (PROCENV_PLATFORM_LINUX) || \
+ defined (PROCENV_PLATFORM_BSD) || \
+ defined (PROCENV_PLATFORM_HURD) || \
+ defined (PROCENV_PLATFORM_MINIX)
+
+void show_cpu_affinities_generic (void);
+
+#endif
+
+#if defined (PROCENV_PLATFORM_LINUX) || \
+ defined (PROCENV_PLATFORM_BSD) || \
+ defined (PROCENV_PLATFORM_HURD) || \
+ defined (PROCENV_PLATFORM_MINIX) || \
+ defined (PROCENV_PLATFORM_DARWIN)
+
+void show_pathconfs (ShowMountType what, const char *dir);
+
+#endif
+
+#if defined (PROCENV_PLATFORM_BSD) || \
+ defined (PROCENV_PLATFORM_MINIX) || \
+ defined (PROCENV_PLATFORM_DARWIN)
+
+char *get_mount_opts_generic_bsd (const struct procenv_map64 *opts, uint64_t flags);
+void show_mounts_generic_bsd (ShowMountType what,
+ const struct procenv_map64 *mntopt_map);
+
+#endif
+
+#if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_HURD)
+
+void show_mounts_generic_linux (ShowMountType what);
+int get_canonical_generic_linux (const char *path, char *canonical, size_t len);
+
+#endif /* PROCENV_PLATFORM_LINUX || PROCENV_PLATFORM_HURD */
+
+#if !defined (PROCENV_PLATFORM_DARWIN)
+bool get_time_generic (struct timespec *ts);
+void show_clocks_generic (void);
+#endif
+
+#endif /* _PROCENV_PLATFORM_GENERIC_H */
diff --git a/src/platform/unknown/platform-unknown.h b/src/platform/unknown/platform-unknown.h
new file mode 100644
index 0000000..049c060
--- /dev/null
+++ b/src/platform/unknown/platform-unknown.h
@@ -0,0 +1,25 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PLATFORM_UNKNOWN_H
+#define _PROCENV_PLATFORM_UNKNOWN_H
+
+#include "platform.h"
+#include "util.h"
+
+#endif /* _PROCENV_PLATFORM_UNKNOWN_H */
diff --git a/src/platform/unknown/platform.c b/src/platform/unknown/platform.c
new file mode 100644
index 0000000..0f3d9f6
--- /dev/null
+++ b/src/platform/unknown/platform.c
@@ -0,0 +1,91 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "platform-unknown.h"
+
+static struct procenv_map signal_map_generic[] = {
+
+ mk_map_entry (SIGABRT),
+ mk_map_entry (SIGALRM),
+ mk_map_entry (SIGBUS),
+
+ { SIGCHLD, "SIGCHLD|SIGCLD" },
+
+ mk_map_entry (SIGCONT),
+
+#if defined SIGEMT
+ mk_map_entry (SIGEMT),
+#endif
+
+ mk_map_entry (SIGFPE),
+ mk_map_entry (SIGHUP),
+ mk_map_entry (SIGILL),
+
+#if defined SIGINFO
+ mk_map_entry (SIGINFO),
+#endif
+
+ mk_map_entry (SIGINT),
+
+#if defined SIGIO
+ mk_map_entry (SIGIO),
+#endif
+
+#if defined SIGIOT
+ mk_map_entry (SIGIOT),
+#endif
+
+ mk_map_entry (SIGKILL),
+ mk_map_entry (SIGPIPE),
+ mk_map_entry (SIGPOLL),
+ mk_map_entry (SIGPROF),
+
+#if defined SIGPWR
+ mk_map_entry (SIGPWR),
+#endif
+
+ mk_map_entry (SIGQUIT),
+ mk_map_entry (SIGSEGV),
+ mk_map_entry (SIGSTOP),
+ mk_map_entry (SIGSYS),
+ mk_map_entry (SIGTERM),
+ mk_map_entry (SIGTRAP),
+ mk_map_entry (SIGTSTP),
+ mk_map_entry (SIGTTIN),
+ mk_map_entry (SIGTTOU),
+ mk_map_entry (SIGURG),
+ mk_map_entry (SIGUSR1),
+ mk_map_entry (SIGUSR2),
+ mk_map_entry (SIGVTALRM),
+ mk_map_entry (SIGWINCH),
+ mk_map_entry (SIGXCPU),
+ mk_map_entry (SIGXFSZ),
+
+ { 0, NULL },
+};
+
+struct procenv_ops platform_ops =
+{
+ .driver = PROCENV_SET_DRIVER (unknown),
+
+ .get_time = get_time_generic,
+
+ .signal_map = signal_map_generic,
+ .show_fds = show_fds_generic,
+ .show_clocks = show_clocks_generic,
+};
diff --git a/src/pr_list.c b/src/pr_list.c
index f1403bd..cb20a22 100644
--- a/src/pr_list.c
+++ b/src/pr_list.c
@@ -48,7 +48,7 @@ pr_list_new (void *data)
return list;
}
-inline int
+int
pr_list_empty(PRList *list)
{
assert (list);
@@ -262,9 +262,9 @@ pr_list_add_sorted_internal(PRList *list,
direction = prepend ? 1 : -1;
if (direction > 0) {
- p = start = list->next;
+ start = list->next;
} else {
- p = start = list->prev;
+ start = list->prev;
}
for (p = start; p != list; p = pr_list_next(p, direction)) {
diff --git a/src/pr_list.h b/src/pr_list.h
index 7c430ae..9a97084 100644
--- a/src/pr_list.h
+++ b/src/pr_list.h
@@ -1,7 +1,7 @@
/*--------------------------------------------------------------------
* procenv - generic list handling header.
*
- * Copyright 2012-2015 James Hunt <jamesodhunt@ubuntu.com>.
+ * Copyright 2012-2016 James Hunt <jamesodhunt@ubuntu.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/procenv.c b/src/procenv.c
index 966eef5..fa4780f 100644
--- a/src/procenv.c
+++ b/src/procenv.c
@@ -9,7 +9,7 @@
* Licence: GPLv3. See below...
*--------------------------------------------------------------------
*
- * Copyright © 2012-2015 James Hunt <jamesodhunt@ubuntu.com>.
+ * Copyright © 2012-2016 James Hunt <jamesodhunt@ubuntu.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,55 +36,11 @@
pstring *doc = NULL;
/**
- * output:
- *
- * Where to send output.
- **/
-Output output = OUTPUT_STDOUT;
-
-/**
- * output_format:
- *
- * Format output will be displayed in.
- **/
-OutputFormat output_format = OUTPUT_FORMAT_TEXT;
-
-/**
- * output_file:
- *
- * Name or output file to send output to if not NULL.
- **/
-const char *output_file = NULL;
-
-/**
- * text_separator:
- *
- * Separator used for text output format to separate a name from a
- * value.
- **/
-const char *text_separator = PROCENV_DEFAULT_TEXT_SEPARATOR;
-
-/**
- * crumb_separator:
- *
- * Separator used for text output format to separate a name from a
- * value.
- **/
-const char *crumb_separator = PROCENV_DEFAULT_CRUMB_SEPARATOR;
-
-/**
- * output_fd:
- *
- * File descriptor associated with output_file.
- **/
-int output_fd = -1;
-
-/**
* reexec:
*
- * TRUE if we should re-exec at the end.
+ * true if we should re-exec at the end.
**/
-int reexec = FALSE;
+int reexec = false;
/**
* selected_option:
@@ -95,27 +51,6 @@ int reexec = FALSE;
**/
int selected_option = 0;
-/**
- * indent:
- *
- * Current output indent value.
- **/
-int indent = 0;
-
-/**
- * indent_amount:
- *
- * Number of INDENT_CHARs to emit for an indent.
- **/
-int indent_amount = DEFAULT_INDENT_AMOUNT;
-
-/**
- * indent_char, wide_indent_char:
- *
- * Character to use for indenting and wide-char equivalent.
- **/
-const char *indent_char = DEFAULT_INDENT_CHAR;
-wchar_t wide_indent_char;
/**
* program_name:
@@ -142,288 +77,20 @@ int argvc = 0;
**/
char *saved_locale = NULL;
-/**
- * last_element: Type of previous element handled.
- **/
-ElementType last_element = ELEMENT_TYPE_NONE;
-
-/**
- * current_element: Type of element currently being handled.
- **/
-ElementType current_element = ELEMENT_TYPE_NONE;
+/* Get a handle to the platform-specific routines */
+extern struct procenv_ops platform_ops;
+struct procenv_ops *ops = &platform_ops;
-/**
- * crumb_list:
- *
- * List used to store breadcrumbs when OUTPUT_FORMAT_CRUMB being used.
- **/
-static PRList *crumb_list = NULL;
+extern wchar_t wide_indent_char;
+extern int indent;
struct procenv_user user;
struct procenv_misc misc;
struct procenv_priority priority;
+struct procenv_priority priority_io;
struct utsname uts;
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-struct mntopt_map {
- uint64_t flag;
- char *name;
-} mntopt_map[] = {
-
- { MNT_ACLS , "acls" },
- { MNT_ASYNC , "asynchronous" },
- { MNT_EXPORTED , "NFS-exported" },
- { MNT_GJOURNAL , "gjournal" },
- { MNT_LOCAL , "local" },
- { MNT_MULTILABEL , "multilabel" },
-#ifndef PROCENV_GNU_BSD
- { MNT_NFS4ACLS , "nfsv4acls" },
-#endif
- { MNT_NOATIME , "noatime" },
- { MNT_NOCLUSTERR , "noclusterr" },
- { MNT_NOCLUSTERW , "noclusterw" },
- { MNT_NOEXEC , "noexec" },
- { MNT_NOSUID , "nosuid" },
- { MNT_NOSYMFOLLOW , "nosymfollow" },
- { MNT_QUOTA , "with quotas" },
- { MNT_RDONLY , "read-only" },
- { MNT_SOFTDEP , "soft-updates" },
- { MNT_SUIDDIR , "suiddir" },
-#if ! defined (PROCENV_GNU_BSD) && defined (MNT_SUJ)
- { MNT_SUJ , "journaled soft-updates" },
-#endif
- { MNT_SYNCHRONOUS , "synchronous" },
- { MNT_UNION , "union" },
-
- { 0, NULL }
-};
-#endif
-
-struct procenv_map output_map[] = {
- { OUTPUT_FILE , "file" },
- { OUTPUT_STDERR , "stderr" },
- { OUTPUT_STDOUT , "stdout" },
- { OUTPUT_SYSLOG , "syslog" },
- { OUTPUT_TERM , "terminal" },
-
- { 0, NULL }
-};
-
-struct procenv_map output_format_map[] = {
- { OUTPUT_FORMAT_TEXT, "text" },
- { OUTPUT_FORMAT_CRUMB, "crumb" },
- { OUTPUT_FORMAT_JSON, "json" },
- { OUTPUT_FORMAT_XML, "xml" },
-
- { 0, NULL }
-};
-
-struct baud_speed baud_speeds[] = {
- SPEED (B0),
- SPEED (B50),
- SPEED (B75),
- SPEED (B110),
- SPEED (B134),
- SPEED (B150),
- SPEED (B200),
- SPEED (B300),
- SPEED (B600),
- SPEED (B1200),
- SPEED (B1800),
- SPEED (B2400),
- SPEED (B4800),
- SPEED (B9600),
- SPEED (B19200),
- SPEED (B38400),
- SPEED (B57600),
- SPEED (B115200),
- SPEED (B230400),
-
- /* terminator */
- { 0, NULL }
-};
-
-struct if_flag_map {
- unsigned int flag;
- char *name;
-} if_flag_map[] = {
- mk_map_entry (IFF_UP),
- mk_map_entry (IFF_BROADCAST),
- mk_map_entry (IFF_DEBUG),
- mk_map_entry (IFF_LOOPBACK),
- mk_map_entry (IFF_POINTOPOINT),
- mk_map_entry (IFF_RUNNING),
- mk_map_entry (IFF_NOARP),
- mk_map_entry (IFF_PROMISC),
-
-#if defined (PROCENV_LINUX)
- mk_map_entry (IFF_NOTRAILERS),
-#endif
-
- mk_map_entry (IFF_ALLMULTI),
-
-#if defined (PROCENV_LINUX)
- mk_map_entry (IFF_MASTER),
- mk_map_entry (IFF_SLAVE),
-#endif
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
- mk_map_entry (IFF_SIMPLEX),
-#endif
-
- mk_map_entry (IFF_MULTICAST),
-
-#if defined (PROCENV_LINUX)
- mk_map_entry (IFF_PORTSEL),
- mk_map_entry (IFF_AUTOMEDIA),
- mk_map_entry (IFF_DYNAMIC),
- mk_map_entry (IFF_LOWER_UP),
- mk_map_entry (IFF_DORMANT),
-# ifdef IFF_ECHO
- mk_map_entry (IFF_ECHO),
-# endif
-#endif
-
- { 0, NULL }
-};
-
-/*
- * Note the gross hack to avoid need for flexible arrays.
- */
-TranslateTable translate_table[] = {
- {
- OUTPUT_FORMAT_XML,
- {
- { L'\'', L"&apos;" },
- { L'"', L"&quot;" },
- { L'&', L"&amp;" },
- { L'<', L"&lt;" },
- { L'>', L"&gt;" },
-
- /* terminator */
- { L'\0', NULL }
- }
- },
- {
- OUTPUT_FORMAT_JSON,
- {
- { L'"', L"\\\"" },
- { L'\\', L"\\\\" },
-
- /* hack! */
- { L'\0', NULL },
- { L'\0', NULL },
- { L'\0', NULL },
-
- /* terminator */
- { L'\0', NULL }
- }
- },
-};
-
-#if defined (PROCENV_LINUX)
-struct if_extended_flag_map {
- unsigned int flag;
- char *name;
-} if_extended_flag_map[] = {
-#if defined (IFF_802_1Q_VLAN)
- mk_map_entry (IFF_802_1Q_VLAN),
-#endif
-#if defined (IFF_EBRIDGE)
- mk_map_entry (IFF_EBRIDGE),
-#endif
-#if defined (IFF_SLAVE_INACTIVE)
- mk_map_entry (IFF_SLAVE_INACTIVE),
-#endif
-#if defined (IFF_MASTER_8023AD)
- mk_map_entry (IFF_MASTER_8023AD),
-#endif
-#if defined (IFF_MASTER_ALB)
- mk_map_entry (IFF_MASTER_ALB),
-#endif
-#if defined (IFF_BONDING)
- mk_map_entry (IFF_BONDING),
-#endif
-#if defined (IFF_SLAVE_NEEDARP)
- mk_map_entry (IFF_SLAVE_NEEDARP),
-#endif
-#if defined (IFF_ISATAP)
- mk_map_entry (IFF_ISATAP),
-#endif
- { 0, NULL }
-};
-
-struct personality_map {
- unsigned int personality;
- char *name;
-} personality_map[] = {
- mk_map_entry (PER_LINUX),
- mk_map_entry (PER_LINUX_32BIT),
- mk_map_entry (PER_SVR4),
- mk_map_entry (PER_SVR3),
- mk_map_entry (PER_SCOSVR3),
- mk_map_entry (PER_OSR5),
- mk_map_entry (PER_WYSEV386),
- mk_map_entry (PER_ISCR4),
- mk_map_entry (PER_BSD),
- mk_map_entry (PER_SUNOS),
- mk_map_entry (PER_XENIX),
-#if defined (PER_LINUX32)
- mk_map_entry (PER_LINUX32),
-#endif
-#if defined (PER_LINUX32_3GB)
- mk_map_entry (PER_LINUX32_3GB),
-#endif
- mk_map_entry (PER_IRIX32),
- mk_map_entry (PER_IRIXN32),
- mk_map_entry (PER_IRIX64),
- mk_map_entry (PER_RISCOS),
- mk_map_entry (PER_SOLARIS),
- mk_map_entry (PER_UW7),
- mk_map_entry (PER_OSF4),
- mk_map_entry (PER_HPUX),
-
- { 0, NULL }
-};
-
-struct personality_flag_map {
- unsigned int flag;
- char *name;
-} personality_flag_map[] = {
-#if defined (ADDR_COMPAT_LAYOUT)
- mk_map_entry (ADDR_COMPAT_LAYOUT),
-#endif
-#if defined (ADDR_LIMIT_32BIT)
- mk_map_entry (ADDR_LIMIT_32BIT),
-#endif
-#if defined (ADDR_LIMIT_3GB)
- mk_map_entry (ADDR_LIMIT_3GB),
-#endif
-#if defined (ADDR_NO_RANDOMIZE)
- mk_map_entry (ADDR_NO_RANDOMIZE),
-#endif
-#if defined (MMAP_PAGE_ZERO)
- mk_map_entry (MMAP_PAGE_ZERO),
-#endif
-#if defined (READ_IMPLIES_EXEC)
- mk_map_entry (READ_IMPLIES_EXEC),
-#endif
-#if defined (SHORT_INODE)
- mk_map_entry (SHORT_INODE),
-#endif
-#if defined (STICKY_TIMEOUTS)
- mk_map_entry (STICKY_TIMEOUTS),
-#endif
-#if defined (WHOLE_SECONDS)
- mk_map_entry (WHOLE_SECONDS),
-#endif
-
- { 0, NULL }
-};
-
-#endif
-
/* Really, every single sysconf variable should be ifdef'ed since it
* may not exist on a particular system, but that makes the code look
* untidy.
@@ -611,11 +278,11 @@ struct procenv_map sysconf_map[] = {
#endif
#if defined (_SC_EQUIV_CLASS_MAX)
- mk_sysconf_map_entry (_SC_EQUIV_CLASS_MAX),
+ mk_sysconf_map_entry (_SC_EQUIV_CLASS_MAX),
#endif
#if defined (_SC_EXPR_NEST_MAX)
- mk_sysconf_map_entry (_SC_EXPR_NEST_MAX),
+ mk_sysconf_map_entry (_SC_EXPR_NEST_MAX),
#endif
#if defined (_SC_FD_MGMT)
@@ -782,7 +449,7 @@ struct procenv_map sysconf_map[] = {
mk_sysconf_map_entry (_SC_MQ_PRIO_MAX),
#endif
-#ifdef _SC_MULTI_PROCESS
+#if defined (_SC_MULTI_PROCESS)
mk_sysconf_map_entry (_SC_MULTI_PROCESS),
#endif
@@ -1281,83 +948,9 @@ struct procenv_map sysconf_map[] = {
{ 0, NULL }
};
-/* Signal numbers are different per architecture.
- *
- * This lookup table allows use to ignore the numbers and display nice
- * symbolic names and also to order by signal number (which values
- * change on different architectures).
- */
-struct procenv_map signal_map[] = {
-
- mk_map_entry (SIGABRT),
- mk_map_entry (SIGALRM),
- mk_map_entry (SIGBUS),
-
- { SIGCHLD, "SIGCHLD|SIGCLD" },
-
- mk_map_entry (SIGCONT),
- mk_map_entry (SIGFPE),
- mk_map_entry (SIGHUP),
- mk_map_entry (SIGILL),
- mk_map_entry (SIGINT),
- mk_map_entry (SIGKILL),
- mk_map_entry (SIGPIPE),
- mk_map_entry (SIGQUIT),
- mk_map_entry (SIGSEGV),
- mk_map_entry (SIGSTOP),
- mk_map_entry (SIGTERM),
- mk_map_entry (SIGTRAP),
- mk_map_entry (SIGTSTP),
- mk_map_entry (SIGTTIN),
- mk_map_entry (SIGTTOU),
- mk_map_entry (SIGUSR1),
- mk_map_entry (SIGUSR2),
- mk_map_entry (SIGIO),
-#if defined (PROCENV_LINUX)
- mk_map_entry (SIGIOT),
-#endif
-
-#if defined (PROCENV_LINUX)
- {SIGPOLL, "SIGPOLL|SIGIO" },
-#endif
-
- mk_map_entry (SIGPROF),
-
-#if defined (PROCENV_LINUX)
- mk_map_entry (SIGPWR),
-#ifdef SIGSTKFLT
- mk_map_entry (SIGSTKFLT),
-#endif
-#endif
-
- mk_map_entry (SIGSYS),
-
-#if defined (PROCENV_LINUX)
-#ifdef SIGUNUSED
- mk_map_entry (SIGUNUSED),
-#endif
-#endif
- mk_map_entry (SIGURG),
- mk_map_entry (SIGVTALRM),
- mk_map_entry (SIGWINCH),
- mk_map_entry (SIGXCPU),
- mk_map_entry (SIGXFSZ),
-
-#if defined (PROCENV_BSD) || defined (PROCENV_HURD)
- mk_map_entry (SIGEMT),
- mk_map_entry (SIGINFO),
-#endif
-
-#if defined (PROCENV_HURD)
- mk_map_entry (SIGLOST),
-#endif
-
- { 0, NULL },
-};
-
struct procenv_map locale_map[] = {
- /* The non-conditional ones are POSIX. */
+ /* The non-conditional ones are POSIX. */
#ifdef LC_ADDRESS
mk_map_entry (LC_ADDRESS),
#endif
@@ -1386,35 +979,19 @@ struct procenv_map locale_map[] = {
{ 0, NULL }
};
-struct procenv_map scheduler_map[] = {
-
- mk_map_entry (SCHED_OTHER),
- mk_map_entry (SCHED_FIFO),
- mk_map_entry (SCHED_RR),
-#if defined (PROCENV_LINUX) && ! defined (PROCENV_ANDROID)
- mk_map_entry (SCHED_BATCH),
-#ifdef SCHED_IDLE
- mk_map_entry (SCHED_IDLE),
-#endif
-#endif
-
- { 0, NULL }
-};
-
struct procenv_map thread_sched_policy_map[] = {
mk_map_entry (SCHED_OTHER),
mk_map_entry (SCHED_FIFO),
mk_map_entry (SCHED_RR)
};
-#if defined (PROCENV_LINUX) && defined (HAVE_NUMA_H)
-struct procenv_map numa_mempolicy_map[] = {
- mk_map_entry (MPOL_DEFAULT),
- mk_map_entry (MPOL_PREFERRED),
- mk_map_entry (MPOL_BIND),
- mk_map_entry (MPOL_INTERLEAVE),
+struct network_map {
+ struct ifaddrs ifaddr;
+ char *mac_address;
+
+ struct network_map *next;
+ struct network_map *prev;
};
-#endif
void
usage (void)
@@ -1433,7 +1010,7 @@ usage (void)
show (" -C, --cpu : Display CPU and scheduler details.");
show (" --crumb-separator=<str> : Specify string '<str>' as alternate delimiter");
show (" for crumb format output (default='%s').",
- PROCENV_DEFAULT_CRUMB_SEPARATOR);
+ get_crumb_separator ());
show (" -d, --compiler : Display compiler details.");
show (" -e, --environment : Display environment variables.");
show (" -E, --semaphores : Display semaphore details.");
@@ -1441,6 +1018,8 @@ usage (void)
show (" -f, --fds : Display file descriptor details.");
show (" -F, --namespaces : Display namespace details.");
show (" --file=<file> : Send output to <file> (implies --output=file).");
+ show (" --file-append : Append to file specified by '--file='");
+ show (" rather than overwriting");
show (" --format=<format> : Specify output format. <format> can be one of:");
show ("");
show (" crumb : ASCII 'breadcrumbs'");
@@ -1452,9 +1031,9 @@ usage (void)
show (" -h, --help : This help text.");
show (" -i, --misc : Display miscellaneous details.");
show (" --indent : Number of indent characters to use for each indent");
- show (" (default=%d).", DEFAULT_INDENT_AMOUNT);
+ show (" (default=%d).", get_indent_amount ());
show (" --indent-char=<c> : Use character '<c>' for indenting");
- show (" (default='%s').", DEFAULT_INDENT_CHAR);
+ show (" (default='%s').", get_indent_char ());
show (" -j, --uname : Display uname details.");
show (" -k, --clocks : Display clock details.");
show (" -l, --limits : Display limits.");
@@ -1479,7 +1058,7 @@ usage (void)
show (" -r, --ranges : Display range of data types.");
show (" --separator=<str> : Specify string '<str>' as alternate delimiter");
show (" for text format output (default='%s').",
- PROCENV_DEFAULT_TEXT_SEPARATOR);
+ get_text_separator ());
show (" -s, --signals : Display signal details.");
show (" -S, --shared-memory : Display shared memory details.");
show (" -t, --tty : Display terminal details.");
@@ -1496,7 +1075,7 @@ usage (void)
show ("Notes:");
show ("");
show (" - Options are considered in order, so '--output' should");
- show (" precede any other option.");
+ show (" precede any other option.");
show (" - If no display option is specified, all details are displayed.");
show (" - Only one display option may be specified.");
show (" - All values for '--indent-char' are literal except '\\t' which can be");
@@ -1512,786 +1091,6 @@ usage (void)
show ("");
}
-void
-show_pathconfs (ShowMountType what,
- const char *dir)
-{
- assert (dir);
-
- if (what == SHOW_PATHCONF) {
- header (dir);
- } else {
- header ("pathconf");
- }
-
-
-#if defined (_PC_ALLOC_SIZE_MIN)
- show_pathconf (what, dir, _PC_ALLOC_SIZE_MIN);
-#endif
-
-#if defined (_PC_ASYNC_IO)
- show_pathconf (what, dir, _PC_ASYNC_IO);
-#endif
-
-#if defined (_PC_CHOWN_RESTRICTED)
- show_pathconf (what, dir, _PC_CHOWN_RESTRICTED);
-#endif
-
-#if defined (_PC_FILESIZEBITS)
- show_pathconf (what, dir, _PC_FILESIZEBITS);
-#endif
-
-#if defined (_PC_LINK_MAX)
- show_pathconf (what, dir, _PC_LINK_MAX);
-#endif
-
-#if defined (_PC_MAX_CANON)
- show_pathconf (what, dir, _PC_MAX_CANON);
-#endif
-
-#if defined (_PC_MAX_INPUT)
- show_pathconf (what, dir, _PC_MAX_INPUT);
-#endif
-
-#if defined (_PC_NAME_MAX)
- show_pathconf (what, dir, _PC_NAME_MAX);
-#endif
-
-#if defined (_PC_NO_TRUNC)
- show_pathconf (what, dir, _PC_NO_TRUNC);
-#endif
-
-#if defined (_PC_PATH_MAX)
- show_pathconf (what, dir, _PC_PATH_MAX);
-#endif
-
-#if defined (_PC_PIPE_BUF)
- show_pathconf (what, dir, _PC_PIPE_BUF);
-#endif
-
-#if defined (_PC_PRIO_IO)
- show_pathconf (what, dir, _PC_PRIO_IO);
-#endif
-
-#if defined (_PC_REC_INCR_XFER_SIZE)
- show_pathconf (what, dir, _PC_REC_INCR_XFER_SIZE);
-#endif
-
-#if defined (_PC_REC_MAX_XFER_SIZE)
- show_pathconf (what, dir, _PC_REC_MAX_XFER_SIZE);
-#endif
-
-#if defined (_PC_REC_MIN_XFER_SIZE)
- show_pathconf (what, dir, _PC_REC_MIN_XFER_SIZE);
-#endif
-
-#if defined (_PC_REC_XFER_ALIGN)
- show_pathconf (what, dir, _PC_REC_XFER_ALIGN);
-#endif
-
-#if defined (_PC_SOCK_MAXBUF)
- show_pathconf (what, dir, _PC_SOCK_MAXBUF);
-#endif
-
-#if defined (_PC_SYMLINK_MAX)
- show_pathconf (what, dir, _PC_SYMLINK_MAX);
-#endif
-
-#if defined (_PC_2_SYMLINKS)
- show_pathconf (what, dir, _PC_2_SYMLINKS);
-#endif
-
-#if defined (_PC_SYNC_IO)
- show_pathconf (what, dir, _PC_SYNC_IO);
-#endif
-
-#if defined (_PC_VDISABLE)
- show_pathconf (what, dir, _PC_VDISABLE);
-#endif
-
- footer ();
-}
-
-const char *
-get_speed (speed_t speed)
-{
- struct baud_speed *s;
-
- for (s = baud_speeds; s && s->name; s++) {
- if (speed == s->speed)
- return s->name;
- }
-
- return NULL;
-}
-
-/**
- * _show:
- *
- * @prefix: string prefix to write,
- * @indent: number of spaces to indent output to,
- * @fmt: printf-style format with associated arguments that comprises
- * the value part.
- *
- * Write output to @string, indented by @indent spaces. A trailing newline
- * will be added.
- *
- * Note that error scenarios cannot call die() as by definition output
- * may not be possible.
- **/
-void
-_show (const char *prefix, int indent, const char *fmt, ...)
-{
- va_list ap;
- char *buffer = NULL;
-
- assert (fmt);
-
- if (indent)
- appendf (&buffer, "%*s", indent, indent_char);
-
- if (prefix && *prefix)
- appendf (&buffer, "%s: ", prefix);
-
- va_start (ap, fmt);
- appendva (&buffer, fmt, ap);
- va_end (ap);
-
- append (&buffer, "\n");
-
- _show_output (buffer);
-
- free (buffer);
-}
-
-/**
- * entry:
- *
- * @name: name of thing to display,
- * @fmt: printf-style format with associated arguments that comprises
- * the value part.
- *
- * Add name/value pair represented by @name and value comprising
- * printf-format string to the @doc global. The value added will be
- * indented appropriately.
- **/
-void
-entry (const char *name, const char *fmt, ...)
-{
- va_list ap;
- pstring *encoded_name = NULL;
- pstring *encoded_value = NULL;
-
- assert (name);
- assert (fmt);
-
- common_assert ();
-
- change_element (ELEMENT_TYPE_ENTRY);
-
- encoded_name = char_to_pstring (name);
- if (! encoded_name)
- die ("failed to encode name");
-
- /* annoyingly, we must encode here; we cannot simply call
- * encode_string() once just prior to showing the output
- * document since if the output format is XML, we'd end
- * up encoding the XML tags themselves, not just the values
- * within!
- */
- if (encode_string (&encoded_name) < 0)
- die ("failed to encode name");
-
- /* expand format */
- va_start (ap, fmt);
- wmappendva (&encoded_value, fmt, ap);
- va_end (ap);
-
- if (encode_string (&encoded_value) < 0)
- die ("failed to encode value");
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB:
- assert (crumb_list);
-
- /* Add the bread crumbs */
- PR_LIST_FOREACH (crumb_list, iter) {
- char *crumb = (char *)iter->data;
- wappendf (&doc,
- L"%s%s",
- crumb,
- crumb_separator);
- }
-
- wappendf (&doc,
- L"%ls%s%ls\n",
- encoded_name->buf,
- text_separator,
- encoded_value->buf);
- break;
-
- case OUTPUT_FORMAT_TEXT:
- wappendf (&doc,
- L"%ls%s%ls",
- encoded_name->buf,
- text_separator,
- encoded_value->buf);
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappendf (&doc,
- L"\"%ls\" : \"%ls\"",
- encoded_name->buf,
- encoded_value->buf);
- break;
-
- case OUTPUT_FORMAT_XML:
- wappendf (&doc,
- L"<entry name=\"%ls\">%ls</entry>",
- encoded_name->buf,
- encoded_value->buf);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-
- pstring_free (encoded_name);
- pstring_free (encoded_value);
-}
-
-/**
- * _show_output:
- *
- * @string: String to display.
- *
- * Write output @string to appropriate location based on Output
- * destination.
- **/
-void
-_show_output_pstring (const pstring *pstr)
-{
- char *str;
-
- assert (pstr);
-
- str = pstring_to_char (pstr);
-
- _show_output (str);
-
- free (str);
-}
-
-void
-_show_output (const char *str)
-{
- int ret;
-
- assert (str);
-
- switch (output) {
- case OUTPUT_SYSLOG:
- syslog (LOG_INFO, "%s", str);
- ret = 0;
- break;
-
- case OUTPUT_STDOUT:
- ret = fputs (str, stdout);
- break;
-
- case OUTPUT_STDERR:
- ret = fputs (str, stderr);
- break;
-
- case OUTPUT_TERM:
- assert (user.tty_fd != -1);
- ret = write (user.tty_fd, str, strlen (str));
- if (ret < 0) {
- fprintf (stderr, "ERROR: failed to write to terminal\n");
- exit (EXIT_FAILURE);
- }
- break;
-
- case OUTPUT_FILE:
- assert (output_file);
- if (output_fd < 0) {
- output_fd = open (output_file,
- (O_WRONLY|O_CREAT),
- (S_IRWXU|S_IRGRP|S_IROTH));
- if (output_fd < 0) {
- fprintf (stderr, "ERROR: failed to open file '%s'\n",
- output_file);
- exit (EXIT_FAILURE);
- }
- }
- ret = write (output_fd, str, strlen (str));
- if (ret < 0) {
- fprintf (stderr, "ERROR: failed to write to file '%s'\n",
- output_file);
- exit (EXIT_FAILURE);
- }
- break;
-
- default:
- fprintf (stderr, "ERROR: invalid output type: %d\n", output);
- exit (EXIT_FAILURE);
- break;
- }
-
- if (ret < 0) {
- fprintf (stderr, "ERROR: failed to output message\n");
- exit (EXIT_FAILURE);
- }
-}
-
-/**
- * inc_indent:
- *
- * Increase indent.
- **/
-void
-inc_indent (void)
-{
- assert (indent >= 0);
-
- indent += indent_amount;
-}
-
-/**
- * dec_indent:
- *
- * Decrease indent.
- **/
-void
-dec_indent (void)
-{
- assert (indent >= 0);
-
- indent -= indent_amount;
-
- assert (indent >= 0);
-}
-
-/**
- * add_indent:
- *
- * Insert the current indent to the output document.
- **/
-void
-add_indent (pstring **doc)
-{
- common_assert ();
-
- if (! indent)
- return;
-
- if (! strcmp (indent_char, DEFAULT_INDENT_CHAR)) {
- wappendf (doc, L"%*s", indent, indent_char);
- } else {
- pstring *buffer = NULL;
-
- // Expand the buffer to the appropriate
- // length by filling it with spaces and a random
- // character.
- wappendf (&buffer, L"%*lc", indent, wide_indent_char);
-
-
- /* Now, replace the spaces and the random character with
- * the chosen character. This convoluted approach is
- * necessary as printf-type functions don't allow the
- * padding character to be specified.
- */
- wmemset (buffer->buf, wide_indent_char, wcslen (buffer->buf));
-
- pappend (doc, buffer);
- pstring_free (buffer);
- }
-}
-
-/**
- * master_header:
- *
- * @doc: document to write footer to.
- *
- * Main header which is displayed once.
- **/
-void
-master_header (pstring **doc)
-{
- common_assert ();
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_JSON:
- object_open (FALSE);
- break;
-
- case OUTPUT_FORMAT_XML:
- wappend (doc, L"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- wappendf (doc, L"<%s version=\"%s\" package_string=\"%s\" "
- "mode=\"%s%s\" format_version=\"%d\">\n",
- PACKAGE_NAME, PACKAGE_VERSION, PACKAGE_STRING,
- user.euid ? _(NON_STR) "-" : "",
- PRIVILEGED_STR,
- PROCENV_FORMAT_VERSION);
-
- inc_indent ();
-
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * master_footer:
- *
- * @doc: document to write footer to.
- *
- * Main footer which is displayed once.
- **/
-void
-master_footer (pstring **doc)
-{
- common_assert ();
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* Tweak */
- wappend (doc, L"\n");
- break;
-
- case OUTPUT_FORMAT_JSON:
- object_close (FALSE);
-
- /* Tweak */
- wappend (doc, L"\n");
- break;
-
- case OUTPUT_FORMAT_XML:
- /* Tweak */
- wappend (doc, L"\n");
- dec_indent ();
- wappendf (doc, L"</%s>\n", PACKAGE_NAME);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * object_open:
- *
- * @retain: if TRUE, do not disrupt the current element such that the
- * opening of the object will be invisible to the state machine, but
- * will still produce the required output.
- *
- * Note: @retain is only meaningful for OUTPUT_FORMAT_JSON.
- *
- * Handle opening an object.
- **/
-void
-object_open (int retain)
-{
- common_assert ();
-
- if (output_format == OUTPUT_FORMAT_JSON) {
- if (retain) {
- format_element ();
- } else {
- change_element (ELEMENT_TYPE_OBJECT_OPEN);
- }
- } else {
- /* Objects are only required for handling JSON. In
- * fact, they cause problems for other output formats
- * that do not have visible "objects" in that they cause
- * the state table to lose track of the previous element
- * since it is actually the previous-previous element
- * (as the pointless object is the previous element).
- *
- * As such, ignore them.
- */
- }
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappend (&doc, L"{");
- break;
-
- case OUTPUT_FORMAT_XML:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * object_close:
- *
- * @retain: if TRUE, do not disrupt the current element such that the
- * object closure will be invisible to the state machine, but will still
- * produce @retain: if TRUE, do not disrupt the current element.
- *
- * Note: @retain is only meaningful for OUTPUT_FORMAT_JSON.
- *
- * Handle closing an object.
- **/
-void
-object_close (int retain)
-{
- common_assert ();
-
- if (output_format == OUTPUT_FORMAT_JSON) {
- if (retain) {
- format_element ();
- } else {
- change_element (ELEMENT_TYPE_OBJECT_CLOSE);
- }
- } else {
- /* Objects are only required for handling JSON. In
- * fact, they cause problems for other output formats
- * that do not have visible "objects" in that they cause
- * the state table to lose track of the previous element
- * since it is actually the previous-previous element
- * (as the pointless object is the previous element).
- *
- * As such, ignore them.
- */
- }
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappend (&doc, L"}");
- break;
-
- case OUTPUT_FORMAT_XML:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * section_open:
- *
- * @name: name of section.
- *
- * Start a new section which will contain >0 entry() calls.
- **/
-void
-section_open (const char *name)
-{
- assert (name);
- common_assert ();
-
- change_element (ELEMENT_TYPE_SECTION_OPEN);
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- wappendf (&doc, L"%s:", name);
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- add_breadcrumb (name);
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappendf (&doc, L"\"%s\" : {", name);
- break;
-
- case OUTPUT_FORMAT_XML:
- wappendf (&doc, L"<section name=\"%s\">", name);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-section_close (void)
-{
- common_assert ();
-
- change_element (ELEMENT_TYPE_SECTION_CLOSE);
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- remove_breadcrumb ();
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappend (&doc, L"}");
- break;
-
- case OUTPUT_FORMAT_XML:
- wappend (&doc, L"</section>");
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * container_open:
- *
- * @name: name of container.
- *
- * Start a new container which will contain >0 entry() calls.
- *
- * This is primarily to handle JSON arrays.
- **/
-void
-container_open (const char *name)
-{
- assert (name);
- common_assert ();
-
- change_element (ELEMENT_TYPE_CONTAINER_OPEN);
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- wappendf (&doc, L"%s:", name);
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- add_breadcrumb (name);
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappendf (&doc, L"\"%s\" : [", name);
- break;
-
- case OUTPUT_FORMAT_XML:
- wappendf (&doc, L"<container name=\"%s\">", name);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * container_close:
- *
- * Finish with a container.
- **/
-void
-container_close (void)
-{
- common_assert ();
-
- change_element (ELEMENT_TYPE_CONTAINER_CLOSE);
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- remove_breadcrumb ();
- break;
-
- case OUTPUT_FORMAT_JSON:
- wappend (&doc, L"]");
- break;
-
- case OUTPUT_FORMAT_XML:
- wappend (&doc, L"</container>");
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-header (const char *name)
-{
- assert (name);
- common_assert ();
-
- section_open (name);
-}
-
-void
-footer (void)
-{
- common_assert ();
- section_close ();
-}
-
-/**
- * fd_valid:
- * @fd: file descriptor.
- *
- * Return 1 if @fd is valid, else 0.
- **/
-int
-fd_valid (int fd)
-{
- int flags = 0;
-
- if (fd < 0)
- return 0;
-
- errno = 0;
- flags = fcntl (fd, F_GETFL);
-
- if (flags < 0)
- return 0;
-
- /* redundant really */
- if (errno == EBADF)
- return 0;
-
- return 1;
-}
-
/**
* show_signals:
*
@@ -2320,23 +1119,38 @@ fd_valid (int fd)
void
show_signals (void)
{
- int i;
- int rc;
- int blocked;
- int ignored;
- sigset_t old_sigset;
- struct sigaction act;
+ int i;
+ int rc;
+ int blocked;
+ int ignored;
+ sigset_t old_sigset;
+ struct sigaction act;
+ const struct procenv_map *p;
+ int max;
container_open ("signals");
/* Query blocked signals.
*
- * How should be 0, but valgrind complains.
+ * arg 1 ('how') should be 0, but valgrind complains.
*/
if (sigprocmask (SIG_BLOCK, NULL, &old_sigset) < 0)
die ("failed to query signal mask");
- for (i = 1; i <= NUM_SIGNALS; i++) {
+ /* first, count the number of entries in the platform-specific
+ * signal map.
+ */
+ for (p = ops->signal_map, max = 1;
+ p && p->name;
+ p++, max++) {
+ ; /* NOP */
+ }
+
+ /* Note that we don't interate the signal map directly in case the
+ * entries are out of order. Instead, present the signals in numeric
+ * order.
+ */
+ for (i = 1; i < max; i++) {
const char *signal_name;
const char *signal_desc;
@@ -2365,7 +1179,7 @@ show_signals (void)
signal_desc = strsignal (i);
- object_open (FALSE);
+ object_open (false);
section_open (signal_name);
@@ -2377,73 +1191,12 @@ show_signals (void)
section_close ();
- object_close (FALSE);
+ object_close (false);
}
- container_close ();
+ container_close ();
}
-void
-show_rlimits (void)
-{
- header ("limits");
-
- show_limit (RLIMIT_AS);
- show_limit (RLIMIT_CORE);
- show_limit (RLIMIT_CPU);
- show_limit (RLIMIT_DATA);
- show_limit (RLIMIT_FSIZE);
-
-#if defined (PROCENV_LINUX)
-
- if (LINUX_KERNEL_MMR (2, 6, 25)) {
-#if defined (RLIMIT_RTTIME)
- show_limit (RLIMIT_RTTIME);
-#endif
- }
- show_limit (RLIMIT_LOCKS);
-#endif
-
- show_limit (RLIMIT_MEMLOCK);
-
-#if defined (PROCENV_LINUX)
-
- if (LINUX_KERNEL_MMR (2, 6, 8)) {
-#if defined (RLIMIT_MSGQUEUE)
- show_limit (RLIMIT_MSGQUEUE);
-#endif
- }
-
- if (LINUX_KERNEL_MMR (2, 6, 12)) {
-#if defined RLIMIT_NICE
- show_limit (RLIMIT_NICE);
-#endif
- }
-
-#endif
-
- show_limit (RLIMIT_NOFILE);
- show_limit (RLIMIT_NPROC);
- show_limit (RLIMIT_RSS);
-
-#if defined (PROCENV_LINUX)
- show_limit (RLIMIT_RTPRIO);
-#endif
-
-#if defined (PROCENV_LINUX)
-
- if (LINUX_KERNEL_MMR (2, 6, 8)) {
-#if defined (RLIMIT_SIGPENDING)
- show_limit (RLIMIT_SIGPENDING);
-#endif
- }
-
-#endif
-
- show_limit (RLIMIT_STACK);
-
- footer ();
-}
void
show_rusage (void)
@@ -2470,305 +1223,29 @@ show_rusage (void)
show_usage (usage, ru_nvcsw);
show_usage (usage, ru_nivcsw);
- footer ();
+ footer ();
}
void
show_sysconf (void)
{
- struct procenv_map *p;
- long value;
+ struct procenv_map *p;
+ long value;
header ("sysconf");
for (p = sysconf_map; p && p->name; p++) {
value = get_sysconf (p->num);
- if (value == -1)
+ if (value == -1) {
entry (p->name, "%s", NA_STR);
- else
+ } else {
entry (p->name, "%ld", value);
+ }
}
- footer ();
-}
-
-#ifndef PROCENV_ANDROID
-
-void
-show_confstrs (void)
-{
- header ("confstr");
-
-#if defined (_CS_GNU_LIBC_VERSION)
- show_confstr (_CS_GNU_LIBC_VERSION);
-#endif
-
-#if defined (_CS_GNU_LIBPTHREAD_VERSION)
- show_confstr (_CS_GNU_LIBPTHREAD_VERSION);
-#endif
-
-#if defined (_CS_LFS64_CFLAGS)
- show_confstr (_CS_LFS64_CFLAGS);
-#endif
-
-#if defined (_CS_LFS64_LDFLAGS)
- show_confstr (_CS_LFS64_LDFLAGS);
-#endif
-
-#if defined (_CS_LFS64_LIBS)
- show_confstr (_CS_LFS64_LIBS);
-#endif
-
-#if defined (_CS_LFS64_LINTFLAGS)
- show_confstr (_CS_LFS64_LINTFLAGS);
-#endif
-
-#if defined (_CS_LFS_CFLAGS)
- show_confstr (_CS_LFS_CFLAGS);
-#endif
-
-#if defined (_CS_LFS_LDFLAGS)
- show_confstr (_CS_LFS_LDFLAGS);
-#endif
-
-#if defined (_CS_LFS_LIBS)
- show_confstr (_CS_LFS_LIBS);
-#endif
-
-#if defined (_CS_LFS_LINTFLAGS)
- show_confstr (_CS_LFS_LINTFLAGS);
-#endif
-
-#if defined (_CS_PATH)
- show_confstr (_CS_PATH);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32_CFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32_LDFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32_LIBS)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFF32_LINTFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFF32_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LIBS)
- show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS)
- show_confstr (_CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LP64_OFF64_CFLAGS)
- show_confstr (_CS_POSIX_V6_LP64_OFF64_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LP64_OFF64_LDFLAGS)
- show_confstr (_CS_POSIX_V6_LP64_OFF64_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LP64_OFF64_LIBS)
- show_confstr (_CS_POSIX_V6_LP64_OFF64_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V6_LP64_OFF64_LINTFLAGS)
- show_confstr (_CS_POSIX_V6_LP64_OFF64_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS)
- show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS)
- show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LIBS)
- show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS)
- show_confstr (_CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFF32_CFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFF32_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFF32_LDFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFF32_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFF32_LIBS)
- show_confstr (_CS_POSIX_V7_ILP32_OFF32_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFF32_LINTFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFF32_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LIBS)
- show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS)
- show_confstr (_CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LP64_OFF64_CFLAGS)
- show_confstr (_CS_POSIX_V7_LP64_OFF64_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LP64_OFF64_LDFLAGS)
- show_confstr (_CS_POSIX_V7_LP64_OFF64_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LP64_OFF64_LIBS)
- show_confstr (_CS_POSIX_V7_LP64_OFF64_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V7_LP64_OFF64_LINTFLAGS)
- show_confstr (_CS_POSIX_V7_LP64_OFF64_LINTFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS)
- show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS)
- show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LIBS)
- show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS)
- show_confstr (_CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
- show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS);
-#endif
-
-#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
- _show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS, "_XBS5_WIDTH_RESTRICTED_ENVS");
-#endif
-
-#if defined (_CS_V5_WIDTH_RESTRICTED_ENVS)
- _show_confstr (_CS_V5_WIDTH_RESTRICTED_ENVS, "XBS5_WIDTH_RESTRICTED_ENVS");
-#endif
-
-#if defined (_CS_V6_WIDTH_RESTRICTED_ENVS)
- show_confstr (_CS_V6_WIDTH_RESTRICTED_ENVS);
-#endif
-
-#if defined (_CS_V6_WIDTH_RESTRICTED_ENVS)
- _show_confstr (_CS_V6_WIDTH_RESTRICTED_ENVS, "POSIX_V6_WIDTH_RESTRICTED_ENVS,_POSIX_V6_WIDTH_RESTRICTED_ENVS");
-#endif
-
-#if defined (_CS_V7_WIDTH_RESTRICTED_ENVS)
- show_confstr (_CS_V7_WIDTH_RESTRICTED_ENVS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFF32_CFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFF32_CFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFF32_LDFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFF32_LDFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFF32_LIBS)
- show_confstr (_CS_XBS5_ILP32_OFF32_LIBS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFF32_LINTFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFF32_LINTFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFFBIG_CFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFFBIG_LDFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFFBIG_LIBS)
- show_confstr (_CS_XBS5_ILP32_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_XBS5_ILP32_OFFBIG_LINTFLAGS)
- show_confstr (_CS_XBS5_ILP32_OFFBIG_LINTFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LP64_OFF64_CFLAGS)
- show_confstr (_CS_XBS5_LP64_OFF64_CFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LP64_OFF64_LDFLAGS)
- show_confstr (_CS_XBS5_LP64_OFF64_LDFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LP64_OFF64_LIBS)
- show_confstr (_CS_XBS5_LP64_OFF64_LIBS);
-#endif
-
-#if defined (_CS_XBS5_LP64_OFF64_LINTFLAGS)
- show_confstr (_CS_XBS5_LP64_OFF64_LINTFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LPBIG_OFFBIG_CFLAGS)
- show_confstr (_CS_XBS5_LPBIG_OFFBIG_CFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LPBIG_OFFBIG_LDFLAGS)
- show_confstr (_CS_XBS5_LPBIG_OFFBIG_LDFLAGS);
-#endif
-
-#if defined (_CS_XBS5_LPBIG_OFFBIG_LIBS)
- show_confstr (_CS_XBS5_LPBIG_OFFBIG_LIBS);
-#endif
-
-#if defined (_CS_XBS5_LPBIG_OFFBIG_LINTFLAGS)
- show_confstr (_CS_XBS5_LPBIG_OFFBIG_LINTFLAGS);
-#endif
-
-
footer ();
}
-#endif
-
void
get_misc (void)
{
@@ -2776,43 +1253,16 @@ get_misc (void)
(void)umask (misc.umask_value);
assert (getcwd (misc.cwd, sizeof (misc.cwd)));
-#if defined (PROCENV_LINUX)
- get_canonical (ROOT_PATH, misc.root, sizeof (misc.root));
-#endif
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
- get_misc_bsd ();
-#endif
-}
-
-#if !defined (PROCENV_HURD)
-/**
- * is_console:
- * @fd: open file descriptor.
- *
- * Check if specified file descriptor is attached to a _console_
- * device (physical or virtual).
- *
- * Notes:
- * - ptys are NOT consoles :)
- * - running inside screen/tmux will report not running on console.
- *
- * Returns: TRUE if @fd is attached to a console, else FALSE.
- **/
-int
-is_console (int fd)
-{
- struct vt_mode vt;
- int ret;
-
- ret = ioctl (fd, VT_GETMODE, &vt);
-
- return !ret;
+ if (ops->get_user_misc)
+ ops->get_user_misc (&user, &misc);
}
-#endif
void
show_proc (void)
{
+ const char *suid = NULL;
+ const char *sgid = NULL;
+
header ("process");
entry ("process id (pid)", "%d", user.pid);
@@ -2824,12 +1274,12 @@ show_proc (void)
entry ("name", "'%s'", user.proc_name);
- show_proc_branch ();
+ handle_proc_branch ();
entry ("process group id", "%d (leader=%s)",
user.pgroup,
is_process_group_leader () ? YES_STR : NO_STR);
-
+
entry ("foreground process group", "%d", user.fg_pgroup);
entry ("terminal", "'%s'", user.ctrl_terminal);
@@ -2837,7 +1287,10 @@ show_proc (void)
entry ("has controlling terminal", "%s",
has_ctty () ? YES_STR : NO_STR);
-#if defined (PROCENV_HURD)
+ /* FIXME: Is it possible to detect if on console on hurd/minix? */
+#if defined (PROCENV_PLATFORM_HURD) || \
+ defined (PROCENV_PLATFORM_MINIX) || \
+ defined (PROCENV_PLATFORM_DARWIN)
entry ("on console", "%s", UNKNOWN_STR);
#else
entry ("on console", "%s",
@@ -2854,9 +1307,12 @@ show_proc (void)
user.euid,
get_user_name (user.euid));
- entry ("saved set-user-id (suid)", "%d ('%s')",
+ suid = get_user_name (user.suid);
+ entry ("saved set-user-id (suid)", "%d (%s%s%s)",
user.suid,
- get_user_name (user.suid));
+ suid ? "'" : "",
+ suid ? suid : UNKNOWN_STR,
+ suid ? "'" : "");
section_close ();
@@ -2870,9 +1326,12 @@ show_proc (void)
user.egid,
get_group_name (user.egid));
- entry ("saved set-group-id (sgid)", "%d ('%s')",
+ sgid = get_group_name (user.sgid);
+ entry ("saved set-group-id (sgid)", "%d (%s%s%s)",
user.sgid,
- get_group_name (user.sgid));
+ sgid ? "'" : "",
+ sgid ? sgid : UNKNOWN_STR,
+ sgid ? "'" : "");
section_close ();
@@ -2882,7 +1341,7 @@ show_proc (void)
entry ("name", "'%s'", user.passwd.pw_name);
-#if ! defined (PROCENV_ANDROID)
+#if ! defined (PROCENV_PLATFORM_ANDROID)
/* No gecos on Android. In fact it doesn't actually use the
* passwd database, but meh.
*/
@@ -2894,7 +1353,10 @@ show_proc (void)
section_close ();
+#if ! defined (PROCENV_PLATFORM_MINIX)
+ /* Calling getgroups(2) with Minix 3.3.0 always returns EINVAL :( */
show_all_groups ();
+#endif
footer ();
}
@@ -2902,19 +1364,10 @@ show_proc (void)
void
show_priorities (void)
{
-#if defined (PROCENV_LINUX)
- int sched;
-
- sched = sched_getscheduler (0);
-#endif
-
section_open ("scheduler");
-#if defined (PROCENV_LINUX)
- entry ("type", "%s",
- sched < 0 ? UNKNOWN_STR :
- get_scheduler_name (sched));
-#endif
+ if (ops->handle_scheduler_type)
+ ops->handle_scheduler_type ();
section_open ("priority");
@@ -2924,83 +1377,19 @@ show_priorities (void)
section_close ();
- section_close ();
-}
-
-void
-show_misc (void)
-{
-#if defined (PROCENV_LINUX)
- int domain = 0x0;
-
- /* magic value - see personality(2) */
- unsigned int persona = 0xFFFFFFFF;
-
- unsigned int mask = PER_MASK;
-
- const char *personality_name = NULL;
- char *personality_flags = NULL;
-#endif
-
- header ("misc");
-
- entry ("umask", "%4.4o", misc.umask_value);
- entry ("current directory (cwd)", "'%s'", misc.cwd);
-#if defined (PROCENV_LINUX)
- entry ("root", "%s%s%s",
- strcmp (misc.root, UNKNOWN_STR) ? "'" : "",
- misc.root,
- strcmp (misc.root, UNKNOWN_STR) ? "'" : "");
-#endif
- entry ("chroot", "%s", in_chroot () ? YES_STR : NO_STR);
- entry ("container", "%s", container_type ());
-
-#if defined (PROCENV_LINUX)
- show_prctl_linux ();
-
- section_open ("linux security module");
- show_security_module_linux ();
- show_security_module_context_linux ();
- section_close ();
-#endif
-
-#if defined (PROCENV_LINUX)
-#ifdef LINUX_VERSION_CODE
- entry ("kernel headers version", "%u.%u.%u",
- (LINUX_VERSION_CODE >> 16),
- ((LINUX_VERSION_CODE >> 8) & 0xFF),
- (LINUX_VERSION_CODE & 0xFF));
-#endif
-
- domain = personality (persona);
-
- personality_name = get_personality_name (domain & mask);
-
- section_open ("personality");
-
- entry ("type", "%s", personality_name
- ? personality_name
- : UNKNOWN_STR);
-
- personality_flags = get_personality_flags (domain & (-1 ^ mask));
- entry ("flags", "%s",
- personality_flags
- ? personality_flags
- : "");
+ if (ops->show_io_priorities) {
+ section_open ("I/O priority");
+ ops->show_io_priorities ();
+ section_close ();
+ }
section_close ();
-
- if (personality_flags)
- free (personality_flags);
-#endif
-
- footer ();
}
void
show_platform (void)
{
- long kernel_bits;
+ long kernel_bits = -1;
long executable_bits;
header ("platform");
@@ -3008,7 +1397,8 @@ show_platform (void)
entry ("operating system", "%s", get_os ());
entry ("architecture", "%s", get_arch ());
- kernel_bits = get_kernel_bits ();
+ if (ops->get_kernel_bits)
+ kernel_bits = ops->get_kernel_bits ();
executable_bits = sizeof (void *) * CHAR_BIT * sizeof (char);
@@ -3020,11 +1410,11 @@ show_platform (void)
entry ("executable bits", "%lu", executable_bits);
entry ("code endian", "%s",
- is_big_endian () ? BIG_STR : LITTLE_STR);
+ is_big_endian () ? BIG_STR : LITTLE_STR);
show_data_model ();
- footer ();
+ footer ();
}
void
@@ -3032,14 +1422,11 @@ show_cpu (void)
{
header ("cpu");
-#if defined (PROCENV_LINUX)
- show_cpu_linux ();
-#endif
+ if (ops->show_cpu)
+ ops->show_cpu ();
-#if defined (PROCENV_BSD)
- show_cpu_bsd ();
-#endif
- show_cpu_affinities ();
+ if (ops->show_cpu_affinities)
+ ops->show_cpu_affinities ();
show_priorities ();
@@ -3053,224 +1440,30 @@ show_memory (void)
entry ("page size", "%d bytes", getpagesize ());
-#if defined (PROCENV_LINUX)
- show_numa_memory ();
-#endif /* PROCENV_LINUX */
+ if (ops->handle_numa_memory)
+ ops->handle_numa_memory ();
footer ();
}
-/* Display cpu affinities in the same compressed but reasonably
- * human-readable fashion as /proc/self/status:Cpus_allowed_list under Linux.
- */
-void
-show_cpu_affinities (void)
-{
- int ret = 0;
- long max;
- size_t size;
-#if defined (PROCENV_BSD) || ! defined (CPU_ALLOC)
- PROCENV_CPU_SET_TYPE cpu_set_real;
-#endif
- PROCENV_CPU_SET_TYPE *cpu_set;
- long cpu;
- char *cpu_list = NULL;
-
- /* TRUE if any enabled cpus have been displayed yet */
- int displayed = FALSE;
-
- /* Number of cpu's in *current* range */
- size_t count = 0;
-
- /* Only valid to read these when count is >0 */
- size_t last = 0;
- size_t first = 0;
-
- max = get_sysconf (_SC_NPROCESSORS_ONLN);
- if (max < 0)
- die ("failed to query cpu count");
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD) || defined (PROCENV_HURD)
-
-#if defined (CPU_ALLOC)
-
- cpu_set = CPU_ALLOC (max);
- assert (cpu_set);
-
- size = CPU_ALLOC_SIZE (max);
- CPU_ZERO_S (size, cpu_set);
-
-#else /* ! CPU_ALLOC */
-
- /* RHEL 5 */
-
- cpu_set = &cpu_set_real;
-
- size = sizeof (PROCENV_CPU_SET_TYPE);
-
-#endif /* CPU_ALLOC */
-
-#elif defined (PROCENV_BSD) || ! defined (CPU_ALLOC)
- cpu_set = &cpu_set_real;
-
- size = sizeof (PROCENV_CPU_SET_TYPE);
-
-#endif /* PROCENV_LINUX || PROCENV_GNU_BSD || PROCENV_HURD */
-
- /* We could use sched_getaffinity(2) rather than
- * sched_getaffinity() on Linux (2.5.8+) but
- * pthread_getaffinity_np() provides the same information...
- * Except it is missing on kFreeBSD systems (!) so we have to
- * use sched_getaffinity() there. :(
- */
-#if (defined (PROCENV_GNU_BSD) || defined (PROCENV_HURD)) || (defined (PROCENV_LINUX) && ! defined (CPU_ALLOC))
- ret = sched_getaffinity (0, size, cpu_set);
-#else
-
-#if defined (PROCENV_LINUX) && defined (CPU_ALLOC)
- /* On a hyperthreaded system, "size" as above may not actually
- be big enough, and we get EINVAL. (hwloc has a similar
- workaround.) */
-
- {
- int mult = 0;
- while ((ret = pthread_getaffinity_np (pthread_self (), size, cpu_set))
- == EINVAL) {
- CPU_FREE (cpu_set);
- /* Bail out at an arbitrary value. */
- if (mult > 128) break;
- mult += 2;
- cpu_set = CPU_ALLOC (mult * max);
- size = CPU_ALLOC_SIZE (mult * max);
- CPU_ZERO_S (size, cpu_set);
- }
- }
-#endif /* PROCENV_LINUX && CPU_ALLOC */
-
-#endif
-
- if (ret)
- goto out;
-
- for (cpu = 0; cpu < max; cpu++) {
-
- if (CPU_ISSET (cpu, cpu_set)) {
-
- /* Record first entry in the range */
- if (! count)
- first = cpu;
-
- last = cpu;
- count++;
- } else {
- if (count) {
- if (first == last) {
- appendf (&cpu_list, "%s%d",
- displayed ? "," : "",
- first);
- } else {
- appendf (&cpu_list, "%s%d-%d",
- displayed ? "," : "",
- first, last);
- }
- displayed = TRUE;
- }
-
- /* Reset */
- count = 0;
- }
- }
-
- if (count) {
- if (first == last) {
- appendf (&cpu_list, "%s%d",
- displayed ? "," : "",
- first);
- } else {
- appendf (&cpu_list, "%s%d-%d",
- displayed ? "," : "",
- first, last);
- }
- }
-
-out:
- entry ("affinity list", "%s", cpu_list ? cpu_list : "-1");
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD) || defined (PROCENV_HURD)
-#if defined (CPU_ALLOC)
- CPU_FREE (cpu_set);
-#endif
-#endif
-
- free (cpu_list);
-}
-
-
void
show_fds (void)
{
-#if defined (PROCENV_LINUX)
- show_fds_linux ();
-#else
- show_fds_generic ();
-#endif
+ container_open ("file descriptors");
-}
-
-void
-show_namespaces (void)
-{
-#if defined (PROCENV_LINUX)
- show_namespaces_linux ();
-#else
- show_namespaces_stub ();
-#endif
+ if (ops->show_fds)
+ ops->show_fds ();
+ container_close ();
}
void
-show_fds_generic (void)
+show_namespaces (void)
{
- int fd;
- int max;
-
- container_open ("file descriptors");
-
- max = get_sysconf (_SC_OPEN_MAX);
-
- for (fd = 0; fd < max; fd++) {
- int is_tty = isatty (fd);
- char *name = NULL;
- char *num = NULL;
-
- if (! fd_valid (fd))
- continue;
-
-#if ! defined (PROCENV_ANDROID)
- name = ttyname (fd);
-#endif
- appendf (&num, "%d", fd);
-
- object_open (FALSE);
-
- section_open (num);
-
- entry ("terminal", "%s", is_tty ? YES_STR : NO_STR);
- entry ("valid", "%s", fd_valid (fd) ? YES_STR : NO_STR);
- entry ("device", "%s", name ? name : NA_STR);
-
- section_open ("capabilities");
-#if defined (PROCENV_BSD) && defined (HAVE_SYS_CAPABILITY_H)
- show_capabilities_bsd (fd);
-#endif
- section_close ();
-
- section_close ();
-
- object_close (FALSE);
+ container_open ("namespaces");
- free (num);
- }
+ if (ops->show_namespaces)
+ ops->show_namespaces ();
container_close ();
}
@@ -3343,30 +1536,34 @@ get_user_info (void)
{
struct passwd *pw;
void *p;
+#if defined (HAVE_GETRESUID) || defined (HAVE_GETRESGID)
int ret;
+#endif
user.pid = getpid ();
user.ppid = getppid ();
-#if defined (PROCENV_LINUX)
- if (LINUX_KERNEL_MMR (2, 6, 11)) {
- if (prctl (PR_GET_NAME, user.proc_name, 0, 0, 0) < 0)
- strcpy (user.proc_name, UNKNOWN_STR);
- }
-#endif
+ if (ops->get_proc_name)
+ ops->get_proc_name(&user);
-#ifdef _GNU_SOURCE
+#ifdef HAVE_GETRESUID
ret = getresuid (&user.uid, &user.euid, &user.suid);
assert (! ret);
+#else
+ user.uid = getuid ();
+ user.euid = geteuid ();
+ /* no saved uid */
+ user.suid = -1;
+#endif
+#ifdef HAVE_GETRESGID
getresgid (&user.gid, &user.egid, &user.sgid);
assert (! ret);
#else
- /* NB: no saved uid+gid */
- user.uid = getuid ();
- user.euid = geteuid ();
user.gid = getgid ();
user.egid = getegid ();
+ /* no saved gid */
+ user.sgid = -1;
#endif
user.sid = getsid ((pid_t)0);
@@ -3384,7 +1581,7 @@ get_user_info (void)
user.login = getlogin ();
user.pgroup = getpgrp ();
-#if defined (PROCENV_ANDROID)
+#if defined (PROCENV_PLATFORM_ANDROID)
sprintf (user.ctrl_terminal, "/dev/tty");
#else
ctermid (user.ctrl_terminal);
@@ -3406,7 +1603,6 @@ get_user_info (void)
user.tty_fd = STDIN_FILENO;
user.fg_pgroup = tcgetpgrp (user.tty_fd);
- user.pgid_sid = tcgetsid (user.tty_fd);
errno = 0;
pw = getpwuid (user.uid);
@@ -3417,464 +1613,6 @@ get_user_info (void)
assert (p == (void *)&user.passwd);
}
-/* append @src to @dest */
-void
-append (char **dest, const char *src)
-{
- size_t len;
-
- assert (dest);
- assert (src);
-
- len = strlen (src);
-
- appendn (dest, src, len);
-}
-
-/* Version of append() that operates on a wide string @dest and @src */
-void
-wappend (pstring **dest, const wchar_t *src)
-{
- size_t len;
-
- assert (dest);
- assert (src);
-
- len = wcslen (src);
-
- wappendn (dest, src, len);
-}
-
-/* Version of append() that operates on a wide string @dest
- * and multi-byte @src.
- */
-void
-wmappend (pstring **dest, const char *src)
-{
- wchar_t *wide_src = NULL;
-
- assert (dest);
- assert (src);
-
- wide_src = char_to_wchar (src);
- if (! wide_src)
- die ("failed to allocate space for wide string");
-
- wappend (dest, wide_src);
-
- free (wide_src);
-}
-
-/**
- * appendn:
- *
- * @dest: [output] string to append to,
- * @src: string to append to @dest,
- * @len: length of @new.
- *
- * Append first @len bytes of @new to @str,
- * ensuring result is nul-terminated.
- **/
-void
-appendn (char **dest, const char *src, size_t len)
-{
- size_t total;
-
- assert (dest);
- assert (src);
-
- if (! len)
- return;
-
- if (! *dest)
- *dest = strdup ("");
- if (! *dest)
- die ("failed to allocate space for string");
-
- /* +1 for terminating nul */
- total = strlen (*dest) + 1;
-
- total += len;
-
- *dest = realloc (*dest, total);
- assert (*dest);
-
- if (! *dest) {
- /* string is empty, so initialise the memory to avoid
- * surprises with strncat() being unable to find the
- * terminator!
- */
- memset (*dest, '\0', total);
- }
-
- strncat (*dest, src, len);
-
- assert ((*dest)[total-1] == '\0');
-}
-
-/* Version of appendn() that operates on a wide string @dest and @src */
-void
-wappendn (pstring **dest, const wchar_t *src, size_t len)
-{
- wchar_t *p;
- size_t total;
- size_t bytes;
-
- assert (dest);
- assert (src);
-
- if (! len)
- return;
-
- if (! *dest)
- *dest = pstring_new ();
- if (! *dest)
- die ("failed to allocate space for pstring");
-
- total = (*dest)->len + len;
-
- /* +1 for terminating nul */
- bytes = (1 + total) * sizeof (wchar_t);
-
- p = realloc ((*dest)->buf, bytes);
-
- /* FIXME: turn into die() [all occurences!] */
- assert (p);
-
- (*dest)->buf = p;
-
- if (! (*dest)->len) {
- /* pstring is empty, so initialise the memory to avoid
- * surprises with wcsncat() being unable to find the
- * terminator!
- */
- memset ((*dest)->buf, 0, bytes);
- }
-
- /* Used to check for overrun */
- (*dest)->buf[total] = L'\0';
-
- wcsncat ((*dest)->buf + (*dest)->len, src, len);
-
- /* update */
- (*dest)->len = total;
- (*dest)->size = bytes;
-
- /* check for overrun */
- assert ((*dest)->buf[total] == L'\0');
-}
-
-
-/* Version of appendn() that operates on a wide string @dest and
- * multi-byte @src.
- */
-void
-wmappendn (pstring **dest, const char *src, size_t len)
-{
- wchar_t *wide_src = NULL;
-
- assert (dest);
- assert (src);
-
- if (! len)
- return;
-
- wide_src = char_to_wchar (src);
- if (! wide_src)
- die ("failed to allocate space for wide string");
-
- wappendn (dest, wide_src, wcslen (wide_src));
-
- free (wide_src);
-}
-
-/* append @fmt and args to @dest */
-void
-appendf (char **dest, const char *fmt, ...)
-{
- va_list ap;
-
- assert (dest);
- assert (fmt);
-
- va_start (ap, fmt);
-
- appendva (dest, fmt, ap);
-
- va_end (ap);
-}
-
-/* Version of appendf() that operates on a wide string @dest
- * and @fmt.
- */
-void
-wappendf (pstring **dest, const wchar_t *fmt, ...)
-{
- va_list ap;
-
- assert (dest);
- assert (fmt);
-
- va_start (ap, fmt);
-
- wappendva (dest, fmt, ap);
-
- va_end (ap);
-}
-
-/* Version of appendf() that operates on a wide string @dest
- * and multi-byte @fmt.
- */
-void
-wmappendf (pstring **dest, const char *fmt, ...)
-{
- wchar_t *wide_fmt = NULL;
- va_list ap;
-
- assert (dest);
- assert (fmt);
-
- wide_fmt = char_to_wchar (fmt);
- if (! wide_fmt)
- die ("failed to allocate memory for wide format");
-
- va_start (ap, fmt);
-
- wappendva (dest, wide_fmt, ap);
-
- va_end (ap);
-
- free (wide_fmt);
-}
-
-/* append @fmt and args to @dest */
-void
-appendva (char **dest, const char *fmt, va_list ap)
-{
- int ret;
- char *new = NULL;
- char *p;
- size_t bytes;
-
- /* Start with a guess for how big we think the buffer needs to
- * be.
- */
- size_t len = DEFAULT_ALLOC_GUESS_SIZE;
-
- assert (dest);
- assert (fmt);
-
- bytes = (1 + len) * sizeof (char);
-
- /* we could use vasprintf(3), but that's GNU-specific and hence
- * not available everywhere we need it.
- */
- new = malloc (bytes);
- if (! new)
- die ("failed to allocate space for string");
-
- memset (new, '\0', bytes);
-
- /* keep on increasing size of buffer until the translation
- * succeeds.
- */
- while (TRUE) {
- va_list ap_copy;
-
- va_copy (ap_copy, ap);
- ret = vsnprintf (new, len, fmt, ap_copy);
- va_end (ap_copy);
-
- if (ret < 0)
- die ("failed to format string");
-
- if ((size_t)ret < len) {
- /* now we have sufficient space */
- break;
- }
-
- /* Bump to allow one char to be written */
- len++;
-
- /* recalculate number of bytes */
- bytes = (1 + len) * sizeof (char);
-
- p = realloc (new, bytes);
- if (! p)
- die ("failed to allocate space for string");
-
- new = p;
- }
-
- if (*dest) {
- append (dest, new);
- free (new);
- } else {
- *dest = new;
- }
-}
-
-/* Version of appendva() that operates on a wide string @dest
- * and @fmt.
- */
-void
-wappendva (pstring **dest, const wchar_t *fmt, va_list ap)
-{
- int ret;
- wchar_t *new = NULL;
- wchar_t *p;
- size_t bytes;
- va_list ap_copy;
-
- /* Start with a guess for how big we think the buffer needs to
- * be.
- */
- size_t len = DEFAULT_ALLOC_GUESS_SIZE;
-
- assert (dest);
- assert (fmt);
-
- bytes = (1 + len) * sizeof (wchar_t);
-
- new = malloc (bytes);
- if (! new)
- die ("failed to allocate space for wide string");
-
- memset (new, '\0', bytes);
-
- /* keep on increasing size of buffer until the translation
- * succeeds.
- */
- while (TRUE) {
- va_copy (ap_copy, ap);
- ret = vswprintf (new, len, fmt, ap_copy);
- va_end (ap_copy);
-
- if ((size_t)ret < len) {
- /* now we have sufficient space, so update for
- * actual number of bytes used (including the
- * terminator!)
- *
- * Note that, conveniently, if the string is
- * zero-characters long (ie ""), ret will be -1
- * which we correct to 0.
- */
- len = ret + 1;
-
- break;
- }
-
- /* Bump to allow one more wide-char to be written */
- len++;
-
- /* recalculate number of bytes */
- bytes = (1 + len) * sizeof (wchar_t);
-
- p = realloc (new, bytes);
- if (! p)
- die ("failed to allocate space for string");
-
- new = p;
-
- memset (new, '\0', bytes);
- }
-
- if (*dest) {
- wappend (dest, new);
- free (new);
- } else {
- wchar_t *n;
-
- /* recalculate number of bytes */
- bytes = (1 + len) * sizeof (wchar_t);
-
- /* compress */
- n = realloc (new, bytes);
-
- if (! n)
- die ("failed to reallocate space");
-
- new = n;
-
- (*dest) = pstring_new ();
- assert (*dest);
- (*dest)->buf = new;
- (*dest)->len = len;
- (*dest)->size = bytes;
- }
-}
-
-/* Version of appendva() that operates on a wide string @dest
- * and multi-byte @fmt.
- */
-void
-wmappendva (pstring **dest, const char *fmt, va_list ap)
-{
- wchar_t *wide_fmt = NULL;
- va_list ap_copy;
-
- assert (dest);
- assert (fmt);
-
- wide_fmt = char_to_wchar (fmt);
- if (! wide_fmt)
- die ("failed to allocate memory for wide format");
-
- va_copy (ap_copy, ap);
- wappendva (dest, wide_fmt, ap_copy);
- va_end (ap_copy);
-
- free (wide_fmt);
-}
-
-/*
- * Append @src onto the end of @dest.
- */
-void
-pappend (pstring **dest, const pstring *src)
-{
- size_t total;
- size_t bytes;
- wchar_t *p;
-
- assert (dest);
- assert (src);
-
- if (! src->len)
- return;
-
- if (! *dest)
- *dest = pstring_new ();
- if (! *dest)
- die ("failed to allocate space for pstring");
-
- total = (*dest)->len + src->len;
-
- /* adjust since we only store _one_ of the string terminators
- * from @dest and @src.
- */
- total--;
-
- /* +1 for terminating nul */
- bytes = (1 + total) * sizeof (wchar_t);
-
- p = realloc ((*dest)->buf, bytes);
-
- /* FIXME: turn into die() [all occurences!] */
- assert (p);
-
- (*dest)->buf = p;
-
- wcsncat ((*dest)->buf + (*dest)->len, src->buf, src->len);
-
- /* update */
- (*dest)->len = total;
- (*dest)->size = bytes;
-
- /* Used to check for overrun */
- (*dest)->buf[total] = L'\0';
-}
-
void
show_all_groups (void)
{
@@ -3901,7 +1639,7 @@ show_all_groups (void)
memset (groups, '\0', bytes);
- while (TRUE) {
+ while (true) {
ret = getgroups (size, groups);
if (ret >= 0)
break;
@@ -3919,7 +1657,7 @@ show_all_groups (void)
size = ret;
if (size == 0) {
- char *group;
+ const char *group;
free (groups);
@@ -4008,23 +1746,13 @@ restore_locale (void)
}
void
-handle_indent_char (void)
+init (void)
{
- size_t len;
-
- const char *new = indent_char;
+ assert (ops);
- len = mbsrtowcs (NULL, &new, 0, NULL);
- if (len != 1)
- die ("invalid indent character");
+ if (ops->init)
+ ops->init ();
- if (mbsrtowcs (&wide_indent_char, &new, len, NULL) != len)
- die ("failed to convert indent character");
-}
-
-void
-init (void)
-{
save_locale ();
handle_indent_char ();
@@ -4037,6 +1765,9 @@ init (void)
get_user_info ();
get_misc ();
get_priorities ();
+
+ if (ops->get_io_priorities)
+ ops->get_io_priorities (&priority_io);
}
void
@@ -4047,34 +1778,12 @@ cleanup (void)
close (user.tty_fd);
- if (output_fd != -1)
- close (output_fd);
-
- if (output == OUTPUT_SYSLOG)
- closelog ();
-
- if (output_format == OUTPUT_FORMAT_CRUMB && crumb_list) {
- clear_breadcrumbs ();
- free (crumb_list);
- }
+ output_finalise ();
pstring_free (doc);
-}
-
-/**
- * is_big_endian:
- *
- * Returns: TRUE if system is big-endian, else FALSE.
- **/
-bool
-is_big_endian (void)
-{
- int x = 1;
- if (*(char *)&x == 1)
- return FALSE;
-
- return TRUE;
+ if (ops->cleanup)
+ ops->cleanup ();
}
void
@@ -4099,6 +1808,11 @@ show_meta (void)
entry ("build-type", "%s", build_type);
+ section_open ("driver");
+ entry ("name", ops->driver.name);
+ entry ("file", ops->driver.file);
+ section_close ();
+
entry ("format-type", "%s", get_output_format_name ());
entry ("format-version", "%d", PROCENV_FORMAT_VERSION);
@@ -4121,11 +1835,11 @@ show_arguments (void)
appendf (&buffer, "argv[%d]", i);
- object_open (FALSE);
+ object_open (false);
entry (buffer, "%s", argvp[i]);
- object_close (FALSE);
+ object_close (false);
free (buffer);
}
@@ -4228,21 +1942,6 @@ show_stat (void)
footer ();
}
-long
-get_kernel_bits (void)
-{
-#if defined (PROCENV_LINUX) && ! defined (PROCENV_ANDROID)
- long value;
-
- errno = 0;
- value = get_sysconf (_SC_LONG_BIT);
- if (value == -1 && errno != 0)
- return -1;
- return value;
-#endif
- return -1;
-}
-
/* Dump out data in alphabetical fashion */
void
dump (void)
@@ -4256,16 +1955,12 @@ dump (void)
show_cgroups ();
show_clocks ();
show_compiler ();
-#ifndef PROCENV_ANDROID
show_confstrs ();
-#endif
show_cpu ();
show_env ();
show_fds ();
show_libc ();
-#ifndef PROCENV_ANDROID
show_libs ();
-#endif
show_rlimits ();
show_locale ();
show_memory ();
@@ -4283,6 +1978,7 @@ dump (void)
* as possible.
*/
show_rusage ();
+
show_semaphores ();
show_shared_mem ();
show_signals ();
@@ -4334,13 +2030,13 @@ get_network_address (const struct sockaddr *address, int family, char *name)
void
decode_if_flags (unsigned int flags)
{
- struct if_flag_map *p;
+ const struct procenv_map *p;
- for (p = if_flag_map; p && p->name; p++) {
- if (flags & p->flag) {
- object_open (FALSE);
- entry (p->name, "0x%x", p->flag);
- object_close (FALSE);
+ for (p = ops->if_flag_map; p && p->name; p++) {
+ if (flags & p->num) {
+ object_open (false);
+ entry (p->name, "0x%x", p->num);
+ object_close (false);
}
}
}
@@ -4382,64 +2078,37 @@ get_ipv6_scope_name (uint32_t scope)
return UNKNOWN_STR;
}
-int
-get_mtu (const struct ifaddrs *ifaddr)
-{
- int sock;
- struct ifreq ifr;
- unsigned long request = SIOCGIFMTU;
-
- assert (ifaddr);
-
- /* We need to create a socket to query an interfaces mac
- * address. Don't ask me why...
- */
- sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
-
- if (sock < 0)
- return -1;
-
- memset (&ifr, 0, sizeof (struct ifreq));
- strncpy (ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ-1);
-
- if (ioctl (sock, request, &ifr) < 0)
- ifr.ifr_mtu = 0;
-
- close (sock);
-
- return ifr.ifr_mtu;
-}
-
/*
*
* Returns: IEEE-802 format MAC address, or NULL on error.
*/
+#if !defined (PROCENV_PLATFORM_MINIX)
char *
get_mac_address (const struct ifaddrs *ifaddr)
{
char *data = NULL;
char *mac_address = NULL;
int i;
- int valid = FALSE;
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+ int valid = false;
+#if defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN)
struct sockaddr_dl *link_layer;
#else
struct ifreq ifr;
int sock = -1;
#endif
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
+#if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_HURD) || defined (PROCENV_PLATFORM_GENERIC)
unsigned long request = SIOCGIFHWADDR;
#endif
assert (ifaddr);
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+#if defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN)
link_layer = (struct sockaddr_dl *)ifaddr->ifa_addr;
#else
- /* We need to create a socket to query an interfaces mac
- * address. Don't ask me why...
+ /* We need to create a socket to query an interfaces MAC
+ * address.
*/
sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
@@ -4453,7 +2122,7 @@ get_mac_address (const struct ifaddrs *ifaddr)
goto out;
#endif
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+#if defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN)
data = LLADDR (link_layer);
#else
data = (char *)ifr.ifr_hwaddr.sa_data;
@@ -4462,7 +2131,7 @@ get_mac_address (const struct ifaddrs *ifaddr)
if (data) {
for (i = 0; i < 6; i++) {
if (data[i]) {
- valid = TRUE;
+ valid = true;
break;
}
}
@@ -4490,412 +2159,24 @@ get_mac_address (const struct ifaddrs *ifaddr)
out:
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+#if defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN)
/* NOP */
#else
close (sock);
#endif
return mac_address;
}
+#endif /* PROCENV_PLATFORM_MINIX */
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-void
-show_mounts_linux (ShowMountType what)
-{
- FILE *mtab;
- struct mntent *mnt;
- struct statvfs fs;
- unsigned int major = 0;
- unsigned int minor = 0;
- int have_stats;
-#if defined (PROCENV_LINUX)
- char canonical[PATH_MAX];
-#endif
-
- common_assert ();
-
- mtab = fopen (MOUNTS, "r");
-
- if (! mtab)
- return;
-
- while ((mnt = getmntent (mtab))) {
- have_stats = TRUE;
-
- if (what == SHOW_ALL || what == SHOW_MOUNTS) {
- unsigned multiplier = 0;
- fsblkcnt_t blocks = 0;
- fsblkcnt_t bfree = 0;
- fsblkcnt_t bavail = 0;
- fsblkcnt_t used_blocks = 0;
- fsblkcnt_t used_files = 0;
-#if defined (PROCENV_LINUX)
- int ret;
-#endif
-
- if (statvfs (mnt->mnt_dir, &fs) < 0) {
- have_stats = FALSE;
- } else {
- multiplier = fs.f_bsize / DF_BLOCK_SIZE;
-
- blocks = fs.f_blocks * multiplier;
- bfree = fs.f_bfree * multiplier;
- bavail = fs.f_bavail * multiplier;
- used_blocks = blocks - bfree;
- used_files = fs.f_files - fs.f_ffree;
- }
-
- (void)get_major_minor (mnt->mnt_dir,
- &major,
- &minor);
-
- assert (mnt->mnt_dir);
- section_open (mnt->mnt_dir);
-
- entry ("filesystem", "'%s'", mnt->mnt_fsname);
-
-#if defined (PROCENV_LINUX)
- ret = get_canonical (mnt->mnt_fsname, canonical, sizeof (canonical));
- entry ("canonical", "%s%s%s",
- ret ? "'" : "",
- canonical,
- ret ? "'" : "");
-#endif
-
- entry ("type", "'%s'", mnt->mnt_type);
- entry ("options", "'%s'", mnt->mnt_opts);
-
- show_pathconfs (what, mnt->mnt_dir);
-
- section_open ("device");
- entry ("major", "%u", major);
- entry ("minor", "%u", minor);
- section_close ();
-
- entry ("dump frequency", "%d", mnt->mnt_freq);
- entry ("fsck pass number", "%d", mnt->mnt_passno);
-
- if (have_stats) {
- union fsid_u {
- unsigned long int fsid;
- unsigned int val[2];
- } fsid_val;
-
- fsid_val.fsid = fs.f_fsid;
-
- entry ("fsid", "%.*x%.*x",
- 2 * sizeof (fsid_val.val[0]),
- fsid_val.val[0],
- 2 * sizeof (fsid_val.val[1]),
- fsid_val.val[1]);
-
- entry ("optimal block size", "%lu", fs.f_bsize);
-
- section_open ("blocks");
-
- entry ("size", "%lu bytes", DF_BLOCK_SIZE);
- entry ("total", "%lu", blocks);
- entry ("used", "%lu", used_blocks);
- entry ("free", "%lu", bfree);
- entry ("available", "%lu", bavail);
-
- section_close ();
-
- section_open ("files/inodes");
-
- entry ("total", "%lu", fs.f_files);
- entry ("used", "%lu", used_files);
- entry ("free", "%lu", fs.f_ffree);
-
- section_close ();
- } else {
- entry ("fsid", "%s", UNKNOWN_STR);
- entry ("optimal block size", "%s", UNKNOWN_STR);
-
- section_open ("blocks");
-
- entry ("size", "%lu bytes", DF_BLOCK_SIZE);
- entry ("total", "%s", UNKNOWN_STR);
- entry ("used", "%s", UNKNOWN_STR);
- entry ("free", "%s", UNKNOWN_STR);
- entry ("available", "%s", UNKNOWN_STR);
-
- section_close ();
-
- section_open ("files/inodes");
-
- entry ("total", "%s", UNKNOWN_STR);
- entry ("used", "%s", UNKNOWN_STR);
- entry ("free", "%s", UNKNOWN_STR);
-
- section_close ();
- }
-
- section_close ();
- } else {
- show_pathconfs (what, mnt->mnt_dir);
- }
- }
-
- fclose (mtab);
-}
-#endif
-
-#if defined (PROCENV_LINUX)
-void
-decode_extended_if_flags (const char *interface, unsigned short *flags)
-{
- int sock;
- struct ifreq ifr;
- struct if_extended_flag_map *p;
-
- assert (interface);
- assert (flags);
-
- /* We need to create a socket to query an interfaces mac
- * address. Don't ask me why...
- */
- sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
-
- if (sock < 0)
- return;
-
- memset (&ifr, 0, sizeof (struct ifreq));
- strncpy (ifr.ifr_name, interface, IFNAMSIZ-1);
-
- if (ioctl (sock, SIOCGIFPFLAGS, &ifr) < 0)
- goto out;
-
- *flags = ifr.ifr_flags;
-
- for (p = if_extended_flag_map; p && p->name; p++) {
- if (*flags & p->flag) {
- object_open (FALSE);
- entry (p->name, "0x%x", p->flag);
- object_close (FALSE);
- }
- }
-out:
- close (sock);
-}
-
-
-/**
- * linux_kernel_version:
- *
- * @major: major kernel version number,
- * @minor: minor kernel version number,
- * @revision: kernel revision version,
- *
- * @minor and @revision may be -1 to denote that those version
- * elements are not important to the caller. Once a parameter
- * has been specified as -1, subsequent parameters are ignored
- * (treated as -1 too).
- *
- * Returns: TRUE if running Linux kernel is atleast at version
- * specified by (@major, @minor, @revision), else FALSE.
- **/
-bool
-linux_kernel_version (int major, int minor, int revision)
-{
- int actual_version = 0x000000;
- int requested_version = 0x000000;
- int actual_major = -1;
- int actual_minor = -1;
- int actual_revision = -1;
- int ret;
-
- assert (uts.release);
- assert (sizeof (int) >= 4);
-
- /* We need something to work with */
- assert (major > 0);
-
- ret = sscanf (uts.release, "%d.%d.%d",
- &actual_major, &actual_minor,
- &actual_revision);
-
- /* We need something to compare against */
- assert (ret && actual_major != -1);
-
- requested_version |= (0xFF0000 & (major << 16));
-
- if (minor != -1) {
- requested_version |= (0x00FF00 & (minor << 8));
-
- if (revision != -1)
- requested_version |= (0x0000FF & revision);
- }
-
- if (actual_revision != -1) {
- actual_version |= (0x0000FF & actual_revision);
- }
-
- if (actual_minor != -1)
- actual_version |= (0x00FF00 & (actual_minor << 8));
-
- if (actual_major != -1)
- actual_version |= (0xFF0000 & (actual_major << 16));
-
-
- if (actual_version >= requested_version)
- return TRUE;
-
- return FALSE;
-}
-
-void
-show_numa_memory (void)
-{
-#if defined (HAVE_NUMA_H)
- int policy;
- const char *policy_name;
- char *allowed_list = NULL;
- int ret;
- unsigned long node;
- unsigned long allowed_size;
-
-#if defined (HAVE_NUMA_H)
-#if LIBNUMA_API_VERSION == 2
- struct bitmask *allowed;
-#else
- nodemask_t allowed;
-#endif
-#endif
-
- /* part of the libnuma public API - stop the library calling
- * exit(3) on error.
- */
- numa_exit_on_error = 0;
-
- /* TRUE if any numa nodes have been displayed yet */
- int displayed = FALSE;
-
- /* Number of numa nodes in *current* range */
- size_t count = 0;
-
- /* Only valid to read these when count is >0 */
- size_t last = 0;
- size_t first = 0;
-#endif /* HAVE_NUMA_H */
-
- header ("numa");
-
-#if defined (HAVE_NUMA_H)
- if (numa_available () < 0)
- /* NUMA not supported on this system */
- goto out;
-
-#if LIBNUMA_API_VERSION == 2
- entry ("api version", "%d", 2);
-#else
- entry ("api version", "%d", 1);
-#endif
-
- ret = get_mempolicy (&policy, NULL, 0, 0, 0);
-
- if (ret < 0) {
- entry ("policy", "%s", UNKNOWN_STR);
- goto out;
- }
-
- policy_name = get_numa_policy (policy);
-
- entry ("policy", "%s", policy_name ? policy_name : UNKNOWN_STR);
-
-#if LIBNUMA_API_VERSION == 2
- entry ("maximum nodes", "%d", numa_num_possible_nodes ());
- entry ("configured nodes", "%d", numa_num_configured_nodes ());
-
- allowed = numa_get_mems_allowed ();
- if (! allowed)
- die ("failed to query NUMA allowed list");
-
- allowed_size = allowed->size;
-
-#else
- entry ("maximum nodes", "%s", UNKNOWN_STR);
- entry ("configured nodes", "%d", numa_max_node ());
-
- allowed = numa_get_run_node_mask ();
- allowed_size = NUMA_NUM_NODES;
-#endif
-
- for (node = 0; node < allowed_size; node++) {
- if (PROCENV_NUMA_BITMASK_ISSET (allowed, node)) {
- /* Record first entry in the range */
- if (! count)
- first = node;
-
- last = node;
- count++;
- } else {
- if (count) {
- if (first == last) {
- appendf (&allowed_list, "%s%d",
- displayed ? "," : "",
- first);
- } else {
- appendf (&allowed_list, "%s%d-%d",
- displayed ? "," : "",
- first, last);
- }
- displayed = TRUE;
- }
-
- /* Reset */
- count = 0;
- }
- }
-
- if (count) {
- if (first == last) {
- appendf (&allowed_list, "%s%d",
- displayed ? "," : "",
- first);
- } else {
- appendf (&allowed_list, "%s%d-%d",
- displayed ? "," : "",
- first, last);
- }
- }
-
- entry ("allowed list", "%s", allowed_list);
-
-#if LIBNUMA_API_VERSION == 2
- numa_free_nodemask (allowed);
-#endif
-
- free (allowed_list);
-
-out:
-#endif /* HAVE_NUMA_H */
- footer ();
-}
-
-#if defined (HAVE_NUMA_H)
-const char *
-get_numa_policy (int policy)
-{
- struct procenv_map *p;
-
- for (p = numa_mempolicy_map; p && p->name; p++) {
- if (p->num == policy)
- return p->name;
- }
-
- return NULL;
-}
-#endif /* HAVE_NUMA_H */
-
+#if defined (PROCENV_PLATFORM_LINUX)
const char *
get_personality_name (unsigned int domain)
{
- struct personality_map *m;
-
- for (m = personality_map; m && m->name; m++) {
- if (m->personality == (domain & PER_MASK))
+ const struct procenv_map *m;
+
+ for (m = ops->personality_map; m && m->name; m++) {
+ if (m->num == (domain & PER_MASK))
return m->name;
}
@@ -4905,23 +2186,23 @@ get_personality_name (unsigned int domain)
char *
get_personality_flags (unsigned int flags)
{
- struct personality_flag_map *m;
- char *list = NULL;
- int first = TRUE;
+ const struct procenv_map *m;
+ char *list = NULL;
+ int first = true;
- for (m = personality_flag_map; m && m->name; m++) {
- if (flags & m->flag) {
+ for (m = ops->personality_flag_map; m && m->name; m++) {
+ if (flags & m->num) {
appendf (&list, "%s%s",
first ? "" : ", ",
m->name);
- first = FALSE;
+ first = false;
}
}
return list;
}
-#endif /* PROCENV_LINUX */
+#endif /* PROCENV_PLATFORM_LINUX */
void
show_mounts (ShowMountType what)
@@ -4930,13 +2211,8 @@ show_mounts (ShowMountType what)
header (what == SHOW_PATHCONF ? "pathconf" : "mounts");
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- show_mounts_linux (what);
-#endif
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
- show_mounts_bsd (what);
-#endif
+ if (ops->show_mounts)
+ ops->show_mounts (what);
footer ();
}
@@ -4945,13 +2221,13 @@ const char *
get_net_family_name (sa_family_t family)
{
switch (family) {
-#if defined (PROCENV_LINUX)
+#if defined (PROCENV_PLATFORM_LINUX)
case AF_PACKET:
return "AF_PACKET";
break;
#endif
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
+#if defined (PROCENV_PLATFORM_BSD)
case AF_LINK:
return "AF_LINK";
break;
@@ -5009,9 +2285,8 @@ show_network_if (const struct ifaddrs *ifa, const char *mac_address)
container_open ("fields");
-#if defined (PROCENV_LINUX)
- decode_extended_if_flags (ifa->ifa_name, &ext_flags);
-#endif
+ if (ops->show_extended_if_flags)
+ ops->show_extended_if_flags (ifa->ifa_name, &ext_flags);
container_close ();
@@ -5019,9 +2294,10 @@ show_network_if (const struct ifaddrs *ifa, const char *mac_address)
/*******************************/
- mtu = get_mtu (ifa);
+ if (ops->get_mtu)
+ mtu = ops->get_mtu (ifa);
-#if defined (PROCENV_HURD)
+#if defined (PROCENV_PLATFORM_HURD)
/* No AF_LINK/AF_PACKET on Hurd atm */
entry ("mac", "%s", UNKNOWN_STR);
#else
@@ -5041,7 +2317,8 @@ show_network_if (const struct ifaddrs *ifa, const char *mac_address)
get_network_address (ifa->ifa_netmask, family, address);
entry ("netmask", "%s", ifa->ifa_netmask ? address : NA_STR);
-#if !defined (PROCENV_HURD)
+#if !defined (PROCENV_PLATFORM_HURD)
+#if defined (IFF_BROADCAST)
if (family != PROCENV_LINK_LEVEL_FAMILY) {
if ((ifa->ifa_flags & IFF_BROADCAST) && ifa->ifa_broadaddr) {
get_network_address (ifa->ifa_broadaddr, family, address);
@@ -5050,483 +2327,25 @@ show_network_if (const struct ifaddrs *ifa, const char *mac_address)
}
} else {
#endif
+#endif
entry ("broadcast", "%s", NA_STR);
-#if !defined (PROCENV_HURD)
+#if !defined (PROCENV_PLATFORM_HURD)
+#if defined (IFF_BROADCAST)
}
#endif
+#endif
+#if defined (IFF_POINTOPOINT)
if (ifa->ifa_flags & IFF_POINTOPOINT && ifa->ifa_dstaddr) {
get_network_address (ifa->ifa_dstaddr, family, address);
entry ("point-to-point", "%s", address);
}
-
- section_close ();
-}
-
-/*
- * BSD returns an additional AF_LINK ifaddrs containing the
- * actual link-layer MAC address for each interface.
- *
- * Linux does the same but with one additional AF_PACKET family / interface.
- *
- * This is somewhat noisome since for BSD we need to cache the MAC addresses
- * such that they can be retrieved when the _next_ ifaddrs structure
- * appears for the *same* interface, but we only want to
- * display the non-AF_LINK elements *unless* they refer
- * to an interface with no associated address.
- *
- * The situation for Linux is similar but we only care
- * about AF_PACKET entries for interfaces that have no
- * associated address since we can extract the MAC
- * address using an ioctl (rather than considering the
- * AF_PACKET element).
- *
- * The strategy therefore is to:
- *
- * 1) Cache all AF_LINK/AF_PACKET elements.
- * 2) Once an element arrives that matches an interface
- * name found in the cache, use that as necessary (extra
- * the MAC for BSD, NOP for Linux), then free that cache
- * element.
- * 3) Having processed all entries, if any entries are
- * left in the cache, they must refer to interfaces that
- * have no address, so display them.
- *
- * XXX: Note the implicit assumption that the AF_LINK/AF_PACKET entries
- * will appear _before_ the corresponding entry containing address
- * details for the interface in the output of getifaddrs(): observations
- * suggests this _seems_ to be the case, but is not documented as being
- * guaranteed.
- */
-#ifdef PROCENV_ANDROID
-
-void
-show_network (void)
-{
- /* Bionic isn't actually that bionic at all :( */
- header ("network");
- footer ();
-}
-
-#else
-
-void
-show_network (void)
-{
- struct ifaddrs *if_addrs;
- struct ifaddrs *ifa;
- char *mac_address = NULL;
- struct network_map *head = NULL;
- struct network_map *node = NULL;
- struct network_map *tmp = NULL;
-
- common_assert ();
-
- header ("network");
-
- /* Query all network interfaces */
- if (getifaddrs (&if_addrs) < 0)
- return;
-
- /* Construct an initial node for the cache */
- head = calloc (1, sizeof (struct network_map));
- assert (head);
-
- /* Iterate over all network interfaces */
- for (ifa = if_addrs; ifa; ifa = ifa->ifa_next) {
-#if !defined (PROCENV_HURD)
- int family;
#endif
- if (! ifa->ifa_addr)
- continue;
-
-#if !defined (PROCENV_HURD)
- family = ifa->ifa_addr->sa_family;
-
- if (family == PROCENV_LINK_LEVEL_FAMILY) {
-
- /* Add link level interface details to the cache */
- mac_address = get_mac_address (ifa);
-
- node = calloc (1, sizeof (struct network_map));
- assert (node);
-
- /* Conveniently, an ifaddrs contains a bunch of
- * pointers and some flags.
- *
- * Since all those pointers are valid until we
- * call freeifaddrs(), all we need to do is copy
- * the flags since the memcpy will copy the
- * pointers addresses for us :)
- */
- memcpy (&node->ifaddr, ifa, sizeof (struct ifaddrs));
- node->ifaddr.ifa_flags = ifa->ifa_flags;
-
- /* Since we've already formatted the MAC
- * address, we'll cache that too.
- */
- node->mac_address = mac_address;
- mac_address = NULL;
-
- /* prepend */
- node->next = head->next;
- if (head->next)
- head->next->prev = node;
- node->prev = head;
- head->next = node;
-
- continue;
- }
-#endif
-
- /* From now on, we're only looking at interfaces with an
- * address.
- */
-
- /* Search for an entry corresponding to the interface in the cache */
- for (node = head->next; node && node->ifaddr.ifa_name; node = node->next) {
- if (! strcmp (node->ifaddr.ifa_name, ifa->ifa_name)) {
-
- /* Save */
- mac_address = node->mac_address
- ? strdup (node->mac_address)
- : NULL;
-
- /* Unlink existing node as it has now served its purpose */
- node->prev->next = node->next;
- if (node->next)
- node->next->prev = node->prev;
-
- /* Destroy */
- if (node->mac_address)
- free (node->mac_address);
- free (node);
-
- break;
- }
- }
-
- /* Display the interface (which must have an associated address) */
- show_network_if (ifa, mac_address);
- if (mac_address) {
- free (mac_address);
- mac_address = NULL;
- }
- }
-
- /* Destroy the cache, displaying any interfaces not previously displayed.
- * These by definition cannot have addresses assigned to them.
- */
- for (node = head->next; node && node->ifaddr.ifa_name; node = tmp) {
-
- tmp = node->next;
-
- show_network_if (&node->ifaddr, node->mac_address);
-
- /* Destroy */
- if (node->mac_address)
- free (node->mac_address);
- free (node);
- }
-
- free (head);
- freeifaddrs (if_addrs);
-
- footer ();
-}
-#endif
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-
-char *
-get_mount_opts_bsd (uint64_t flags)
-{
- struct mntopt_map *opt;
- char *str = NULL;
- size_t len = 0;
- size_t total = 0;
- int count = 0;
-
- if (! flags)
- return strdup ("");
-
- /* Calculate how much space we need to allocate by iterating
- * array for the first time.
- */
- for (opt = mntopt_map; opt && opt->name; opt++) {
- if (flags & opt->flag) {
- count++;
- len += strlen (opt->name);
- }
- }
-
- if (count > 1) {
- /* we need space for the option value themselves, plus a
- * ", " separator between each option (except the first),
- * and finally space for the nul terminator */
- total = len + (count-1) + 1;
- } else {
- total = len + 1;
- }
-
- str = calloc (total, sizeof (char));
- if (! str)
- die ("failed to allocate space for mount options");
-
- /* Re-iterate to construct the string. This is still going to be
- * a lot quicker than calling malloc a stack of times.
- */
- for (opt = mntopt_map; opt && opt->name; opt++) {
- if (flags & opt->flag) {
- strcat (str, opt->name);
- if (count > 1)
- strcat (str, ",");
- count--;
- }
- }
-
- return str;
-}
-
-void
-show_mounts_bsd (ShowMountType what)
-{
- int count;
- struct statfs *mounts;
- struct statfs *mnt;
- unsigned int major = 0;
- unsigned int minor = 0;
- int i;
- unsigned multiplier = 0;
- statfs_int_type blocks;
- statfs_int_type bfree;
- statfs_int_type bavail;
- statfs_int_type used;
-
- common_assert ();
-
- /* Note that returned memory cannot be freed (by us) */
- count = getmntinfo (&mounts, MNT_WAIT);
-
- if (! count)
- die ("unable to query mount info");
-
- mnt = mounts;
-
- for (i = 0; i < count; i++) {
- char *opts = NULL;
-
- opts = get_mount_opts_bsd (mnt->f_flags);
- if (! opts)
- die ("cannot determine FS flags for mountpoint '%s'",
- mnt->f_mntonname);
-
- if (what == SHOW_ALL || what == SHOW_MOUNTS) {
- (void)get_major_minor (mnt->f_mntonname,
- &major,
- &minor);
-
- multiplier = mnt->f_bsize / DF_BLOCK_SIZE;
- blocks = mnt->f_blocks * multiplier;
- bfree = mnt->f_bfree * multiplier;
- bavail = mnt->f_bavail * multiplier;
- used = blocks - bfree;
-
- assert (mnt->f_mntfromname);
- section_open (mnt->f_mntfromname);
-
- entry ("dir", "'%s'", mnt->f_mntonname);
- entry ("type", "%s", mnt->f_fstypename);
- entry ("options", "'%s'", opts);
-
- section_open ("device");
- entry ("major", "%u", major);
- entry ("minor", "%u", minor);
- section_close ();
-
- entry ("fsid", "%.*x%.*x",
- /* Always zero on BSD? */
- 2 * sizeof (mnt->f_fsid.val[0]),
- mnt->f_fsid.val[0],
- 2 * sizeof (mnt->f_fsid.val[1]),
- mnt->f_fsid.val[1]);
-
- entry ("optimal block size", "%" statfs_int_fmt,
- mnt->f_bsize);
-
- section_open ("blocks");
-
- entry ("size", "%lu bytes", DF_BLOCK_SIZE);
-
- entry ("total", "%" statfs_int_fmt, blocks);
- entry ("used", "%"statfs_int_fmt, used);
- entry ("free", "%" statfs_int_fmt, bfree);
- entry ("available", "%" statfs_int_fmt, bavail);
-
- section_close ();
-
- section_open ("files/inodes");
-
- entry ("total", "%" statfs_int_fmt, mnt->f_files);
- entry ("used", "%" statfs_int_fmt,
- mnt->f_files - mnt->f_ffree);
- entry ("free", "%" statfs_int_fmt, mnt->f_ffree);
-
- section_close ();
-
- section_close ();
- }
-
- if (what == SHOW_ALL || what == SHOW_PATHCONF)
- show_pathconfs (what, mnt->f_mntonname);
- mnt++;
-
- free (opts);
- }
-}
-
-#endif
-
-#if defined (PROCENV_BSD) && defined (HAVE_SYS_CAPABILITY_H)
-void
-show_capabilities_bsd (int fd)
-{
- int ret;
- u_int mode;
- cap_rights_t rights;
-
- ret = cap_getmode (&mode);
- if (ret < 0) {
- /* No Capsicum support */
- goto out;
- }
-
- ret = cap_rights_get (fd, &rights);
- if (ret < 0) {
- /* Cannot query capabilities */
- goto out;
- }
-
- show_capsicum_cap (rights, CAP_ACCEPT);
- show_capsicum_cap (rights, CAP_ACL_CHECK);
- show_capsicum_cap (rights, CAP_ACL_DELETE);
- show_capsicum_cap (rights, CAP_ACL_GET);
- show_capsicum_cap (rights, CAP_ACL_SET);
- show_capsicum_cap (rights, CAP_BIND);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_BINDAT);
- show_capsicum_cap (rights, CAP_CHFLAGSAT);
-#endif
- show_capsicum_cap (rights, CAP_CONNECT);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_CONNECTAT);
-#endif
- show_capsicum_cap (rights, CAP_CREATE);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_EVENT);
-#endif
- show_capsicum_cap (rights, CAP_EXTATTR_DELETE);
- show_capsicum_cap (rights, CAP_EXTATTR_GET);
- show_capsicum_cap (rights, CAP_EXTATTR_LIST);
- show_capsicum_cap (rights, CAP_EXTATTR_SET);
- show_capsicum_cap (rights, CAP_FCHDIR);
- show_capsicum_cap (rights, CAP_FCHFLAGS);
- show_capsicum_cap (rights, CAP_FCHMOD);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_FCHMODAT);
-#endif
- show_capsicum_cap (rights, CAP_FCHOWN);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_FCHOWNAT);
-#endif
- show_capsicum_cap (rights, CAP_FCNTL);
- show_capsicum_cap (rights, CAP_FEXECVE);
- show_capsicum_cap (rights, CAP_FLOCK);
- show_capsicum_cap (rights, CAP_FPATHCONF);
- show_capsicum_cap (rights, CAP_FSCK);
- show_capsicum_cap (rights, CAP_FSTAT);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_FSTATAT);
-#endif
- show_capsicum_cap (rights, CAP_FSTATFS);
- show_capsicum_cap (rights, CAP_FSYNC);
- show_capsicum_cap (rights, CAP_FTRUNCATE);
- show_capsicum_cap (rights, CAP_FUTIMES);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_FUTIMESAT);
-#endif
- show_capsicum_cap (rights, CAP_GETPEERNAME);
- show_capsicum_cap (rights, CAP_GETSOCKNAME);
- show_capsicum_cap (rights, CAP_GETSOCKOPT);
- show_capsicum_cap (rights, CAP_IOCTL);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_KQUEUE);
- show_capsicum_cap (rights, CAP_KQUEUE_CHANGE);
- show_capsicum_cap (rights, CAP_KQUEUE_EVENT);
- show_capsicum_cap (rights, CAP_LINKAT);
-#endif
- show_capsicum_cap (rights, CAP_LISTEN);
- show_capsicum_cap (rights, CAP_LOOKUP);
- show_capsicum_cap (rights, CAP_MAC_GET);
- show_capsicum_cap (rights, CAP_MAC_SET);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_MKDIRAT);
- show_capsicum_cap (rights, CAP_MKFIFOAT);
- show_capsicum_cap (rights, CAP_MKNODAT);
- show_capsicum_cap (rights, CAP_MMAP);
- show_capsicum_cap (rights, CAP_MMAP_R);
- show_capsicum_cap (rights, CAP_MMAP_RW);
- show_capsicum_cap (rights, CAP_MMAP_RWX);
- show_capsicum_cap (rights, CAP_MMAP_RX);
- show_capsicum_cap (rights, CAP_MMAP_W);
- show_capsicum_cap (rights, CAP_MMAP_WX);
- show_capsicum_cap (rights, CAP_MMAP_X);
-#endif
- show_capsicum_cap (rights, CAP_PDGETPID);
- show_capsicum_cap (rights, CAP_PDKILL);
- show_capsicum_cap (rights, CAP_PDWAIT);
- show_capsicum_cap (rights, CAP_PEELOFF);
- show_capsicum_cap (rights, CAP_POLL_EVENT);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_PREAD);
- show_capsicum_cap (rights, CAP_PWRITE);
-#endif
- show_capsicum_cap (rights, CAP_READ);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_RECV);
- show_capsicum_cap (rights, CAP_RENAMEAT);
-#endif
- show_capsicum_cap (rights, CAP_SEEK);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_SEEK_TELL);
-#endif
- show_capsicum_cap (rights, CAP_SEM_GETVALUE);
- show_capsicum_cap (rights, CAP_SEM_POST);
- show_capsicum_cap (rights, CAP_SEM_WAIT);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_SEND);
-#endif
- show_capsicum_cap (rights, CAP_SETSOCKOPT);
- show_capsicum_cap (rights, CAP_SHUTDOWN);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_SOCK_CLIENT);
- show_capsicum_cap (rights, CAP_SOCK_SERVER);
- show_capsicum_cap (rights, CAP_SYMLINKAT);
-#endif
- show_capsicum_cap (rights, CAP_TTYHOOK);
-#if __FreeBSD__ > 9
- show_capsicum_cap (rights, CAP_UNLINKAT);
-#endif
- show_capsicum_cap (rights, CAP_WRITE);
-
-out:
- /* clang requires this */
- return;
+ section_close ();
}
-#endif /* (PROCENV_BSD) && defined (HAVE_SYS_CAPABILITY_H) */
void
get_priorities (void)
@@ -5536,685 +2355,14 @@ get_priorities (void)
priority.user = getpriority (PRIO_USER , 0);
}
-bool
-uid_match (uid_t uid)
-{
- return uid == getuid ();
-}
-
-
-/**
- * in_container:
- *
- * Determine if running inside a container.
- *
- * Returns: Name of container type, or NO_STR.
- **/
-const char *
-container_type (void)
-{
- struct stat statbuf;
- char buffer[1024];
- FILE *f;
-#if defined (PROCENV_LINUX)
- dev_t expected;
-
- expected = makedev (5, 1);
-#endif
-
- if (stat ("/dev/console", &statbuf) < 0)
- goto out;
-
-#if defined (PROCENV_BSD)
- if (misc.in_jail)
- return "jail";
-#endif
- /* LXC's /dev/console is actually a pty */
-#if defined (PROCENV_LINUX)
- if (major (statbuf.st_rdev) != major (expected)
- || (minor (statbuf.st_rdev)) != minor (expected))
- return "lxc";
-#endif
-
- if (! stat ("/proc/vz", &statbuf) && stat ("/proc/bc", &statbuf) < 0)
- return "openvz";
-
- f = fopen ("/proc/self/status", "r");
- if (! f)
- goto out;
-
- while (fgets (buffer, sizeof (buffer), f)) {
- size_t len = strlen (buffer);
- buffer[len-1] = '\0';
-
- if (strstr (buffer, "VxID") == buffer) {
- fclose (f);
- return "vserver";
- }
- }
-
- fclose (f);
-
-out:
- return NO_STR;
-}
-
-/**
- * in_chroot:
- *
- * Determine if running inside a chroot environment.
- *
- * Failures are fatal.
- *
- * Returns TRUE if within a chroot, else FALSE.
- **/
-bool
-in_chroot (void)
-{
- struct stat st;
- int i;
- int root_inode, self_inode;
- char root[] = "/";
- char self[] = "/proc/self/root";
- char bsd_self[] = "/proc/curproc";
- char *dir = NULL;
-
- i = stat (root, &st);
- if (i != 0) {
- dir = root;
- goto error;
- }
-
- root_inode = st.st_ino;
-
- /*
- * Inode 2 is the root inode for most filesystems. However, XFS
- * uses 128 for root.
- */
- if (root_inode != 2 && root_inode != 128)
- return TRUE;
-
- i = stat (bsd_self, &st);
- if (i == 0) {
- /* Give up here if running on BSD */
- return FALSE;
- }
-
- i = stat (self, &st);
- if (i != 0)
- return FALSE;
-
- self_inode = st.st_ino;
-
- if (root_inode == self_inode)
- return FALSE;
-
- return TRUE;
-
-error:
- die ("cannot stat '%s'", dir);
-
- /* compiler appeasement */
- return FALSE;
-}
-
-/* detect if setsid(2) has been called */
-bool
-is_session_leader (void)
-{
- return user.sid == user.pid;
-}
-
-/* detect if setpgrp(2)/setpgid(2) (or setsid(2)) has been called */
-bool
-is_process_group_leader (void)
-{
- return user.pgroup == user.pid;
-}
-
-void
-show_proc_branch (void)
-{
- common_assert ();
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD)
- show_proc_branch_linux ();
-#endif
-
-#if defined (PROCENV_HURD)
- /* FIXME: how can this be queried in Hurd?? */
-#endif
-
-#if defined (PROCENV_BSD)
- show_proc_branch_bsd ();
-#endif
-}
-
-#if defined (PROCENV_BSD)
-/* Who would have thought handling PIDs was so tricky? */
-void
-show_proc_branch_bsd (void)
-{
- int count = 0;
- int i;
- char errors[_POSIX2_LINE_MAX];
- kvm_t *kvm;
- struct kinfo_proc *procs;
- struct kinfo_proc *p;
- pid_t self, current;
- int done = FALSE;
- char *str = NULL;
- pid_t ultimate_parent = 0;
-
- common_assert ();
-
- self = current = getpid ();
-
- kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
- if (! kvm)
- die ("unable to open kvm");
-
- procs = kvm_getprocs (kvm, KERN_PROC_PROC, 0, &count);
- if (! procs)
- die ("failed to get process info");
-
- /* Calculate the lowest PID number which gives us the ultimate
- * parent of all processes.
- *
- * On BSD sytems, normally PID 0 ('[kernel]') is the ultimate
- * parent rather than PID 1 ('init').
- *
- * However, this doesn't work in a BSD jail since in that
- * environment:
- *
- * - there is no init process visible.
- * - there is no kernel thread visible.
- * - the ultimate parent PID will either by 1 (the "invisible"
- * init process) or 'n' where 'n' is a PID>1 which is also
- * "invisible" (since it lives outside the jail in the host
- * environment).
- *
- * Confused yet?
- */
-
- p = &procs[0];
- ultimate_parent = p->ki_pid;
-
- for (i = 1; i < count; i++) {
- p = &procs[i];
- if (p->ki_pid < ultimate_parent)
- ultimate_parent = p->ki_pid;
- }
-
- while (! done) {
- for (i = 0; i < count && !done; i++) {
- p = &procs[i];
-
- if (p->ki_pid == current) {
- if (misc.in_jail) {
- struct kinfo_proc *p2;
- int ppid_found = FALSE;
- int j;
-
- /* Determine if the parent PID
- * actually exists within the
- * jail.
- */
- for (j = 0; j < count; j++) {
- p2 = &procs[j];
-
- if (p2->ki_pid == p->ki_ppid) {
- ppid_found = TRUE;
- break;
- }
- }
-
- if (p->ki_ppid == 1 || (p->ki_ppid && ! ppid_found)) {
- /* Found the "last" PID (whose parent is either
- * the "invisible init" or which exists outside the jail)
- * so record it and hop out.
- */
- appendf (&str, "%d ('%s') %d (%s)",
- (int)current, p->ki_comm,
- p->ki_ppid, UNKNOWN_STR);
- done = TRUE;
- break;
- } else {
- /* Found a valid parent pid */
- appendf (&str, "%d ('%s'), ",
- (int)current, p->ki_comm);
- }
-
- } else if (! ultimate_parent && current == ultimate_parent) {
-
- /* Found the "last" PID so record it and hop out */
- appendf (&str, "%d ('%s')",
- (int)current, p->ki_comm);
- done = TRUE;
- break;
-
- } else {
-
- /* Found a valid parent pid */
- appendf (&str, "%d ('%s'), ",
- (int)current, p->ki_comm);
- }
-
- /* Move on */
- current = p->ki_ppid;
- }
- }
- }
-
- if (kvm_close (kvm) < 0)
- die ("failed to close kvm");
-
- entry ("ancestry", "%s", str);
- free (str);
-}
-#endif
-
-#if defined (PROCENV_LINUX)
-void
-show_prctl_linux (void)
-{
- int rc;
- int arg2;
- char name[17] = { 0 };
-
- common_assert ();
-
- section_open ("prctl");
-
-#ifdef PR_GET_ENDIAN
- if (LINUX_KERNEL_MMR (2, 6, 18)) {
- const char *value;
-
- rc = prctl (PR_GET_ENDIAN, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_ENDIAN_BIG:
- value = BIG_STR;
- break;
- case PR_ENDIAN_LITTLE:
- value = LITTLE_STR;
- break;
- case PR_ENDIAN_PPC_LITTLE:
- value = "PowerPC pseudo little endian";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("process endian", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_DUMPABLE
- if (LINUX_KERNEL_MMR (2, 3, 20)) {
- const char *value;
- rc = prctl (PR_GET_DUMPABLE, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case 0:
- value = NO_STR;
- break;
- case 1:
- value = YES_STR;
- break;
- case 2:
- value = "root-only";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("dumpable", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_FPEMU
- /* Use the earliest version where this option was introduced
- * (for some architectures).
- */
- if (LINUX_KERNEL_MMR (2, 4, 18)) {
- const char *value;
-
- rc = prctl (PR_GET_FPEMU, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_FPEMU_NOPRINT:
- value = YES_STR;
- break;
- case PR_FPEMU_SIGFPE:
- value = "send SIGFPE";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("floating point emulation", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_FPEXC
- /* Use the earliest version where this option was introduced
- * (for some architectures).
- */
- if (LINUX_KERNEL_MMR (2, 4, 21)) {
- const char *value;
-
- rc = prctl (PR_GET_FPEXC, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_FP_EXC_SW_ENABLE:
- value = "software";
- break;
- case PR_FP_EXC_DISABLED:
- value = "disabled";
- break;
- case PR_FP_EXC_NONRECOV:
- value = "non-recoverable";
- break;
- case PR_FP_EXC_ASYNC:
- value = "asynchronous";
- break;
- case PR_FP_EXC_PRECISE:
- value = "precise";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("floating point exceptions", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_NAME
- if (LINUX_KERNEL_MMR (2, 6, 11)) {
- rc = prctl (PR_GET_NAME, name, 0, 0, 0);
- if (rc < 0)
- entry ("process name", "%s", UNKNOWN_STR);
- else
- entry ("process name", "%s", name);
- }
-
-#endif
-
-#ifdef PR_GET_PDEATHSIG
- if (LINUX_KERNEL_MMR (2, 3, 15)) {
- rc = prctl (PR_GET_PDEATHSIG, &arg2, 0, 0, 0);
- if (rc < 0)
- entry ("parent death signal", "%s", UNKNOWN_STR);
- else if (rc == 0)
- entry ("parent death signal", "disabled");
- else
- entry ("parent death signal", "%d", arg2);
- }
-#endif
-
-#ifdef PR_GET_SECCOMP
- if (LINUX_KERNEL_MMR (2, 6, 23)) {
- const char *value;
-
- rc = prctl (PR_GET_SECCOMP, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case 0:
- value = "disabled";
- break;
- case 1:
- value = "read/write/exit (mode 1)";
- break;
- case 2:
- value = "BPF (mode 2)";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("secure computing", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_TIMING
- /* Not 100% accurate - this option was actually
- * introduced in 2.6.0-test4
- */
- if (LINUX_KERNEL_MMR (2, 6, 1)) {
- const char *value;
- rc = prctl (PR_GET_TIMING, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case PR_TIMING_STATISTICAL:
- value = "statistical";
- break;
- case PR_TIMING_TIMESTAMP:
- value = "time-stamp";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("process timing", "%s", value);
- }
-#endif
-
-#if defined (PR_GET_TSC) && defined (PROCENV_ARCH_X86)
- if (LINUX_KERNEL_MMR (2, 6, 26)) {
- const char *value;
-
- rc = prctl (PR_GET_TSC, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_TSC_ENABLE:
- value = "enabled";
- break;
- case PR_TSC_SIGSEGV:
- value = "segmentation fault";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("timestamp counter read", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_UNALIGNED
- if (LINUX_KERNEL_MMR (2, 3, 48)) {
- const char *value;
-
- rc = prctl (PR_GET_UNALIGNED, &arg2, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (arg2) {
- case PR_UNALIGN_NOPRINT:
- value = "fix-up";
- break;
- case PR_UNALIGN_SIGBUS:
- value = "send SIGBUS";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("unaligned access", "%s", value);
- }
-#endif
-
-#ifdef PR_MCE_KILL_GET
- if (LINUX_KERNEL_MMR (2, 6, 32)) {
- const char *value;
-
- rc = prctl (PR_MCE_KILL_GET, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case PR_MCE_KILL_DEFAULT:
- value = "system default";
- break;
- case PR_MCE_KILL_EARLY:
- value = "early kill";
- break;
- case PR_MCE_KILL_LATE:
- value = "late kill";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("machine-check exception", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_NO_NEW_PRIVS
- if (LINUX_KERNEL_MM (3, 5)) {
- const char *value;
-
- rc = prctl (PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
- if (rc < 0)
- value = UNKNOWN_STR;
- else {
- switch (rc) {
- case 0:
- value = "normal execve";
- break;
- case 1:
- value = "enabled";
- break;
- default:
- value = UNKNOWN_STR;
- break;
- }
- }
- entry ("no new privileges", "%s", value);
- }
-#endif
-
-#ifdef PR_GET_TIMERSLACK
- if (LINUX_KERNEL_MMR (2, 6, 28)) {
- rc = prctl (PR_GET_TIMERSLACK, 0, 0, 0, 0);
- if (rc < 0)
- entry ("timer slack", "%s", UNKNOWN_STR);
- else
- entry ("timer slack", "%dns", rc);
- }
-#endif
-
-#ifdef PR_GET_CHILD_SUBREAPER
- if (LINUX_KERNEL_MM (3, 4)) {
- rc = prctl (PR_GET_CHILD_SUBREAPER, &arg2, 0, 0, 0);
- if (rc < 0)
- entry ("child subreaper", "%s", UNKNOWN_STR);
- else
- entry ("child subreaper", "%s", arg2 ? YES_STR : NO_STR);
- }
-#endif
-
-#ifdef PR_GET_TID_ADDRESS
- rc = prctl (PR_GET_TID_ADDRESS, &arg2, 0, 0, 0);
- if (rc < 0)
- entry ("clear child tid address", "%s", UNKNOWN_STR);
- else
- entry ("clear child tid address", "%p", arg2);
-#endif
-
- section_close ();
-}
-
-#endif
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD)
void
-show_proc_branch_linux (void)
+handle_proc_branch (void)
{
- char buffer[1024];
- char path[PATH_MAX];
- char name[16];
- char pid[16];
- char ppid[16];
- size_t len;
- char *p;
- FILE *f;
- char *str = NULL;
-
common_assert ();
- sprintf (pid, "%d", (int)getpid ());
-
- /* This is one God-awful interface */
- while (TRUE) {
- sprintf (path, "/proc/%s/status", pid);
-
- f = fopen (path, "r");
- if (! f) {
- appendf (&str, "%s", UNKNOWN_STR);
- goto out;
- }
-
- while (fgets (buffer, sizeof (buffer), f)) {
- len = strlen (buffer);
- buffer[len-1] = '\0';
-
- if ((p=strstr (buffer, "Name:")) == buffer) {
- p += 1+strlen ("Name:"); /* jump over tab char */
- sprintf (name, "%s", p);
- }
-
- if ((p=strstr (buffer, "PPid:")) == buffer) {
- p += 1+strlen ("PPid:"); /* jump over tab char */
- sprintf (ppid, "%s", p);
-
- /* got all we need now */
- break;
- }
- }
-
- fclose (f);
-
- /* ultimate parent == PID 1 == '/sbin/init' */
- if (! strcmp (pid, "1")) {
- appendf (&str, "%s ('%s')", pid, name);
- break;
- } else {
- appendf (&str, "%s ('%s'), ", pid, name);
- }
-
- /* parent is now the pid to search for */
- sprintf (pid, "%s", ppid);
- }
-out:
-
- entry ("ancestry", "%s", str);
- free (str);
+ if (ops->handle_proc_branch)
+ ops->handle_proc_branch ();
}
-#endif
/* More verbose version of stty(1).
*
@@ -6259,9 +2407,8 @@ show_tty_attrs (void)
work:
user.tty_fd = fds[i];
-#ifdef PROCENV_LINUX
- get_tty_locked_status (&lock_status);
-#endif
+ if (ops->get_tty_locked_status)
+ ops->get_tty_locked_status (&lock_status);
/*****************************************/
section_open ("c_iflag (input)");
@@ -6277,14 +2424,16 @@ work:
show_const_tty (tty, c_iflag, INLCR, lock_status);
show_const_tty (tty, c_iflag, IGNCR, lock_status);
show_const_tty (tty, c_iflag, ICRNL, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (IUCLC)
show_const_tty (tty, c_iflag, IUCLC, lock_status);
#endif
show_const_tty (tty, c_iflag, IXON, lock_status);
show_const_tty (tty, c_iflag, IXANY, lock_status);
show_const_tty (tty, c_iflag, IXOFF, lock_status);
show_const_tty (tty, c_iflag, IMAXBEL, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (IUTF8)
show_const_tty (tty, c_iflag, IUTF8, lock_status);
#endif
@@ -6296,23 +2445,43 @@ work:
entry ("c_oflag", "0x%x", tty.c_oflag);
show_const_tty (tty, c_oflag, OPOST, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (OLCUC)
show_const_tty (tty, c_oflag, OLCUC, lock_status);
#endif
show_const_tty (tty, c_oflag, ONLCR, lock_status);
show_const_tty (tty, c_oflag, OCRNL, lock_status);
show_const_tty (tty, c_oflag, ONOCR, lock_status);
show_const_tty (tty, c_oflag, ONLRET, lock_status);
-#if defined (PROCENV_LINUX)
+#if defined (OFILL)
show_const_tty (tty, c_oflag, OFILL, lock_status);
+#endif
+
+#if defined (OFDEL)
show_const_tty (tty, c_oflag, OFDEL, lock_status);
+#endif
+
+#if defined (NLDLY)
show_const_tty (tty, c_oflag, NLDLY, lock_status);
+#endif
+
+#if defined (CRDLY)
show_const_tty (tty, c_oflag, CRDLY, lock_status);
#endif
+
+#if defined (TABDLY)
show_const_tty (tty, c_oflag, TABDLY, lock_status);
-#if defined (PROCENV_LINUX)
+#endif
+
+#if defined (BSDLY)
show_const_tty (tty, c_oflag, BSDLY, lock_status);
+#endif
+
+#if defined (VTDLY)
show_const_tty (tty, c_oflag, VTDLY, lock_status);
+#endif
+
+#if defined (FFDLY)
show_const_tty (tty, c_oflag, FFDLY, lock_status);
#endif
@@ -6323,9 +2492,10 @@ work:
entry ("value", "0x%x", tty.c_cflag);
-#if defined (PROCENV_LINUX)
+#if defined (CBAUDEX)
show_const_tty (tty, c_cflag, CBAUDEX, lock_status);
#endif
+
show_const_tty (tty, c_cflag, CSIZE, lock_status);
show_const_tty (tty, c_cflag, CSTOPB, lock_status);
show_const_tty (tty, c_cflag, CREAD, lock_status);
@@ -6333,14 +2503,15 @@ work:
show_const_tty (tty, c_cflag, PARODD, lock_status);
show_const_tty (tty, c_cflag, HUPCL, lock_status);
show_const_tty (tty, c_cflag, CLOCAL, lock_status);
-#if defined (PROCENV_LINUX)
+
#ifdef CIBAUD
show_const_tty (tty, c_cflag, CIBAUD, lock_status);
#endif
+
#ifdef CMSPAR
show_const_tty (tty, c_cflag, CMSPAR, lock_status);
#endif
-#endif
+
show_const_tty (tty, c_cflag, CRTSCTS, lock_status);
section_close ();
@@ -6351,9 +2522,11 @@ work:
entry ("value", "0x%x", tty.c_lflag);
show_const_tty (tty, c_lflag, ISIG, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (XCASE)
show_const_tty (tty, c_lflag, XCASE, lock_status);
#endif
+
show_const_tty (tty, c_lflag, ICANON, lock_status);
show_const_tty (tty, c_lflag, ECHO, lock_status);
show_const_tty (tty, c_lflag, ECHOE, lock_status);
@@ -6380,9 +2553,11 @@ work:
show_cc_tty (tty, VEOF, lock_status);
show_cc_tty (tty, VTIME, lock_status);
show_cc_tty (tty, VMIN, lock_status);
-#if defined (PROCENV_LINUX)
+
+#if defined (VSWTC)
show_cc_tty (tty, VSWTC, lock_status);
#endif
+
show_cc_tty (tty, VSTART, lock_status);
show_cc_tty (tty, VSTOP, lock_status);
show_cc_tty (tty, VSUSP, lock_status);
@@ -6470,9 +2645,9 @@ get_signal_name (int signum)
{
assert (signum);
- struct procenv_map *p;
+ const struct procenv_map *p;
- for (p = signal_map; p && p->name; p++) {
+ for (p = ops->signal_map; p && p->name; p++) {
if (signum == p->num)
return p->name;
}
@@ -6486,7 +2661,7 @@ get_signal_name (int signum)
* Returns: static string representing best guess
* at operating system.
**/
-char *
+const char *
get_os (void)
{
#ifdef _AIX
@@ -6497,11 +2672,7 @@ get_os (void)
return "Android";
#endif
-#ifdef __FreeBSD__
- return "FreeBSD";
-#endif
-
-#if defined (__MACH__) || defined (__GNU__) || defined (__gnu_hurd__)
+#if (defined (__MACH__) && defined (__GNU__)) || defined (__gnu_hurd__)
return "GNU (Hurd)";
#endif
@@ -6513,11 +2684,7 @@ get_os (void)
return "iSeries (OS/400)";
#endif
-#if defined (PROCENV_GNU_BSD) && defined (__GNUC__)
- return "GNU/kFreeBSD";
-#endif
-
-#ifdef PROCENV_LINUX
+#ifdef PROCENV_PLATFORM_LINUX
#ifdef __s390x__
return "Linux (zSeries)";
#endif
@@ -6532,11 +2699,15 @@ get_os (void)
return "Linux";
#endif
-#ifdef _NetBSD__
+#ifdef __FreeBSD__
+ return "FreeBSD";
+#endif
+
+#ifdef __NetBSD__
return "NetBSD";
#endif
-#ifdef _OpenBSD__
+#ifdef __OpenBSD__
return "OpenBSD";
#endif
@@ -6560,6 +2731,10 @@ get_os (void)
return "z/OS (MVS)";
#endif
+#if defined (__APPLE__)
+ return "Apple/Darwin";
+#endif
+
#ifndef __COVERITY__
return UNKNOWN_STR;
#endif
@@ -6571,7 +2746,7 @@ get_os (void)
* Returns: static string representing best guess
* at architecture.
**/
-char *
+const char *
get_arch (void)
{
@@ -6664,8 +2839,8 @@ get_arch (void)
return UNKNOWN_STR;
}
-#ifndef PROCENV_ANDROID
-int
+#if ! defined (PROCENV_PLATFORM_ANDROID) && ! defined (PROCENV_PLATFORM_DARWIN)
+static int
libs_callback (struct dl_phdr_info *info, size_t size, void *data)
{
const char *name;
@@ -6689,7 +2864,7 @@ libs_callback (struct dl_phdr_info *info, size_t size, void *data)
name = path;
}
- object_open (FALSE);
+ object_open (false);
section_open (name);
@@ -6698,10 +2873,11 @@ libs_callback (struct dl_phdr_info *info, size_t size, void *data)
section_close ();
- object_close (FALSE);
+ object_close (false);
return 0;
}
+#endif
void
show_libs (void)
@@ -6710,46 +2886,42 @@ show_libs (void)
container_open ("libraries");
+#if ! defined (PROCENV_PLATFORM_ANDROID) && ! defined (PROCENV_PLATFORM_DARWIN)
dl_iterate_phdr (libs_callback, NULL);
+#endif
container_close ();
}
-#endif
void
show_clocks (void)
{
header ("clocks");
- show_clock_res (CLOCK_REALTIME);
+ if (ops->show_clocks)
+ ops->show_clocks();
-#if defined (__FreeBSD__)
- show_clock_res (CLOCK_REALTIME_PRECISE);
- show_clock_res (CLOCK_REALTIME_FAST);
-#endif
+ footer ();
+}
- show_clock_res (CLOCK_MONOTONIC);
+void
+show_rlimits (void)
+{
+ header ("limits");
-#if defined (__FreeBSD__) || defined (PROCENV_GNU_BSD)
- show_clock_res (CLOCK_MONOTONIC_PRECISE);
- show_clock_res (CLOCK_MONOTONIC_FAST);
- show_clock_res (CLOCK_UPTIME);
- show_clock_res (CLOCK_UPTIME_PRECISE);
- show_clock_res (CLOCK_UPTIME_FAST);
- show_clock_res (CLOCK_VIRTUAL);
-#endif
+ if (ops->show_rlimits)
+ ops->show_rlimits ();
-#if defined (__FreeBSD__)
- show_clock_res (CLOCK_PROF);
-#endif
+ footer ();
+}
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-#ifdef CLOCK_MONOTONIC_RAW
- show_clock_res (CLOCK_MONOTONIC_RAW);
-#endif
- show_clock_res (CLOCK_PROCESS_CPUTIME_ID);
- show_clock_res (CLOCK_THREAD_CPUTIME_ID);
-#endif
+void
+show_confstrs (void)
+{
+ header ("confstr");
+
+ if (ops->show_confstrs)
+ ops->show_confstrs();
footer ();
}
@@ -6757,11 +2929,12 @@ show_clocks (void)
void
show_timezone (void)
{
-#if defined (PROCENV_LINUX)
- show_timezone_linux ();
-#else
- show_timezone_stub ();
-#endif
+ header ("timezone");
+
+ if (ops->show_timezone)
+ ops->show_timezone ();
+
+ footer ();
}
void
@@ -6774,7 +2947,11 @@ show_sizeof (void)
show_sizeof_type (blkcnt_t);
show_sizeof_type (blksize_t);
show_sizeof_type (char);
+
+#if !defined (PROCENV_PLATFORM_DARWIN)
show_sizeof_type (clockid_t);
+#endif
+
show_sizeof_type (clock_t);
show_sizeof_type (dev_t);
show_sizeof_type (div_t);
@@ -6817,8 +2994,12 @@ show_sizeof (void)
show_sizeof_type (off_t);
show_sizeof_type (pid_t);
show_sizeof_type (pthread_attr_t);
+
+#if !defined (PROCENV_PLATFORM_MINIX) && !defined (PROCENV_PLATFORM_DARWIN)
show_sizeof_type (pthread_barrierattr_t);
show_sizeof_type (pthread_barrier_t);
+#endif
+
show_sizeof_type (pthread_condattr_t);
show_sizeof_type (pthread_cond_t);
show_sizeof_type (pthread_key_t);
@@ -6827,7 +3008,11 @@ show_sizeof (void)
show_sizeof_type (pthread_once_t);
show_sizeof_type (pthread_rwlockattr_t);
show_sizeof_type (pthread_rwlock_t);
+
+#if !defined (PROCENV_PLATFORM_MINIX) && !defined (PROCENV_PLATFORM_DARWIN)
show_sizeof_type (pthread_spinlock_t);
+#endif
+
show_sizeof_type (pthread_t);
show_sizeof_type (ptrdiff_t);
show_sizeof_type (rlim_t);
@@ -6836,7 +3021,11 @@ show_sizeof (void)
show_sizeof_type (size_t);
show_sizeof_type (ssize_t);
show_sizeof_type (suseconds_t);
+
+#if !defined (PROCENV_PLATFORM_DARWIN)
show_sizeof_type (timer_t);
+#endif
+
show_sizeof_type (time_t);
show_sizeof_type (uid_t);
show_sizeof_type (uint16_t);
@@ -7040,46 +3229,46 @@ show_compiler (void)
section_open ("feature test macros");
-#ifdef __STDC_VERSION__
- entry ("__STDC_VERSION__", "%lu", __STDC_VERSION__);
+#ifdef _ATFILE_SOURCE
+ entry ("_ATFILE_SOURCE", "%s", DEFINED_STR);
#else
- entry ("__STDC_VERSION__", "%s", NOT_DEFINED_STR);
+ entry ("_ATFILE_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef __STRICT_ANSI__
- entry ("__STRICT_ANSI__", "%s", DEFINED_STR);
+#ifdef _BSD_SOURCE
+ entry ("_BSD_SOURCE", "%s", DEFINED_STR);
#else
- entry ("__STRICT_ANSI__", "%s", NOT_DEFINED_STR);
+ entry ("_BSD_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _POSIX_C_SOURCE
- entry ("_POSIX_C_SOURCE", "%lu", _POSIX_C_SOURCE);
+#ifdef _DEFAULT_SOURCE
+ entry ("_DEFAULT_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_POSIX_C_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_DEFAULT_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#if defined (_POSIX_RAW_SOCKETS)
- entry ("_POSIX_RAW_SOCKETS", "%s", DEFINED_STR),
+#ifdef _FILE_OFFSET_BITS
+ entry ("_FILE_OFFSET_BITS", "%lu", _FILE_OFFSET_BITS);
#else
- entry ("_POSIX_RAW_SOCKETS", "%s", NOT_DEFINED_STR),
+ entry ("_FILE_OFFSET_BITS", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _POSIX_SOURCE
- entry ("_POSIX_SOURCE", "%s", DEFINED_STR);
+#ifdef _FORTIFY_SOURCE
+ entry ("_FORTIFY_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_POSIX_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_FORTIFY_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _XOPEN_SOURCE
- entry ("_XOPEN_SOURCE", "%lu", _XOPEN_SOURCE);
+#ifdef _GNU_SOURCE
+ entry ("_GNU_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_XOPEN_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_GNU_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _XOPEN_SOURCE_EXTENDED
- entry ("_XOPEN_SOURCE_EXTENDED", "%s", DEFINED_STR);
+#ifdef _ISOC11_SOURCE
+ entry ("_ISOC11_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_XOPEN_SOURCE_EXTENDED", "%s", NOT_DEFINED_STR);
+ entry ("_ISOC11_SOURCE", "%s", NOT_DEFINED_STR);
#endif
#ifdef _ISOC95_SOURCE
@@ -7094,10 +3283,10 @@ show_compiler (void)
entry ("_ISOC99_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _ISOC11_SOURCE
- entry ("_ISOC11_SOURCE", "%s", DEFINED_STR);
+#ifdef _LARGEFILE64_SOURCE
+ entry ("_LARGEFILE64_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_ISOC11_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_LARGEFILE64_SOURCE", "%s", NOT_DEFINED_STR);
#endif
#ifdef _LARGEFILE_SOURCE
@@ -7106,46 +3295,64 @@ show_compiler (void)
entry ("_LARGEFILE_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _LARGEFILE64_SOURCE
- entry ("_LARGEFILE64_SOURCE", "%s", DEFINED_STR);
+#ifdef _POSIX_C_SOURCE
+ entry ("_POSIX_C_SOURCE", "%lu", _POSIX_C_SOURCE);
#else
- entry ("_LARGEFILE64_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_POSIX_C_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _FILE_OFFSET_BITS
- entry ("_FILE_OFFSET_BITS", "%lu", _FILE_OFFSET_BITS);
+#if defined (_POSIX_RAW_SOCKETS)
+ entry ("_POSIX_RAW_SOCKETS", "%s", DEFINED_STR),
#else
- entry ("_FILE_OFFSET_BITS", "%s", NOT_DEFINED_STR);
+ entry ("_POSIX_RAW_SOCKETS", "%s", NOT_DEFINED_STR),
#endif
-#ifdef _BSD_SOURCE
- entry ("_BSD_SOURCE", "%s", DEFINED_STR);
+#ifdef _POSIX_SOURCE
+ entry ("_POSIX_SOURCE", "%s", DEFINED_STR);
#else
- entry ("_BSD_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_POSIX_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _SVID_SOURCE
- entry ("_SVID_SOURCE", "%s", DEFINED_STR);
+#ifdef _REENTRANT
+ entry ("_REENTRANT", "%s", DEFINED_STR);
#else
- entry ("_SVID_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_REENTRANT", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _ATFILE_SOURCE
- entry ("_ATFILE_SOURCE", "%s", DEFINED_STR);
+#ifdef __STDC_VERSION__
+ entry ("__STDC_VERSION__", "%lu", __STDC_VERSION__);
#else
- entry ("_ATFILE_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("__STDC_VERSION__", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _GNU_SOURCE
- entry ("_GNU_SOURCE", "%s", DEFINED_STR);
+#ifdef __STRICT_ANSI__
+ entry ("__STRICT_ANSI__", "%s", DEFINED_STR);
#else
- entry ("_GNU_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("__STRICT_ANSI__", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _REENTRANT
- entry ("_REENTRANT", "%s", DEFINED_STR);
+#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
+ entry ("__STDC_WANT_IEC_60559_BFP_EXT__", "%lu", __STDC_WANT_IEC_60559_BFP_EXT__);
#else
- entry ("_REENTRANT", "%s", NOT_DEFINED_STR);
+ entry ("__STDC_WANT_IEC_60559_BFP_EXT__", "%s", NOT_DEFINED_STR);
+#endif
+
+#ifdef __STDC_WANT_IEC_60559_FUNCS_EXT__
+ entry ("__STDC_WANT_IEC_60559_FUNCS_EXT__", "%lu", __STDC_WANT_IEC_60559_FUNCS_EXT__);
+#else
+ entry ("__STDC_WANT_IEC_60559_FUNCS_EXT__", "%s", NOT_DEFINED_STR);
+#endif
+
+#ifdef __STDC_WANT_LIB_EXT2__
+ entry ("__STDC_WANT_LIB_EXT2__", "%lu", __STDC_WANT_LIB_EXT2__);
+#else
+ entry ("__STDC_WANT_LIB_EXT2__", "%s", NOT_DEFINED_STR);
+#endif
+
+#ifdef _SVID_SOURCE
+ entry ("_SVID_SOURCE", "%s", DEFINED_STR);
+#else
+ entry ("_SVID_SOURCE", "%s", NOT_DEFINED_STR);
#endif
#ifdef _THREAD_SAFE
@@ -7154,16 +3361,16 @@ show_compiler (void)
entry ("_THREAD_SAFE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _FORTIFY_SOURCE
- entry ("_FORTIFY_SOURCE", "%s", DEFINED_STR);
+#ifdef _XOPEN_SOURCE
+ entry ("_XOPEN_SOURCE", "%lu", _XOPEN_SOURCE);
#else
- entry ("_FORTIFY_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_XOPEN_SOURCE", "%s", NOT_DEFINED_STR);
#endif
-#ifdef _DEFAULT_SOURCE
- entry ("_DEFAULT_SOURCE", "%s", DEFINED_STR);
+#ifdef _XOPEN_SOURCE_EXTENDED
+ entry ("_XOPEN_SOURCE_EXTENDED", "%s", DEFINED_STR);
#else
- entry ("_DEFAULT_SOURCE", "%s", NOT_DEFINED_STR);
+ entry ("_XOPEN_SOURCE_EXTENDED", "%s", NOT_DEFINED_STR);
#endif
section_close ();
@@ -7238,7 +3445,10 @@ show_time (void)
struct timespec ts;
struct tm *tm;
- if (clock_gettime (CLOCK_REALTIME, &ts) < 0)
+ if (! ops->get_time)
+ return;
+
+ if (ops->get_time (&ts))
die ("failed to determine time");
tm = localtime (&ts.tv_sec);
@@ -7287,7 +3497,7 @@ show_uname (void)
entry ("version", "%s", uts.version);
entry ("machine", "%s", uts.machine);
-#if defined (_GNU_SOURCE) && defined (PROCENV_LINUX)
+#if defined (_GNU_SOURCE) && defined (PROCENV_PLATFORM_LINUX)
entry ("domainname", "%s", uts.domainname[0] ? uts.domainname : UNKNOWN_STR);
#endif
@@ -7297,888 +3507,36 @@ show_uname (void)
void
show_cgroups (void)
{
-#if defined (PROCENV_LINUX)
- show_cgroups_linux ();
-#else
- show_cgroups_stub ();
-#endif
-}
-
-void
-show_oom (void)
-{
-#if defined (PROCENV_LINUX)
- show_oom_linux ();
-#else
- show_oom_stub ();
-#endif
-}
-
-void
-show_capabilities (void)
-{
-#if defined (PROCENV_LINUX)
- show_capabilities_linux ();
-#else
- show_capabilities_stub ();
-#endif
-}
-
-#if defined (PROCENV_LINUX)
-
-#if defined (HAVE_SYS_CAPABILITY_H)
-int
-get_capability_by_flag_type (cap_t cap_p, cap_flag_t type, cap_value_t cap)
-{
- int ret;
- cap_flag_value_t result;
-
- assert (cap_p);
-
- ret = cap_get_flag (cap_p, cap, type, &result);
-
- return ret < 0 ? ret : result;
-}
-#endif /* HAVE_SYS_CAPABILITY_H */
-
-void
-show_capabilities_linux (void)
-{
-#if defined (HAVE_SYS_CAPABILITY_H)
- int last_known;
- cap_t caps;
-
- /* Most recently-added capability that procenv knew about at
- * compile time.
- */
- last_known = CAP_LAST_CAP;
-#endif
-
- header ("capabilities");
-
-#if defined (HAVE_SYS_CAPABILITY_H)
- caps = cap_get_proc ();
-
- entry ("count (CAP_LAST_CAP+1)", "%d", CAP_LAST_CAP+1);
-
- if (! caps)
- goto out;
-
- section_open ("known");
-
- show_capability (caps, CAP_CHOWN);
- show_capability (caps, CAP_DAC_OVERRIDE);
- show_capability (caps, CAP_DAC_READ_SEARCH);
- show_capability (caps, CAP_FOWNER);
- show_capability (caps, CAP_FSETID);
- show_capability (caps, CAP_KILL);
- show_capability (caps, CAP_SETGID);
- show_capability (caps, CAP_SETUID);
- show_capability (caps, CAP_SETPCAP);
- show_capability (caps, CAP_LINUX_IMMUTABLE);
- show_capability (caps, CAP_NET_BIND_SERVICE);
- show_capability (caps, CAP_NET_BROADCAST);
- show_capability (caps, CAP_NET_ADMIN);
- show_capability (caps, CAP_NET_RAW);
- show_capability (caps, CAP_IPC_LOCK);
- show_capability (caps, CAP_IPC_OWNER);
- show_capability (caps, CAP_SYS_MODULE);
- show_capability (caps, CAP_SYS_RAWIO);
- show_capability (caps, CAP_SYS_CHROOT);
- show_capability (caps, CAP_SYS_PTRACE);
- show_capability (caps, CAP_SYS_PACCT);
- show_capability (caps, CAP_SYS_ADMIN);
- show_capability (caps, CAP_SYS_BOOT);
- show_capability (caps, CAP_SYS_NICE);
- show_capability (caps, CAP_SYS_RESOURCE);
- show_capability (caps, CAP_SYS_TIME);
- show_capability (caps, CAP_SYS_TTY_CONFIG);
-
- if (LINUX_KERNEL_MM (2, 4)) {
- show_capability (caps, CAP_MKNOD);
- show_capability (caps, CAP_LEASE);
- }
-
- if (LINUX_KERNEL_MMR (2, 6, 11)) {
- show_capability (caps, CAP_AUDIT_WRITE);
- show_capability (caps, CAP_AUDIT_CONTROL);
- }
- if (LINUX_KERNEL_MMR (2, 6, 24))
- show_capability (caps, CAP_SETFCAP);
- if (LINUX_KERNEL_MMR (2, 6, 25)) {
- show_capability (caps, CAP_MAC_OVERRIDE);
- show_capability (caps, CAP_MAC_ADMIN);
- }
-
-#ifdef CAP_SYSLOG
- if (LINUX_KERNEL_MMR (2, 6, 37))
- show_capability (caps, CAP_SYSLOG);
-
-#endif
-
-#ifdef CAP_WAKE_ALARM
- if (LINUX_KERNEL_MM (3, 0))
- show_capability (caps, CAP_WAKE_ALARM);
-#endif
-
-#ifdef CAP_BLOCK_SUSPEND
- if (LINUX_KERNEL_MM (3, 5))
- show_capability (caps, CAP_BLOCK_SUSPEND);
-#endif
-
-#ifdef CAP_AUDIT_READ
- if (LINUX_KERNEL_MM (3, 16)) {
- show_capability (caps, CAP_AUDIT_READ);
- }
-#endif
-
- section_close ();
-
- /* It's possible that procenv is running on a system which has
- * more capabilities that the system it was built on (for
- * example, it might be running in a chroot with a newer kernel
- * than the chroot environment). So display any unknown
- * capabilities. We don't have their names, but it's useful to
- * see that there are additional capabilities in available in
- * the environment.
- */
- section_open ("unknown");
-
-#if defined (PR_CAPBSET_READ)
- for (int i = 1+last_known; ; i++) {
- int ret;
- char *name = NULL;
-
- ret = cap_get_bound (i);
- if (ret < 0)
- break;
-
- /* Found an "unknown" */
-
- appendf (&name, "CAP_LAST_CAP+%d", i);
-
- _show_capability (caps, i, name);
-
- free (name);
- }
-#endif
-
- cap_free (caps);
-
- section_close ();
-
-#ifdef PR_GET_KEEPCAPS
- if (LINUX_KERNEL_MMR (2, 2, 18)) {
- int ret;
- ret = prctl (PR_GET_KEEPCAPS, 0, 0, 0, 0);
- if (ret < 0)
- entry ("keep", "%s", UNKNOWN_STR);
- else
- entry ("keep", "%s", ret ? YES_STR : NO_STR);
- }
-#endif
-
-
-#if defined (PR_GET_SECUREBITS) && defined (HAVE_LINUX_SECUREBITS_H)
- if (LINUX_KERNEL_MMR (2, 6, 26)) {
- int ret;
-
- ret = prctl (PR_GET_SECUREBITS, 0, 0, 0, 0);
- if (ret < 0)
- entry ("securebits", "%s", UNKNOWN_STR);
- else {
- struct securebits_t {
- unsigned int securebits;
- } flags;
- flags.securebits = (unsigned int)ret;
-
- section_open ("securebits");
-
- entry ("value", "0x%x", flags.securebits);
-
- container_open ("fields");
-
- show_const (flags, securebits, SECBIT_KEEP_CAPS);
- show_const (flags, securebits, SECBIT_NO_SETUID_FIXUP);
- show_const (flags, securebits, SECBIT_NOROOT);
-
- container_close ();
-
- section_close ();
- }
- }
-#endif
-
-out:
-#endif /* HAVE_SYS_CAPABILITY_H */
- footer ();
-}
-
-#if defined (HAVE_SYS_CAPABILITY_H)
-#ifdef PROCENV_NEED_LOCAL_CAP_GET_BOUND
-
-int cap_get_bound (cap_value_t cap)
-{
-#if defined (PR_CAPBSET_READ)
- return prctl (PR_CAPBSET_READ, cap);
-#else
- return -1;
-#endif
-}
-
-#endif /* PROCENV_NEED_LOCAL_CAP_GET_BOUND */
-#endif /* HAVE_SYS_CAPABILITY_H */
-
-void
-show_timezone_linux (void)
-{
- tzset ();
-
- header ("timezone");
-
- entry ("tzname[0]", "'%s'", tzname[0]);
- entry ("tzname[1]", "'%s'", tzname[1]);
- entry ("timezone", "%ld", timezone);
- entry ("daylight", "%d", daylight);
-
- footer ();
-}
-
-void
-show_security_module_linux (void)
-{
- char *lsm = UNKNOWN_STR;
-
-#if defined (HAVE_APPARMOR)
- if (aa_is_enabled ())
- lsm = "AppArmor";
-#endif
-
-#if defined (HAVE_SELINUX_SELINUX_H)
- if (is_selinux_enabled () == 1) {
-
- if (is_selinux_mls_enabled () == 1)
- lsm = "SELinux (MLS)";
- else
- lsm = "SELinux";
- }
-#endif
-
- entry ("name", "%s", lsm);
-}
-
-void
-show_security_module_context_linux (void)
-{
- char *context = NULL;
- char *mode = NULL;
-
-#if defined (HAVE_APPARMOR)
- if (aa_is_enabled ()) {
- /* XXX: The mode string is *NOT* be freed since it forms
- * part of the allocation returned in context.
- *
- * See aa_gettaskcon(2) for details.
- */
- if (aa_gettaskcon (user.pid, &context, &mode) < 0)
- die ("failed to query AppArmor context");
- }
-#endif
-
-#if defined (HAVE_SELINUX_SELINUX_H)
- if (is_selinux_enabled ()) {
- if (getpidcon (user.pid, &context) < 0)
- die ("failed to query SELinux context");
- }
-#endif
- if (context) {
- if (mode) {
- entry ("context", "%s (%s)", context, mode);
- } else {
- entry ("context", "%s", context);
- }
- } else {
- entry ("context", "%s", UNKNOWN_STR);
- }
-
- free (context);
-}
-
-void
-show_cgroups_linux (void)
-{
- const char *delim = ":";
- char *file = "/proc/self/cgroup";
- FILE *f;
- char buffer[1024];
- size_t len;
-
header ("cgroups");
- f = fopen (file, "r");
-
- if (! f)
- goto out;
-
- while (fgets (buffer, sizeof (buffer), f)) {
- char *buf, *b;
- char *hierarchy;
- char *subsystems;
- char *path;
-
- len = strlen (buffer);
- /* Remove NL */
- buffer[len-1] = '\0';
-
- buf = b = strdup (buffer);
- if (! buf)
- die ("failed to alloate storage");
-
- hierarchy = strsep (&b, delim);
- if (! hierarchy)
- goto next;
-
- subsystems = strsep (&b, delim);
- if (! subsystems)
- goto next;
-
- path = strsep (&b, delim);
- if (! path)
- goto next;
-
- /* FIXME: should sort by hierarchy */
- container_open (hierarchy);
-
- object_open (FALSE);
-
- /* FIXME: should split this on comma */
- entry ("subsystems", "%s", subsystems);
-
- entry ("path", "%s", path);
-
- object_close (FALSE);
-
- container_close ();
-
-next:
- free (buf);
- }
-
- fclose (f);
-
-out:
+ if (ops->show_cgroups)
+ ops->show_cgroups ();
footer ();
}
void
-show_fds_linux (void)
-{
- DIR *dir;
- struct dirent *ent;
- char *prefix_path = "/proc/self/fd";
- struct stat st;
- char path[MAXPATHLEN];
- char link[MAXPATHLEN];
- ssize_t len;
-
- container_open ("file descriptors");
-
- dir = opendir (prefix_path);
- if (! dir)
- return;
-
- while ((ent=readdir (dir)) != NULL) {
- int fd;
- char *num = NULL;
-
- if (! strcmp (ent->d_name, ".") || ! strcmp (ent->d_name, ".."))
- continue;
-
- sprintf (path, "%s/%s", prefix_path, ent->d_name);
- fd = atoi (ent->d_name);
-
- len = readlink (path, link, sizeof (link)-1);
- if (len < 0)
- /* ignore errors */
- continue;
-
- appendf (&num, "%d", fd);
-
- assert (len);
- link[len] = '\0';
-
- if (link[0] == '/') {
-
- if (stat (link, &st) < 0) {
- free (num);
- continue;
- }
-
- /* Ignore the last (invalid) entry */
- if (S_ISDIR (st.st_mode)) {
- free (num);
- continue;
- }
- }
-
- object_open (FALSE);
-
- section_open (num);
- free (num);
-
- entry ("terminal", "%s", isatty (fd) ? YES_STR : NO_STR);
- entry ("valid", "%s", fd_valid (fd) ? YES_STR : NO_STR);
- entry ("device", "%s", link);
-
- section_close ();
-
- object_close (FALSE);
- }
-
- closedir (dir);
-
- container_close ();
-}
-
-void
-show_namespaces_linux (void)
-{
- DIR *dir;
- struct dirent *ent;
- char *prefix_path = "/proc/self/ns";
- char path[MAXPATHLEN];
- char link[MAXPATHLEN];
- ssize_t len;
- PRList *list = NULL;
-
- container_open ("namespaces");
-
- dir = opendir (prefix_path);
- if (! dir)
- goto end;
-
- list = pr_list_new (NULL);
- assert (list);
-
- while ((ent=readdir (dir)) != NULL) {
- PRList *entry;
-
- if (! strcmp (ent->d_name, ".") || ! strcmp (ent->d_name, ".."))
- continue;
-
- sprintf (path, "%s/%s", prefix_path, ent->d_name);
-
- len = readlink (path, link, sizeof (link)-1);
- if (len < 0)
- /* ignore errors */
- continue;
-
- assert (len);
- link[len] = '\0';
-
- entry = pr_list_new (strdup (link));
- assert (entry);
-
- assert (pr_list_prepend_str_sorted (list, entry));
- }
-
- closedir (dir);
-
- PR_LIST_FOREACH_SAFE (list, iter) {
- char *tmp;
- char *name;
- char *value;
-
- pr_list_remove (iter);
-
- tmp = iter->data;
-
- name = strsep (&tmp, ":");
- if (! name)
- goto give_up;
-
- value = strsep (&tmp, "]");
- if (! value)
- goto give_up;
-
- if (*value == '[' && value+1 && *(value+1)) {
- value++;
- }
-
- object_open (FALSE);
- entry (name, "%s", value);
- object_close (FALSE);
-
-give_up:
- free ((char *)iter->data);
- free(iter);
- }
-
- free_if_set (list);
-
-end:
- container_close ();
-}
-
-void
-show_oom_linux (void)
+show_oom (void)
{
- char *dir = "/proc/self";
- char *files[] = { "oom_score", "oom_adj", "oom_score_adj", NULL };
- char **file;
- FILE *f;
- char buffer[PROCENV_BUFFER];
- char path[PATH_MAX];
- size_t len;
- int ret;
- int seen = FALSE;
-
header ("oom");
- for (file = files; file && *file; file++) {
- ret = sprintf (path, "%s/%s", dir, *file);
- if (ret < 0)
- continue;
-
- f = fopen (path, "r");
- if (! f)
- continue;
-
- seen = TRUE;
-
- while (fgets (buffer, sizeof (buffer), f)) {
- len = strlen (buffer);
- buffer[len-1] = '\0';
- entry (*file, "%s", buffer);
- }
-
- fclose (f);
- }
-
- if (! seen)
- entry ("%s", UNKNOWN_STR);
+ if (ops->show_oom)
+ ops->show_oom ();
footer ();
}
-char *
-get_scheduler_name (int sched)
-{
- struct procenv_map *p;
-
- for (p = scheduler_map; p && p->name; p++) {
- if (p->num == sched)
- return p->name;
- }
-
- return NULL;
-}
-
void
-show_cpu_linux (void)
-{
- int cpu = -1;
- long max;
-
- max = get_sysconf (_SC_NPROCESSORS_ONLN);
-
-#if HAVE_SCHED_GETCPU
- cpu = sched_getcpu ();
- if (cpu < 0)
- goto unknown_sched_cpu;
-
-#else
- cpu = procenv_getcpu ();
- if (cpu < 0)
- goto unknown_sched_cpu;
-#endif
-
- /* adjust to make 1-based */
- cpu++;
-
- entry ("number", "%u of %ld", cpu, max);
- return;
-
-unknown_sched_cpu:
-
- entry ("number", "%s of %ld", UNKNOWN_STR, max);
-}
-
-#if ! defined (HAVE_SCHED_GETCPU)
-
-/* Crutch function for RHEL 5 */
-int
-procenv_getcpu (void)
-{
- int cpu = -1;
- FILE *f;
- char **fields;
- const char *field;
- char buffer[1024];
- size_t len;
- size_t count;
-
- f = fopen ("/proc/self/stat", "r");
- if (! f)
- goto out;
-
- if (! fgets (buffer, sizeof (buffer), f))
- goto out;
-
- fclose (f);
-
- len = strlen (buffer);
- buffer[len-1] = '\0';
-
- count = split_fields (buffer, ' ', TRUE, &fields);
-
- if (! count)
- return -1;
-
- if (count != 42)
- goto cleanup;
-
- field = fields[41];
- assert (field);
-
- cpu = atoi (field);
-
-cleanup:
-
- for (len = 0; len < count; len++)
- free (fields[len]);
- free (fields);
-
-out:
- return cpu;
-}
-#endif
-
-/**
- * get_canonical:
- *
- * @path: path to convert to canonical form,
- * @canonical [out]: canonical version of @path,
- * @len: Size of @canonical (should be atleast PATH_MAX).
- *
- * FIXME: this should fully resolve not just sym links but replace all
- * occurences of '../' by the appropriate direcotry!
- **/
-int
-get_canonical (const char *path, char *canonical, size_t len)
-{
- ssize_t bytes;
- int ret = TRUE;
-
- assert (path);
- assert (canonical);
- assert (len);
-
- bytes = readlink (path, canonical, len);
- if (bytes < 0) {
- sprintf (canonical, UNKNOWN_STR);
- ret = FALSE;
- } else {
- canonical[bytes <= len ? bytes : len] = '\0';
- }
-
- return ret;
-}
-
-void
-get_tty_locked_status (struct termios *lock_status)
-{
- assert (lock_status);
- assert (user.tty_fd != -1);
-
- if (ioctl (user.tty_fd, TIOCGLCKTRMIOS, lock_status) < 0) {
- /* Set to unlocked */
- memset (lock_status, '\0', sizeof (struct termios));
- }
-}
-#else
-
-void
-show_namespaces_stub (void)
-{
- header ("namespaces");
- footer ();
-}
-void
-show_cgroups_stub (void)
-{
- header ("cgroups");
- footer ();
-}
-
-void
-show_oom_stub (void)
-{
- header ("oom");
- footer ();
-}
-
-void
-show_timezone_stub (void)
-{
- header ("timezone");
- footer ();
-}
-
-void
-show_capabilities_stub (void)
+show_capabilities (void)
{
header ("capabilities");
- footer ();
-}
-void
-show_shared_mem_stub (void)
-{
- header ("shared memory");
- footer ();
-}
-
-void
-show_semaphores_stub (void)
-{
- header ("semaphores");
- footer ();
-}
+ if (ops->show_capabilities)
+ ops->show_capabilities();
-void
-show_msg_queues_stub (void)
-{
- header ("message queues");
footer ();
}
-#endif /* PROCENV_LINUX */
-
-bool
-has_ctty (void)
-{
- int fd;
- fd = open ("/dev/tty", O_RDONLY | O_NOCTTY);
-
- if (fd < 0)
- return FALSE;
-
- close (fd);
-
- return TRUE;
-}
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-void
-show_cpu_bsd (void)
-{
- long max;
- kvm_t *kvm;
- struct kinfo_proc *proc;
- int ignored;
- int cpu;
- char errors[_POSIX2_LINE_MAX];
-
- assert (user.pid > 0);
-
- max = get_sysconf (_SC_NPROCESSORS_ONLN);
-
- kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
- if (! kvm)
- die ("unable to open kvm");
-
- proc = kvm_getprocs (kvm, KERN_PROC_PID, user.pid, &ignored);
- if (! proc)
- die ("failed to get process info");
-
- /* cpu values are zero-based */
- cpu = 1 + proc->ki_oncpu;
-
- if (kvm_close (kvm) < 0)
- die ("failed to close kvm");
-
- entry ("number", "%u of %lu", cpu, max);
-}
-
-void
-get_misc_bsd (void)
-{
- char errors[_POSIX2_LINE_MAX];
- kvm_t *kvm;
- struct kinfo_proc *proc;
- int ignored;
-
- kvm = kvm_openfiles (NULL, _PATH_DEVNULL, NULL, O_RDONLY, errors);
- if (! kvm)
- die ("unable to open kvm");
-
- proc = kvm_getprocs (kvm, KERN_PROC_PID, user.pid, &ignored);
- if (! proc)
- die ("failed to get process info");
-
- misc.in_jail = (proc->ki_flag & P_JAILED) ? TRUE : FALSE;
- strcpy (user.proc_name, proc->ki_comm);
-
- if (kvm_close (kvm) < 0)
- die ("failed to close kvm");
-}
-
-#endif
-
-int
-get_output_value (const char *name)
-{
- struct procenv_map *p;
-
- assert (name);
-
- for (p = output_map; p && p->name; p++) {
- if (! strcmp (name, p->name)) {
- return p->num;
- }
- }
- die ("invalid output value: '%s'", name);
-
- /* compiler appeasement */
- return -1;
-}
-
-int
-get_output_format (const char *name)
-{
- struct procenv_map *p;
-
- assert (name);
-
- for (p = output_format_map; p && p->name; p++) {
- if (! strcmp (name, p->name)) {
- return p->num;
- }
- }
- die ("invalid output format value: '%s'", name);
-
- /* compiler appeasement */
- return -1;
-}
-
-const char *
-get_output_format_name (void)
-{
- struct procenv_map *p;
-
- for (p = output_format_map; p && p->name; p++) {
- if (output_format == p->num)
- return p->name;
- }
-
- bug ("invalid output format: %d", output_format);
-
- /* compiler appeasement */
- return NULL;
-}
-
void
check_envvars (void)
{
@@ -8190,45 +3548,51 @@ check_envvars (void)
e = getenv (PROCENV_OUTPUT_ENV);
if (e && *e) {
- output = get_output_value (e);
+ set_output_value (e);
}
e = getenv (PROCENV_FILE_ENV);
if (e && *e) {
- output_file = e;
- output = OUTPUT_FILE;
+ set_output_file (e);
+ set_output_value_raw (OUTPUT_FILE);
+ }
+
+ e = getenv (PROCENV_FILE_APPEND_ENV);
+ if (e && *e) {
+ set_output_file_append ();
}
e = getenv (PROCENV_FORMAT_ENV);
if (e && *e) {
- output_format = get_output_format (e);
+ set_output_format (e);
}
e = getenv (PROCENV_INDENT_ENV);
if (e && *e) {
- indent_amount = atoi (e);
+ set_indent_amount (atoi (e));
}
e = getenv (PROCENV_INDENT_CHAR_ENV);
if (e && *e) {
/* Special character handling */
if (! strcmp (e, "\\t"))
- indent_char = "\t";
+ set_indent_char ("\t");
else
- indent_char = e;
+ set_indent_char (e);
}
e = getenv (PROCENV_SEPARATOR_ENV);
if (e && *e) {
- text_separator = e;
+ set_text_separator (e);
}
e = getenv (PROCENV_CRUMB_SEPARATOR_ENV);
if (e && *e) {
- if (! strcmp (e, "\\t"))
- crumb_separator = "\t";
- else
- crumb_separator = e;
+ if (! strcmp (e, "\\t")) {
+ set_crumb_separator ("\t");
+ } else {
+ set_crumb_separator (e);
+ }
}
e = getenv (PROCENV_EXEC_ENV);
@@ -8236,10 +3600,18 @@ check_envvars (void)
char *tmp;
string = strdup (e);
- if (! string)
+ if (! string) {
die ("failed to copy environment string");
+ }
+
+ if (! *string) {
+ die ("invalid command");
+ }
+
+ /* there must be atleast an no-arg command to run */
+ count = 1;
- /* establish number of fields */
+ /* establish number of fields required for program arguments */
for (tmp = string; tmp && *tmp; ) {
tmp = index (tmp, ' ');
if (tmp) {
@@ -8247,10 +3619,9 @@ check_envvars (void)
tmp++;
count++;
}
-
}
- /* allocate space for arguments.
+ /* allocate space for exec arguments.
* +1 for terminator.
*/
exec_args = calloc (count + 1, sizeof (char *));
@@ -8268,6 +3639,8 @@ check_envvars (void)
die ("failed to allocate space for exec arg");
}
+ reexec = true;
+
free (string);
}
}
@@ -8286,13 +3659,13 @@ get_major_minor (const char *path, unsigned int *_major, unsigned int *_minor)
* user does not have permission to check.
*/
*_major = *_minor = 0;
- return FALSE;
+ return false;
}
*_major = major (st.st_dev);
*_minor = minor (st.st_dev);
- return TRUE;
+ return true;
}
/**
@@ -8395,7 +3768,7 @@ show_threads (void)
entry ("stack size", "%lu bytes",
(unsigned long int)stack_size);
-#if defined (PROCENV_ANDROID)
+#if defined (PROCENV_PLATFORM_ANDROID)
ret = 0;
scope = pthread_attr_getscope (&attr);
#else
@@ -8406,7 +3779,16 @@ show_threads (void)
scope == PTHREAD_SCOPE_SYSTEM ? "PTHREAD_SCOPE_SYSTEM"
: "PTHREAD_SCOPE_PROCESS");
+#if defined (PROCENV_PLATFORM_MINIX)
+ {
+ int size;
+ ret = pthread_attr_getguardsize (&attr, &size);
+ guard_size = size;
+ }
+#else
ret = pthread_attr_getguardsize (&attr, &guard_size);
+#endif
+
if (ret == 0) {
entry ("guard size", "%lu bytes",
(unsigned long int)guard_size);
@@ -8428,7 +3810,7 @@ show_threads (void)
else
entry ("priority", "%d", param.sched_priority);
-#ifdef PROCENV_ANDROID
+#ifdef PROCENV_PLATFORM_ANDROID
section_close ();
#else
ret = pthread_attr_getinheritsched (&attr, &inherit_sched);
@@ -8440,9 +3822,12 @@ show_threads (void)
section_close ();
+#if !defined (PROCENV_PLATFORM_NETBSD)
entry ("concurrency", "%d", pthread_getconcurrency ());
#endif
+#endif
+
footer ();
}
@@ -8501,61 +3886,62 @@ int
main (int argc,
char *argv[])
{
- int option;
- int long_index;
- int done = FALSE;
+ int option;
+ int long_index;
+ int done = false;
struct option long_options[] = {
- {"meta" , no_argument, NULL, 'a'},
- {"arguments" , no_argument, NULL, 'A'},
- {"libs" , no_argument, NULL, 'b'},
- {"libc" , no_argument, NULL, 'B'},
- {"cgroups" , no_argument, NULL, 'c'},
- {"cpu" , no_argument, NULL, 'C'},
- {"compiler" , no_argument, NULL, 'd'},
- {"crumb-separator" , required_argument, NULL, 0},
- {"environment" , no_argument, NULL, 'e'},
- {"semaphores" , no_argument, NULL, 'E'},
- {"fds" , no_argument, NULL, 'f'},
- {"namespaces" , no_argument, NULL, 'F'},
- {"sizeof" , no_argument, NULL, 'g'},
- {"help" , no_argument, NULL, 'h'},
- {"misc" , no_argument, NULL, 'i'},
- {"uname" , no_argument, NULL, 'j'},
- {"clocks" , no_argument, NULL, 'k'},
- {"limits" , no_argument, NULL, 'l'},
- {"locale" , no_argument, NULL, 'L'},
- {"mounts" , no_argument, NULL, 'm'},
- {"message-queues" , no_argument, NULL, 'M'},
- {"confstr" , no_argument, NULL, 'n'},
- {"network" , no_argument, NULL, 'N'},
- {"oom" , no_argument, NULL, 'o'},
- {"process" , no_argument, NULL, 'p'},
- {"platform" , no_argument, NULL, 'P'},
- {"time" , no_argument, NULL, 'q'},
- {"ranges" , no_argument, NULL, 'r'},
- {"signals" , no_argument, NULL, 's'},
- {"shared-memory" , no_argument, NULL, 'S'},
- {"tty" , no_argument, NULL, 't'},
- {"threads" , no_argument, NULL, 'T'},
- {"stat" , no_argument, NULL, 'u'},
- {"rusage" , no_argument, NULL, 'U'},
- {"version" , no_argument, NULL, 'v'},
- {"capabilities" , no_argument, NULL, 'w'},
- {"pathconf" , no_argument, NULL, 'x'},
- {"sysconf" , no_argument, NULL, 'y'},
- {"memory" , no_argument, NULL, 'Y'},
- {"timezone" , no_argument, NULL, 'z'},
- {"exec" , no_argument , NULL, 0},
- {"file" , required_argument, NULL, 0},
- {"format" , required_argument, NULL, 0},
- {"indent" , required_argument, NULL, 0},
- {"indent-char" , required_argument, NULL, 0},
- {"output" , required_argument, NULL, 0},
- {"separator" , required_argument, NULL, 0},
+ {"meta" , no_argument , NULL, 'a'},
+ {"arguments" , no_argument , NULL, 'A'},
+ {"libs" , no_argument , NULL, 'b'},
+ {"libc" , no_argument , NULL, 'B'},
+ {"cgroups" , no_argument , NULL, 'c'},
+ {"cpu" , no_argument , NULL, 'C'},
+ {"compiler" , no_argument , NULL, 'd'},
+ {"crumb-separator" , required_argument , NULL, 0 },
+ {"environment" , no_argument , NULL, 'e'},
+ {"semaphores" , no_argument , NULL, 'E'},
+ {"fds" , no_argument , NULL, 'f'},
+ {"namespaces" , no_argument , NULL, 'F'},
+ {"sizeof" , no_argument , NULL, 'g'},
+ {"help" , no_argument , NULL, 'h'},
+ {"misc" , no_argument , NULL, 'i'},
+ {"uname" , no_argument , NULL, 'j'},
+ {"clocks" , no_argument , NULL, 'k'},
+ {"limits" , no_argument , NULL, 'l'},
+ {"locale" , no_argument , NULL, 'L'},
+ {"mounts" , no_argument , NULL, 'm'},
+ {"message-queues" , no_argument , NULL, 'M'},
+ {"confstr" , no_argument , NULL, 'n'},
+ {"network" , no_argument , NULL, 'N'},
+ {"oom" , no_argument , NULL, 'o'},
+ {"process" , no_argument , NULL, 'p'},
+ {"platform" , no_argument , NULL, 'P'},
+ {"time" , no_argument , NULL, 'q'},
+ {"ranges" , no_argument , NULL, 'r'},
+ {"signals" , no_argument , NULL, 's'},
+ {"shared-memory" , no_argument , NULL, 'S'},
+ {"tty" , no_argument , NULL, 't'},
+ {"threads" , no_argument , NULL, 'T'},
+ {"stat" , no_argument , NULL, 'u'},
+ {"rusage" , no_argument , NULL, 'U'},
+ {"version" , no_argument , NULL, 'v'},
+ {"capabilities" , no_argument , NULL, 'w'},
+ {"pathconf" , no_argument , NULL, 'x'},
+ {"sysconf" , no_argument , NULL, 'y'},
+ {"memory" , no_argument , NULL, 'Y'},
+ {"timezone" , no_argument , NULL, 'z'},
+ {"exec" , no_argument , NULL, 0 },
+ {"file" , required_argument , NULL, 0 },
+ {"file-append" , no_argument , NULL, 0 },
+ {"format" , required_argument , NULL, 0 },
+ {"indent" , required_argument , NULL, 0 },
+ {"indent-char" , required_argument , NULL, 0 },
+ {"output" , required_argument , NULL, 0 },
+ {"separator" , required_argument , NULL, 0 },
/* terminator */
- {NULL , no_argument , NULL, 0}
+ {NULL , no_argument , NULL, 0 }
};
doc = pstring_new ();
@@ -8573,7 +3959,7 @@ main (int argc,
init ();
- while (TRUE) {
+ while (true) {
option = getopt_long (argc, argv,
"aAbBcCdeEfFghijklLmMnNopPqrsStTuUvwxyYz",
long_options, &long_index);
@@ -8585,7 +3971,7 @@ main (int argc,
* count non-display options).
*/
if (option) {
- done = TRUE;
+ done = true;
master_header (&doc);
}
@@ -8599,47 +3985,53 @@ main (int argc,
die ("Must specify non-display options before display options");
if (! strcmp ("output", long_options[long_index].name)) {
- output = get_output_value (optarg);
+ set_output_value (optarg);
} else if (! strcmp ("file", long_options[long_index].name)) {
- output = OUTPUT_FILE;
- output_file = optarg;
+ set_output_value_raw (OUTPUT_FILE);
+ set_output_file (optarg);
+ } else if (! strcmp ("file-append", long_options[long_index].name)) {
+ set_output_file_append ();
} else if (! strcmp ("exec", long_options[long_index].name)) {
- reexec = TRUE;
+ reexec = true;
} else if (! strcmp ("format", long_options[long_index].name)) {
- output_format = get_output_format (optarg);
+ set_output_format (optarg);
} else if (! strcmp ("indent", long_options[long_index].name)) {
- indent_amount = atoi (optarg);
- if (indent_amount <= 0)
+ set_indent_amount (atoi (optarg));
+ if (get_indent_amount () <= 0)
die ("cannot specify indent <= 0");
} else if (! strcmp ("indent-char", long_options[long_index].name)) {
+ char *c = NULL;
+
/* Special character handling */
if (! strcmp (optarg, "\\t")) {
- indent_char = "\t";
+ c = "\t";
} else {
- indent_char = optarg;
+ c = optarg;
}
- if (! indent_char)
+ if (! c)
die ("cannot use nul indent character");
+ set_indent_char (c);
+
/* call again */
handle_indent_char ();
} else if (! strcmp ("separator", long_options[long_index].name)) {
if (! strcmp (optarg, "\\t")) {
- text_separator = "\t";
+ set_text_separator ("\t");
} else {
- text_separator = optarg;
+ set_text_separator (optarg);
}
} else if (! strcmp ("crumb-separator", long_options[long_index].name)) {
if (! strcmp (optarg, "\\t")) {
- crumb_separator = "\t";
+ set_crumb_separator ("\t");
} else {
- crumb_separator = optarg;
- }
+ set_crumb_separator (optarg);
+ }
}
/* reset */
selected_option = 0;
- indent = 0;
+ reset_indent ();
break;
@@ -8652,9 +4044,7 @@ main (int argc,
break;
case 'b':
-#ifndef PROCENV_ANDROID
show_libs ();
-#endif
break;
case 'B':
@@ -8729,9 +4119,7 @@ main (int argc,
break;
case 'n':
-#ifndef PROCENV_ANDROID
- show_confstrs ();
-#endif
+ show_confstrs();
break;
case 'N':
@@ -8818,18 +4206,14 @@ main (int argc,
master_footer (&doc);
- chomp (doc);
-
+ pstring_chomp (doc);
if (output_format != OUTPUT_FORMAT_XML && output_format != OUTPUT_FORMAT_JSON) {
- compress (&doc, wide_indent_char);
+ pstring_compress (&doc, wide_indent_char);
}
-
- goto finish;
}
- if (output == OUTPUT_SYSLOG)
- openlog (PACKAGE_NAME, LOG_CONS | LOG_PID, LOG_USER);
+ output_init ();
if (reexec && ! exec_args && optind >= argc)
die ("must specify atleast one argument with '--exec'");
@@ -8842,13 +4226,14 @@ main (int argc,
}
}
- dump ();
+ if (! done) {
+ dump ();
- chomp (doc);
+ pstring_chomp (doc);
- compress (&doc, wide_indent_char);
+ pstring_compress (&doc, wide_indent_char);
+ }
-finish:
_show_output_pstring (doc);
cleanup ();
@@ -8862,7 +4247,9 @@ finish:
}
-char *
+/* FIXME: we _assume_ the returned value is a static, but is it guaranteed?
+*/
+const char *
get_user_name (uid_t uid)
{
struct passwd *p;
@@ -8872,7 +4259,9 @@ get_user_name (uid_t uid)
return p ? p->pw_name : NULL;
}
-char *
+/* FIXME: we _assume_ the returned value is a static, but is it guaranteed?
+*/
+const char *
get_group_name (gid_t gid)
{
struct group *g;
@@ -8882,1081 +4271,6 @@ get_group_name (gid_t gid)
return g ? g->gr_name : NULL;
}
-/**
- * encode_string:
- *
- * @str: string to encode.
- *
- * Returns: 0 on success, -1 on failure.
- *
- * Convert the specified string to its encoded form. If no encoding is
- * necessary, the string will not be modified.
- *
- * Notes:
- *
- * - By encoding, we mean replacing literals with their
- * format-langage-specific encodings. For example for XML output,
- * '<' is converted to '&lt;'.
- *
- * - It is the callers responsibility to free @str iff this function
- * is successful. any previous value of @str will be freed by
- * encode_string().
- *
- * BUGS: this is just horribly, horribly gross :(
- **/
-int
-encode_string (pstring **pstr)
-{
- int ret = 0;
- pstring *new = NULL;
- wchar_t *p, *q;
- size_t non_printables;
- size_t len = 0;
- size_t bytes;
-
- assert (pstr);
- assert (*pstr);
-
- if ((*pstr)->len <= 1) {
- /* Nothing to do */
- return 0;
- }
-
- switch (output_format) {
-
- case OUTPUT_FORMAT_CRUMB: /* FALL */
- case OUTPUT_FORMAT_TEXT:
- /* Nothing to do */
- ret = 0;
- break;
-
- case OUTPUT_FORMAT_JSON: /* FALL THROUGH */
- case OUTPUT_FORMAT_XML:
- new = translate (*pstr);
- if (new) {
- pstring_free (*pstr);
- *pstr = new;
- new = NULL;
- } else {
- ret = -1;
- }
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-
- if (ret < 0)
- return ret;
-
- /* Now, search for evil non-printable characters and encode those
- * appropriately.
- */
- for (p = (*pstr)->buf, non_printables = 0; p && *p; p++) {
- if (! iswprint (*p))
- non_printables++;
- }
-
- if (non_printables &&
- (output_format == OUTPUT_FORMAT_XML
- || output_format == OUTPUT_FORMAT_JSON)) {
-
- size_t new_size = 0;
-
- wchar_t *json_format = L"\\u%4.4x";
-
- /* XXX:
- *
- * Although this format spec _may_ produce valid XML,
- * the rules are arcane and some(?) control characters
- * cannot be used within an XML document, hence the
- * "may".
- *
- * Aside from simply discarding non-printable characters
- * (thus distorting the output), we are left with
- * attempting to produce some sort of encoded
- * representation which may well choke a validating
- * parser.
- *
- * Realistically, the problem is confined to handling
- * control characters set in environment variables when
- * attempting to output XML. This may occur if you run
- * GNU Screen since it sets $TERMCAP which includes
- * binary characters.
- *
- * FIXME:
- *
- * If you hit this issue, raise a bug so we can consider
- * simply discarding all non-printables when attempting
- * XML output.
- */
- wchar_t *xml_format = L"&#x%2.2x;";
-
- len = (*pstr)->len;
-
- /* Calculate expanded size of string by removing
- * count of non-printable byte and adding back the
- * number of bytes required to encode them in expanded
- * form.
- */
- switch (output_format) {
- case OUTPUT_FORMAT_XML:
- new_size = (len - non_printables) + (non_printables * wcslen (L"&#x..;"));
- break;
-
- case OUTPUT_FORMAT_JSON:
- new_size = (len - non_printables) + (non_printables * wcslen (L"\\u...."));
- break;
- default:
- break;
- }
-
- new = pstring_new ();
- if (! new)
- return -1;
-
- bytes = (1 + new_size) * sizeof (wchar_t);
-
- new->buf = malloc (bytes);
- if (! new->buf) {
- free (new);
- return -1;
- }
-
- new->size = bytes;
-
- memset (new->buf, '\0', bytes);
-
- for (p = (*pstr)->buf, q = new->buf; p && *p; p++) {
- if (iswprint (*p)) {
- *q = *p;
- q++;
- new->len++;
- } else {
- ret = swprintf (q,
- new_size,
- output_format == OUTPUT_FORMAT_JSON
- ? json_format : xml_format,
- *p);
- q += ret;
- }
- }
-
- /* include terminator */
- new->len = wcslen (new->buf) + 1;
-
- pstring_free (*pstr);
- *pstr = new;
- }
-
- return ret;
-}
-
-/* Performs simple substitution on the input */
-pstring *
-translate (const pstring *pstr)
-{
- pstring *result = NULL;
- const wchar_t *start;
- const wchar_t *p;
- TranslateTable *table;
- size_t i;
- size_t len;
- size_t extra;
- size_t bytes;
- size_t amount;
- wchar_t from;
-
- assert (pstr);
- assert (output_format != OUTPUT_FORMAT_TEXT);
- assert (output_format != OUTPUT_FORMAT_CRUMB);
-
- /* Find the correct translation table for the chosen output format */
- for (i = 0; i < sizeof (translate_table) / sizeof (translate_table[0]); i++) {
- table = &translate_table[i];
- if (table && table->output_format == output_format)
- break;
- }
-
- if (! table)
- return NULL;
-
- len = pstr->len;
- start = pstr->buf;
-
- /* First, calculate the amount of space needed for the expanded
- * buffer.
- */
- extra = 0;
- while (start && *start) {
- for (i = 0; i < TRANSLATE_MAP_ENTRIES; i++) {
- from = table->map[i].from;
- if (*start == from) {
- /* Subtract one to take account of the
- * pre-existing character we're going to
- * replace.
- */
- extra += (wcslen (table->map[i].to) - 1);
- }
- }
- start++;
- }
-
- if (! extra) {
- /* No translation required.
- *
- * FIXME: this is inefficient - we should really have
- * the function accept a 'pstring **' to avoid
- * re-copying.
- */
- return pstring_create (pstr->buf);
- }
-
- len += extra;
-
- result = pstring_new ();
- if (! result)
- return NULL;
-
- /* Note that this includes the space for the terminator
- * (since a pstring's len includes the terminator)
- */
- bytes = len * sizeof (wchar_t);
-
- result->buf = malloc (bytes);
- if (! result->buf) {
- pstring_free (result);
- return NULL;
- }
-
- /* We're using wcsncat() so we'd better make sure there is a
- * nul for it to find!
- *
- * Note: we could have used calloc to do this for us, but
- * the code is clearer using the @bytes idiom.
- */
- memset (result->buf, '\0', bytes);
-
- result->size = bytes;
-
- /* Sanity check for upcoming overrun check */
- assert (result->buf[len-1] == L'\0');
-
- /* Now, iterate the string again, performing the actual
- * replacements.
- */
- p = start = pstr->buf;
-
- while (p && *p) {
- for (i = 0; i < TRANSLATE_MAP_ENTRIES; i++) {
- wchar_t *to;
- size_t len;
-
- from = table->map[i].from;
-
- if (*p != from)
- continue;
-
- to = table->map[i].to;
-
- amount = p - start;
-
- /* Copy from start to match */
- wcsncat (result->buf + result->len, start, amount);
-
- result->len += amount;
-
- /* Copy replacement text */
- len = wcslen (to);
- wcsncat (result->buf + result->len, to, len);
- result->len += len;
-
- /* Jump over the matching character */
- start = p + 1;
-
- break;
- }
- p++;
- }
-
- /* Copy remaining non-matching chars */
- amount = p - start;
- wcsncat (result->buf + result->len, start, amount);
- result->len += amount;
-
- /* Account for terminator */
- result->len += 1;
-
- /* check for buffer overrun */
- assert (result->buf[len-1] == L'\0');
-
- return result;
-}
-/**
- * change_element:
- *
- * Handle changing to a new element type. Depending on the output
- * format, this may require separators and newlines to be emitted to
- * produce well-formatted output.
- **/
-void
-change_element (ElementType new)
-{
- common_assert ();
-
- last_element = current_element;
-
- current_element = new;
-
- format_element ();
-}
-
-void
-format_element (void)
-{
- switch (output_format) {
-
- case OUTPUT_FORMAT_TEXT:
- format_text_element ();
- break;
-
- case OUTPUT_FORMAT_CRUMB:
- /* NOP */
- break;
-
- case OUTPUT_FORMAT_JSON:
- format_json_element ();
- break;
-
- case OUTPUT_FORMAT_XML:
- format_xml_element ();
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-format_text_element (void)
-{
- common_assert ();
- switch (last_element) {
-
- case ELEMENT_TYPE_ENTRY:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_NONE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-format_json_element (void)
-{
- common_assert ();
-
- switch (last_element) {
-
- case ELEMENT_TYPE_ENTRY:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L",\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- case ELEMENT_TYPE_OBJECT_OPEN:
- /* NOP */
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- assert_not_reached ();
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L",\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- /* NOP */
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- case ELEMENT_TYPE_SECTION_CLOSE:
- assert_not_reached ();
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L",\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- case ELEMENT_TYPE_SECTION_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- case ELEMENT_TYPE_SECTION_OPEN:
- wappend (&doc, L",\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_NONE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-void
-format_xml_element (void)
-{
- common_assert ();
-
- switch (last_element) {
-
- case ELEMENT_TYPE_ENTRY:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- assert_not_reached ();
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_SECTION_CLOSE:
- assert_not_reached ();
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- wappend (&doc, L"\n");
- dec_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_OBJECT_OPEN:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_CONTAINER_OPEN:
- wappend (&doc, L"\n");
- inc_indent ();
- add_indent (&doc);
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- /* NOP */
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_OBJECT_CLOSE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE:
- /* NOP */
- break;
-
- case ELEMENT_TYPE_CONTAINER_CLOSE:
- case ELEMENT_TYPE_ENTRY:
- wappend (&doc, L"\n");
- dec_indent ();
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- case ELEMENT_TYPE_NONE:
- {
- switch (current_element) {
- case ELEMENT_TYPE_ENTRY: /* FALL */
- case ELEMENT_TYPE_CONTAINER_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_OPEN: /* FALL */
- case ELEMENT_TYPE_SECTION_CLOSE: /* FALL */
- case ELEMENT_TYPE_CONTAINER_CLOSE: /* FALL */
- case ELEMENT_TYPE_OBJECT_OPEN: /* FALL */
- case ELEMENT_TYPE_OBJECT_CLOSE:
- add_indent (&doc);
- break;
-
- default:
- assert_not_reached ();
- break;
- }
- }
- break;
-
- default:
- assert_not_reached ();
- break;
- }
-}
-
-/**
- * compress:
- *
- * Remove lines composed entirely of whitespace from @str.
- *
- * This is required specifically for '--output=text' which in some
- * scenarios generates lines comprising pure whitespace. This is
- * unecessary and results from the fact that when an
- * ELEMENT_TYPE_OBJECT_* is encountered, formatting is applied for the
- * previously seen element, but sometimes such "objects" should be
- * invisible.
- **/
-void
-compress (pstring **wstr, wchar_t remove_char)
-{
- wchar_t *from;
- wchar_t *to;
- wchar_t *p;
- wchar_t *start;
- size_t count = 0;
- size_t blanks = 0;
- size_t new_len;
- size_t bytes;
-
- assert (wstr);
-
- to = from = (*wstr)->buf;
-
- while (to && *to) {
-again:
- while (*to == L'\n' && *(to+1) == L'\n') {
- /* skip over blank lines */
- to++;
- blanks++;
- }
-
- start = to;
-
- while (*to == remove_char) {
- /* skip runs of contiguous characters */
- to++;
- count++;
- }
-
- if (to != start) {
- /* Only start consuming NLs at the end of a
- * contiguous run *iff* there was more than a
- * single removed char. This is a heuristic to
- * avoid removing valid entries for example env
- * vars that are set to nul are shown as:
- *
- * 'var: '
- *
- * Shudder.
- */
- if (*to == L'\n' && to != start+1) {
- while (*to == L'\n') {
- /* consume the NL at the end of the contiguous run */
- to++;
- }
-
- /* check to ensure that we haven't entered a new line
- * containing another block of chars to remove.
- */
- if (*to == remove_char)
- goto again;
-
- blanks++;
-
- } else {
- /* not a full line so backtrack */
- to = start;
- count = 0;
- }
- }
-
- *from++ = *to++;
- }
-
- /* terminate */
- *from = L'\0';
-
- if (blanks || count) {
- new_len = (*wstr)->len - (blanks + count);
-
- bytes = new_len * sizeof (wchar_t);
-
- p = realloc ((*wstr)->buf, bytes);
- assert (p);
-
- (*wstr)->buf = p;
-
- (*wstr)->buf[new_len-1] = L'\0';
-
- (*wstr)->len = new_len;
- (*wstr)->size = bytes;
- }
-}
-/**
- * chomp:
- *
- * Remove trailing extraneous newlines and indent_chars from @str.
- **/
-void
-chomp (pstring *str)
-{
- size_t len;
- int removable = 0;
- wchar_t *p;
-
- assert (str);
-
- /* Unable to add '\n' in this scenario */
- if (str->len < 2)
- return;
-
- for (p = str->buf+str->len-1; *p == L'\n' || *p == wide_indent_char;
- p--, removable++)
- ;
-
- /* Chop string at the appropriate place after first adding a new
- * newline.
- */
- if (removable > 1) {
- len = str->len - (removable-1);
- str->buf[len-1] = L'\n';
- str->buf[len] = L'\0';
- str->len = len;
- }
-}
-
void
show_version (void)
{
@@ -9974,424 +4288,35 @@ show_version (void)
void
show_shared_mem (void)
{
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- show_shared_mem_linux ();
-#else
- show_shared_mem_stub ();
-#endif
-}
-
-void
-show_semaphores (void)
-{
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- show_semaphores_linux ();
-#else
- show_semaphores_stub ();
-#endif
-}
-
-void
-show_msg_queues (void)
-{
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- show_msg_queues_linux ();
-#else
- show_msg_queues_stub ();
-#endif
-}
-
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-void
-show_shared_mem_linux (void)
-{
- int i;
- int id;
- int max;
- struct shm_info info;
- struct shmid_ds shmid_ds;
- struct ipc_perm *perm;
- char formatted_atime[CTIME_BUFFER];
- char formatted_ctime[CTIME_BUFFER];
- char formatted_dtime[CTIME_BUFFER];
- char *modestr = NULL;
- int locked = -1;
- int destroy = -1;
- char *cpid = NULL;
- char *lpid = NULL;
-
header ("shared memory");
- max = shmctl (0, SHM_INFO, (void *)&info);
- if (max < 0)
- goto out;
-
- /* Display summary details */
-
- section_open ("info");
-
- entry ("segments", "%u", info.used_ids);
- entry ("pages", "%lu", info.shm_tot);
- entry ("shm_rss", "%lu", info.shm_rss);
- entry ("shm_swp", "%lu", info.shm_swp);
-
- /* Apparently unused */
- entry ("swap_attempts", "%lu", info.swap_attempts);
- entry ("swap_successes", "%lu", info.swap_successes);
-
- section_close ();
-
- container_open ("segments");
-
- object_open (FALSE);
-
- for (i = 0; i <= max; i++) {
- char *id_str = NULL;
-
- id = shmctl (i, SHM_STAT, &shmid_ds);
- if (id < 0) {
- /* found an unused slot, so ignore it */
- continue;
- }
-
- perm = &shmid_ds.shm_perm;
-
- modestr = format_perms (perm->mode);
- if (! modestr)
- die ("failed to allocate space for permissions string");
-
-#ifdef PROCENV_LINUX
- locked = (perm->mode & SHM_LOCKED);
- destroy = (perm->mode & SHM_DEST);
-#endif
-
- format_time (&shmid_ds.shm_atime, formatted_atime, sizeof (formatted_atime));
- format_time (&shmid_ds.shm_ctime, formatted_ctime, sizeof (formatted_ctime));
- format_time (&shmid_ds.shm_dtime, formatted_dtime, sizeof (formatted_dtime));
-
- cpid = pid_to_name (shmid_ds.shm_cpid);
- lpid = pid_to_name (shmid_ds.shm_lpid);
-
- appendf (&id_str, "%d", id);
-
- container_open (id_str);
- free (id_str);
-
- object_open (FALSE);
-
- /* pad out to max pointer size represented in hex.
- */
- entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
- entry ("sequence", "%u", perm->__seq);
-
- section_open ("permissions");
- entry ("octal", "%4.4o", perm->mode);
- entry ("symbolic", "%s", modestr);
- section_close ();
-
- section_open ("pids");
- entry ("create", "%d (%s)", shmid_ds.shm_cpid, cpid ? cpid : UNKNOWN_STR);
- entry ("last", "%d (%s)", shmid_ds.shm_lpid, lpid ? lpid : UNKNOWN_STR);
- section_close ();
-
- entry ("attachers", "%lu", shmid_ds.shm_nattch);
-
- section_open ("creator");
- entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
- entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
- section_close ();
-
- section_open ("owner");
- entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
- entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
- section_close ();
-
- entry ("segment size", "%lu", shmid_ds.shm_segsz);
-
- section_open ("times");
- entry ("last attach (atime)", "%lu (%s)", shmid_ds.shm_atime, formatted_atime);
- entry ("last detach (dtime)", "%lu (%s)", shmid_ds.shm_dtime, formatted_dtime);
- entry ("last change (ctime)", "%lu (%s)", shmid_ds.shm_ctime, formatted_ctime);
- section_close ();
-
- entry ("locked", "%s", locked == 0 ? NO_STR
- : locked > 0 ? YES_STR
- : NA_STR);
- entry ("destroy", "%s", destroy == 0 ? NO_STR
- : destroy > 0 ? YES_STR
- : NA_STR);
-
- object_close (FALSE);
-
- container_close ();
-
- free (modestr);
- if (cpid)
- free (cpid);
- if (lpid)
- free (lpid);
- }
-
- object_close (FALSE);
-
- container_close ();
+ if (ops->show_shared_mem)
+ ops->show_shared_mem ();
-out:
footer ();
}
void
-show_semaphores_linux (void)
+show_semaphores (void)
{
- int i;
- int id;
- int max;
- struct semid_ds semid_ds;
- struct seminfo info;
- struct ipc_perm *perm;
- char formatted_otime[CTIME_BUFFER];
- char formatted_ctime[CTIME_BUFFER];
- char *modestr = NULL;
- union semun arg;
-
header ("semaphores");
- arg.array = (unsigned short int *)(void *)&info;
- max = semctl (0, 0, SEM_INFO, arg);
- if (max < 0)
- goto out;
-
- section_open ("info");
-
- entry ("semmap", "%d", info.semmap);
- entry ("semmni", "%d", info.semmni);
- entry ("semmns", "%d", info.semmns);
- entry ("semmnu", "%d", info.semmnu);
- entry ("semmsl", "%d", info.semmsl);
- entry ("semopm", "%d", info.semopm);
- entry ("semume", "%d", info.semume);
- entry ("semusz", "%d", info.semusz);
- entry ("semvmx", "%d", info.semvmx);
- entry ("semaem", "%d", info.semaem);
-
- section_close ();
-
- container_open ("set");
-
- object_open (FALSE);
-
- for (i = 0; i <= max; i++) {
- char *id_str = NULL;
-
- /* see semctl(2) */
- arg.buf = (struct semid_ds *)&semid_ds;
-
- id = semctl (i, 0, SEM_STAT, arg);
- if (id < 0) {
- /* found an unused slot, so ignore it */
- continue;
- }
-
- perm = &semid_ds.sem_perm;
-
- modestr = format_perms (perm->mode);
- if (! modestr)
- die ("failed to allocate space for permissions string");
-
- /* May not have been set */
- if (semid_ds.sem_otime)
- format_time (&semid_ds.sem_otime, formatted_otime, sizeof (formatted_otime));
- else
- sprintf (formatted_otime, "%s", NA_STR);
-
- format_time (&semid_ds.sem_ctime, formatted_ctime, sizeof (formatted_ctime));
-
- appendf (&id_str, "%d", id);
-
- container_open (id_str);
- free (id_str);
-
- object_open (FALSE);
-
- /* pad out to max pointer size represented in hex.
- */
- entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
- entry ("sequence", "%u", perm->__seq);
-
- entry ("number in set", "%lu", semid_ds.sem_nsems);
-
- section_open ("permissions");
- entry ("octal", "%4.4o", perm->mode);
- entry ("symbolic", "%s", modestr);
- free (modestr);
- section_close ();
-
- section_open ("creator");
- entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
- entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
- section_close ();
-
- section_open ("owner");
- entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
- entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
- section_close ();
-
- section_open ("times");
- entry ("last semop (otime)", "%lu (%s)", semid_ds.sem_otime, formatted_otime);
- entry ("last change (ctime)", "%lu (%s)", semid_ds.sem_ctime, formatted_ctime);
- section_close ();
-
- object_close (FALSE);
-
- container_close ();
- }
-
- object_close (FALSE);
-
- container_close ();
+ if (ops->show_semaphores)
+ ops->show_semaphores ();
-out:
footer ();
}
void
-show_msg_queues_linux (void)
+show_msg_queues (void)
{
- int i;
- int id;
- int max;
- struct msginfo info;
- struct msqid_ds msqid_ds;
- struct ipc_perm *perm;
- char formatted_stime[CTIME_BUFFER];
- char formatted_rtime[CTIME_BUFFER];
- char formatted_ctime[CTIME_BUFFER];
- char *modestr = NULL;
- char *lspid = NULL;
- char *lrpid = NULL;
-
header ("message queues");
- max = msgctl (0, MSG_INFO, (void *)&info);
- if (max < 0)
- goto out;
-
- section_open ("info");
-
- entry ("msgpool", "%d", info.msgpool);
- entry ("msgmap", "%d", info.msgmap);
- entry ("msgmax", "%d", info.msgmax);
- entry ("msgmnb", "%d", info.msgmnb);
- entry ("msgmni", "%d", info.msgmni);
- entry ("msgssz", "%d", info.msgssz);
- entry ("msgtql", "%d", info.msgtql);
- entry ("msgseg", "%d", info.msgseg);
-
- section_close ();
-
- container_open ("sets");
-
- object_open (FALSE);
-
- for (i = 0; i <= max; i++) {
- char *id_str = NULL;
-
- id = msgctl (i, MSG_STAT, &msqid_ds);
- if (id < 0) {
- /* found an unused slot, so ignore it */
- continue;
- }
-
- perm = &msqid_ds.msg_perm;
-
- modestr = format_perms (perm->mode);
- if (! modestr)
- die ("failed to allocate space for permissions string");
-
- /* May not have been set */
- if (msqid_ds.msg_stime)
- format_time (&msqid_ds.msg_stime, formatted_stime, sizeof (formatted_stime));
- else
- sprintf (formatted_stime, "%s", NA_STR);
-
- /* May not have been set */
- if (msqid_ds.msg_rtime)
- format_time (&msqid_ds.msg_rtime, formatted_rtime, sizeof (formatted_rtime));
- else
- sprintf (formatted_rtime, "%s", NA_STR);
-
- /* May not have been set */
- if (msqid_ds.msg_ctime)
- format_time (&msqid_ds.msg_ctime, formatted_ctime, sizeof (formatted_ctime));
- else
- sprintf (formatted_ctime, "%s", NA_STR);
-
- lspid = pid_to_name (msqid_ds.msg_lspid);
- lrpid = pid_to_name (msqid_ds.msg_lrpid);
-
- appendf (&id_str, "%d", id);
-
- container_open (id_str);
- free (id_str);
-
- object_open (FALSE);
+ if (ops->show_msg_queues)
+ ops->show_msg_queues ();
- /* pad out to max pointer size represented in hex */
- entry ("key", "0x%.*x", POINTER_SIZE * 2, perm->__key);
- entry ("sequence", "%u", perm->__seq);
-
- section_open ("permissions");
- entry ("octal", "%4.4o", perm->mode);
- entry ("symbolic", "%s", modestr);
- section_close ();
-
- section_open ("creator");
- entry ("euid", "%u ('%s')", perm->cuid, get_user_name (perm->cuid));
- entry ("egid", "%u ('%s')", perm->cgid, get_group_name (perm->cgid));
- section_close ();
-
- section_open ("owner");
- entry ("uid", "%u ('%s')", perm->uid, get_user_name (perm->uid));
- entry ("gid", "%u ('%s')", perm->gid, get_group_name (perm->gid));
- section_close ();
-
- section_open ("times");
- entry ("last send (stime)", "%lu (%s)", msqid_ds.msg_stime, formatted_stime);
- entry ("last receive (rtime)", "%lu (%s)", msqid_ds.msg_rtime, formatted_rtime);
- entry ("last change (ctime)", "%lu (%s)", msqid_ds.msg_ctime, formatted_ctime);
- section_close ();
-
- entry ("queue_bytes", "%lu", msqid_ds.__msg_cbytes);
-
- entry ("msg_qnum", "%lu", msqid_ds.msg_qnum);
- entry ("msg_qbytes", "%lu", msqid_ds.msg_qbytes);
-
- entry ("last msgsnd pid", "%d (%s)", msqid_ds.msg_lspid,
- lspid ? lspid : UNKNOWN_STR);
-
- entry ("last msgrcv pid", "%d (%s)", msqid_ds.msg_lrpid,
- lrpid ? lrpid : UNKNOWN_STR);
-
- object_close (FALSE);
-
- container_close ();
-
- free (modestr);
- if (lspid)
- free (lspid);
- if (lrpid)
- free (lrpid);
- }
-
- object_close (FALSE);
-
- container_close ();
-
-out:
footer ();
}
-#endif /* PROCENV_LINUX || PROCENV_HURD */
void
format_time (const time_t *t, char *buffer, size_t len)
@@ -10461,290 +4386,258 @@ format_perms (mode_t mode)
return modestr;
}
-char *
-pid_to_name (pid_t pid)
-{
- char path[PATH_MAX];
- char *name = NULL;
- FILE *f = NULL;
-
- sprintf (path, "/proc/%d/cmdline", (int)pid);
-
- f = fopen (path, "r");
- if (! f)
- goto out;
-
- /* Reuse buffer */
- if (! fgets (path, sizeof (path), f))
- goto out;
-
- /* Nul delimiting within /proc file will ensure we only get the
- * program name.
- */
- append (&name, path);
-
-out:
- if (f)
- fclose (f);
-
- return name;
-}
-
+/*
+ * BSD returns an additional AF_LINK ifaddrs containing the
+ * actual link-layer MAC address for each interface.
+ *
+ * Linux does the same but with one additional AF_PACKET family / interface.
+ *
+ * This is somewhat noisome since for BSD we need to cache the MAC addresses
+ * such that they can be retrieved when the _next_ ifaddrs structure
+ * appears for the *same* interface, but we only want to
+ * display the non-AF_LINK elements *unless* they refer
+ * to an interface with no associated address.
+ *
+ * The situation for Linux is similar but we only care
+ * about AF_PACKET entries for interfaces that have no
+ * associated address since we can extract the MAC
+ * address using an ioctl (rather than considering the
+ * AF_PACKET element).
+ *
+ * The strategy therefore is to:
+ *
+ * 1) Cache all AF_LINK/AF_PACKET elements.
+ * 2) Once an element arrives that matches an interface
+ * name found in the cache, use that as necessary (extra
+ * the MAC for BSD, NOP for Linux), then free that cache
+ * element.
+ * 3) Having processed all entries, if any entries are
+ * left in the cache, they must refer to interfaces that
+ * have no address, so display them.
+ *
+ * XXX: Note the implicit assumption that the AF_LINK/AF_PACKET entries
+ * will appear _before_ the corresponding entry containing address
+ * details for the interface in the output of getifaddrs(): observations
+ * suggests this _seems_ to be the case, but is not documented as being
+ * guaranteed.
+ */
+#ifdef PROCENV_PLATFORM_ANDROID
+// FIXME: split out to platfom
void
-add_breadcrumb (const char *name)
+show_network (void)
{
- assert (name);
-
- if (! crumb_list)
- crumb_list = pr_list_new (NULL);
-
- assert (crumb_list);
-
- pr_list_prepend_str (crumb_list, name);
+ /* Bionic isn't actually that bionic at all :( */
+ header ("network");
+ footer ();
}
-void
-remove_breadcrumb (void)
-{
- PRList *entry;
-
- assert (crumb_list);
-
- entry = pr_list_remove (crumb_list->prev);
- assert (entry);
-
- free ((char *)entry->data);
- free (entry);
-}
+#else
void
-clear_breadcrumbs (void)
-{
- assert (crumb_list);
-
- while (crumb_list->prev != crumb_list)
- remove_breadcrumb ();
-}
-
-wchar_t *
-char_to_wchar (const char *str)
+show_network (void)
{
- const char *p;
- wchar_t *wstr = NULL;
- size_t len;
- size_t bytes;
-
- assert (str);
-
- len = mbsrtowcs (NULL, &str, 0, NULL);
- if (len <= 0)
- return NULL;
-
- /* include space for terminator */
- bytes = (1 + len) * sizeof (wchar_t);
-
- wstr = malloc (bytes);
- if (! wstr)
- return NULL;
-
- p = str;
+ struct ifaddrs *if_addrs;
+ struct ifaddrs *ifa;
+ char *mac_address = NULL;
+ struct network_map *head = NULL;
+ struct network_map *node = NULL;
+ struct network_map *tmp = NULL;
- if (mbsrtowcs (wstr, &p, len, NULL) != len)
- goto error;
+ common_assert ();
- /* ensure it's terminated */
- wstr[len] = L'\0';
+ header ("network");
- return wstr;
+ /* Query all network interfaces */
+ if (getifaddrs (&if_addrs) < 0)
+ return;
-error:
- free (wstr);
- return NULL;
-}
+ /* Construct an initial node for the cache */
+ head = calloc (1, sizeof (struct network_map));
+ assert (head);
-pstring *
-pstring_new (void)
-{
- pstring *pstr = NULL;
+ /* Iterate over all network interfaces */
+ for (ifa = if_addrs; ifa; ifa = ifa->ifa_next) {
+#if !defined (PROCENV_PLATFORM_HURD)
+ int family;
+#endif
- pstr = calloc (1, sizeof (pstring));
- if (! pstr)
- return NULL;
+ if (! ifa->ifa_addr)
+ continue;
- pstr->len = 0;
- pstr->size = 0;
- pstr->buf = NULL;
+#if !defined (PROCENV_PLATFORM_HURD)
+ family = ifa->ifa_addr->sa_family;
- return pstr;
-}
+ if (family == PROCENV_LINK_LEVEL_FAMILY) {
-pstring *
-pstring_create (const wchar_t *str)
-{
- pstring *pstr = NULL;
+ /* MAC address cannot be queries on minix seemingly */
+#if !defined (PROCENV_PLATFORM_MINIX)
+ /* Add link level interface details to the cache */
+ mac_address = get_mac_address (ifa);
+#endif
- assert (str);
+ node = calloc (1, sizeof (struct network_map));
+ assert (node);
- pstr = pstring_new ();
+ /* Conveniently, an ifaddrs contains a bunch of
+ * pointers and some flags.
+ *
+ * Since all those pointers are valid until we
+ * call freeifaddrs(), all we need to do is copy
+ * the flags since the memcpy will copy the
+ * pointers addresses for us :)
+ */
+ memcpy (&node->ifaddr, ifa, sizeof (struct ifaddrs));
+ node->ifaddr.ifa_flags = ifa->ifa_flags;
- if (! pstr)
- return NULL;
+ /* Since we've already formatted the MAC
+ * address, we'll cache that too.
+ */
+ node->mac_address = mac_address;
+ mac_address = NULL;
- pstr->buf = wcsdup (str);
- if (! pstr->buf) {
- pstring_free (pstr);
- return NULL;
- }
+ /* prepend */
+ node->next = head->next;
+ if (head->next)
+ head->next->prev = node;
+ node->prev = head;
+ head->next = node;
- /* include the L'\0' terminator */
- pstr->len = 1 + wcslen (pstr->buf);
+ continue;
+ }
+#endif
- pstr->size = pstr->len * sizeof (wchar_t);
+ /* From now on, we're only looking at interfaces with an
+ * address.
+ */
- return pstr;
-}
+ /* Search for an entry corresponding to the interface in the cache */
+ for (node = head->next; node && node->ifaddr.ifa_name; node = node->next) {
+ if (! strcmp (node->ifaddr.ifa_name, ifa->ifa_name)) {
-void
-pstring_free (pstring *str)
-{
- assert (str);
+ /* Save */
+ mac_address = node->mac_address
+ ? strdup (node->mac_address)
+ : NULL;
- if (str->buf)
- free (str->buf);
+ /* Unlink existing node as it has now served its purpose */
+ node->prev->next = node->next;
+ if (node->next)
+ node->next->prev = node->prev;
- free (str);
-}
+ /* Destroy */
+ if (node->mac_address)
+ free (node->mac_address);
+ free (node);
-pstring *
-char_to_pstring (const char *str)
-{
- pstring *pstr = NULL;
- wchar_t *s;
+ break;
+ }
+ }
- assert (str);
+ /* Display the interface (which must have an associated address) */
+ show_network_if (ifa, mac_address);
+ if (mac_address) {
+ free (mac_address);
+ mac_address = NULL;
+ }
+ }
- s = char_to_wchar (str);
- if (! s)
- return NULL;
+ /* Destroy the cache, displaying any interfaces not previously displayed.
+ * These by definition cannot have addresses assigned to them.
+ */
+ for (node = head->next; node && node->ifaddr.ifa_name; node = tmp) {
- pstr = pstring_create (s);
+ tmp = node->next;
- free (s);
+ show_network_if (&node->ifaddr, node->mac_address);
- return pstr;
-}
+ /* Destroy */
+ if (node->mac_address)
+ free (node->mac_address);
+ free (node);
+ }
-char *
-pstring_to_char (const pstring *str)
-{
- assert (str);
+ free (head);
+ freeifaddrs (if_addrs);
- return wchar_to_char (str->buf);
+ footer ();
}
+#endif
-char *
-wchar_to_char (const wchar_t *wstr)
+void
+show_misc (void)
{
- char *str = NULL;
- size_t len;
- size_t bytes;
- size_t ret;
-
- assert (wstr);
-
- len = wcslen (wstr);
-
- /* determine number of MBS (char) bytes requires to hold the
- * wchar_t string.
- */
- bytes = wcstombs (NULL, wstr, len);
- if (! bytes)
- return NULL;
-
- str = calloc (bytes + 1, sizeof (char));
- if (! str)
- return NULL;
-
- /* actually perform the conversion */
- ret = wcstombs (str, wstr, bytes);
-
- if (! ret)
- goto error;
-
- return str;
+#if defined (PROCENV_PLATFORM_LINUX)
+ int domain = 0x0;
-error:
- free (str);
- return NULL;
-}
+ /* magic value - see personality(2) */
+ unsigned int persona = 0xFFFFFFFF;
-#if ! defined (HAVE_SCHED_GETCPU)
+ unsigned int mask = PER_MASK;
-/**
- * @string: input,
- * @delimiter: field delimiter,
- * @compress: if TRUE, ignore repeated contiguous delimiter characters,
- * @array: [output] array of fields, which this function will allocate.
- *
- * Notes: it is the callers responsibility to free @array
- * if the returned value is >0.
- *
- * Returns: number of fields in @string.
- **/
-size_t
-split_fields (const char *string, char delimiter, int compress, char ***array)
-{
- const char *p = NULL;
- const char *start = NULL;
- size_t count = 0;
- char *elem;
- char **new;
+ const char *personality_name = NULL;
+ char *personality_flags = NULL;
+#endif
- assert (string);
- assert (delimiter);
- assert (array);
+ header ("misc");
- *array = NULL;
+ entry ("umask", "%4.4o", misc.umask_value);
+ entry ("current directory (cwd)", "'%s'", misc.cwd);
+#if defined (PROCENV_PLATFORM_LINUX)
+ entry ("root", "%s%s%s",
+ strcmp (misc.root, UNKNOWN_STR) ? "'" : "",
+ misc.root,
+ strcmp (misc.root, UNKNOWN_STR) ? "'" : "");
+#endif
+ entry ("chroot", "%s", in_chroot () ? YES_STR : NO_STR);
+ entry ("container", "%s", container_type ());
- new = realloc ((*array), sizeof (char *) * (1+count));
- assert (new);
+ entry ("vm", "%s",
+ ops->in_vm ?
+ ops->in_vm () ? YES_STR : NO_STR
+ : UNKNOWN_STR);
- new[0] = NULL;
- *array = new;
+ if (ops->show_prctl) {
+ section_open ("prctl");
+ ops->show_prctl ();
+ section_close ();
+ }
- p = string;
+ if (ops->show_security_module) {
+ section_open ("security module");
+ ops->show_security_module ();
+ section_close ();
+ }
- while (p && *p) {
- /* skip leading prefix */
- while (compress && p && *p == delimiter)
- p++;
+#if defined (PROCENV_PLATFORM_LINUX)
+#ifdef LINUX_VERSION_CODE
+ entry ("kernel headers version", "%u.%u.%u",
+ (LINUX_VERSION_CODE >> 16),
+ ((LINUX_VERSION_CODE >> 8) & 0xFF),
+ (LINUX_VERSION_CODE & 0xFF));
+#endif
- if (! *p)
- break;
+ domain = personality (persona);
- /* found a field */
- count++;
+ personality_name = get_personality_name (domain & mask);
- if (! compress)
- p++;
+ section_open ("personality");
- /* skip over the field */
- start = p;
- while (p && *p && *p != delimiter)
- p++;
+ entry ("type", "%s", personality_name
+ ? personality_name
+ : UNKNOWN_STR);
- elem = strndup (start, p-start);
- assert (elem);
+ personality_flags = get_personality_flags (domain & (-1 ^ mask));
+ entry ("flags", "%s",
+ personality_flags
+ ? personality_flags
+ : "");
- new = realloc ((*array), sizeof (char *) * (1+count));
- assert (new);
+ section_close ();
- new[count-1] = elem;
- *array = new;
- }
+ if (personality_flags)
+ free (personality_flags);
+#endif
- return count;
+ footer ();
}
-
-#endif
diff --git a/src/procenv.h b/src/procenv.h
index 501fa08..4d3f905 100644
--- a/src/procenv.h
+++ b/src/procenv.h
@@ -1,5 +1,5 @@
/*--------------------------------------------------------------------
- * Copyright © 2012-2015 James Hunt <jamesodhunt@ubuntu.com>.
+ * Copyright © 2012-2016 James Hunt <jamesodhunt@ubuntu.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,6 +50,10 @@
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
+
+/* XXX: must come before sched.h on Minix! */
+#include <pthread.h>
+
#include <sched.h>
#include <termios.h>
#include <getopt.h>
@@ -59,38 +63,52 @@
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include <link.h>
#include <fenv.h>
#include <sys/utsname.h>
#include <locale.h>
-#include <pthread.h>
-#include <netdb.h>
#include <sys/socket.h>
+#include <netdb.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "util.h"
+#include "string-util.h"
+#include "pr_list.h"
+#include "output.h"
+#include "platform.h"
-#include <pr_list.h>
+#include "platform-headers.h"
+
+/*********************************************************************/
+// FIXME: ANDROID - need to auto-generate values!!
+
+#if defined PROCENV_PLATFORM_ANDROID
-/* FIXME: Android testing */
-#if 1
#ifndef PACKAGE_NAME
#define PACKAGE_NAME "procenv"
#endif
-/* FIXME: ugh */
#ifndef PACKAGE_VERSION
-#define PACKAGE_VERSION "0.28"
+#define PACKAGE_VERSION "0.24"
#endif
#ifndef PACKAGE_STRING
#define PACKAGE_STRING PACKAGE_NAME
#endif
-#endif /* FIXME */
+/* major(3) / minor(3) */
+#include <sys/sysmacros.h>
+
+#endif /* PROCENV_PLATFORM_ANDROID */
+
+/*********************************************************************/
/**
* PROCENV_FORMAT_VERSION:
@@ -133,422 +151,52 @@
* - Added --namespaces.
* VERSION 12:
* - Change format of --namespaces output.
+ * VERSION 13:
+ * - Added I/O priority to --cpu.
+ * VERSION 14:
+ * - Added driver to --meta.
+ * VERION 15:
+ * - Renamed "linux security module" to "security" module in --misc.
+ * - Added procenv driver details to --meta.
+ * VERSION 16:
+ * - Sort feature-test macros.
+ * VERSION 17:
+ * - Added 'vm' to --misc output.
**/
-#define PROCENV_FORMAT_VERSION 12
-
-#define PROCENV_DEFAULT_TEXT_SEPARATOR ": "
-
-#define PROCENV_DEFAULT_CRUMB_SEPARATOR ":"
-
-#if defined (__FreeBSD__) \
- || defined (__NetBSD__) \
- || defined (__OpenBSD__)
-#define PROCENV_BSD
-#endif
-
-#ifdef __linux__
-#define PROCENV_LINUX
-#endif
-
-#if defined (PROCENV_LINUX) && defined (__BIONIC__)
-#define PROCENV_ANDROID
-#endif
-
-#if defined (__FreeBSD_kernel__) && defined (__GNUC__)
-/* Debian kFreeBSD (GNU userland + BSD kernel) */
-#define PROCENV_GNU_BSD
-#endif
-
-#ifdef __GNU__
-#define PROCENV_HURD
-#endif
-
-#if defined (__i386__) || defined (__x86_64__)
-#define PROCENV_ARCH_X86
-#endif
-
-#if defined PROCENV_ANDROID
-#ifndef PACKAGE_NAME
-#define PACKAGE_NAME "procenv"
-#endif
-
-#ifndef PACKAGE_VERSION
-#define PACKAGE_VERSION "0.24"
-#endif
-
-#ifndef PACKAGE_STRING
-#define PACKAGE_STRING PACKAGE_NAME
-#endif
-
-/* major(3) / minor(3) */
-#include <sys/sysmacros.h>
-#endif
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-#include <mntent.h>
-#include <sys/vfs.h>
-#include <sys/statvfs.h>
-#endif
-
-#if defined (PROCENV_LINUX)
-#include <linux/if.h>
-
-#include <sys/inotify.h>
-#include <sys/prctl.h>
-#include <sys/personality.h>
-
-#include <linux/prctl.h>
-#include <linux/version.h>
-
-#if defined (HAVE_NUMA_H)
-
-#include <numa.h>
-#include <numaif.h>
-
-#if LIBNUMA_API_VERSION == 2
-#define PROCENV_NUMA_BITMASK_ISSET(mask, node) numa_bitmask_isbitset ((mask), (node))
-#else
-#define PROCENV_NUMA_BITMASK_ISSET(mask, node) nodemask_isset (&(mask), (node))
-int procenv_getcpu (void);
-#endif
-#endif /* HAVE_NUMA_H */
-
-#if ! defined(HAVE_SCHED_GETCPU)
-size_t split_fields (const char *string, char delimiter, int compress, char ***array);
-#endif
-
-/* Lucid provides prctl.h, but not securebits.h */
-#if defined (PR_GET_SECUREBITS) && defined (HAVE_LINUX_SECUREBITS_H)
-#include <linux/securebits.h>
-#endif
-
-#include <linux/capability.h>
-#include <linux/vt.h>
-
-#if defined (HAVE_SYS_APPARMOR_H)
-#include <sys/apparmor.h>
-#endif
+#define PROCENV_FORMAT_VERSION 17
-#if defined (HAVE_SELINUX_SELINUX_H)
-#include <selinux/selinux.h>
-#endif
-
-/**
- * show_capability:
- * @caps: cap_t,
- * @cap: capability.
- *
- * Display specified capability, or NOT_DEFINED_STR if value is
- * unknown.
- **/
-#ifdef PR_CAPBSET_READ
-#define show_capability(caps, cap) \
- _show_capability (caps, cap, #cap)
-#define _show_capability(caps, cap, name) \
-{ \
- int bound; \
- int effective; \
- int inheritable; \
- int permitted; \
- \
- bound = cap_get_bound (cap); \
- \
- effective = get_capability_by_flag_type (caps, CAP_EFFECTIVE, cap); \
- inheritable = get_capability_by_flag_type (caps, CAP_INHERITABLE, cap); \
- permitted = get_capability_by_flag_type (caps, CAP_PERMITTED, cap); \
- \
- section_open (name); \
- \
- entry ("number", "%d", cap); \
- \
- entry ("supported", "%s", \
- CAP_IS_SUPPORTED (cap) \
- ? YES_STR : NO_STR); \
- \
- entry ("in bounding set", "%s", \
- bound < 0 \
- ? UNKNOWN_STR \
- : bound \
- ? YES_STR \
- : NO_STR); \
- \
- entry ("effective", "%s", \
- effective < 0 \
- ? NOT_DEFINED_STR \
- : effective == CAP_SET \
- ? YES_STR \
- : NO_STR); \
- \
- entry ("inheritable", "%s", \
- inheritable < 0 \
- ? NOT_DEFINED_STR \
- : inheritable == CAP_SET \
- ? YES_STR \
- : NO_STR); \
- \
- entry ("permitted", "%s", \
- permitted < 0 \
- ? NOT_DEFINED_STR \
- : permitted == CAP_SET \
- ? YES_STR \
- : NO_STR); \
- \
- section_close (); \
-}
-#else
-#define show_capability(caps, cap)
-#endif
-
-/**
- * LINUX_KERNEL_M:
- * @major: Linux major kernel version number.
- *
- * Returns: TRUE if running Linux kernel is atleast at version
- * specified by @major else FALSE.
- **/
-#define LINUX_KERNEL_M(major) \
- (linux_kernel_version (major, -1, -1))
-
-/**
- * LINUX_KERNEL_MM:
- * @major: Linux major kernel version number,
- * @minor: Linux minor kernel version number.
- *
- * Returns: TRUE if running Linux kernel is atleast at version
- * specified by (@major, @minor) else FALSE.
- **/
-#define LINUX_KERNEL_MM(major, minor) \
- (linux_kernel_version (major, minor, -1))
-
-/**
- * LINUX_KERNEL_MMR:
- * @major: Linux major kernel version number,
- * @minor: Linux minor kernel version number,
- * @revision: kernel revision version.
- *
- * Returns: TRUE if running Linux kernel is atleast at version
- * specified by (@major, @minor, @revision) else FALSE.
- **/
-#define LINUX_KERNEL_MMR(major, minor, revision) \
- (linux_kernel_version (major, minor, revision))
-
-#endif
-
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-#include <kvm.h>
-#include <sys/sysctl.h>
-#include <sys/user.h>
-#include <sys/ucred.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <netinet/in.h>
-#include <sys/consio.h>
-#endif
-
-#if defined (PROCENV_HURD)
-#include <net/if.h>
-#endif
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-#include <sys/mount.h>
-#endif
-
-#if defined (PROCENV_BSD)
-#define PROCENV_CPU_SET_TYPE cpuset_t
-#include <pthread_np.h>
-
-#if defined (HAVE_SYS_CAPABILITY_H)
-#include <sys/capability.h>
-
-#if defined (PROCENV_BSD) && __FreeBSD__ == 9
-/* FreeBSD 9 introduced optional capabilities. FreeBSD enabled them by
- * default, changing some of the system calls in the process, so handle
- * the name changes.
- */
-#define cap_rights_get(fd, rightsp) cap_getrights (fd, (rightsp))
-#define cap_rights_is_set(rightsp, cap) ((*rightsp) & (cap))
-#endif /* PROCENV_BSD && __FreeBSD__ == 9 */
-
-#define show_capsicum_cap(rights, cap) \
- entry (#cap, "%s", cap_rights_is_set ((&rights), cap) ? YES_STR : NO_STR)
-#endif /* HAVE_SYS_CAPABILITY_H */
-
-#elif defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD) || defined (PROCENV_HURD)
-
-#if defined (HAVE_SYS_CAPABILITY_H)
-#include <sys/capability.h>
-#endif
+#if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_HURD)
#if ! defined (_LINUX_CAPABILITY_VERSION_3) && ! defined (CAP_LAST_CAP)
/* Ugh */
#define CAP_LAST_CAP 30
#endif
-#define PROCENV_CPU_SET_TYPE cpu_set_t
-
-#endif /* PROCENV_LINUX || PROCENV_GNU_BSD || PROCENV_HURD */
-
-#if defined (PROCENV_LINUX)
-#if defined (HAVE_SYS_CAPABILITY_H)
-#ifndef CAP_IS_SUPPORTED
-int cap_get_bound (cap_value_t cap);
-#define CAP_IS_SUPPORTED(cap) (cap_get_bound (cap) >= 0)
-#define PROCENV_NEED_LOCAL_CAP_GET_BOUND
-#endif
-#endif
-#endif
-
-
-/* Horrid hack for Hurd... :-( */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
+#endif /* PROCENV_PLATFORM_LINUX || PROCENV_PLATFORM_HURD */
/* Environment Variables */
#define PROCENV_OUTPUT_ENV "PROCENV_OUTPUT"
#define PROCENV_FORMAT_ENV "PROCENV_FORMAT"
#define PROCENV_FILE_ENV "PROCENV_FILE"
+#define PROCENV_FILE_APPEND_ENV "PROCENV_FILE_APPEND"
#define PROCENV_EXEC_ENV "PROCENV_EXEC"
#define PROCENV_INDENT_ENV "PROCENV_INDENT"
#define PROCENV_INDENT_CHAR_ENV "PROCENV_INDENT_CHAR"
#define PROCENV_SEPARATOR_ENV "PROCENV_SEPARATOR"
#define PROCENV_CRUMB_SEPARATOR_ENV "PROCENV_CRUMB_SEPARATOR"
-#define CTIME_BUFFER 32
-#define PROCENV_BUFFER 1024
-#define DEFAULT_ALLOC_GUESS_SIZE 8
-#define MOUNTS "/proc/mounts"
-#define ROOT_PATH "/proc/self/root"
+#define PROCENV_BUFFER 1024
-#ifndef TRUE
-#define TRUE 1
-#endif
+/* FIXME: explain! */
+#define CTIME_BUFFER 32
-#ifndef FALSE
-#define FALSE (!TRUE)
-#endif
-
-/* Network family for entries containing link-level interface
- * details. These entries will be cached to allow MAC addresses
- * to be extracted from them when displaying the corresponding
- * higher-level network family entries for the interface in
- * question.
- */
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-#define PROCENV_LINK_LEVEL_FAMILY AF_LINK
-#elif defined (PROCENV_LINUX)
-#define PROCENV_LINK_LEVEL_FAMILY AF_PACKET
-#endif
-
-#if defined (PROCENV_BSD)
-#define statfs_int_type uint64_t
-#define statfs_int_fmt PRIu64
-#elif defined (PROCENV_GNU_BSD)
-#define statfs_int_type uint64_t
-#define statfs_int_fmt "lu"
-#endif
-
-/* FIXME: gettext */
-#define _(str) str
-
-#define YES_STR _("yes")
-#define NO_STR _("no")
-#define NON_STR _("non")
-#define NA_STR _("n/a")
-#define UNKNOWN_STR _("unknown")
-#define MAX_STR _(" (max)")
-#define DEFINED_STR _("defined")
-#define NOT_DEFINED_STR _("not defined")
-#define NOT_IMPLEMENTED_STR _("[not implemented]")
-#define BIG_STR _("big")
-#define LITTLE_STR _("little")
-#define PRIVILEGED_STR _("privileged")
-#define SUPPRESSED_STR _("[suppressed]")
-#define BUILD_TYPE_STD_STR _("standard")
-#define BUILD_TYPE_REPRODUCIBLE_STR _("reproducible")
-
-#if defined (PROCENV_BSD)
- /* SIGTHL is hidden by default */
-#define NUM_SIGNALS 31
-#else
-#define NUM_SIGNALS 32
-#endif
+#include "messages.h"
/* Size of blocks we will show the user (as df(1) does) */
#define DF_BLOCK_SIZE 1024
-/* Default character to use for indent */
-#define DEFAULT_INDENT_CHAR " "
-
-/* If an indent is required, use this many INDENT_CHARs by default */
-#define DEFAULT_INDENT_AMOUNT 2
-
#define PROGRAM_AUTHORS "James Hunt <jamesodhunt@ubuntu.com>"
-#define show(...) _show ("", indent, __VA_ARGS__)
-
-/**
- * showi:
- *
- * @_indent: additional indent amount,
- * @fmt: printf-style format and optional arguments.
- *
- * Write indented message to appropriate output location.
- **/
-#define showi(_indent, ...) _show ("", indent+_indent, __VA_ARGS__)
-
-/**
- * _message:
- * @prefix: Fixed message prefix,
- * @fmt: printf-style format and optional arguments.
- *
- * Write unindented message to appropriate output location.
- **/
-#define _message(prefix, ...) _show (prefix, 0, __VA_ARGS__)
-
-#define warn(...) \
-{ \
- _message ("WARNING", __VA_ARGS__); \
-}
-
-#ifdef DEBUG
-/* for when running under GDB */
-#define die_finalise() raise (SIGUSR1)
-#else
-#define die_finalise() exit (EXIT_FAILURE)
-#endif
-
-#define bug(...) \
-{ \
- _show ("BUG", 0, __VA_ARGS__); \
- exit (EXIT_FAILURE); \
-}
-
-#define POINTER_SIZE (sizeof (void *))
-
-#define die(...) \
-{ \
- output = OUTPUT_STDERR; \
- _message ("ERROR", __VA_ARGS__); \
- cleanup (); \
- die_finalise (); \
-}
-
-#define common_assert() \
- assert (doc); \
- assert (indent >= 0)
-
-#define assert_not_reached() \
- do { \
- die ("%s:%d: Not reached assertion failed in %s", \
- __FILE__, __LINE__, __func__); \
- } while (0)
-
#define type_hex_width(type) \
(sizeof (type) * 2)
@@ -564,9 +212,9 @@ int cap_get_bound (cap_value_t cap);
}
#define show_const(t, flag, constant) \
- object_open (FALSE); \
+ object_open (false); \
entry (#constant, "%d", !!(t.flag & constant)); \
- object_close (FALSE)
+ object_close (false)
/**
* Show a terminal special characters attribute.
@@ -624,26 +272,27 @@ int cap_get_bound (cap_value_t cap);
\
errno = 0; \
len = confstr(s, NULL, 0); \
- assert (len && errno == 0); \
- \
- buffer = calloc (1, len); \
- if (! buffer) { \
- die ("failed to allocate space for confstr"); \
+ if (len && errno == 0) { \
+ \
+ buffer = calloc (1, len); \
+ if (! buffer) { \
+ die ("failed to allocate space for confstr"); \
+ } \
+ \
+ assert (confstr (s, buffer, len) == len); \
+ \
+ /* Convert multi-line values to multi-field */ \
+ for (size_t i = 0; i < len; i++) { \
+ if (buffer[i] == '\n') buffer[i] = ' '; \
+ } \
+ \
+ entry (name, "%s%s%s", \
+ buffer && buffer[0] ? "'" : "", \
+ buffer && buffer[0] ? buffer : NA_STR, \
+ buffer && buffer[0] ? "'" : ""); \
+ \
+ free (buffer); \
} \
- \
- assert (confstr (s, buffer, len) == len); \
- \
- /* Convert multi-line values to multi-field */ \
- for (size_t i = 0; i < len; i++) { \
- if (buffer[i] == '\n') buffer[i] = ' '; \
- } \
- \
- entry (name, "%s%s%s", \
- buffer && buffer[0] ? "'" : "", \
- buffer && buffer[0] ? buffer : NA_STR, \
- buffer && buffer[0] ? "'" : ""); \
- \
- free (buffer); \
}
/* Note: param is ignored */
@@ -693,406 +342,60 @@ int cap_get_bound (cap_value_t cap);
(unsigned long int)sizeof (type), \
sizeof (type) == 1 ? "" : "s")
-/**
- * @buf: string,
- * @len: number of _characters_ (*NOT* bytes!) in @buf,
- * @size: allocated size of @buf in bytes.
- **/
-typedef struct procenv_string {
- wchar_t *buf;
- size_t len;
- size_t size;
-} pstring;
-
-typedef enum {
- SHOW_ALL,
- SHOW_MOUNTS,
- SHOW_PATHCONF
-} ShowMountType;
-
-typedef enum {
- OUTPUT_FORMAT_TEXT,
- OUTPUT_FORMAT_CRUMB,
- OUTPUT_FORMAT_JSON,
- OUTPUT_FORMAT_XML
-} OutputFormat;
-
-typedef struct translate_map_entry {
- wchar_t from;
- wchar_t *to;
-} TranslateMapEntry;
-
-typedef enum element_type {
- ELEMENT_TYPE_ENTRY,
- ELEMENT_TYPE_SECTION_OPEN,
- ELEMENT_TYPE_SECTION_CLOSE,
- ELEMENT_TYPE_CONTAINER_OPEN,
- ELEMENT_TYPE_CONTAINER_CLOSE,
- ELEMENT_TYPE_OBJECT_OPEN,
- ELEMENT_TYPE_OBJECT_CLOSE,
- ELEMENT_TYPE_NONE = -1
-} ElementType;
-
-typedef struct element {
- ElementType type;
-
- char *name;
- char *value;
-
- /* Optional array of name/value pairs associated with @name */
- char **attributes;
-} Element;
-
-/*
- * XXX: Gross magic number must equal the maximum number of entries in
- * any particular OutputFormats translation table.
- *
- * This must be updated to reflect the maximum values in any
- * TranslateMapEntry, plus 1.
- */
-#define TRANSLATE_MAP_ENTRIES (5+1)
-
#define free_if_set(ptr) \
if (ptr) free (ptr)
-typedef struct translate_table {
- OutputFormat output_format;
- TranslateMapEntry map[TRANSLATE_MAP_ENTRIES];
-} TranslateTable;
-
-struct procenv_map {
- int num;
- char *name;
-};
-
-typedef enum procenv_output {
- OUTPUT_FILE,
- OUTPUT_STDERR,
- OUTPUT_STDOUT,
- OUTPUT_SYSLOG,
- OUTPUT_TERM
-} Output;
-
-struct baud_speed
-{
- speed_t speed;
- char *name;
-};
-
-struct procenv_user {
- pid_t pid;
- pid_t ppid;
- pid_t sid;
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
- char proc_name[16];
-#endif
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
- char proc_name[COMMLEN+1];
-#endif
-
- pid_t pgroup;
- pid_t fg_pgroup;
- pid_t pgid_sid;
- char ctrl_terminal[L_ctermid];
- int tty_fd;
-
- uid_t uid;
- uid_t euid;
- uid_t suid;
-
- char *login;
-
- gid_t gid;
- gid_t egid;
- gid_t sgid;
-
- struct passwd passwd;
-};
-
-struct procenv_misc {
- char cwd[PATH_MAX];
- char root[PATH_MAX];
- mode_t umask_value;
- int cpu;
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
- int in_jail;
-#endif
-};
-
-struct procenv_priority {
- int process;
- int pgrp;
- int user;
-};
-
-struct network_map {
- struct ifaddrs ifaddr;
- char *mac_address;
-
- struct network_map *next;
- struct network_map *prev;
-};
-
-pstring *pstring_new (void);
-pstring *pstring_create (const wchar_t *str);
-void pstring_free (pstring *str);
-pstring *char_to_pstring (const char *str);
-wchar_t *char_to_wchar (const char *str);
-char *wchar_to_char (const wchar_t *wstr);
-char *pstring_to_char (const pstring *str);
-
-void master_header (pstring **doc);
-void master_footer (pstring **doc);
-
-void header (const char *name);
-void footer (void);
-
-void object_open (int retain);
-void object_close (int retain);
-void section_open (const char *name);
-void section_close (void);
-
-void container_open (const char *name);
-void container_close (void);
-
-void entry (const char *name, const char *fmt, ...);
-void _show (const char *prefix, int indent, const char *fmt, ...);
-void _show_output (const char *str);
-void _show_output_pstring (const pstring *pstr);
-
-/* operate on multi-bytes */
-void append (char **dest, const char *src);
-void appendn (char **dest, const char *src, size_t len);
-void appendf (char **dest, const char *fmt, ...);
-void appendva (char **dest, const char *fmt, va_list ap);
-
-/* operate on pure wide-characters */
-void wappend (pstring **dest, const wchar_t *src);
-void wappendn (pstring **dest, const wchar_t *src, size_t len);
-void wappendf (pstring **dest, const wchar_t *fmt, ...);
-void wappendva (pstring **dest, const wchar_t *fmt, va_list ap);
-
-/* operate on wide-characters, but using multi-byte formats */
-void wmappend (pstring **dest, const char *src);
-void wmappendn (pstring **dest, const char *src, size_t len);
-void wmappendf (pstring **dest, const char *fmt, ...);
-void wmappendva (pstring **dest, const char *fmt, va_list ap);
-
-void pappend (pstring **dest, const pstring *src);
-
-int get_indent (void);
-void inc_indent (void);
-void dec_indent (void);
-void add_indent (pstring **doc);
-
-void change_element (ElementType new);
-void format_element (void);
-void format_text_element (void);
-void format_json_element (void);
-void format_xml_element (void);
-
-int encode_string (pstring **pstr);
-pstring *translate (const pstring *pstr);
-void compress (pstring **wstr, wchar_t remove_char);
-void chomp (pstring *str);
-
-void show_version (void);
-void save_locale (void);
-void restore_locale (void);
-void handle_indent_char (void);
-void init (void);
-void cleanup (void);
-bool in_chroot (void);
-const char *container_type (void);
-bool is_process_group_leader (void);
-bool is_session_leader (void);
-void assert_cwd (void);
-void assert_chroot (void);
-void assert_user (void);
-void dump_options (void);
-void show_proc (void);
-void show_misc (void);
-void show_env (void);
-void show_rlimits (void);
-void show_rusage (void);
-void show_sysconf (void);
-char *get_user_name (gid_t gid);
-char *get_group_name (gid_t gid);
-char *pid_to_name (pid_t pid);
-
-#ifndef PROCENV_ANDROID
-void show_confstrs (void);
-#endif
-
-void show_priorities (void);
-void show_shared_mem (void);
-void show_semaphores (void);
-void show_msg_queues (void);
-void dump_priorities (void);
-void show_mounts (ShowMountType what);
-void get_user_info (void);
-void get_priorities (void);
-void format_time (const time_t *t, char *buffer, size_t len);
-char *format_perms (mode_t mode);
-void get_config (void);
-void get_config_from_env (void);
-void check_config (void);
-void show_proc_branch (void);
-void show_tty_attrs (void);
-const char *get_speed (speed_t speed);
+char *get_path (const char *argv0);
+char *get_personality_flags (unsigned int flags);
+const char *get_arch (void);
+const char *get_group_name (gid_t gid);
+const char *get_os (void);
+const char *get_personality_name (unsigned int domain);
const char *get_signal_name (int signum);
-void show_arguments (void);
-void show_meta (void);
-char *get_os (void);
-char *get_arch (void);
-void show_platform (void);
-
-#ifndef PROCENV_ANDROID
-int libs_callback (struct dl_phdr_info *info, size_t size, void *data);
-void show_libs (void);
-#endif
+const char *get_thread_scheduler_name (int sched);
+const char *get_user_name (gid_t gid);
+int get_major_minor (const char *path, unsigned int *_major, unsigned int *_minor);
+long get_kernel_bits (void);
+void get_priorities (void);
+void get_uname (void);
+void show_all_groups (void);
+void show_capabilities (void);
+void show_cgroups (void);
void show_clocks (void);
-void show_timezone (void);
-void show_time (void);
-void show_signals (void);
-void show_pathconfs (ShowMountType what, const char *dir);
-void show_sizeof (void);
-void show_ranges (void);
void show_compiler (void);
+void show_confstrs (void);
+void show_data_model (void);
void show_libc (void);
-void get_uname (void);
-void show_uname (void);
-void show_all_groups (void);
-void show_fds (void);
-void show_namespaces (void);
-void show_fds_generic (void);
-
-#if !defined (PROCENV_HURD)
-int is_console (int fd);
-#endif
-
-long get_kernel_bits (void);
-bool has_ctty (void);
-void show_cpu (void);
-void show_cpu_affinities (void);
-void show_memory (void);
-void show_threads (void);
-void check_envvars (void);
-int get_output_value (const char *name);
-int get_output_format (const char *name);
-const char *get_output_format_name (void);
-void show_stat (void);
+void show_libs (void);
void show_locale (void);
-int get_major_minor (const char *path, unsigned int *_major, unsigned int *_minor);
-bool uid_match (uid_t uid);
-char *get_path (const char *argv0);
-bool is_big_endian (void);
-const char *get_thread_scheduler_name (int sched);
-int qsort_compar (const void *a, const void *b);
-void show_data_model (void);
-const char *get_net_family_name (sa_family_t family);
+void show_mounts (ShowMountType what);
+void show_misc (void);
+void show_msg_queues (void);
void show_network (void);
-void show_network_if (const struct ifaddrs *ifa, const char *mac_address);
-void get_network_name (const struct sockaddr *address, int family, char *name);
-const char *get_ipv6_scope_name (uint32_t scope);
-char *get_mac_address (const struct ifaddrs *ifaddr);
-int get_mtu (const struct ifaddrs *ifaddr);
-void set_breadcrumb (const char *name);
-void add_breadcrumb (const char *name);
-void remove_breadcrumb (void);
-void clear_breadcrumbs (void);
-void show_cgroups (void);
void show_oom (void);
-void show_capabilities (void);
-
-#if defined (PROCENV_LINUX)
-
-void decode_if_flags (unsigned int flags);
-void decode_extended_if_flags (const char *interface, unsigned short *flags);
-int get_canonical (const char *path, char *canonical, size_t len);
-void get_tty_locked_status (struct termios *lock_status);
-void show_fds_linux (void);
-void show_namespaces_linux (void);
-void show_cgroups_linux (void);
-void show_oom_linux (void);
-void show_timezone_linux (void);
-
-#if defined (HAVE_SYS_CAPABILITY_H)
-int get_capability_by_flag_type (cap_t cap_p, cap_flag_t type, cap_value_t cap);
-#endif /* HAVE_SYS_CAPABILITY_H */
-
-void show_capabilities_linux (void);
-void show_security_module_linux (void);
-void show_security_module_context_linux (void);
-void show_prctl_linux (void);
-void show_cpu_linux (void);
-char *get_scheduler_name (int sched);
-bool linux_kernel_version (int major, int minor, int revision);
-
-void show_numa_memory (void);
-
-#if defined (HAVE_NUMA_H)
-const char *get_numa_policy (int policy);
-#endif /* HAVE_NUMA_H */
-
-const char *get_personality_name (unsigned int domain);
-char *get_personality_flags (unsigned int flags);
-
-#else /* ! PROCENV_LINUX */
-
-void show_cgroups_stub (void);
-void show_oom_stub (void);
-void show_capabilities_stub (void);
-void show_timezone_stub (void);
-void show_shared_mem_stub (void);
-void show_semaphores_stub ();
-void show_msg_queues_stub (void);
-void show_namespaces_stub (void);
-
-#endif /* PROCENV_LINUX */
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_GNU_BSD)
-void show_proc_branch_linux (void);
-#endif /* PROCENV_LINUX || PROCENV_GNU_BSD */
-
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-void show_shared_mem_linux (void);
-void show_semaphores_linux (void);
-void show_msg_queues_linux (void);
-#endif /* PROCENV_LINUX || PROCENV_HURD */
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-void show_mounts_linux (ShowMountType what);
-#endif
-
-#if defined (PROCENV_BSD) || defined (PROCENV_GNU_BSD)
-char *get_mount_opts_bsd (uint64_t flags);
-void show_mounts_bsd (ShowMountType what);
-void show_network_bsd (void);
-void get_misc_bsd (void);
-void show_proc_branch_bsd (void);
-void show_cpu_bsd (void);
-#endif /* PROCENV_BSD + PROCENV_GNU_BSD */
-
-#if defined (PROCENV_BSD) && defined (HAVE_SYS_CAPABILITY_H)
-void show_capabilities_bsd (int fd);
-#endif /* (PROCENV_BSD) && defined (HAVE_SYS_CAPABILITY_H) */
-
-#if defined (PROCENV_LINUX) || defined (PROCENV_HURD)
-/* semctl(2) on Linux tells us _we_ must define this */
+void show_ranges (void);
+void show_rlimits (void);
+void show_semaphores (void);
+void show_shared_mem (void);
+void show_sizeof (void);
+void show_threads (void);
+void show_time (void);
+void show_timezone (void);
+void show_tty_attrs (void);
+void show_uname (void);
+void show_version (void);
-union semun {
- int val;
- struct semid_ds *buf;
- unsigned short int *array;
- struct seminfo *__buf;
-};
+void handle_proc_branch (void);
-#endif
+char *format_perms (mode_t mode);
+void format_time (const time_t *t, char *buffer, size_t len);
+void restore_locale (void);
+int qsort_compar (const void *a, const void *b);
extern char **environ;
+extern Output output;
+extern pstring *doc;
+
#endif /* PROCENV_H */
diff --git a/src/pstring.c b/src/pstring.c
new file mode 100644
index 0000000..ef845f3
--- /dev/null
+++ b/src/pstring.c
@@ -0,0 +1,310 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2012-2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "pstring.h"
+
+#include <assert.h>
+
+extern wchar_t wide_indent_char;
+
+wchar_t *
+char_to_wchar (const char *str)
+{
+ const char *p;
+ wchar_t *wstr = NULL;
+ size_t len;
+ size_t bytes;
+
+ assert (str);
+
+ len = mbsrtowcs (NULL, &str, 0, NULL);
+ if (len <= 0)
+ return NULL;
+
+ /* include space for terminator */
+ bytes = (1 + len) * sizeof (wchar_t);
+
+ wstr = malloc (bytes);
+ if (! wstr)
+ return NULL;
+
+ p = str;
+
+ if (mbsrtowcs (wstr, &p, len, NULL) != len)
+ goto error;
+
+ /* ensure it's terminated */
+ wstr[len] = L'\0';
+
+ return wstr;
+
+error:
+ free (wstr);
+ return NULL;
+}
+
+char *
+wchar_to_char (const wchar_t *wstr)
+{
+ char *str = NULL;
+ size_t len;
+ size_t bytes;
+ size_t ret;
+
+ assert (wstr);
+
+ len = wcslen (wstr);
+
+ /* determine number of MBS (char) bytes requires to hold the
+ * wchar_t string.
+ */
+ bytes = wcstombs (NULL, wstr, len);
+ if (! bytes)
+ return NULL;
+
+ str = calloc (bytes + 1, sizeof (char));
+ if (! str)
+ return NULL;
+
+ /* actually perform the conversion */
+ ret = wcstombs (str, wstr, bytes);
+
+ if (! ret)
+ goto error;
+
+ return str;
+
+error:
+ free (str);
+ return NULL;
+}
+
+pstring *
+pstring_new (void)
+{
+ pstring *pstr = NULL;
+
+ pstr = calloc (1, sizeof (pstring));
+ if (! pstr)
+ return NULL;
+
+ pstr->len = 0;
+ pstr->size = 0;
+ pstr->buf = NULL;
+
+ return pstr;
+}
+
+pstring *
+pstring_create (const wchar_t *str)
+{
+ pstring *pstr = NULL;
+
+ assert (str);
+
+ pstr = pstring_new ();
+
+ if (! pstr)
+ return NULL;
+
+ pstr->buf = wcsdup (str);
+ if (! pstr->buf) {
+ pstring_free (pstr);
+ return NULL;
+ }
+
+ /* include the L'\0' terminator */
+ pstr->len = 1 + wcslen (pstr->buf);
+
+ pstr->size = pstr->len * sizeof (wchar_t);
+
+ return pstr;
+}
+
+void
+pstring_free (pstring *str)
+{
+ assert (str);
+
+ if (str->buf)
+ free (str->buf);
+
+ free (str);
+}
+
+pstring *
+char_to_pstring (const char *str)
+{
+ pstring *pstr = NULL;
+ wchar_t *s;
+
+ assert (str);
+
+ s = char_to_wchar (str);
+ if (! s)
+ return NULL;
+
+ pstr = pstring_create (s);
+
+ free (s);
+
+ return pstr;
+}
+
+char *
+pstring_to_char (const pstring *str)
+{
+ assert (str);
+
+ return wchar_to_char (str->buf);
+}
+
+/**
+ * pstring_chomp:
+ *
+ * Remove trailing extraneous newlines and indent_chars from @str.
+ **/
+void
+pstring_chomp (pstring *str)
+{
+ size_t len;
+ int removable = 0;
+ wchar_t *p;
+
+ assert (str);
+
+ /* Unable to add '\n' in this scenario */
+ if (str->len < 2)
+ return;
+
+ for (p = str->buf+str->len-1;
+ *p == L'\n' || *p == wide_indent_char;
+ p--, removable++)
+ ;
+
+ /* Chop string at the appropriate place after first adding a new
+ * newline.
+ */
+ if (removable > 1) {
+ len = str->len - (removable-1);
+ str->buf[len-1] = L'\n';
+ str->buf[len] = L'\0';
+ str->len = len;
+ }
+}
+
+/**
+ * pstring_compress:
+ *
+ * Remove lines composed entirely of whitespace from @str.
+ *
+ * This is required specifically for '--output=text' which in some
+ * scenarios generates lines comprising pure whitespace. This is
+ * unecessary and results from the fact that when an
+ * ELEMENT_TYPE_OBJECT_* is encountered, formatting is applied for the
+ * previously seen element, but sometimes such "objects" should be
+ * invisible.
+ **/
+void
+pstring_compress (pstring **wstr, wchar_t remove_char)
+{
+ wchar_t *from;
+ wchar_t *to;
+ wchar_t *p;
+ wchar_t *start;
+ size_t count = 0;
+ size_t blanks = 0;
+ size_t new_len;
+ size_t bytes;
+
+ assert (wstr);
+
+ to = from = (*wstr)->buf;
+ assert (from);
+
+ while (to && *to) {
+again:
+ while (*to == L'\n' && *(to+1) == L'\n') {
+ /* skip over blank lines */
+ to++;
+ blanks++;
+ }
+
+ start = to;
+
+ while (*to == remove_char) {
+ /* skip runs of contiguous characters */
+ to++;
+ count++;
+ }
+
+ if (to != start) {
+ /* Only start consuming NLs at the end of a
+ * contiguous run *iff* there was more than a
+ * single removed char. This is a heuristic to
+ * avoid removing valid entries for example env
+ * vars that are set to nul are shown as:
+ *
+ * 'var: '
+ *
+ * Shudder.
+ */
+ if (*to == L'\n' && to != start+1) {
+ while (*to == L'\n') {
+ /* consume the NL at the end of the contiguous run */
+ to++;
+ }
+
+ /* check to ensure that we haven't entered a new line
+ * containing another block of chars to remove.
+ */
+ if (*to == remove_char)
+ goto again;
+
+ blanks++;
+
+ } else {
+ /* not a full line so backtrack */
+ to = start;
+ count = 0;
+ }
+ }
+
+ *from++ = *to++;
+ }
+
+ /* terminate */
+ *from = L'\0';
+
+ if (blanks || count) {
+ new_len = (*wstr)->len - (blanks + count);
+
+ bytes = new_len * sizeof (wchar_t);
+
+ p = realloc ((*wstr)->buf, bytes);
+ assert (p);
+
+ (*wstr)->buf = p;
+
+ (*wstr)->buf[new_len-1] = L'\0';
+
+ (*wstr)->len = new_len;
+ (*wstr)->size = bytes;
+ }
+}
+
diff --git a/src/pstring.h b/src/pstring.h
new file mode 100644
index 0000000..3f6ab10
--- /dev/null
+++ b/src/pstring.h
@@ -0,0 +1,55 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_PSTRING_H
+#define _PROCENV_PSTRING_H
+
+/* for wcsdup(3) */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+/**
+ * @buf: string,
+ * @len: number of _characters_ (*NOT* bytes!) in @buf,
+ * @size: allocated size of @buf in bytes.
+ **/
+typedef struct procenv_string {
+ wchar_t *buf;
+ size_t len;
+ size_t size;
+} pstring;
+
+pstring *pstring_new (void);
+pstring *pstring_create (const wchar_t *str);
+pstring *char_to_pstring (const char *str);
+char *pstring_to_char (const pstring *str);
+void pstring_chomp (pstring *str);
+void pstring_compress (pstring **wstr, wchar_t remove_char);
+void pstring_free (pstring *str);
+int encode_string (pstring **pstr);
+
+wchar_t *char_to_wchar (const char *str);
+char *wchar_to_char (const wchar_t *wstr);
+
+#endif /* _PROCENV_PSTRING_H */
diff --git a/src/string-util.c b/src/string-util.c
new file mode 100644
index 0000000..dbb181e
--- /dev/null
+++ b/src/string-util.c
@@ -0,0 +1,543 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "string-util.h"
+
+/* append @src to @dest */
+void
+append (char **dest, const char *src)
+{
+ size_t len;
+
+ assert (dest);
+ assert (src);
+
+ len = strlen (src);
+
+ appendn (dest, src, len);
+}
+
+/* Version of append() that operates on a wide string @dest and @src */
+void
+wappend (pstring **dest, const wchar_t *src)
+{
+ size_t len;
+
+ assert (dest);
+ assert (src);
+
+ len = wcslen (src);
+
+ wappendn (dest, src, len);
+}
+
+/* Version of append() that operates on a wide string @dest
+ * and multi-byte @src.
+ */
+void
+wmappend (pstring **dest, const char *src)
+{
+ wchar_t *wide_src = NULL;
+
+ assert (dest);
+ assert (src);
+
+ wide_src = char_to_wchar (src);
+ if (! wide_src)
+ die ("failed to allocate space for wide string");
+
+ wappend (dest, wide_src);
+
+ free (wide_src);
+}
+
+/**
+ * appendn:
+ *
+ * @dest: [output] string to append to,
+ * @src: string to append to @dest,
+ * @len: length of @new.
+ *
+ * Append first @len bytes of @new to @str,
+ * ensuring result is nul-terminated.
+ **/
+void
+appendn (char **dest, const char *src, size_t len)
+{
+ size_t total;
+
+ assert (dest);
+ assert (src);
+
+ if (! len)
+ return;
+
+ if (! *dest)
+ *dest = strdup ("");
+ if (! *dest)
+ die ("failed to allocate space for string");
+
+ /* +1 for terminating nul */
+ total = strlen (*dest) + 1;
+
+ total += len;
+
+ *dest = realloc (*dest, total);
+ assert (*dest);
+
+ if (! *dest) {
+ /* string is empty, so initialise the memory to avoid
+ * surprises with strncat() being unable to find the
+ * terminator!
+ */
+ memset (*dest, '\0', total);
+ }
+
+ strncat (*dest, src, len);
+
+ assert ((*dest)[total-1] == '\0');
+}
+
+/* Version of appendn() that operates on a wide string @dest and @src */
+void
+wappendn (pstring **dest, const wchar_t *src, size_t len)
+{
+ wchar_t *p;
+ size_t total;
+ size_t bytes;
+
+ assert (dest);
+ assert (src);
+
+ if (! len)
+ return;
+
+ if (! *dest)
+ *dest = pstring_new ();
+ if (! *dest)
+ die ("failed to allocate space for pstring");
+
+ total = (*dest)->len + len;
+
+ /* +1 for terminating nul */
+ bytes = (1 + total) * sizeof (wchar_t);
+
+ p = realloc ((*dest)->buf, bytes);
+
+ /* FIXME: turn into die() [all occurences!] */
+ assert (p);
+
+ (*dest)->buf = p;
+
+ if (! (*dest)->len) {
+ /* pstring is empty, so initialise the memory to avoid
+ * surprises with wcsncat() being unable to find the
+ * terminator!
+ */
+ memset ((*dest)->buf, 0, bytes);
+ }
+
+ /* Used to check for overrun */
+ (*dest)->buf[total] = L'\0';
+
+ wcsncat ((*dest)->buf + (*dest)->len, src, len);
+
+ /* update */
+ (*dest)->len = total;
+ (*dest)->size = bytes;
+
+ /* check for overrun */
+ assert ((*dest)->buf[total] == L'\0');
+}
+
+/* Version of appendn() that operates on a wide string @dest and
+ * multi-byte @src.
+ */
+void
+wmappendn (pstring **dest, const char *src, size_t len)
+{
+ wchar_t *wide_src = NULL;
+
+ assert (dest);
+ assert (src);
+
+ if (! len)
+ return;
+
+ wide_src = char_to_wchar (src);
+ if (! wide_src)
+ die ("failed to allocate space for wide string");
+
+ wappendn (dest, wide_src, wcslen (wide_src));
+
+ free (wide_src);
+}
+
+/* append @fmt and args to @dest */
+void
+appendf (char **dest, const char *fmt, ...)
+{
+ va_list ap;
+
+ assert (dest);
+ assert (fmt);
+
+ va_start (ap, fmt);
+
+ appendva (dest, fmt, ap);
+
+ va_end (ap);
+}
+
+/* Version of appendf() that operates on a wide string @dest
+ * and @fmt.
+ */
+void
+wappendf (pstring **dest, const wchar_t *fmt, ...)
+{
+ va_list ap;
+
+ assert (dest);
+ assert (fmt);
+
+ va_start (ap, fmt);
+
+ wappendva (dest, fmt, ap);
+
+ va_end (ap);
+}
+
+/* Version of appendf() that operates on a wide string @dest
+ * and multi-byte @fmt.
+ */
+void
+wmappendf (pstring **dest, const char *fmt, ...)
+{
+ wchar_t *wide_fmt = NULL;
+ va_list ap;
+
+ assert (dest);
+ assert (fmt);
+
+ wide_fmt = char_to_wchar (fmt);
+ if (! wide_fmt)
+ die ("failed to allocate memory for wide format");
+
+ va_start (ap, fmt);
+
+ wappendva (dest, wide_fmt, ap);
+
+ va_end (ap);
+
+ free (wide_fmt);
+}
+
+/* append @fmt and args to @dest */
+void
+appendva (char **dest, const char *fmt, va_list ap)
+{
+ int ret;
+ char *new = NULL;
+ char *p;
+ size_t bytes;
+
+ /* Start with a guess for how big we think the buffer needs to
+ * be.
+ */
+ size_t len = DEFAULT_ALLOC_GUESS_SIZE;
+
+ assert (dest);
+ assert (fmt);
+
+ bytes = (1 + len) * sizeof (char);
+
+ /* we could use vasprintf(3), but that's GNU-specific and hence
+ * not available everywhere we need it.
+ */
+ new = malloc (bytes);
+ if (! new)
+ die ("failed to allocate space for string");
+
+ memset (new, '\0', bytes);
+
+ /* keep on increasing size of buffer until the translation
+ * succeeds.
+ */
+ while (true) {
+ va_list ap_copy;
+
+ va_copy (ap_copy, ap);
+ ret = vsnprintf (new, len, fmt, ap_copy);
+ va_end (ap_copy);
+
+ if (ret < 0)
+ die ("failed to format string");
+
+ if ((size_t)ret < len) {
+ /* now we have sufficient space */
+ break;
+ }
+
+ /* Bump to allow one char to be written */
+ len++;
+
+ /* recalculate number of bytes */
+ bytes = (1 + len) * sizeof (char);
+
+ p = realloc (new, bytes);
+ if (! p)
+ die ("failed to allocate space for string");
+
+ new = p;
+ }
+
+ if (*dest) {
+ append (dest, new);
+ free (new);
+ } else {
+ *dest = new;
+ }
+}
+
+/* Version of appendva() that operates on a wide string @dest
+ * and @fmt.
+ */
+void
+wappendva (pstring **dest, const wchar_t *fmt, va_list ap)
+{
+ int ret;
+ wchar_t *new = NULL;
+ wchar_t *p;
+ size_t bytes;
+ va_list ap_copy;
+
+ /* Start with a guess for how big we think the buffer needs to
+ * be.
+ */
+ size_t len = DEFAULT_ALLOC_GUESS_SIZE;
+
+ assert (dest);
+ assert (fmt);
+
+ bytes = (1 + len) * sizeof (wchar_t);
+
+ new = malloc (bytes);
+ if (! new)
+ die ("failed to allocate space for wide string");
+
+ memset (new, '\0', bytes);
+
+ /* keep on increasing size of buffer until the translation
+ * succeeds.
+ */
+ while (true) {
+ va_copy (ap_copy, ap);
+ ret = vswprintf (new, len, fmt, ap_copy);
+ va_end (ap_copy);
+
+ if ((size_t)ret < len) {
+ /* now we have sufficient space, so update for
+ * actual number of bytes used (including the
+ * terminator!)
+ *
+ * Note that, conveniently, if the string is
+ * zero-characters long (ie ""), ret will be -1
+ * which we correct to 0.
+ */
+ len = ret + 1;
+
+ break;
+ }
+
+ /* Bump to allow one more wide-char to be written */
+ len++;
+
+ /* recalculate number of bytes */
+ bytes = (1 + len) * sizeof (wchar_t);
+
+ p = realloc (new, bytes);
+ if (! p)
+ die ("failed to allocate space for string");
+
+ new = p;
+
+ memset (new, '\0', bytes);
+ }
+
+ if (*dest) {
+ wappend (dest, new);
+ free (new);
+ } else {
+ wchar_t *n;
+
+ /* recalculate number of bytes */
+ bytes = (1 + len) * sizeof (wchar_t);
+
+ /* compress */
+ n = realloc (new, bytes);
+
+ if (! n)
+ die ("failed to reallocate space");
+
+ new = n;
+
+ (*dest) = pstring_new ();
+ assert (*dest);
+ (*dest)->buf = new;
+ (*dest)->len = len;
+ (*dest)->size = bytes;
+ }
+}
+
+/* Version of appendva() that operates on a wide string @dest
+ * and multi-byte @fmt.
+ */
+void
+wmappendva (pstring **dest, const char *fmt, va_list ap)
+{
+ wchar_t *wide_fmt = NULL;
+ va_list ap_copy;
+
+ assert (dest);
+ assert (fmt);
+
+ wide_fmt = char_to_wchar (fmt);
+ if (! wide_fmt)
+ die ("failed to allocate memory for wide format");
+
+ va_copy (ap_copy, ap);
+ wappendva (dest, wide_fmt, ap_copy);
+ va_end (ap_copy);
+
+ free (wide_fmt);
+}
+
+/*
+ * Append @src onto the end of @dest.
+ */
+void
+pappend (pstring **dest, const pstring *src)
+{
+ size_t total;
+ size_t bytes;
+ wchar_t *p;
+
+ assert (dest);
+ assert (src);
+
+ if (! src->len)
+ return;
+
+ if (! *dest)
+ *dest = pstring_new ();
+ if (! *dest)
+ die ("failed to allocate space for pstring");
+
+ total = (*dest)->len + src->len;
+
+ /* adjust since we only store _one_ of the string terminators
+ * from @dest and @src.
+ */
+ total--;
+
+ /* +1 for terminating nul */
+ bytes = (1 + total) * sizeof (wchar_t);
+
+ p = realloc ((*dest)->buf, bytes);
+
+ /* FIXME: turn into die() [all occurences!] */
+ assert (p);
+
+ (*dest)->buf = p;
+
+ wcsncat ((*dest)->buf + (*dest)->len, src->buf, src->len);
+
+ /* update */
+ (*dest)->len = total;
+ (*dest)->size = bytes;
+
+ /* Used to check for overrun */
+ (*dest)->buf[total] = L'\0';
+}
+
+/**
+ * @string: input,
+ * @delimiter: field delimiter,
+ * @compress: if true, ignore repeated contiguous delimiter characters,
+ * @array: [output] array of fields, which this function will allocate.
+ *
+ * Notes: it is the callers responsibility to free @array
+ * if the returned value is >0.
+ *
+ * Returns: number of fields in @string.
+ **/
+size_t
+split_fields (const char *string, char delimiter, int compress, char ***array)
+{
+ const char *p = NULL;
+ const char *start = NULL;
+ size_t count = 0;
+ char *elem;
+ char **new;
+
+ assert (string);
+ assert (delimiter);
+ assert (array);
+
+ *array = NULL;
+
+ new = realloc ((*array), sizeof (char *) * (1+count));
+ assert (new);
+
+ new[0] = NULL;
+ *array = new;
+
+ p = string;
+
+ while (p && *p) {
+ /* skip leading prefix */
+ while (compress && p && *p == delimiter)
+ p++;
+
+ if (! *p)
+ break;
+
+ /* found a field */
+ count++;
+
+ if (! compress)
+ p++;
+
+ /* skip over the field */
+ start = p;
+ while (p && *p && *p != delimiter)
+ p++;
+
+ elem = strndup (start, p-start);
+ assert (elem);
+
+ new = realloc ((*array), sizeof (char *) * (1+count));
+ assert (new);
+
+ new[count-1] = elem;
+ *array = new;
+ }
+
+ return count;
+}
+
diff --git a/src/string-util.h b/src/string-util.h
new file mode 100644
index 0000000..a3b5795
--- /dev/null
+++ b/src/string-util.h
@@ -0,0 +1,60 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_STRING_UTIL_H
+#define _PROCENV_STRING_UTIL_H
+
+/* for strndup(3) */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#include "pstring.h"
+#include "output.h"
+#include "util.h"
+
+#define DEFAULT_ALLOC_GUESS_SIZE 8
+
+/* operate on multi-bytes */
+void append (char **dest, const char *src);
+void appendn (char **dest, const char *src, size_t len);
+void appendf (char **dest, const char *fmt, ...);
+void appendva (char **dest, const char *fmt, va_list ap);
+
+/* operate on pure wide-characters */
+void wappend (pstring **dest, const wchar_t *src);
+void wappendn (pstring **dest, const wchar_t *src, size_t len);
+void wappendf (pstring **dest, const wchar_t *fmt, ...);
+void wappendva (pstring **dest, const wchar_t *fmt, va_list ap);
+
+/* operate on wide-characters, but using multi-byte formats */
+void wmappend (pstring **dest, const char *src);
+void wmappendn (pstring **dest, const char *src, size_t len);
+void wmappendf (pstring **dest, const char *fmt, ...);
+void wmappendva (pstring **dest, const char *fmt, va_list ap);
+
+void pappend (pstring **dest, const pstring *src);
+size_t split_fields (const char *string, char delimiter,
+ int compress, char ***array);
+
+#endif /* _PROCENV_STRING_UTIL_H */
diff --git a/src/tests/check_all_args.in b/src/tests/check_all_args.in
index 75584bc..3a2f121 100755
--- a/src/tests/check_all_args.in
+++ b/src/tests/check_all_args.in
@@ -8,6 +8,7 @@ script_name=${0##*/}
# Use full path to build binary
procenv="@builddir@/procenv"
man_path="@man_path@"
+driver="@procenv_platform@"
template="/tmp/${script_name}.XXXXXXXXXX"
@@ -93,7 +94,11 @@ _run_command()
debug "Running: '$cmdline'"
+ # interestingly, all environment except OpenBSD allow the code below
+ # to run even if cmdline fail.s
+ set +e
{ eval "$cmdline"; ret=$?; } || :
+ set -e
if [ "$expected_outcome" = success ]
then
@@ -157,8 +162,135 @@ run_tests()
procenv_version=$($procenv --version|grep "version: [0-9]"|awk '{print $2}')
[ -n "$procenv_version" ] || die "failed to query procenv version"
+ # list of all output sections seen when running with an individual
+ # argument.
+ arg_sections=$(mktemp "$template")
+
#---------------------------------------------------------------------
- msg "Running tests for language '$LANG'"
+ msg "Running procenv version $procenv_version tests for language '$LANG'"
+
+ arg="--help"
+ msg "Ensure '$arg' works"
+
+ stdout=$(mktemp "$template")
+ stderr=$(mktemp "$template")
+ cmd="$procenv $arg 1>\"$stdout\" 2>\"$stderr\""
+ run_command "$cmd" "$stdout" "$stderr"
+
+ [ -s "$stdout" ] || die "Expected stdout output in file $stdout"
+ [ -s "$stderr" ] && die "Unexpected stderr output in file $stdout"
+
+ rm -f "$stdout" "$stderr"
+
+ #---------------------------------------------------------------------
+ # XXX: note that we run with each argument in turn *BEFORE*
+ # running with no arguments to avoid the situation where a
+ # particular type of outputcauses procenv to hang/spin but it's
+ # unclear which argument that output relates to if procenv is
+ # run without args.
+
+ msg "Ensure all documented options produce output"
+
+ procenv_options=$(get_procenv_options)
+ echo "$procenv_options" | while read arg
+ do
+ stdout=$(mktemp "$template")
+ stderr=$(mktemp "$template")
+
+ # No format option
+ cmd="$procenv $arg 1>\"$stdout\" 2>\"$stderr\""
+ msg "Running '$cmd'"
+ run_command "$cmd" "$stdout" "$stderr"
+
+ [ -z "$stdout" ] && die "No stdout output running '$cmd'"
+ [ -s "$stderr" ] && die "Unexpected stderr output running '$cmd' ($stderr)"
+
+ # Establish the name of the section
+ section=$(head -1 "$stdout"|grep "^[^ ].*:$" || :)
+ [ -z "$section" ] && die "No section title found running '$cmd'"
+
+ # record the section we've seen
+ echo "$section" >> "$arg_sections"
+
+ rm -f "$stdout" "$stderr"
+
+ # Text format
+ cmd="$procenv --format=text $arg 1>\"$stdout\" 2>\"$stderr\""
+ msg "Running '$cmd'"
+ run_command "$cmd" "$stdout" "$stderr"
+
+ [ -z "$stdout" ] && die "No stdout output running '$cmd'"
+ [ -s "$stderr" ] && die "Unexpected stderr output running '$cmd' ($stderr)"
+
+ if [ "$section" = "capabilities:" ]
+ then
+ tmp=$(grep 'CAP_LAST_CAP+1' "$stdout"|cut -d: -f2|tr -d ' ' || :)
+ # take care to only perform this test on
+ # platforms the _have_ capabilities :)
+ if [ -n "$tmp" ]
+ then
+ last=$(expr "$tmp" - 1)
+
+ [ -n "$last" ] || die "unable to establish last capability"
+ { grep -q "number: $last" "$stdout"; ret=$?; } || :
+ if [ $ret -ne 0 ]
+ then
+ warn ""
+ warn ""
+ warn "Found extra capability procenv is not aware of (number $last)"
+ warn ""
+ warn "Note that this warning will appear if procenv is built on a"
+ warn "system which is running a newer kernel than the"
+ warn "development environment assumes (for example if built in a"
+ warn "chroot for a back-level release of ubuntu)"
+ warn ""
+ warn "Please check for a newer version of procenv, "
+ warn "build on a newer system, or raise a bug at:"
+ warn ""
+ warn " @package_url@"
+ warn ""
+ warn ""
+ fi
+ fi
+ fi
+
+ rm -f "$stdout" "$stderr"
+
+ # JSON format
+ if [ "$json_tests" -eq 1 ]
+ then
+ cmd="$procenv --format=json $arg 1>\"$stdout\" 2>\"$stderr\""
+ msg "Running '$cmd'"
+ run_command "$cmd" "$stdout" "$stderr"
+
+ [ -z "$stdout" ] && die "No stdout output running '$cmd'"
+ [ -s "$stderr" ] && die "Unexpected stderr output running '$cmd' ($stderr)"
+
+ run_command "$json_checker < \"$stdout\" >/dev/null" "" ""
+
+ rm -f "$stdout" "$stderr"
+ fi
+
+ # XML format
+ if [ "$xml_tests" -eq 1 ]
+ then
+ cmd="$procenv --format=xml $arg"
+ if [ "$section" = "environment:" -a "$control_chars_in_env" -eq 1 ]
+ then
+ warn "Skipping '$cmd' as control characters found in environment"
+ else
+ msg "Running '$cmd'"
+ cmd="$cmd 1>\"$stdout\" 2>\"$stderr\""
+ run_command "$cmd" "$stdout" "$stderr"
+ [ -z "$stdout" ] && die "No stdout output running '$cmd'"
+ [ -s "$stderr" ] && die "Unexpected stderr output running '$cmd' ($stderr)"
+ [ -z "$($xml_checker "$stdout")" ] || die "XML output not well-formed"
+ fi
+
+ rm -f "$stdout" "$stderr"
+ fi
+ done
+
#---------------------------------------------------------------------
msg "Ensure $procenv runs with no errors"
@@ -167,7 +299,9 @@ run_tests()
$procenv 1>"$stdout" 2>"$stderr"
rm -f "$stdout" "$stderr"
- # Save all sections that are displayed by default for later checks
+ # Save all section names to compare to the total set of section
+ # names generated by running procenv once for each output
+ # argument.
sections=$($procenv|grep "^[a-z0-9][a-z0-9 ]*:$")
msg "Ensuring output is sorted by section"
@@ -175,11 +309,18 @@ run_tests()
main_sections=$(mktemp "$template")
sorted_sections=$(mktemp "$template")
unique_sections=$(mktemp "$template")
+ unique_arg_sections=$(mktemp "$template")
+
+ echo "$sections"|grep -q ^meta: || die "no meta section in main sections"
+ grep -q ^meta: "$arg_sections" || die "no meta section in arg sections"
# ignore meta which always comes first
- echo "$sections"|grep -v meta: > "$main_sections"
- echo "$sections"|grep -v meta:|sort > "$sorted_sections"
- echo "$sections"|grep -v meta:|sort -u > "$unique_sections"
+ echo "$sections" |grep -v meta: > "$main_sections"
+ echo "$sections" |grep -v meta:|sort > "$sorted_sections"
+ echo "$sections" |grep -v meta:|sort -u > "$unique_sections"
+
+ cat "$arg_sections"|egrep -v "^(meta|version|pathconf):"|\
+ sort -u > "$unique_arg_sections"
diff=$(diff "$main_sections" "$sorted_sections" || :)
[ -n "$diff" ] && die "sections are not sorted - diff: $diff"
@@ -187,14 +328,30 @@ run_tests()
diff=$(diff "$sorted_sections" "$unique_sections" || :)
[ -n "$diff" ] && die "sections are not unique - diff: $diff"
- rm -f "$main_sections" "$sorted_sections" "$unique_sections"
+ # Note that we don't compare the sorted and unique arg_sections
+ # since there are 2 ways to produce the same section output
+ # (short and long option).
+
+ diff=$(diff "$unique_sections" "$unique_arg_sections" || :)
+ [ -n "$diff" ] && die "default output sections do not match arg-collected sections - diff: $diff"
+
+ rm -f "$main_sections" \
+ "$sorted_sections" \
+ "$unique_sections" \
+ "$arg_sections" \
+ "$unique_arg_sections"
- remaining_file=$(mktemp "$template")
- echo "$sections" > "$remaining_file"
+ # pathconf cannot be handled like other sections since it is
+ # indented under the mount output, so just check we can find
+ # some evidence of it being displayed.
+ #
+ # Don't do this for the unknown driver since that doesn't produce
+ # mount output.
- # pathconf cannot be handled below as it is indented under the mount
- # output, so just check we can find some evidence of it being displayed.
- $procenv|egrep -q "\<pathconf\>:" || die "Failed to find pathconf"
+ if [ "$driver" != "unknown" ]
+ then
+ $procenv|egrep -q "\<pathconf\>:" || die "Failed to find pathconf"
+ fi
#---------------------------------------------------------------------
msg "Ensure --file=<file> works"
@@ -213,6 +370,62 @@ run_tests()
rm -f "$stdout" "$stderr"
#---------------------------------------------------------------------
+ msg "Ensure running multiple '--file=<file> --version' works"
+
+ out=$(mktemp "$template")
+ stdout=$(mktemp "$template")
+ stderr=$(mktemp "$template")
+ cmd="$procenv --file=\"$out\" --version 1>\"$stdout\" 2>\"$stderr\""
+
+ # run twice - we expect the output file to be overwritten
+ for expected in 1 1
+ do
+ run_command "$cmd" "$stdout" "$stderr"
+ [ -s "$stdout" ] && die "Unexpected stdout output: $stdout"
+ [ -s "$stderr" ] && die "Unexpected stderr output: $stderr"
+ [ -s "$out" ] || die "Expected output in file $out"
+
+ count=$(grep -c ^version: "$out")
+ [ "$count" -eq "$expected" ] || die "expected $expected match in file $out - got $count"
+ done
+
+ rm "$out"
+ rm -f "$stdout" "$stderr"
+
+ #---------------------------------------------------------------------
+ msg "Ensure '--file-append --file=<file> --version' works"
+
+ out=$(mktemp "$template")
+ stdout=$(mktemp "$template")
+ stderr=$(mktemp "$template")
+ for options in "--file=\"$out\" --file-append" "--file-append --file=\"$out\""
+ do
+ cmd="$procenv $options --version 1>\"$stdout\" 2>\"$stderr\""
+
+ run_command "$cmd" "$stdout" "$stderr"
+ [ -s "$stdout" ] && die "Unexpected stdout output: $stdout"
+ [ -s "$stderr" ] && die "Unexpected stderr output: $stderr"
+ [ -s "$out" ] || die "Expected output in file $out"
+
+ expected=1
+ count=$(grep -c ^version: "$out")
+ [ "$count" -eq "$expected" ] || die "expected $expected match in file $out - got $count"
+
+ run_command "$cmd" "$stdout" "$stderr"
+ [ -s "$stdout" ] && die "Unexpected stdout output: $stdout"
+ [ -s "$stderr" ] && die "Unexpected stderr output: $stderr"
+ [ -s "$out" ] || die "Expected output in file $out"
+
+ # the output file should be appended
+ expected=$((expected+1))
+ count=$(grep -c ^version: "$out")
+ [ "$count" -eq "$expected" ] || die "expected $expected match in file $out - got $count"
+
+ rm "$out"
+ rm -f "$stdout" "$stderr"
+ done
+
+ #---------------------------------------------------------------------
msg "Ensure --output=stdout works"
stdout=$(mktemp "$template")
@@ -242,7 +455,7 @@ run_tests()
rm -f "$stdout" "$stderr"
#---------------------------------------------------------------------
- msg "Ensure --exec works"
+ msg "Ensure --exec works (with no previous arguments)"
str="hello world"
out=$(mktemp "$template")
@@ -263,7 +476,29 @@ run_tests()
rm -f "$stdout" "$stderr" "$out"
#---------------------------------------------------------------------
- msg "Ensure --exec can exec $procenv"
+ msg "Ensure '--version --exec' works"
+
+ str="hello world"
+ out=$(mktemp "$template")
+ stdout=$(mktemp "$template")
+ stderr=$(mktemp "$template")
+ cmd="$procenv --output=file --file=\"$out\" --version \
+ --exec echo \"$str\" 1>\"$stdout\" 2>\"$stderr\""
+ run_command "$cmd" "$stdout" "$stderr"
+
+ [ -s "$out" ] || die "Expected $procenv output in file $out"
+ grep -q ^version: "$out" || die "Expected $procenv --version output in file $out"
+ [ -s "$stderr" ] && die "Unexpected stderr output in file $stderr"
+ [ -s "$stdout" ] || die "Expected stdout output in file $stdout"
+ result=$(cat "$stdout")
+
+ [ "$result" != "$str" ] && die \
+ "Expected file $stdout to contain '$str', found '$result'"
+
+ rm -f "$stdout" "$stderr" "$out"
+
+ #---------------------------------------------------------------------
+ msg "Ensure '--exec' can exec $procenv"
out=$(mktemp "$template")
out2=$(mktemp "$template")
@@ -283,6 +518,38 @@ run_tests()
rm -f "$stdout" "$stderr" "$out" "$out2"
#---------------------------------------------------------------------
+ msg "Ensure 'PROCENV_EXEC' and 'PROCENV_FILE' variables work"
+
+ out=$(mktemp "$template")
+ stdout=$(mktemp "$template")
+ stderr=$(mktemp "$template")
+
+ test_script=$(mktemp "$template")
+ test_log=$(mktemp "$template")
+ expected="foo"
+ cat <<EOT > "$test_script"
+ #!/bin/sh
+
+ echo "$expected" > "$test_log"
+EOT
+ chmod +x "$test_script"
+
+ (PROCENV_FILE="$out" PROCENV_EXEC="$test_script" \
+ "$procenv" 1>"$stdout" 2>"$stderr")
+
+ [ -s "$out" ] || die "Expected $procenv output in file $out"
+ [ -s "$test_log" ] || die "Expected output in test log file $test_log"
+ output=$(cat "$test_log")
+
+ [ "$output" = "$expected" ] || \
+ die "incorect output from script (expected '$expected', got '$output')"
+
+ [ -s "$stdout" ] && die "Unexpected stdout output in file $stdout"
+ [ -s "$stderr" ] && die "Unexpected stderr output in file $stderr"
+
+ rm -f "$out" "$stdout" "$stderr" "$test_script" "$test_log"
+
+ #---------------------------------------------------------------------
arg='--format=text'
msg "Ensure '$arg' works"
@@ -464,122 +731,6 @@ run_tests()
rm -f "$stdout" "$stderr"
fi
- #---------------------------------------------------------------------
- msg "Ensure all documented options produce output"
- procenv_options=$(get_procenv_options)
- echo "$procenv_options" | while read arg
- do
- stdout=$(mktemp "$template")
- stderr=$(mktemp "$template")
-
- # No format option
- cmd="$procenv $arg 1>\"$stdout\" 2>\"$stderr\""
- msg "Running '$cmd'"
- run_command "$cmd" "$stdout" "$stderr"
-
- [ -z "$stdout" ] && die "No stdout output running '$cmd'"
- [ -s "$stderr" ] && die "Unexpected stderr output running '$cmd' ($stderr)"
-
- # Establish the name of the section
- section=$(head -1 "$stdout"|grep "^[^ ].*:$" || :)
- [ -z "$section" ] && die "No section title found running '$cmd'"
-
- if [ "$section" != "version:" ]
- then
- # XXX: pathconf has already been handled above.
- if [ "$section" != "pathconf:" ]
- then
- # Check that that same section appears in the
- # default output. If not, we forgot to update
- # dump().
- echo "$sections"|grep -q "^${section}$" || \
- die "Failed to find section '$section' in default $procenv output"
- fi
- fi
-
- # Remove this section as it's now been handled
- remaining=$(cat "$remaining_file"|grep -v "^${section}$" || :)
- echo "$remaining"> "$remaining_file"
-
- rm -f "$stdout" "$stderr"
-
- # Text format
- cmd="$procenv --format=text $arg 1>\"$stdout\" 2>\"$stderr\""
- msg "Running '$cmd'"
- run_command "$cmd" "$stdout" "$stderr"
-
- [ -z "$stdout" ] && die "No stdout output running '$cmd'"
- [ -s "$stderr" ] && die "Unexpected stderr output running '$cmd' ($stderr)"
-
- if [ "$section" = "capabilities:" ]
- then
- tmp=$(grep 'CAP_LAST_CAP+1' "$stdout"|cut -d: -f2|tr -d ' ' || :)
- # take care to only perform this test on
- # platforms the _have_ capabilities :)
- if [ -n "$tmp" ]
- then
- last=$(expr "$tmp" - 1)
-
- [ -n "$last" ] || die "unable to establish last capability"
- { grep -q "number: $last" "$stdout"; ret=$?; } || :
- if [ $ret -ne 0 ]
- then
- warn ""
- warn ""
- warn "Found extra capability procenv is not aware of (number $last)"
- warn ""
- warn "Note that this warning will appear if procenv is built on a"
- warn "system which is running a newer kernel than the"
- warn "development environment assumes (for example if built in a"
- warn "chroot for a back-level release of ubuntu)"
- warn ""
- warn "Please check for a newer version of procenv, "
- warn "build on a newer system, or raise a bug at:"
- warn ""
- warn " @package_url@"
- warn ""
- warn ""
- fi
- fi
- fi
-
- rm -f "$stdout" "$stderr"
-
- # JSON format
- if [ "$json_tests" -eq 1 ]
- then
- cmd="$procenv --format=json $arg 1>\"$stdout\" 2>\"$stderr\""
- msg "Running '$cmd'"
- run_command "$cmd" "$stdout" "$stderr"
-
- [ -z "$stdout" ] && die "No stdout output running '$cmd'"
- [ -s "$stderr" ] && die "Unexpected stderr output running '$cmd' ($stderr)"
-
- run_command "$json_checker < \"$stdout\" >/dev/null" "" ""
-
- rm -f "$stdout" "$stderr"
- fi
-
- # XML format
- if [ "$xml_tests" -eq 1 ]
- then
- cmd="$procenv --format=xml $arg"
- if [ "$section" = "environment:" -a "$control_chars_in_env" -eq 1 ]
- then
- warn "Skipping '$cmd' as control characters found in environment"
- else
- msg "Running '$cmd'"
- cmd="$cmd 1>\"$stdout\" 2>\"$stderr\""
- run_command "$cmd" "$stdout" "$stderr"
- [ -z "$stdout" ] && die "No stdout output running '$cmd'"
- [ -s "$stderr" ] && die "Unexpected stderr output running '$cmd' ($stderr)"
- [ -z "$($xml_checker "$stdout")" ] || die "XML output not well-formed"
- fi
-
- rm -f "$stdout" "$stderr"
- fi
- done
-
for arg in $non_display_options
do
# XXX: specifying a non-display option _after_
@@ -601,17 +752,6 @@ run_tests()
rm -f "$stdout" "$stderr"
done
- # If there are any remaining sections that were produced by default
- # output but which have not been handed by command-line options, we
- # forgot to update usage().
- msg "Checking for missing arguments"
- remaining=$(cat "$remaining_file")
-
- [ -n "$remaining" ] && \
- die "No command-line option found for the following section(s): '$remaining'"
-
- rm -f "$remaining_file"
-
msg "Ensure an empty environment is tolerated"
if command -v env >/dev/null 2>&1
then
@@ -641,13 +781,19 @@ run_final_tests()
}
#---------------------------------------------------------------------
+# main
+#---------------------------------------------------------------------
-# allow this useful function to be called independent of the tests.
-case "$1" in
- options)
- get_procenv_options
- exit 0
-esac
+while getopts "o" opt
+do
+ case "$opt" in
+ o)
+ # allow this useful function to be called independent of the tests.
+ get_procenv_options
+ exit 0
+ ;;
+ esac
+done
init
diff --git a/src/tests/show_compiler_details b/src/tests/show_compiler_details
index fbbc253..678d63b 100755
--- a/src/tests/show_compiler_details
+++ b/src/tests/show_compiler_details
@@ -8,6 +8,10 @@ CC=${CC:-cc}
CPP=${CPP:-cpp}
LD=${LD:-ld}
+# handle strange environments
+command -v gcpp >/dev/null 2>&1 && CPP=gcpp
+command -v gcc >/dev/null 2>&1 && CC=gcc
+
echo "XXX:--------------------------------------------------"
echo "XXX: $0: preprocessor ('$CPP') version"
echo
diff --git a/src/tests/show_machine_details b/src/tests/show_machine_details
new file mode 100755
index 0000000..c689e3f
--- /dev/null
+++ b/src/tests/show_machine_details
@@ -0,0 +1,59 @@
+#!/bin/sh
+#---------------------------------------------------------------------
+# Description: Script to dump machine details.
+#---------------------------------------------------------------------
+
+echo "XXX:--------------------------------------------------"
+echo "XXX: $0: Memory details"
+echo
+cat /proc/meminfo
+echo
+
+echo "XXX:--------------------------------------------------"
+echo "XXX: $0: ulimit details"
+echo
+ulimit -a
+echo
+
+echo "XXX:--------------------------------------------------"
+echo "XXX: $0: CPU count"
+echo
+grep -c ^processor /proc/cpuinfo
+
+echo
+
+echo "XXX:--------------------------------------------------"
+echo "XXX: $0: CPU details"
+echo
+
+# show first CPU only
+awk 'BEGIN { RS=""; } { printf ("%s\n", $0); exit (0); }' /proc/cpuinfo
+echo
+
+kvm=$(cat /sys/module/kvm_intel/parameters/nested 2>/dev/null || echo N)
+
+echo "XXX:--------------------------------------------------"
+echo "XXX: $0: Nested KVM support"
+echo
+echo "$kvm"
+echo
+
+echo "XXX:--------------------------------------------------"
+echo "XXX: $0: uname"
+echo
+uname -a
+echo
+
+echo "XXX:--------------------------------------------------"
+echo "XXX: $0: kernel modules"
+echo
+lsmod|sort
+echo
+
+echo "XXX:--------------------------------------------------"
+echo "XXX: $0: distro details"
+echo
+cat /etc/os-release 2>/dev/null
+cat /etc/lsb-release 2>/dev/null
+cat /etc/issue 2>/dev/null
+echo
diff --git a/src/types.h b/src/types.h
new file mode 100644
index 0000000..02f7c0e
--- /dev/null
+++ b/src/types.h
@@ -0,0 +1,34 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_TYPES_H
+#define _PROCENV_TYPES_H
+
+#include <stdint.h>
+
+struct procenv_map {
+ unsigned int num;
+ const char *name;
+};
+
+struct procenv_map64 {
+ uint64_t num;
+ const char *name;
+};
+
+#endif /* _PROCENV_TYPES_H */
diff --git a/src/util.c b/src/util.c
new file mode 100644
index 0000000..fea4b32
--- /dev/null
+++ b/src/util.c
@@ -0,0 +1,294 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#include "util.h"
+#if __GLIBC__
+#include <sys/sysmacros.h>
+#endif
+
+// FIXME
+extern struct procenv_user user;
+extern struct procenv_misc misc;
+
+struct baud_speed
+{
+ speed_t speed;
+ char *name;
+};
+
+/**
+ * fd_valid:
+ * @fd: file descriptor.
+ *
+ * Return 1 if @fd is valid, else 0.
+ **/
+int
+fd_valid (int fd)
+{
+ int flags = 0;
+
+ if (fd < 0)
+ return 0;
+
+ errno = 0;
+ flags = fcntl (fd, F_GETFL);
+
+ if (flags < 0)
+ return 0;
+
+ /* redundant really */
+ if (errno == EBADF)
+ return 0;
+
+ return 1;
+}
+
+#if !defined (PROCENV_PLATFORM_HURD) && \
+ !defined (PROCENV_PLATFORM_MINIX) && \
+ !defined (PROCENV_PLATFORM_DARWIN)
+
+/**
+ * is_console:
+ * @fd: open file descriptor.
+ *
+ * Check if specified file descriptor is attached to a _console_
+ * device (physical or virtual).
+ *
+ * Notes:
+ * - ptys are NOT consoles :)
+ * - running inside screen/tmux will report not running on console.
+ *
+ * Returns: true if @fd is attached to a console, else false.
+ **/
+int
+is_console (int fd)
+{
+ struct vt_mode vt;
+ int ret;
+
+ ret = ioctl (fd, VT_GETMODE, &vt);
+
+ return !ret;
+}
+#endif
+
+/**
+ * is_big_endian:
+ *
+ * Returns: true if system is big-endian, else false.
+ **/
+bool
+is_big_endian (void)
+{
+ int x = 1;
+
+ if (*(char *)&x == 1)
+ return false;
+
+ return true;
+}
+
+bool
+has_ctty (void)
+{
+ int fd;
+ fd = open ("/dev/tty", O_RDONLY | O_NOCTTY);
+
+ if (fd < 0)
+ return false;
+
+ close (fd);
+
+ return true;
+}
+
+bool
+uid_match (uid_t uid)
+{
+ return uid == getuid ();
+}
+
+/**
+ * in_container:
+ *
+ * Determine if running inside a container.
+ *
+ * Returns: Name of container type, or NO_STR.
+ **/
+const char *
+container_type (void)
+{
+ struct stat statbuf;
+ char buffer[1024];
+ FILE *f;
+#if defined (PROCENV_PLATFORM_LINUX)
+ dev_t expected;
+
+ expected = makedev (5, 1);
+#endif
+
+ if (stat ("/dev/console", &statbuf) < 0)
+ goto out;
+
+#if defined (PROCENV_PLATFORM_FREEBSD)
+ if (misc.in_jail)
+ return "jail";
+#endif
+
+ /* LXC's /dev/console is actually a pty */
+#if defined (PROCENV_PLATFORM_LINUX)
+ if (major (statbuf.st_rdev) != major (expected)
+ || (minor (statbuf.st_rdev)) != minor (expected))
+ return "lxc";
+#endif
+
+ if (! stat ("/proc/vz", &statbuf) && stat ("/proc/bc", &statbuf) < 0)
+ return "openvz";
+
+ f = fopen ("/proc/self/status", "r");
+ if (! f)
+ goto out;
+
+ while (fgets (buffer, sizeof (buffer), f)) {
+ size_t len = strlen (buffer);
+ buffer[len-1] = '\0';
+
+ if (strstr (buffer, "VxID") == buffer) {
+ fclose (f);
+ return "vserver";
+ }
+ }
+
+ fclose (f);
+
+out:
+ return NO_STR;
+}
+
+/**
+ * in_chroot:
+ *
+ * Determine if running inside a chroot environment.
+ *
+ * Failures are fatal.
+ *
+ * Returns true if within a chroot, else false.
+ **/
+// FIXME: add different implementations?
+bool
+in_chroot (void)
+{
+ struct stat st;
+ int i;
+ int root_inode, self_inode;
+ char root[] = "/";
+ char self[] = "/proc/self/root";
+ char bsd_self[] = "/proc/curproc";
+ char *dir = NULL;
+
+ i = stat (root, &st);
+ if (i != 0) {
+ dir = root;
+ goto error;
+ }
+
+ root_inode = st.st_ino;
+
+ /*
+ * Inode 2 is the root inode for most filesystems. However, XFS
+ * uses 128 for root.
+ */
+ if (root_inode != 2 && root_inode != 128)
+ return true;
+
+ i = stat (bsd_self, &st);
+ if (i == 0) {
+ /* Give up here if running on BSD */
+ return false;
+ }
+
+ i = stat (self, &st);
+ if (i != 0)
+ return false;
+
+ self_inode = st.st_ino;
+
+ if (root_inode == self_inode)
+ return false;
+
+ return true;
+
+error:
+ die ("cannot stat '%s'", dir);
+
+ /* compiler appeasement */
+ return false;
+}
+
+/* detect if setsid(2) has been called */
+bool
+is_session_leader (void)
+{
+ return user.sid == user.pid;
+}
+
+/* detect if setpgrp(2)/setpgid(2) (or setsid(2)) has been called */
+bool
+is_process_group_leader (void)
+{
+ return user.pgroup == user.pid;
+}
+
+static struct baud_speed baud_speeds[] = {
+ SPEED (B0),
+ SPEED (B50),
+ SPEED (B75),
+ SPEED (B110),
+ SPEED (B134),
+ SPEED (B150),
+ SPEED (B200),
+ SPEED (B300),
+ SPEED (B600),
+ SPEED (B1200),
+ SPEED (B1800),
+ SPEED (B2400),
+ SPEED (B4800),
+ SPEED (B9600),
+ SPEED (B19200),
+ SPEED (B38400),
+ SPEED (B57600),
+ SPEED (B115200),
+ SPEED (B230400),
+
+ /* terminator */
+ { 0, NULL }
+};
+
+const char *
+get_speed (speed_t speed)
+{
+ struct baud_speed *s;
+
+ for (s = baud_speeds; s && s->name; s++) {
+ if (speed == s->speed)
+ return s->name;
+ }
+
+ return NULL;
+}
+
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..2df9e6f
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,59 @@
+/*--------------------------------------------------------------------
+ * Copyright © 2016 James Hunt <jamesodhunt@ubuntu.com>.
+ *
+ * This program 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 3 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, see <http://www.gnu.org/licenses/>.
+ *--------------------------------------------------------------------
+ */
+
+#ifndef _PROCENV_UTIL_H
+#define _PROCENV_UTIL_H
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <termios.h>
+
+#if defined (PROCENV_PLATFORM_LINUX)
+#include <linux/vt.h>
+#endif /* PROCENV_PLATFORM_LINUX */
+
+#if defined (PROCENV_PLATFORM_FREEBSD)
+#include <sys/consio.h>
+#endif
+
+#include "platform.h"
+
+bool has_ctty (void);
+bool in_chroot (void);
+bool is_big_endian (void);
+bool is_process_group_leader (void);
+bool is_session_leader (void);
+bool uid_match (uid_t uid);
+const char *container_type (void);
+const char *get_speed (speed_t speed);
+int fd_valid (int fd);
+
+#if !defined (PROCENV_PLATFORM_HURD) && \
+ !defined (PROCENV_PLATFORM_MINIX) && \
+ !defined (PROCENV_PLATFORM_DARWIN)
+int is_console (int fd);
+#endif
+
+#endif /* _PROCENV_UTIL_H */