├── .github └── workflows │ └── build.yaml ├── .travis.yml ├── AUTHORS ├── Android.mk ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── Makefile.in ├── NEWS ├── README-BUILD.md ├── README-DEVELOPER.md ├── README.md ├── TODO ├── aclocal.m4 ├── config.h.in ├── config ├── compile ├── config.guess ├── config.sub ├── depcomp ├── install-sh └── missing ├── configure ├── configure.ac ├── m4 ├── ChangeLog └── ax_check_compile_flag.m4 ├── man └── procenv.1 ├── procenv.spec ├── procenv.spec.in ├── reconf ├── scripts └── find-missing-symbols.sh ├── snap └── snapcraft.yaml └── src ├── Makefile.am ├── Makefile.in ├── messages.h ├── output.c ├── output.h ├── platform-headers.h ├── platform.h ├── platform ├── README.md ├── android │ └── platform.c ├── darwin │ ├── platform-darwin.h │ └── platform.c ├── freebsd │ ├── platform-freebsd.h │ └── platform.c ├── hurd │ ├── platform-hurd.h │ └── platform.c ├── linux │ ├── platform-linux.h │ └── platform.c ├── minix │ ├── platform-minix.h │ └── platform.c ├── netbsd │ ├── platform-netbsd.h │ └── platform.c ├── openbsd │ ├── platform-openbsd.h │ └── platform.c ├── platform-generic.c ├── platform-generic.h └── unknown │ ├── platform-unknown.h │ └── platform.c ├── pr_list.c ├── pr_list.h ├── procenv.c ├── procenv.h ├── pstring.c ├── pstring.h ├── string-util.c ├── string-util.h ├── tests ├── check_all_args.in ├── check_pr_list.c ├── show_compiler_details └── show_machine_details ├── types.h ├── util.c └── util.h /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------- 2 | # Copyright (c) 2021 James O. D. Hunt . 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | #-------------------------------------------------------------------- 6 | 7 | name: Build procenv in GitHub Actions build environment 8 | 9 | on: [push, pull_request] 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Install dependencies 16 | run: | 17 | sudo apt update -qq 18 | sudo apt install -y \ 19 | autoconf autoconf-archive \ 20 | automake \ 21 | autopoint \ 22 | check \ 23 | expat \ 24 | libapparmor-dev \ 25 | libcap-dev \ 26 | libnuma-dev \ 27 | libselinux1-dev 28 | 29 | - name: Checkout code 30 | uses: actions/checkout@v2 31 | 32 | - name: Build 33 | run: | 34 | autoreconf -fi 35 | ./configure 36 | make -j4 37 | make check 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # Copyright (c) 2015-2021 James O. D. Hunt . 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | #--------------------------------------------------------------------- 6 | 7 | dist: focal 8 | branches: 9 | only: 10 | - master 11 | language: c 12 | compiler: 13 | - gcc 14 | - clang 15 | os: 16 | - linux 17 | - osx 18 | before_install: 19 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update -qq; fi 20 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y autopoint automake expat libnuma-dev libcap-dev check; fi 21 | disable_homebrew: true 22 | script: autoreconf -fi && ./configure && make -j4 && make check 23 | notifications: 24 | email: 25 | recipients: 26 | - jamesodhunt@gmail.com 27 | env: 28 | global: 29 | # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created 30 | # via the "travis encrypt" command using the project repo's public key 31 | - secure: "ywIKOpIjRkWL+8KTvJwt2AInz1cgUVU56yo6KIyOv+SRTzCneHXlylQ/F7rxnWYLBZHzOF2GdrWRsUekLDYqIIMdMeYZ50gNT+ZjN4JIVqnlK8X2BJrdpzoxBA4jSJS0gx836GuAX7q0oiI7ZrJikAyFkQJr98n8klR6aFKGiE/0kyxambETqqlOmPnq3/sdsnmeA4HFswflGIX/34s+7RUpmB/O2ix1CTgSt+I8WKo3vvAksVxqo1utx4IwVLlmmvfBfqJXTPK5ZkdcdfieqRSGmSl3hyn9ZgyG8NnR8qFQx2KyGIsgdJAyW4MpxC9lpHq+kWCOz19xjeGVGrWGAPJMWSi/qKFATJXajPVbpKxoPFDmDjd+sUi4rQLyiOb0KI4z2GYXZ3d1let06OTyC9cIe1fwdDJ+7tdLsQpX0uMLHwYL/LrA6O6W3YARSxTVHgi34WQqyQ7P2A1NZHcj6wG2krFLpVEyP/+sxuMi6OFKzZLiUH/oPWjlBBCGPxUXkjV4QV3j1+1XYJS5Xai8WczFB6aWbJD8khMz3l1yICQ/WernY+ro4M4Aw0uBC9wL2Tqj1fu4OW4ws9YyjGA/ok8s918BufOTw9kbA7s96Saw6ZezZLlxwV5fI0AJYrNvbn57dXehS0vfDSQEYQCAEsAczCbpuW4ils/gnnd/uS4=" 32 | addons: 33 | coverity_scan: 34 | project: 35 | name: "jamesodhunt/procenv" 36 | description: "Build submitted via Travis CI" 37 | notification_email: jamesodhunt@gmail.com 38 | build_command_prepend: "autoreconf -fi && ./configure; make clean" 39 | build_command: "make -j 4" 40 | branch_pattern: master 41 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | James Hunt 2 | Kees Cook 3 | Dave Love 4 | Mike Miller 5 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # Copyright (c) 2013-2021 James O. D. Hunt . 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | #--------------------------------------------------------------------- 6 | 7 | LOCAL_PATH := $(call my-dir) 8 | include $(CLEAR_VARS) 9 | 10 | LOCAL_MODULE := procenv 11 | LOCAL_MODULE_TAGS := optional 12 | LOCAL_MODULE_CLASS := EXECUTABLES 13 | LOCAL_SRC_FILES:= procenv.c 14 | LOCAL_C_INCLUDES := $(LOCAL_PATH) 15 | LOCAL_STATIC_LIBRARIES := libc libdl 16 | LOCAL_SHARED_LIBRARIES := libcutils 17 | 18 | include $(BUILD_EXECUTABLE) 19 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesodhunt/procenv/576dd40335a165b56698dce16eefe9fb4e675179/ChangeLog -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------- 2 | # Copyright (c) 2012-2021 James O. D. Hunt . 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | #-------------------------------------------------------------------- 6 | 7 | # Don't require 'README' as we use a markdown file instead. 8 | AUTOMAKE_OPTIONS = foreign 9 | SUBDIRS = src 10 | 11 | ACLOCAL_AMFLAGS = -I m4 12 | 13 | EXTRA_DIST = m4/ChangeLog man/procenv.1 procenv.spec 14 | man1_MANS = man/procenv.1 15 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 0.60 2021-07-13 2 | 3 | * Bump output format version (should have been done for 0.58). 4 | * snap: Add missing staging packages. 5 | * autoconf: Fix AppArmor and SELinux detection 6 | Bug fix that necessitated a new release: previously, the security 7 | context displayed with `--misc` could show as "unknown" due to a 8 | bug in `configure.ac`'s detection code. 9 | * docs: Add snap details to README. 10 | 11 | 0.59 2021-07-13 12 | 13 | * doc improvements (README and man page). 14 | * snap: Add snapcraft config file 15 | * `--sysconf`: 16 | - Display output in order. 17 | - Removed duplicate entry for `_SC_EXPR_NEST_MAX`. 18 | - Added new entries for: 19 | - `_SC_2_PBS_CHECKPOINT` 20 | - `_SC_SS_REPL_MAX` 21 | - `_SC_STREAMS` 22 | - `_SC_TRACE_EVENT_NAME_MAX` 23 | - `_SC_TRACE_NAME_MAX` 24 | - `_SC_TRACE_SYS_MAX` 25 | - `_SC_TRACE_USER_EVENT_MAX` 26 | - `_SC_XOPEN_STREAMS` 27 | * `--misc`: BUG fix: Check for `PR_GET_UNALIGN` `prctl`, **not** 28 | `PR_GET_UNALIGNED`. 29 | * `--namespaces`: BUG fix: Don't fully resolve namespace links to handle 30 | new `pid_for_children` and `time_for_children` namespaces. 31 | 32 | 0.58 2021-06-25 33 | 34 | * darwin: Support `--libs`. 35 | * darwin: Support `AF_LINK` for `--network`. 36 | * docs: Remove TOC. 37 | 38 | 0.57 2021-06-19 39 | 40 | * Add macports installation instructions (thanks Haren). 41 | * --timezone: Enabled for Darwin, FreeBSD, NetBSD and OpenBSD. 42 | * --clocks: Add `CLOCK_BOOTTIME_ALARM`, `CLOCK_PROCESS_CPUTIME_ID` 43 | and `CLOCK_REALTIME_ALARM` to output. 44 | * darwin: Enabled `--clocks`. 45 | 46 | 0.56 2021-06-13 47 | 48 | * tidy: compact and align structs for memory size and performance. 49 | * darwin: Add memory details (total, free, wired, unused, active and 50 | inactive memory). 51 | * doc improvements. 52 | 53 | 0.55 2021-04-08 54 | 55 | * Documentation improvements. 56 | * Hurd build fixes: 57 | - Disable detailed memory reporting as `sysinfo()` not available). 58 | - Fixed detection for modern versions of Hurd. 59 | * Nits. 60 | 61 | 0.54 2021-03-15 62 | 63 | * --capabilities: Added new capabilities: 64 | - `CAP_BPF` 65 | - `CAP_CHECKPOINT_RESTORE` 66 | - `CAP_PERFMON` 67 | * --clocks: Add CLOCK_TAI. 68 | * --memory: Add details of total and available memory and swap. 69 | Requires the `libsysinfo` package on *BSD. 70 | * --process: Fixed nasty bug (infinite loop) on *BSD if any of 71 | the following sysconf's are set: 72 | - `security.bsd.see_other_uids=0` 73 | - `security.bsd.see_other_gids=0` 74 | - `kern.randompid=1` 75 | * Fix compiler flag checking in the configure script. 76 | 77 | 0.53 2021-03-01 78 | 79 | * Really fix FreeBSD capabilities/capsicum build. 80 | 81 | 0.52 2021-02-28 82 | 83 | * Fix GCC-10 build when used with `-Werror=format-overflow` 84 | (thanks Lukas Maerdian). 85 | * Fix FreeBSD capabilities/capsicum build (thanks Li-Wen Hsu). 86 | 87 | 0.51 2019-08-02 88 | 89 | * Fixed failure scenario identified by `scan-build(1)`. 90 | * Fixed GNU Hurd detection. 91 | * Fixed building without `libcap` (thanks Dave Love). 92 | * Fix compiler warnings for gcc9 (thanks Vorlon). 93 | 94 | 0.50 2017-10-16 95 | 96 | * --compiler: Add additional feature test macros. 97 | * --misc: Show if running in a virtual machine. 98 | 99 | 0.49 2017-02-12 100 | 101 | * FreeBSD 11 capsicum fixes. 102 | * Fix PROCENV_EXEC_ENV harder. 103 | 104 | 0.48 2017-01-31 105 | 106 | * Fix makedev(3) compiler error (it's now in sys/sysmacros.h). 107 | (thanks Dave Love). 108 | 109 | 0.47 2017-01-31 110 | 111 | * Fixed hang when using PROCENV_EXEC variable. 112 | * Test improvements. 113 | 114 | 0.46 2016-05-28 115 | 116 | * Fixed --file-append behaviour. 117 | * Test improvements. 118 | * Added support for Apple OSX (darwin). 119 | 120 | 0.45 2016-03-21 121 | 122 | * Code restructured internally to simplify maintenance and adding 123 | new platforms. See src/platform/README.rst (and README-BUILD.rst). 124 | 125 | * Dropped support for: 126 | - kFreeBSD (Debian using a FreeBSD kernel) - defunc project. 127 | - Ubuntu Lucid (10.04) - no longer a supported platform. 128 | 129 | * Added support for NetBSD, OpenBSD and Minix 3. 130 | 131 | * --meta: Now shows details of the procenv platform driver being 132 | used. 133 | 134 | * --misc now shows "security module" rather than 135 | "linux security module". 136 | 137 | * --file-append: new option (env var is "PROCENV_FILE_APPEND") 138 | to append to the --file= specified rather than overwriting. 139 | 140 | 0.44 2016-02-15 141 | 142 | * --cgroup: Handle cgroup2 (cgroups v2). 143 | 144 | * --clocks: now also includes CLOCK_REALTIME_COURSE, CLOCK_REALTIME_HR, 145 | CLOCK_MONOTONIC_COURSE, CLOCK_MONOTONIC_RAW and CLOCK_BOOTTIME. 146 | 147 | * --cpu: added I/O priority. 148 | 149 | * Fixed crash if non-output argument specified before "--exec". 150 | 151 | 0.43 2015-11-24 152 | 153 | * Namespace fix for non-Linux platforms. 154 | 155 | 0.42 2015-11-05 156 | 157 | * Documentation improvements. 158 | * Removed reliance on autoreconf 159 | (required due to limitations in github release process). 160 | * Improved '--namespaces' output by removing indexes. 161 | 162 | 0.41 2015-10-23 163 | 164 | * Further test improvements. 165 | * Correct output order (libc before misc). 166 | * Run compiler test before building procenv to aide remote debugging 167 | should the build fail. 168 | * Code tidy-ups and Coverity tweaks. 169 | * Added '--namespaces'/'-F' option. 170 | 171 | 0.40 2015-09-27 172 | 173 | * Updated email address. 174 | * New --libc'/'-B' option. 175 | * --enable-reproducible-build 176 | * '--compiler': Added _DEFAULT_SOURCE, _LARGEFILE_SUPPORT and 177 | __STDC_VERSION__. 178 | * locale fixes. 179 | 180 | 0.39 2015-08-25 181 | 182 | * Fixed tests harder :) 183 | 184 | 0.38 2015-08-24 185 | 186 | * Fixed tests for non-UTF-8 locales. 187 | 188 | 0.37 2015-08-23 189 | 190 | * Improved error handling. 191 | * Added CAP_AUDIT_READ capability. 192 | * Improved build-time tests. 193 | * Tolerate a completely empty environment. 194 | * Fixed bug where fsid in '--mounts' output was displaying truncated 195 | output on Linux. 196 | * Fix crasher bug triggered by specifying a UTF-8 character to 197 | '--separator' or '--crumb-separator'. 198 | * Allow '--indent-char' to be UTF-8. 199 | 200 | 0.36 2014-08-16 201 | 202 | * RHEL/Centos spec file - thanks Dave Love 203 | (LP: #1327594). 204 | * Improved checks for SELinux/Apparmor (LP: #1333182). 205 | * Added missing types from stdint.h to '--sizeof'. 206 | * Fixed building on systems with old NUMA libraries, such as 207 | Centos/RHEL 5 (LP: #1333194). However, bug is not yet fully 208 | resolved since cpu details seem to be reported incorrectly 209 | on these old systems. 210 | * Corrected SELinux detection code and added MLS detection. 211 | * Added missing conf calls such that '--sysconf', '--pathconf' and 212 | '--confstr' combined are now on par with getconf(1). 213 | * More man page examples. 214 | * Major internal rewrite to handle all data as wchar_t to avoid failing 215 | in locales using UTF-8 characters (LP: #1325494). 216 | 217 | 0.35 2014-06-03 218 | 219 | * Update to handle Linux 3.15 kernel which has 220 | dropped ability to query extended network interfaces flags 221 | (LP: #1324256). 222 | 223 | 0.34 2014-03-25 224 | 225 | * Enable builds for systems with old versions of libcap. 226 | * Add Linux binary personality (with flags) to '--misc' output. 227 | * Fix for rpm spec file. 228 | * Updated man page. 229 | 230 | 0.33 2014-03-14 231 | 232 | * Improved RPM spec file to include check phase and Conditional 233 | architecture dependency logic. 234 | * Updated for OpenRISC. 235 | * --ranges now also shows the symbolic names (such as "LONG_MAX"). 236 | * Reworked capabilities support to show effective, inheritable and 237 | permitted value for each capability in addition to the existing 238 | bounding set value. Will also display "unknown" capabilities if run on 239 | a system whose running kernel has more capabilities than the system 240 | procenv was built on. 241 | 242 | 0.32 2014-01-31 243 | 244 | * Generate .spec file to ensure version stays in sync with 245 | configure.ac. 246 | 247 | 0.31 2014-01-31 248 | 249 | * FEATURE: Added RPM specfile courtesy of Dave Love. 250 | * FEATURE: --capabilities now displays Capsicum capabilities 251 | if available (FreeBSD 9/10+). 252 | * FIX: Environment display could cause a crash. 253 | * FIX: Last attacher process in shared memory display on Linux 254 | incorrectly showed the current process name rather than the last. 255 | 256 | 0.30 2014-01-18 257 | 258 | * FIX: Semaphore fix for PPC and Sparc platforms. 259 | 260 | 0.29 2014-01-13 261 | 262 | * FIX: Allow building on Linux systems whose 263 | architectures are not NUMA-capable. 264 | 265 | 0.28 2014-01-10 266 | 267 | * FIX: Process ancestry now displayed on kFreeBSD by default. 268 | * FIX: Fixes to identify AARCH64, SuperH and PPC64. 269 | * FEATURE: Added ability to identify PPCspe and PPC64LE 270 | architectures. 271 | * FEATURE: '--cpu' now displays processor affinity details (LP: #1251209). 272 | * FEATURE: --memory/-Y added to display NUMA memory details. 273 | * FEATURE: Lots of test improvements. 274 | 275 | 0.27 2013-10-14 276 | 277 | * Added IPC options '--shared-memory', '--semaphores' and 278 | '--message-queues'. 279 | * Added rudimentary "make check" tests. 280 | * Made default text output highly structured. 281 | * Added ability to produce output in XML, JSON and "breadcrumb" 282 | (including CSV) formats. 283 | * Added ability to specify indent amount, indent character and 284 | separators (via command-line or environment variable). 285 | 286 | 0.26 2013-08-27 287 | 288 | * Check to determine if running on a console now works for 289 | FreeBSD/kFreeBSD too. 290 | * Added ability to show all arguments (-A/--arguments) 291 | (useful when using --exec). 292 | * Added ability to display network details (-N/--network). 293 | * Added BSD/Hurd-specific signals. 294 | * Corrected output sort order. 295 | * Mount details now include block, inode and fsck details. 296 | 297 | 0.25 2013-07-19 298 | 299 | * Fixed bug where procenv would hang in a FreeBSD jail. 300 | * Port to Android. 301 | 302 | 0.24 2013-06-28 303 | 304 | * Packaging update for automake-1.13 to ensure procenv output 305 | available in build logs. 306 | 307 | 0.23 2013-05-31 308 | 309 | * Tolerate Linux environments where /proc is not mounted. 310 | * Fix kFreeBSD detection and add support for IBM SystemZ 311 | environments. 312 | 313 | 0.22 2013-05-17 314 | 315 | * Added --platform option which contains some information that 316 | was formally in --misc output, but also now includes the 317 | number of "architecture bits" (executable bits) and the 318 | programming model for the platform (such as LP32/ILP64). 319 | 320 | 0.21 2013-04-07 321 | 322 | * Various improvements from Mike Miller including umask 323 | restoration fix. 324 | * Display terminal attribute locked status (Linux only). 325 | 326 | 0.20 2013-01-15 327 | 328 | * Sort environment variables and groups in locale-aware fashion. 329 | * FreeBSD fix for LC_NAME. 330 | 331 | 0.19 2012-12-17 332 | 333 | * Fixed an assertion failure if running with nice -1. 334 | 335 | 0.18 2012-12-06 336 | 337 | * Improvements to Apparmor+SELinux handling 338 | (Mike Miller). 339 | * prctl fixes (thanks Dave Love). 340 | 341 | 0.17 2012-12-06 342 | 343 | * Further locale improvements from Dave Love. 344 | * Cosmetic man-page improvements. 345 | 346 | 0.16 2012-12-02 347 | 348 | * Add support for RHEL builds (thanks Dave Love). 349 | * Locale improvements. 350 | * Correction for detecting ARMHF. 351 | * Environment variables are now sorted to make diffing easier. 352 | * ChangeLog now reflects bzr branch history. 353 | 354 | 0.15 2012-11-28 355 | 356 | * Fixes for Hurd. 357 | 358 | 0.14 2012-11-28 359 | 360 | * Scheduler and non-Linux platform fixes for --threads. 361 | 362 | 0.13 2012-11-26 363 | 364 | * Added --threads option. 365 | * Additional resilience to running in unusual environments. 366 | 367 | 0.12 2012-11-22 368 | 369 | * Added show_compiler_details test. 370 | * Fix for GNU/Hurd. 371 | 372 | 0.11 2012-11-21 373 | 374 | * Don't allow prctl to fail, even for environments 375 | such as chroots where libc defines the symbols, but 376 | the kernel outside the chroot does not implement 377 | the features. 378 | 379 | 0.10 2012-11-20 380 | 381 | * Further platform fixes identified by building on 382 | Debian-supported buildd's. 383 | * Added locale output. 384 | 385 | 0.9 2012-11-19 386 | 387 | * Platform fixes identified by building on Debian-supported 388 | platforms. 389 | * Improved man page. 390 | 391 | 0.8 2012-11-16 392 | 393 | * Man page updates. 394 | * Added resource usage. 395 | * Added more types for --sizeof. 396 | 397 | 0.7 2012-11-05 398 | 399 | * Fixes for non-x86 kernels and specific kernel versions. 400 | 401 | 0.6 2012-10-27 402 | 403 | * AppArmor, capabilities and prctl(2) contributions from 404 | Kees Cook. 405 | 406 | 0.5 2012-10-27 407 | 408 | * Fluff removal. 409 | 410 | 0.4 2012-10-27 411 | 412 | * Path resolution fixes and strsep() safety. 413 | 414 | 0.3 2012-10-26 415 | 416 | * Man page fixes. 417 | 418 | 0.2 2012-10-26 419 | 420 | * Include man page in distribution. 421 | 422 | 0.1 2012-10-25 423 | 424 | * Initial public release. 425 | -------------------------------------------------------------------------------- /README-BUILD.md: -------------------------------------------------------------------------------- 1 | # Build procenv 2 | 3 | ## Build from source 4 | 5 | 1. Install dependencies 6 | 7 | | Platform | Usage | Required? | Dependency | Rationale | 8 | |-|-|-|-|-| 9 | | common | build | yes | GCC or Clang compiler | For building the code | 10 | | common | build | yes | GNU Autoconf | For configuring the source package | 11 | | common | build | yes | GNU Autoconf Archive | For configuring the source package | 12 | | common | build | yes | GNU Automake | For generating makefiles | 13 | | common | build | yes | GNU Make | For building the code | 14 | | common | build | yes | `pkgconf` / `pkg-config` | For configuring build dependencies | 15 | | common | test | optional | Check | For running unit tests | 16 | | common | test | optional | Expat | For validating XML output | 17 | | common | test | optional | GNU Groff | For checking man page documentation | 18 | | Linux | build | optional | `libapparmor` development package | For AppArmor details | 19 | | Linux | build | optional | `libcap` development package | For capabilities details | 20 | | Linux | build | optional | `libnuma` development package | For NUMA memory details | 21 | | Linux | build | optional | `libselinux` development package | For SELinux details | 22 | | BSD | build | optional | `libsysinfo` package or port | For general memory details | 23 | 24 | > **Note:** 25 | > 26 | > The definitive list of dependenciese can always be seen by looking at the GitHub Actions workflow file here: 27 | > 28 | > - [`.github/workflows/build.yaml`](.github/workflows/build.yaml) 29 | 30 | 1. Checkout the source code: 31 | 32 | ```bash 33 | $ git clone https://github.com/jamesodhunt/procenv 34 | $ cd procenv 35 | ``` 36 | 37 | 1. Configure and build: 38 | 39 | ```bash 40 | $ autoreconf -fi && ./configure 41 | $ make && make check && sudo make install 42 | ``` 43 | 44 | > **Note:** 45 | > 46 | > For BSD systems, replace `make` with `gmake` above to ensure you run using 47 | > GNU Make (BSD make will hang at the test stage!) 48 | 49 | ## Build snap package 50 | 51 | ```bash 52 | $ git clone https://github.com/jamesodhunt/procenv 53 | $ cd procenv 54 | $ snapcraft 55 | ``` 56 | 57 | ### Build on FreeBSD 58 | 59 | FreeBSD is awkward. This worked for me on FreeBSD 10.2: 60 | 61 | ```bash 62 | $ gmake CC=clang-devel LD=ld.gold LDFLAGS='-v -fuse-ld=gold' 63 | ``` 64 | 65 | ### Build on Minix 66 | 67 | Try this: 68 | 69 | ```bash 70 | $ ./configure CC=clang CFLAGS='-I/usr/pkg/include' LDFLAGS='-L/usr/pkg/lib' 71 | ``` 72 | -------------------------------------------------------------------------------- /README-DEVELOPER.md: -------------------------------------------------------------------------------- 1 | # procenv developer details 2 | 3 | > **Note:** 4 | > 5 | > This document assumes you have already read the 6 | > [build document](README-BUILD.md). 7 | 8 | ## Debug with gdb or lldb 9 | 10 | To disable optimisations when building `procenv`, configure by specifying 11 | the `--disable-compiler-optimisations` configure option (which sets the 12 | `-O0` compiler option): 13 | 14 | ```bash 15 | $ /configure --disable-compiler-optimisations 16 | $ make 17 | $ gdb src/procenv 18 | ``` 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GPLv3 license](https://img.shields.io/badge/License-GPLv3-blue.svg)](http://perso.crans.org/besson/LICENSE.html) 2 | [![Build Status](https://travis-ci.org/jamesodhunt/procenv.svg?branch=master)](https://travis-ci.org/jamesodhunt/procenv) 3 | [![Coverity](https://img.shields.io/coverity/scan/jamesodhunt-procenv)](https://scan.coverity.com/projects/jamesodhunt-procenv) 4 | [![Flattr](https://img.shields.io/badge/donate-flattr-blue.svg)](https://flattr.com/profile/jamesodhunt) 5 | [![PayPal](https://img.shields.io/badge/paypal-donate-blue.svg)](https://www.paypal.me/jamesodhunt) 6 | 7 | # `procenv` 8 | 9 | ## Demo 10 | 11 | [![demo](https://asciinema.org/a/118278.svg)](https://asciinema.org/a/118278?autoplay=1) 12 | 13 | ## Overview 14 | 15 | `procenv` is a simple command-line utility, written in C and licensed 16 | under the GPL, that dumps all attributes of the environment in which it 17 | runs, in well-structured plain ASCII, JSON (YAML), XML or CSV. 18 | 19 | > **Note:** 20 | > 21 | > If you find anything missing from the `procenv` output, please either raise 22 | > an issue or send a patch :) 23 | 24 | ## Why? 25 | 26 | When you first read what this tool does, you tend to think, _"Huh?"_, 27 | or _"Why would anyone want a tool like that?"_ or _"How is that useful?"_ 28 | 29 | Here are a few examples to help explain. `procenv` can help... 30 | 31 | - To learn about the Unix/Linux environment 32 | 33 | For example, compare these output files: 34 | 35 | ```bash 36 | $ procenv > /tmp/1 37 | $ sudo procenv > /tmp/2 38 | $ nohup procenv >/tmp/3 & 39 | ``` 40 | 41 | - To debug weird CI failures 42 | 43 | Even scratched your head wondering why your code works perfectly on your 44 | local machine, but explodes in flames in your CI system? 45 | 46 | Maybe you've had to hack your build to run a bunch of shell commands like 47 | the following to help your debug wtf is going wrong?: 48 | 49 | ```bash 50 | echo "INFO: environment variables" 51 | env 52 | 53 | echo "INFO: mounts" 54 | mount 55 | 56 | echo "INFO: time" 57 | date 58 | 59 | echo "INFO: umask" 60 | umask 61 | 62 | echo "INFO: locale" 63 | locale 64 | ``` 65 | 66 | Look familiar? There is a simpler way: just run `procenv` in your CI, run 67 | it locally and `diff(1)` the output! 68 | 69 | - To compare build environments 70 | 71 | When you run `make check` as part of the `procenv` build, the `procenv` 72 | binary runs. This is useful because if you can access the build logs for a 73 | particular build system, you can see the environment _of_ that build system 74 | by looking at the procenv logs. 75 | 76 | > **Note:** See the [results](#results) section for links to some common 77 | > build environments. 78 | 79 | - To compare systems 80 | 81 | More generally, just run procenv on two systems and `diff(1)` the output to 82 | see what's different (different O/S versions, different distro versions, 83 | different Unix variants). 84 | 85 | - To learn about the packaging environment: 86 | 87 | These commands show interesting details of compiler and libc used to build 88 | the package: 89 | 90 | ```bash 91 | $ procenv --compiler 92 | $ procenv --libc 93 | ``` 94 | 95 | - To see what changes for a process on each run 96 | 97 | Every new process creates gets a new process ID. But what else changes? 98 | 99 | ```bash 100 | $ diff <(procenv) <(procenv) 101 | ``` 102 | 103 | ### Party trick 104 | 105 | Since `procenv` can re-exec itself, you can do sneaky things like run 106 | `procenv` _before_ the init daemon runs on your system! But wait, init systems 107 | like `systemd` run as PID 1 I hear you cry! Correct, but using a command like 108 | the following, you can run procenv as PID 1, which will dump it's output and 109 | then launch `systemd` as the _same_ PID and boot the system as normal! 110 | 111 | ```grub 112 | init=/usr/bin/procenv PROCENV_FILE=/dev/ttyS0 PROCENV_EXEC="/sbin/init --foo-bar --baz" 113 | ``` 114 | 115 | > **Note:** Further details about this and more examples are listed in the 116 | > manual page, `procenv(1)`. 117 | 118 | ## Platforms 119 | 120 | `procenv` runs on the following operating systems: 121 | 122 | - Android 123 | - *BSD 124 | - [FreeBSD](#freebsd) 125 | - GNU Hurd 126 | - GNU Linux 127 | - macOS 128 | - [Minix 3](#minix) 129 | 130 | It unashamedly emulates a number of existing system utilities as it is 131 | attempting to be all-encompassing: I wrote it with the aim of being able to 132 | dump "everything" that a process may care about by simply running a single 133 | program (by default). Also, the line of demarcation between "process", 134 | "program" and "system" is slightly blurry in some aspects. For example 135 | `sysconf(3)` variables could arguably be considered system attributes, but 136 | `procenv` shows these too since they are obviously meant to be queryable by 137 | applications. 138 | 139 | ## Build 140 | 141 | For instructions on building from source, see also the 142 | [build document](README-BUILD.md). 143 | 144 | ## Developer documentation 145 | 146 | See the [developer document](README-DEVELOPER.md). 147 | 148 | ## Install 149 | 150 | ### Snap 151 | 152 | [![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/procenv) 153 | 154 | To install the [snap package](https://snapcraft.io/procenv): 155 | 156 | ```bash 157 | $ sudo snap install procenv 158 | ``` 159 | 160 | > **Note:** Alternatively, you can [build your own snap](#build-snap-package). 161 | 162 | ### CentOS 163 | 164 | - Enable EPEL repository. 165 | - Install: 166 | 167 | ```bash 168 | $ sudo dnf -y install procenv 169 | ``` 170 | 171 | ### Debian and Ubuntu 172 | 173 | ```bash 174 | $ sudo apt -y install procenv 175 | ``` 176 | 177 | ### Fedora 178 | 179 | ```bash 180 | $ sudo dnf -y install procenv 181 | ``` 182 | 183 | ### FreeBSD 184 | 185 | To install the binary package: 186 | 187 | ```bash 188 | $ sudo pkg -y install procenv 189 | ``` 190 | 191 | To install the port: 192 | 193 | ```bash 194 | $ cd /usr/ports/sysutils/procenv 195 | $ sudo make install clean 196 | ``` 197 | 198 | > **Note:** See also the [build document](README-BUILD.md). 199 | 200 | ### Minix 201 | 202 | See also the [build document](README-BUILD.md). 203 | 204 | ### Gentoo 205 | 206 | ```bash 207 | $ sudo emerge sys-process/procenv 208 | ``` 209 | 210 | ### macOS 211 | 212 | Install via [MacPorts](https://ports.macports.org/port/procenv/summary): 213 | 214 | ```bash 215 | $ sudo port install procenv 216 | ``` 217 | 218 | ### SUSE 219 | 220 | ```bash 221 | $ sudo zypper install -y procenv 222 | ``` 223 | 224 | ## Results 225 | 226 | `procenv` is extremely useful for learning about the environment 227 | software builds in. Often, such systems disallow login, but do allow 228 | access to log files. Handily, when you build `procenv`, it runs a battery of 229 | tests and *also runs itself*. This means that the build environment gets 230 | captured in the build logs themselves. 231 | 232 | Select a link below and drill down to the build log to see the `procenv` 233 | output: 234 | 235 | ### Debian build environment 236 | 237 | #### `buildd` environment 238 | 239 | - https://buildd.debian.org/status/package.php?p=procenv&suite=sid 240 | 241 | #### Debian `autopkgtest` (DEP-8) environment 242 | 243 | - https://ci.debian.net/packages/p/procenv/ 244 | 245 | ### Fedora build environment 246 | 247 | - https://src.fedoraproject.org/rpms/procenv/ 248 | 249 | ### Gentoo build environment 250 | 251 | - https://packages.gentoo.org/packages/sys-process/procenv 252 | 253 | ### MacPorts build environment 254 | 255 | - https://ports.macports.org/port/procenv/ 256 | 257 | ### Open Build Service (OBS) build environment 258 | 259 | - https://build.opensuse.org/package/show/home:jamesodhunt:procenv/procenv 260 | 261 | If you distro does not yet provide a `procenv` package, binary 262 | packages for RHEL, Fedora, CentOS, SLES, and Arch Linux are available 263 | from here: 264 | 265 | - https://software.opensuse.org/download.html?project=home%3Ajamesodhunt%3Aprocenv&package=procenv 266 | 267 | Click on your icon for your distro and follow the instructions. 268 | 269 | Note that these packages are "bleeding edge" (generated directly from the GitHub repository). 270 | 271 | ### Semaphore-CI build environment 272 | 273 | - https://semaphoreci.com/jamesodhunt/procenv 274 | (Click "Passed", "Job #", then "`make check`" to see output). 275 | 276 | ### Travis-CI build environment 277 | 278 | - https://travis-ci.org/jamesodhunt/procenv 279 | 280 | ### Ubuntu build environment 281 | 282 | - https://launchpad.net/ubuntu/+source/procenv 283 | 284 | ## Porting 285 | 286 | Can you help port `procenv` to other platforms (AIX, HP-UX, Solaris, ...), or 287 | can you give me access to new platforms? If so, please get in contact or take 288 | a look at the [porting document](src/platform). 289 | 290 | ## References 291 | 292 | See http://ifdeflinux.blogspot.com/2012/10/procenv-and-process-environment.html 293 | 294 | ## Author 295 | 296 | `procenv` was written by James Hunt . 297 | 298 | ## Home Page 299 | 300 | - https://github.com/jamesodhunt/procenv 301 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | - Audit `die()` calls. 4 | - Consider changing `UNKNOWN_STR` to show `errno` value (such as `unknown(EPERM)`). 5 | - merge --clocks into --time. 6 | - call clock_getime() for all clock types and show time in 3 formats for each! 7 | - debian license file has incorrect email address. 8 | 9 | - pstring tests. 10 | - add /proc/cmdline? 11 | - could create a kernel category?: 12 | kernel: 13 | version: 14 | headers version: 3.19.8 15 | bits: 64 16 | cmdline: ... 17 | 18 | - XXX: Sort *all* output values. 19 | - sort network interfaces. 20 | - Sort output of show_mounts(). 21 | - add tests to ensure they remain sorted. 22 | 23 | - "--path" ? which shows: 24 | 25 | path: 26 | _POSIX_PATH_MAX: 256 (absolute) 27 | PATH_MAX: 4096 (relative) 28 | MAXPATHLEN: 4096 29 | - LSM 30 | - add details for SMACK and TOMOYO (available in Centos 7). 31 | - move into a new --security section? 32 | - FreeBSD: 33 | - MAC: mac_get_file(3), mac(3,4) 34 | - --stat: 35 | - move current stat details into a stat/self section. 36 | - add stat details for stat/root. 37 | - --cpu: 38 | - change 'number' to 'index' and make it zero-based for consistency 39 | with affinity list 40 | - XXX: bump 'format-version' !! 41 | - Add YAML output format? 42 | - Introduce "value()" that can take a bare value. This will allow for 43 | example mount options to be displayed in an output container. 44 | - Non-root queryable hdd attributes? 45 | - Hurd: 46 | - establish how to determine process ancestry. 47 | - Create a versioned XML schema. 48 | - Restructure code into separate files. 49 | - Use weak symbols/VPATH to avoid ifdefs! 50 | - Display numeric values for all symbols?: 51 | - limits (RLIMIT_AS) 52 | - clocks (CLOCK_REALTIME) 53 | - pathconf (_PC_LINK_MAX) 54 | - sysconf (ARG_MAX) 55 | XXX: must be consistent with existing signals (SIGHUP, etc)!! 56 | - BUG: all numbers are displayed as strings in json output. 57 | - Add in ability to specify a platform restriction for certain details by modifying 58 | section_open() and container_open() to accept string pairs like: 59 | 60 | container_open (const char *name, int count, ...); 61 | | 62 | V 63 | container_open (const char *name, 2, "restriction", "linux"); 64 | - Networking details 65 | - IPv6 scope_id. 66 | - gateway. 67 | - add to show_sizeof(): 68 | - intN_t group 69 | - I18N (gettext) 70 | - Don't hide any option that a particular O/S / arch doesn't 71 | have: show the option with a value of `UNKNOWN_STR'. 72 | - Rework output code to use a cleaner stack-based approach. 73 | - Uptime (using utmp)? 74 | - Text/data/bss/stack details (end(3), sbrk(2)) 75 | - mincore(2)? 76 | - Add process arguments to show_proc_branch()? 77 | - Use CPUID instruction to detect XEN environments? 78 | (http://libcpuid.sourceforge.net/, http://www.etallen.com/cpuid.html) 79 | - Use dlopen to probe for apparmor/selinux. This avoids having to depend 80 | on the existence of the appropriate libs, but still allows security 81 | context information to be queried on systems that provide them. 82 | - ELF details. 83 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the 'clock_gettime' function. */ 4 | #undef HAVE_CLOCK_GETTIME 5 | 6 | /* Define to 1 if you have the 'cpuset_alloc' function. */ 7 | #undef HAVE_CPUSET_ALLOC 8 | 9 | /* Define to 1 if you have the 'getcwd' function. */ 10 | #undef HAVE_GETCWD 11 | 12 | /* Define to 1 if you have the 'getresgid' function. */ 13 | #undef HAVE_GETRESGID 14 | 15 | /* Define to 1 if you have the 'getresuid' function. */ 16 | #undef HAVE_GETRESUID 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_INTTYPES_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_LINUX_SECUREBITS_H 23 | 24 | /* Define to 1 if you have the 'localtime_r' function. */ 25 | #undef HAVE_LOCALTIME_R 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_MINIX_CONFIG_H 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_NUMA_H 32 | 33 | /* Define to 1 if you have the header file. */ 34 | #undef HAVE_PTHREAD_H 35 | 36 | /* Define to 1 if you have the 'sched_getcpu' function. */ 37 | #undef HAVE_SCHED_GETCPU 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #undef HAVE_SELINUX_SELINUX_H 41 | 42 | /* Define to 1 if stdbool.h conforms to C99. */ 43 | #undef HAVE_STDBOOL_H 44 | 45 | /* Define to 1 if you have the header file. */ 46 | #undef HAVE_STDINT_H 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #undef HAVE_STDIO_H 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #undef HAVE_STDLIB_H 53 | 54 | /* Define to 1 if you have the 'strcasecmp' function. */ 55 | #undef HAVE_STRCASECMP 56 | 57 | /* Define to 1 if you have the 'strchr' function. */ 58 | #undef HAVE_STRCHR 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #undef HAVE_STRINGS_H 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #undef HAVE_STRING_H 65 | 66 | /* Define to 1 if you have the 'strstr' function. */ 67 | #undef HAVE_STRSTR 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_SYS_APPARMOR_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_SYS_CAPABILITY_H 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_SYS_CAPSICUM_H 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_SYS_STAT_H 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #undef HAVE_SYS_TYPES_H 83 | 84 | /* Define to 1 if you have the 'ttyname' function. */ 85 | #undef HAVE_TTYNAME 86 | 87 | /* Define to 1 if you have the header file. */ 88 | #undef HAVE_UNISTD_H 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #undef HAVE_WCHAR_H 92 | 93 | /* Define to 1 if the system has the type '_Bool'. */ 94 | #undef HAVE__BOOL 95 | 96 | /* Name of package */ 97 | #undef PACKAGE 98 | 99 | /* Define to the address where bug reports for this package should be sent. */ 100 | #undef PACKAGE_BUGREPORT 101 | 102 | /* Define to the full name of this package. */ 103 | #undef PACKAGE_NAME 104 | 105 | /* Define to the full name and version of this package. */ 106 | #undef PACKAGE_STRING 107 | 108 | /* Define to the one symbol short name of this package. */ 109 | #undef PACKAGE_TARNAME 110 | 111 | /* Define to the home page for this package. */ 112 | #undef PACKAGE_URL 113 | 114 | /* Define to the version of this package. */ 115 | #undef PACKAGE_VERSION 116 | 117 | /* Generate a reproducible build */ 118 | #undef PROCENV_REPRODUCIBLE_BUILD 119 | 120 | /* Define to 1 if all of the C89 standard headers exist (not just the ones 121 | required in a freestanding environment). This macro is provided for 122 | backward compatibility; new code need not use it. */ 123 | #undef STDC_HEADERS 124 | 125 | /* Enable extensions on AIX, Interix, z/OS. */ 126 | #ifndef _ALL_SOURCE 127 | # undef _ALL_SOURCE 128 | #endif 129 | /* Enable general extensions on macOS. */ 130 | #ifndef _DARWIN_C_SOURCE 131 | # undef _DARWIN_C_SOURCE 132 | #endif 133 | /* Enable general extensions on Solaris. */ 134 | #ifndef __EXTENSIONS__ 135 | # undef __EXTENSIONS__ 136 | #endif 137 | /* Enable GNU extensions on systems that have them. */ 138 | #ifndef _GNU_SOURCE 139 | # undef _GNU_SOURCE 140 | #endif 141 | /* Enable X/Open compliant socket functions that do not require linking 142 | with -lxnet on HP-UX 11.11. */ 143 | #ifndef _HPUX_ALT_XOPEN_SOCKET_API 144 | # undef _HPUX_ALT_XOPEN_SOCKET_API 145 | #endif 146 | /* Identify the host operating system as Minix. 147 | This macro does not affect the system headers' behavior. 148 | A future release of Autoconf may stop defining this macro. */ 149 | #ifndef _MINIX 150 | # undef _MINIX 151 | #endif 152 | /* Enable general extensions on NetBSD. 153 | Enable NetBSD compatibility extensions on Minix. */ 154 | #ifndef _NETBSD_SOURCE 155 | # undef _NETBSD_SOURCE 156 | #endif 157 | /* Enable OpenBSD compatibility extensions on NetBSD. 158 | Oddly enough, this does nothing on OpenBSD. */ 159 | #ifndef _OPENBSD_SOURCE 160 | # undef _OPENBSD_SOURCE 161 | #endif 162 | /* Define to 1 if needed for POSIX-compatible behavior. */ 163 | #ifndef _POSIX_SOURCE 164 | # undef _POSIX_SOURCE 165 | #endif 166 | /* Define to 2 if needed for POSIX-compatible behavior. */ 167 | #ifndef _POSIX_1_SOURCE 168 | # undef _POSIX_1_SOURCE 169 | #endif 170 | /* Enable POSIX-compatible threading on Solaris. */ 171 | #ifndef _POSIX_PTHREAD_SEMANTICS 172 | # undef _POSIX_PTHREAD_SEMANTICS 173 | #endif 174 | /* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ 175 | #ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 176 | # undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 177 | #endif 178 | /* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ 179 | #ifndef __STDC_WANT_IEC_60559_BFP_EXT__ 180 | # undef __STDC_WANT_IEC_60559_BFP_EXT__ 181 | #endif 182 | /* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ 183 | #ifndef __STDC_WANT_IEC_60559_DFP_EXT__ 184 | # undef __STDC_WANT_IEC_60559_DFP_EXT__ 185 | #endif 186 | /* Enable extensions specified by C23 Annex F. */ 187 | #ifndef __STDC_WANT_IEC_60559_EXT__ 188 | # undef __STDC_WANT_IEC_60559_EXT__ 189 | #endif 190 | /* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ 191 | #ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ 192 | # undef __STDC_WANT_IEC_60559_FUNCS_EXT__ 193 | #endif 194 | /* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */ 195 | #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ 196 | # undef __STDC_WANT_IEC_60559_TYPES_EXT__ 197 | #endif 198 | /* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ 199 | #ifndef __STDC_WANT_LIB_EXT2__ 200 | # undef __STDC_WANT_LIB_EXT2__ 201 | #endif 202 | /* Enable extensions specified by ISO/IEC 24747:2009. */ 203 | #ifndef __STDC_WANT_MATH_SPEC_FUNCS__ 204 | # undef __STDC_WANT_MATH_SPEC_FUNCS__ 205 | #endif 206 | /* Enable extensions on HP NonStop. */ 207 | #ifndef _TANDEM_SOURCE 208 | # undef _TANDEM_SOURCE 209 | #endif 210 | /* Enable X/Open extensions. Define to 500 only if necessary 211 | to make mbstate_t available. */ 212 | #ifndef _XOPEN_SOURCE 213 | # undef _XOPEN_SOURCE 214 | #endif 215 | 216 | 217 | /* Version number of package */ 218 | #undef VERSION 219 | 220 | /* Number of bits in a file offset, on hosts where this is settable. */ 221 | #undef _FILE_OFFSET_BITS 222 | 223 | /* Define to 1 on platforms where this makes off_t a 64-bit type. */ 224 | #undef _LARGE_FILES 225 | 226 | /* Number of bits in time_t, on hosts where this is settable. */ 227 | #undef _TIME_BITS 228 | 229 | /* Define to 1 on platforms where this makes time_t a 64-bit type. */ 230 | #undef __MINGW_USE_VC2005_COMPAT 231 | -------------------------------------------------------------------------------- /config/compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2018-03-07.03; # UTC 5 | 6 | # Copyright (C) 1999-2021 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # This file is maintained in Automake, please report 28 | # bugs to or send patches to 29 | # . 30 | 31 | nl=' 32 | ' 33 | 34 | # We need space, tab and new line, in precisely that order. Quoting is 35 | # there to prevent tools from complaining about whitespace usage. 36 | IFS=" "" $nl" 37 | 38 | file_conv= 39 | 40 | # func_file_conv build_file lazy 41 | # Convert a $build file to $host form and store it in $file 42 | # Currently only supports Windows hosts. If the determined conversion 43 | # type is listed in (the comma separated) LAZY, no conversion will 44 | # take place. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN* | MSYS*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv/,$2, in 65 | *,$file_conv,*) 66 | ;; 67 | mingw/*) 68 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 69 | ;; 70 | cygwin/* | msys/*) 71 | file=`cygpath -m "$file" || echo "$file"` 72 | ;; 73 | wine/*) 74 | file=`winepath -w "$file" || echo "$file"` 75 | ;; 76 | esac 77 | ;; 78 | esac 79 | } 80 | 81 | # func_cl_dashL linkdir 82 | # Make cl look for libraries in LINKDIR 83 | func_cl_dashL () 84 | { 85 | func_file_conv "$1" 86 | if test -z "$lib_path"; then 87 | lib_path=$file 88 | else 89 | lib_path="$lib_path;$file" 90 | fi 91 | linker_opts="$linker_opts -LIBPATH:$file" 92 | } 93 | 94 | # func_cl_dashl library 95 | # Do a library search-path lookup for cl 96 | func_cl_dashl () 97 | { 98 | lib=$1 99 | found=no 100 | save_IFS=$IFS 101 | IFS=';' 102 | for dir in $lib_path $LIB 103 | do 104 | IFS=$save_IFS 105 | if $shared && test -f "$dir/$lib.dll.lib"; then 106 | found=yes 107 | lib=$dir/$lib.dll.lib 108 | break 109 | fi 110 | if test -f "$dir/$lib.lib"; then 111 | found=yes 112 | lib=$dir/$lib.lib 113 | break 114 | fi 115 | if test -f "$dir/lib$lib.a"; then 116 | found=yes 117 | lib=$dir/lib$lib.a 118 | break 119 | fi 120 | done 121 | IFS=$save_IFS 122 | 123 | if test "$found" != yes; then 124 | lib=$lib.lib 125 | fi 126 | } 127 | 128 | # func_cl_wrapper cl arg... 129 | # Adjust compile command to suit cl 130 | func_cl_wrapper () 131 | { 132 | # Assume a capable shell 133 | lib_path= 134 | shared=: 135 | linker_opts= 136 | for arg 137 | do 138 | if test -n "$eat"; then 139 | eat= 140 | else 141 | case $1 in 142 | -o) 143 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 144 | eat=1 145 | case $2 in 146 | *.o | *.[oO][bB][jJ]) 147 | func_file_conv "$2" 148 | set x "$@" -Fo"$file" 149 | shift 150 | ;; 151 | *) 152 | func_file_conv "$2" 153 | set x "$@" -Fe"$file" 154 | shift 155 | ;; 156 | esac 157 | ;; 158 | -I) 159 | eat=1 160 | func_file_conv "$2" mingw 161 | set x "$@" -I"$file" 162 | shift 163 | ;; 164 | -I*) 165 | func_file_conv "${1#-I}" mingw 166 | set x "$@" -I"$file" 167 | shift 168 | ;; 169 | -l) 170 | eat=1 171 | func_cl_dashl "$2" 172 | set x "$@" "$lib" 173 | shift 174 | ;; 175 | -l*) 176 | func_cl_dashl "${1#-l}" 177 | set x "$@" "$lib" 178 | shift 179 | ;; 180 | -L) 181 | eat=1 182 | func_cl_dashL "$2" 183 | ;; 184 | -L*) 185 | func_cl_dashL "${1#-L}" 186 | ;; 187 | -static) 188 | shared=false 189 | ;; 190 | -Wl,*) 191 | arg=${1#-Wl,} 192 | save_ifs="$IFS"; IFS=',' 193 | for flag in $arg; do 194 | IFS="$save_ifs" 195 | linker_opts="$linker_opts $flag" 196 | done 197 | IFS="$save_ifs" 198 | ;; 199 | -Xlinker) 200 | eat=1 201 | linker_opts="$linker_opts $2" 202 | ;; 203 | -*) 204 | set x "$@" "$1" 205 | shift 206 | ;; 207 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 208 | func_file_conv "$1" 209 | set x "$@" -Tp"$file" 210 | shift 211 | ;; 212 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 213 | func_file_conv "$1" mingw 214 | set x "$@" "$file" 215 | shift 216 | ;; 217 | *) 218 | set x "$@" "$1" 219 | shift 220 | ;; 221 | esac 222 | fi 223 | shift 224 | done 225 | if test -n "$linker_opts"; then 226 | linker_opts="-link$linker_opts" 227 | fi 228 | exec "$@" $linker_opts 229 | exit 1 230 | } 231 | 232 | eat= 233 | 234 | case $1 in 235 | '') 236 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 237 | exit 1; 238 | ;; 239 | -h | --h*) 240 | cat <<\EOF 241 | Usage: compile [--help] [--version] PROGRAM [ARGS] 242 | 243 | Wrapper for compilers which do not understand '-c -o'. 244 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 245 | arguments, and rename the output as expected. 246 | 247 | If you are trying to build a whole package this is not the 248 | right script to run: please start by reading the file 'INSTALL'. 249 | 250 | Report bugs to . 251 | EOF 252 | exit $? 253 | ;; 254 | -v | --v*) 255 | echo "compile $scriptversion" 256 | exit $? 257 | ;; 258 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ 259 | icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) 260 | func_cl_wrapper "$@" # Doesn't return... 261 | ;; 262 | esac 263 | 264 | ofile= 265 | cfile= 266 | 267 | for arg 268 | do 269 | if test -n "$eat"; then 270 | eat= 271 | else 272 | case $1 in 273 | -o) 274 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 275 | # So we strip '-o arg' only if arg is an object. 276 | eat=1 277 | case $2 in 278 | *.o | *.obj) 279 | ofile=$2 280 | ;; 281 | *) 282 | set x "$@" -o "$2" 283 | shift 284 | ;; 285 | esac 286 | ;; 287 | *.c) 288 | cfile=$1 289 | set x "$@" "$1" 290 | shift 291 | ;; 292 | *) 293 | set x "$@" "$1" 294 | shift 295 | ;; 296 | esac 297 | fi 298 | shift 299 | done 300 | 301 | if test -z "$ofile" || test -z "$cfile"; then 302 | # If no '-o' option was seen then we might have been invoked from a 303 | # pattern rule where we don't need one. That is ok -- this is a 304 | # normal compilation that the losing compiler can handle. If no 305 | # '.c' file was seen then we are probably linking. That is also 306 | # ok. 307 | exec "$@" 308 | fi 309 | 310 | # Name of file we expect compiler to create. 311 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 312 | 313 | # Create the lock directory. 314 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 315 | # that we are using for the .o file. Also, base the name on the expected 316 | # object file name, since that is what matters with a parallel build. 317 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 318 | while true; do 319 | if mkdir "$lockdir" >/dev/null 2>&1; then 320 | break 321 | fi 322 | sleep 1 323 | done 324 | # FIXME: race condition here if user kills between mkdir and trap. 325 | trap "rmdir '$lockdir'; exit 1" 1 2 15 326 | 327 | # Run the compile. 328 | "$@" 329 | ret=$? 330 | 331 | if test -f "$cofile"; then 332 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 333 | elif test -f "${cofile}bj"; then 334 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 335 | fi 336 | 337 | rmdir "$lockdir" 338 | exit $ret 339 | 340 | # Local Variables: 341 | # mode: shell-script 342 | # sh-indentation: 2 343 | # eval: (add-hook 'before-save-hook 'time-stamp) 344 | # time-stamp-start: "scriptversion=" 345 | # time-stamp-format: "%:y-%02m-%02d.%02H" 346 | # time-stamp-time-zone: "UTC0" 347 | # time-stamp-end: "; # UTC" 348 | # End: 349 | -------------------------------------------------------------------------------- /config/missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common wrapper for a few potentially missing GNU programs. 3 | 4 | scriptversion=2018-03-07.03; # UTC 5 | 6 | # Copyright (C) 1996-2021 Free Software Foundation, Inc. 7 | # Originally written by Fran,cois Pinard , 1996. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | if test $# -eq 0; then 28 | echo 1>&2 "Try '$0 --help' for more information" 29 | exit 1 30 | fi 31 | 32 | case $1 in 33 | 34 | --is-lightweight) 35 | # Used by our autoconf macros to check whether the available missing 36 | # script is modern enough. 37 | exit 0 38 | ;; 39 | 40 | --run) 41 | # Back-compat with the calling convention used by older automake. 42 | shift 43 | ;; 44 | 45 | -h|--h|--he|--hel|--help) 46 | echo "\ 47 | $0 [OPTION]... PROGRAM [ARGUMENT]... 48 | 49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due 50 | to PROGRAM being missing or too old. 51 | 52 | Options: 53 | -h, --help display this help and exit 54 | -v, --version output version information and exit 55 | 56 | Supported PROGRAM values: 57 | aclocal autoconf autoheader autom4te automake makeinfo 58 | bison yacc flex lex help2man 59 | 60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 61 | 'g' are ignored when checking the name. 62 | 63 | Send bug reports to ." 64 | exit $? 65 | ;; 66 | 67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 68 | echo "missing $scriptversion (GNU Automake)" 69 | exit $? 70 | ;; 71 | 72 | -*) 73 | echo 1>&2 "$0: unknown '$1' option" 74 | echo 1>&2 "Try '$0 --help' for more information" 75 | exit 1 76 | ;; 77 | 78 | esac 79 | 80 | # Run the given program, remember its exit status. 81 | "$@"; st=$? 82 | 83 | # If it succeeded, we are done. 84 | test $st -eq 0 && exit 0 85 | 86 | # Also exit now if we it failed (or wasn't found), and '--version' was 87 | # passed; such an option is passed most likely to detect whether the 88 | # program is present and works. 89 | case $2 in --version|--help) exit $st;; esac 90 | 91 | # Exit code 63 means version mismatch. This often happens when the user 92 | # tries to use an ancient version of a tool on a file that requires a 93 | # minimum version. 94 | if test $st -eq 63; then 95 | msg="probably too old" 96 | elif test $st -eq 127; then 97 | # Program was missing. 98 | msg="missing on your system" 99 | else 100 | # Program was found and executed, but failed. Give up. 101 | exit $st 102 | fi 103 | 104 | perl_URL=https://www.perl.org/ 105 | flex_URL=https://github.com/westes/flex 106 | gnu_software_URL=https://www.gnu.org/software 107 | 108 | program_details () 109 | { 110 | case $1 in 111 | aclocal|automake) 112 | echo "The '$1' program is part of the GNU Automake package:" 113 | echo "<$gnu_software_URL/automake>" 114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" 115 | echo "<$gnu_software_URL/autoconf>" 116 | echo "<$gnu_software_URL/m4/>" 117 | echo "<$perl_URL>" 118 | ;; 119 | autoconf|autom4te|autoheader) 120 | echo "The '$1' program is part of the GNU Autoconf package:" 121 | echo "<$gnu_software_URL/autoconf/>" 122 | echo "It also requires GNU m4 and Perl in order to run:" 123 | echo "<$gnu_software_URL/m4/>" 124 | echo "<$perl_URL>" 125 | ;; 126 | esac 127 | } 128 | 129 | give_advice () 130 | { 131 | # Normalize program name to check for. 132 | normalized_program=`echo "$1" | sed ' 133 | s/^gnu-//; t 134 | s/^gnu//; t 135 | s/^g//; t'` 136 | 137 | printf '%s\n' "'$1' is $msg." 138 | 139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" 140 | case $normalized_program in 141 | autoconf*) 142 | echo "You should only need it if you modified 'configure.ac'," 143 | echo "or m4 files included by it." 144 | program_details 'autoconf' 145 | ;; 146 | autoheader*) 147 | echo "You should only need it if you modified 'acconfig.h' or" 148 | echo "$configure_deps." 149 | program_details 'autoheader' 150 | ;; 151 | automake*) 152 | echo "You should only need it if you modified 'Makefile.am' or" 153 | echo "$configure_deps." 154 | program_details 'automake' 155 | ;; 156 | aclocal*) 157 | echo "You should only need it if you modified 'acinclude.m4' or" 158 | echo "$configure_deps." 159 | program_details 'aclocal' 160 | ;; 161 | autom4te*) 162 | echo "You might have modified some maintainer files that require" 163 | echo "the 'autom4te' program to be rebuilt." 164 | program_details 'autom4te' 165 | ;; 166 | bison*|yacc*) 167 | echo "You should only need it if you modified a '.y' file." 168 | echo "You may want to install the GNU Bison package:" 169 | echo "<$gnu_software_URL/bison/>" 170 | ;; 171 | lex*|flex*) 172 | echo "You should only need it if you modified a '.l' file." 173 | echo "You may want to install the Fast Lexical Analyzer package:" 174 | echo "<$flex_URL>" 175 | ;; 176 | help2man*) 177 | echo "You should only need it if you modified a dependency" \ 178 | "of a man page." 179 | echo "You may want to install the GNU Help2man package:" 180 | echo "<$gnu_software_URL/help2man/>" 181 | ;; 182 | makeinfo*) 183 | echo "You should only need it if you modified a '.texi' file, or" 184 | echo "any other file indirectly affecting the aspect of the manual." 185 | echo "You might want to install the Texinfo package:" 186 | echo "<$gnu_software_URL/texinfo/>" 187 | echo "The spurious makeinfo call might also be the consequence of" 188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" 189 | echo "want to install GNU make:" 190 | echo "<$gnu_software_URL/make/>" 191 | ;; 192 | *) 193 | echo "You might have modified some files without having the proper" 194 | echo "tools for further handling them. Check the 'README' file, it" 195 | echo "often tells you about the needed prerequisites for installing" 196 | echo "this package. You may also peek at any GNU archive site, in" 197 | echo "case some other package contains this missing '$1' program." 198 | ;; 199 | esac 200 | } 201 | 202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ 203 | -e '2,$s/^/ /' >&2 204 | 205 | # Propagate the correct exit status (expected to be 127 for a program 206 | # not found, 63 for a program that failed due to version mismatch). 207 | exit $st 208 | 209 | # Local variables: 210 | # eval: (add-hook 'before-save-hook 'time-stamp) 211 | # time-stamp-start: "scriptversion=" 212 | # time-stamp-format: "%:y-%02m-%02d.%02H" 213 | # time-stamp-time-zone: "UTC0" 214 | # time-stamp-end: "; # UTC" 215 | # End: 216 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------- 2 | # Copyright (c) 2012-2021 James O. D. Hunt . 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | #--------------------------------------------------------------------- 6 | 7 | # Process this file with autoconf to produce a configure script. 8 | 9 | m4_define([procenv_version], [0.60]) 10 | 11 | AC_INIT([procenv],[procenv_version],[jamesodhunt@gmail.com],[procenv],[https://github.com/jamesodhunt/procenv]) 12 | 13 | AC_COPYRIGHT([Copyright (C) 2012-2021 James Hunt and Kees Cook ]) 14 | 15 | AC_CONFIG_SRCDIR([src/procenv.c]) 16 | AC_CONFIG_MACRO_DIR([m4]) 17 | AC_CONFIG_HEADERS([config.h]) 18 | AC_CONFIG_AUX_DIR([config]) 19 | 20 | AC_SUBST(PROCENV_VERSION, procenv_version) 21 | 22 | AC_USE_SYSTEM_EXTENSIONS 23 | AC_SYS_LARGEFILE 24 | 25 | # expose $target 26 | AC_CANONICAL_TARGET 27 | 28 | #--------------------------------------------------------------------- 29 | # Checks for programs. 30 | AC_PROG_CC 31 | AC_PROG_INSTALL 32 | AM_PROG_CC_C_O 33 | 34 | PKG_PROG_PKG_CONFIG 35 | 36 | # Look for C unit test framework (http://check.sourceforge.net/). 37 | PKG_CHECK_MODULES([CHECK], [check], [HAVE_CHECK=yes], [HAVE_CHECK=no]) 38 | 39 | #--------------------------------------------------------------------- 40 | # Checks for header files. 41 | # this header is not available on older distributions (such as Ubuntu 42 | # Lucid) 43 | AC_CHECK_HEADERS([linux/securebits.h]) 44 | AC_CHECK_HEADERS(pthread.h,, [AC_MSG_ERROR([pthread.h required])]) 45 | 46 | #--------------------------------------------------------------------- 47 | # Checks for typedefs, structures, and compiler characteristics. 48 | AC_HEADER_STDBOOL 49 | 50 | # Checks for library functions. 51 | AC_CHECK_FUNCS([clock_gettime getcwd localtime_r strcasecmp strchr strstr sched_getcpu ttyname getresuid getresgid cpuset_alloc]) 52 | 53 | # BSD process inspection library 54 | AC_SEARCH_LIBS([kvm_openfiles], [kvm], 55 | [HAVE_KVM=yes], 56 | [HAVE_KVM=no]) 57 | 58 | AC_SEARCH_LIBS([sysinfo], [sysinfo], 59 | [HAVE_SYSINFO=yes], 60 | [HAVE_SYSINFO=no]) 61 | 62 | AC_SEARCH_LIBS([numa_available], [numa], 63 | [HAVE_NUMA=yes], 64 | [HAVE_NUMA=no]) 65 | AC_CHECK_HEADERS([numa.h]) 66 | 67 | # FreeBSD 9+ with appropriately configured kernel 68 | # (enabled by default in FreeBSD 10) 69 | AC_SEARCH_LIBS([cap_getmode], [c]) 70 | AC_CHECK_HEADERS([sys/capability.h sys/capsicum.h]) 71 | 72 | AC_SEARCH_LIBS([cap_init], [cap], 73 | [HAVE_LIBCAP=yes], 74 | [HAVE_LIBCAP=no]) 75 | 76 | AC_SEARCH_LIBS([pthread_create], [pthread], 77 | [HAVE_PTHREAD=yes], 78 | [HAVE_PTHREAD=no]) 79 | AC_SEARCH_LIBS([getpidcon], [selinux], 80 | [HAVE_SELINUX=yes], 81 | [HAVE_SELINUX=no]) 82 | AM_CONDITIONAL([HAVE_SELINUX], [test x$HAVE_SELINUX = xyes]) 83 | AC_CHECK_HEADERS([selinux/selinux.h]) 84 | 85 | AC_SEARCH_LIBS([aa_gettaskcon], [apparmor], 86 | [HAVE_APPARMOR=yes], 87 | [HAVE_APPARMOR=no]) 88 | 89 | AC_SEARCH_LIBS([clock_gettime], [rt], 90 | [HAVE_LIBRT=yes], 91 | [HAVE_LIBRT=no]) 92 | 93 | AM_CONDITIONAL([HAVE_APPARMOR], [test x$HAVE_APPARMOR = xyes]) 94 | AC_CHECK_HEADERS([sys/apparmor.h]) 95 | 96 | AC_ARG_ENABLE([tests], 97 | AS_HELP_STRING([--disable-tests], 98 | [Disable unit tests]), 99 | [enable_tests=no], [enable_tests=yes]) 100 | 101 | AM_CONDITIONAL([ENABLE_TESTS], test "$enable_tests" = yes) 102 | AM_CONDITIONAL([HAVE_CHECK], test "$HAVE_CHECK" = yes) 103 | AM_CONDITIONAL([PACKAGE_URL], test -n "$PACKAGE_URL") 104 | 105 | #--------------------------------------------------------------------- 106 | # Other checks 107 | 108 | # automake-1.13 defaults to running tests in parallel. As a consequence, 109 | # it also disables verbose output meaning that procenv output is not 110 | # visible in build logs. Therefore, force old behaviour by passing 111 | # 'serial-tests', but only for version of automake >= 1.13 since older 112 | # versions don't recognise that option. 113 | AM_INIT_AUTOMAKE(m4_esyscmd([ 114 | version=`automake --version|head -n 1|grep -o "[0-9][0-9]*\.[0-9][0-9]*"` 115 | major=`echo $version|cut -d\. -f1` 116 | minor=`echo $version|cut -d\. -f2` 117 | if [ "$major" = 1 -a "$minor" -ge 13 ]; then 118 | echo serial-tests 119 | elif [ "$major" -gt 1 ]; then 120 | echo serial-tests 121 | fi 122 | ])) 123 | 124 | # Check available compiler flags 125 | 126 | AX_CHECK_COMPILE_FLAG([-fstack-protector], [CFLAGS="$CFLAGS -fstack-protector"]) 127 | AX_CHECK_COMPILE_FLAG([-Wformat], [CFLAGS="$CFLAGS -Wformat"]) 128 | AX_CHECK_COMPILE_FLAG([-Wformat-security], [CFLAGS="$CFLAGS -Wformat-security"]) 129 | 130 | AC_ARG_ENABLE([compiler-optimisations], 131 | AS_HELP_STRING([--disable-compiler-optimisations], 132 | [Disable compiler optimisations]), 133 | [AS_IF([test "x$enable_compiler_optimisations" = "xno"], 134 | [[CFLAGS=`echo "$CFLAGS" | sed -e "s/ -O[1-9s]*\b/ -O0/g"` 135 | CXXFLAGS=`echo "$CXXFLAGS" | sed -e "s/ -O[1-9s]*\b/ -O0/g"`]])]) 136 | 137 | AC_ARG_ENABLE([linker-optimisations], 138 | AS_HELP_STRING([--disable-linker-optimisations], 139 | [Disable linker optimisations]), 140 | [AS_IF([test "x$enable_linker_optimisations" = "xno"], 141 | [LDFLAGS=`echo "$LDFLAGS" | sed -e "s/ -Wl,-O[0-9]*\b//g"`], 142 | [LDFLAGS="$LDFLAGS -Wl,-O1"])]) 143 | 144 | AC_ARG_ENABLE([debug], 145 | AS_HELP_STRING([--enable-debug], 146 | [enable developer build]), 147 | [AS_IF([test "x$enable_debug" = "xyes"], 148 | [[CFLAGS=`echo "$CFLAGS -DDEBUG -pg"` 149 | CXXFLAGS=`echo "$CXXFLAGS -DDEBUG -pg"` 150 | DEBUG_BUILD=yes]])], [DEBUG_BUILD=no]) 151 | 152 | AC_ARG_ENABLE([reproducible_build], 153 | AS_HELP_STRING([--enable-reproducible-build], 154 | [Disable display of build-time values that are guaranteed to differ between builds]), 155 | [reproducible_build=yes], [reproducible_build=no]) 156 | 157 | if test "$reproducible_build" = yes; then 158 | AC_DEFINE([PROCENV_REPRODUCIBLE_BUILD], [1], [Generate a reproducible build]) 159 | fi 160 | 161 | AC_ARG_WITH([forced_driver], 162 | AS_HELP_STRING([--with-forced-driver=...], 163 | [Used to force a particular platform driver. Warning: These aren't the droids you're looking for...])) 164 | 165 | target_to_consider="$target" 166 | 167 | AS_IF([test "x$with_forced_driver" != "x"], [ 168 | target_to_consider="$withval" 169 | ]) 170 | 171 | #--------------------------------------------------------------------- 172 | # Determine platform 173 | 174 | case "$target_to_consider" in 175 | *darwin*) procenv_platform=darwin;; 176 | *freebsd*) procenv_platform=freebsd;; 177 | 178 | *linux*) procenv_platform=linux;; 179 | 180 | # XXX: must come *AFTER* linux test 181 | *hurd*|*gnu*) procenv_platform=hurd;; 182 | 183 | *minix*) procenv_platform=minix;; 184 | *netbsd*) procenv_platform=netbsd;; 185 | *openbsd*) procenv_platform=openbsd;; 186 | *) procenv_platform=unknown;; 187 | esac 188 | 189 | AM_CONDITIONAL([PROCENV_PLATFORM_DARWIN], [test "$procenv_platform" = darwin]) 190 | AM_CONDITIONAL([PROCENV_PLATFORM_FREEBSD], [test "$procenv_platform" = freebsd]) 191 | AM_CONDITIONAL([PROCENV_PLATFORM_HURD], [test "$procenv_platform" = hurd]) 192 | AM_CONDITIONAL([PROCENV_PLATFORM_NETBSD], [test "$procenv_platform" = netbsd]) 193 | AM_CONDITIONAL([PROCENV_PLATFORM_OPENBSD], [test "$procenv_platform" = openbsd]) 194 | AM_CONDITIONAL([PROCENV_PLATFORM_LINUX], [test "$procenv_platform" = linux]) 195 | AM_CONDITIONAL([PROCENV_PLATFORM_MINIX], [test "$procenv_platform" = minix]) 196 | AM_CONDITIONAL([PROCENV_PLATFORM_GENERIC], [test "$procenv_platform" = unknown]) 197 | 198 | AC_SUBST([procenv_platform]) 199 | 200 | #--------------------------------------------------------------------- 201 | # Platform-specifics 202 | 203 | # Magic options that will remove all unused symbols (defined by 'platform-generic.c'). 204 | AS_IF( 205 | [test $procenv_platform = darwin], 206 | # Handle darwin 207 | [ 208 | AX_CHECK_COMPILE_FLAG([-flto], [CFLAGS="$CFLAGS -flto"]) 209 | AX_CHECK_LINK_FLAG([-flto], [LDFLAGS="$LDFLAGS -flto"]) 210 | ], 211 | # Handle other platforms 212 | [CFLAGS="$CFLAGS -fdata-sections -ffunction-sections"; LDFLAGS="$LDFLAGS -Wl,--gc-sections"] 213 | ) 214 | 215 | #--------------------------------------------------------------------- 216 | # XXX: Dump details of the preprocess/compiler/linker *NOW* so that if 217 | # procenv fails to build later, the build logs will show details of the 218 | # environment that should aid remote debugging. 219 | # 220 | # This may be bad form, but trying to do this at the automake stage 221 | # seems(?) to be impossible. 222 | t=${srcdir}/src/tests/show_compiler_details 223 | msg=$(cat <@@:>@*//') 236 | LDFLAGS=$(echo "$LDFLAGS" | sed 's/^@<:@@<:@:space:@:>@@:>@*//') 237 | 238 | AC_CONFIG_FILES([Makefile src/Makefile procenv.spec]) 239 | AC_OUTPUT 240 | AC_MSG_RESULT([ 241 | Configure settings for $PACKAGE_NAME version $VERSION 242 | 243 | Build platform : $procenv_platform 244 | Reproducible build : ${reproducible_build} 245 | Debug build : ${DEBUG_BUILD} 246 | Check unit test framework : ${HAVE_CHECK} 247 | 248 | Libraries: 249 | 250 | libapparmor : ${HAVE_APPARMOR} 251 | libselinux : ${HAVE_SELINUX} 252 | libcap : ${HAVE_LIBCAP} 253 | libnuma : ${HAVE_NUMA} 254 | libpthread : ${HAVE_PTHREAD} 255 | libkvm : ${HAVE_KVM} 256 | libsysinfo / sysinfo : ${HAVE_SYSINFO} 257 | 258 | Initial CFLAGS : ${CFLAGS} 259 | Initial LDFLAGS : ${LDFLAGS} 260 | ]) 261 | -------------------------------------------------------------------------------- /m4/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesodhunt/procenv/576dd40335a165b56698dce16eefe9fb4e675179/m4/ChangeLog -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 44 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 45 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_COMPILE_FLAGS 54 | -------------------------------------------------------------------------------- /procenv.spec: -------------------------------------------------------------------------------- 1 | Name: procenv 2 | Version: 0.60 3 | Release: 1%{?dist} 4 | Summary: Utility to show process environment 5 | 6 | Group: Applications/System 7 | License: GPLv3+ 8 | URL: https://github.com/jamesodhunt/procenv 9 | Source0: https://github.com/jamesodhunt/procenv/archive/0.60.tar.gz 10 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) 11 | 12 | # fixme: should be autoconf >= 2.68, but Fedora packages or alien'ed dpkg 13 | # need a later m4 too 14 | BuildRequires: gcc, make, binutils, autoconf, automake, pkgconfig, expat, libcap-devel, libselinux-devel 15 | # Only used in testing, not in EPEL. 16 | %if 0%{?fedora} 17 | BuildRequires: perl-JSON-PP 18 | %endif 19 | %ifnarch %{arm} s390 s390x 20 | BuildRequires: numactl-devel 21 | %endif 22 | 23 | %description 24 | This package contains a command-line tool that displays as much 25 | detail about itself and its environment as possible. It can be 26 | used as a test tool, to understand the type of environment a 27 | process runs in, and for comparing system environments. 28 | 29 | %prep 30 | %setup -q 31 | 32 | %build 33 | %configure 34 | make %{?_smp_mflags} 35 | 36 | 37 | %install 38 | rm -rf $RPM_BUILD_ROOT 39 | make install DESTDIR=$RPM_BUILD_ROOT 40 | 41 | %check 42 | %if 0%{?fedora} 43 | make check 44 | %endif 45 | 46 | %clean 47 | rm -rf $RPM_BUILD_ROOT 48 | 49 | %files 50 | %defattr(-,root,root,-) 51 | %{_bindir}/procenv 52 | %{_mandir}/man1/procenv.1.gz 53 | %doc NEWS ChangeLog TODO 54 | 55 | %changelog 56 | * Thu Jun 5 2014 Dave Love - 0.35-2 57 | - Only BR perl-JSON-PP and run tests on fedora 58 | 59 | * Fri Jan 31 2014 James Hunt - 0.32-1 60 | - Update to 0.31. 61 | 62 | * Thu Jan 23 2014 James Hunt - 0.30-1 63 | - Update to 0.30. 64 | 65 | * Thu Nov 14 2013 Dave Love - 0.27-1 66 | - Update to 0.27, fix Source0 67 | 68 | * Sun Dec 9 2012 Dave Love - 0.18-1 69 | - Update to 0.18 70 | 71 | * Tue Dec 4 2012 Dave Love - 0.16-2 72 | - Re-fix locale-reporting. 73 | 74 | * Mon Dec 3 2012 Dave Love - 0.16-1 75 | - Update to 0.16 76 | 77 | * Thu Nov 22 2012 Dave Love - 0.12-1 78 | - Initial packaging 79 | -------------------------------------------------------------------------------- /procenv.spec.in: -------------------------------------------------------------------------------- 1 | Name: @PACKAGE@ 2 | Version: @PROCENV_VERSION@ 3 | Release: 1%{?dist} 4 | Summary: Utility to show process environment 5 | 6 | Group: Applications/System 7 | License: GPLv3+ 8 | URL: https://github.com/jamesodhunt/procenv 9 | Source0: https://github.com/jamesodhunt/procenv/archive/@PROCENV_VERSION@.tar.gz 10 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) 11 | 12 | # fixme: should be autoconf >= 2.68, but Fedora packages or alien'ed dpkg 13 | # need a later m4 too 14 | BuildRequires: gcc, make, binutils, autoconf, automake, pkgconfig, expat, libcap-devel, libselinux-devel 15 | # Only used in testing, not in EPEL. 16 | %if 0%{?fedora} 17 | BuildRequires: perl-JSON-PP 18 | %endif 19 | %ifnarch %{arm} s390 s390x 20 | BuildRequires: numactl-devel 21 | %endif 22 | 23 | %description 24 | This package contains a command-line tool that displays as much 25 | detail about itself and its environment as possible. It can be 26 | used as a test tool, to understand the type of environment a 27 | process runs in, and for comparing system environments. 28 | 29 | %prep 30 | %setup -q 31 | 32 | %build 33 | %configure 34 | make %{?_smp_mflags} 35 | 36 | 37 | %install 38 | rm -rf $RPM_BUILD_ROOT 39 | make install DESTDIR=$RPM_BUILD_ROOT 40 | 41 | %check 42 | %if 0%{?fedora} 43 | make check 44 | %endif 45 | 46 | %clean 47 | rm -rf $RPM_BUILD_ROOT 48 | 49 | %files 50 | %defattr(-,root,root,-) 51 | %{_bindir}/procenv 52 | %{_mandir}/man1/procenv.1.gz 53 | %doc NEWS ChangeLog TODO 54 | 55 | %changelog 56 | * Thu Jun 5 2014 Dave Love - 0.35-2 57 | - Only BR perl-JSON-PP and run tests on fedora 58 | 59 | * Fri Jan 31 2014 James Hunt - 0.32-1 60 | - Update to 0.31. 61 | 62 | * Thu Jan 23 2014 James Hunt - 0.30-1 63 | - Update to 0.30. 64 | 65 | * Thu Nov 14 2013 Dave Love - 0.27-1 66 | - Update to 0.27, fix Source0 67 | 68 | * Sun Dec 9 2012 Dave Love - 0.18-1 69 | - Update to 0.18 70 | 71 | * Tue Dec 4 2012 Dave Love - 0.16-2 72 | - Re-fix locale-reporting. 73 | 74 | * Mon Dec 3 2012 Dave Love - 0.16-1 75 | - Update to 0.16 76 | 77 | * Thu Nov 22 2012 Dave Love - 0.12-1 78 | - Initial packaging 79 | -------------------------------------------------------------------------------- /reconf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p config 4 | rm -f config.cache 5 | aclocal -I m4 6 | autoconf 7 | autoheader 8 | automake -a 9 | exit 10 | -------------------------------------------------------------------------------- /scripts/find-missing-symbols.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #--------------------------------------------------------------------- 3 | # Copyright (c) 2021 James O. D. Hunt . 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-or-later 6 | #--------------------------------------------------------------------- 7 | 8 | #--------------------------------------------------------------------- 9 | # Description: Hacky script to "sniff" for missing symbols that 10 | # procenv should be reporting. It does this by searching through 11 | # the appropriate manpage(s) and include file(s) looking for 12 | # (new) symbols. 13 | #--------------------------------------------------------------------- 14 | 15 | set -o nounset 16 | set -o pipefail 17 | set -e 18 | 19 | export LC_ALL=C 20 | export LANG=C 21 | 22 | # XXX: Slight hack to avoid hyphenation of symbols in man-pages which 23 | # result in the get_*() functions finding invalid symbols. 24 | export MANWIDTH=10000 25 | 26 | verbose=0 27 | 28 | [ -n "${DEBUG:-}" ] && set -o xtrace 29 | 30 | # Strip unicode crud 31 | export man='man -E ascii' 32 | 33 | die() 34 | { 35 | local msg="$*" 36 | 37 | echo -e >&2 "ERROR: $msg" 38 | exit 1 39 | } 40 | 41 | info() 42 | { 43 | local msg="$*" 44 | 45 | echo -e "INFO: $msg" 46 | } 47 | 48 | get_caps() 49 | { 50 | local file="/usr/include/linux/capability.h" 51 | local manpage='capabilities(7)' 52 | 53 | local man_symbols 54 | local include_symbols 55 | local symbols 56 | 57 | [ -e "$file" ] || die "file does not exist: '$file'" 58 | $man -w "$manpage" &>/dev/null || die "invalid manpage: $manpage" 59 | 60 | man_symbols=$($man "$manpage" 2>/dev/null |\ 61 | egrep -o "\" |\ 62 | sort -u) 63 | 64 | include_symbols=$(egrep "#[ ]*define[ ]*\" |\ 75 | sort -u) 76 | 77 | echo "$symbols" 78 | } 79 | 80 | get_clocks() 81 | { 82 | local file="/usr/include/linux/time.h" 83 | local manpage='clock_gettime(2)' 84 | 85 | local man_symbols 86 | local include_symbols 87 | local symbols 88 | 89 | [ -e "$file" ] || die "file does not exist: '$file'" 90 | $man -w "$manpage" &>/dev/null || die "invalid manpage: $manpage" 91 | 92 | man_symbols=$($man "$manpage" 2>/dev/null |\ 93 | egrep -o "\" |\ 109 | sort -u) 110 | 111 | echo "$symbols" 112 | } 113 | 114 | get_confstr() 115 | { 116 | local file="/usr/include/bits/confname.h" 117 | 118 | local confstr_manpage='confstr(3)' 119 | local pathconf_manpage='pathconf(3)' 120 | local sysconf_manpage='sysconf(3)' 121 | 122 | local pathconf_man_symbols 123 | local sysconf_man_symbols 124 | local confstr_man_symbols 125 | 126 | local include_symbols 127 | local symbols 128 | 129 | [ -e "$file" ] || die "file does not exist: '$file'" 130 | 131 | local manpage 132 | 133 | for manpage in "$pathconf_manpage" "$confstr_manpage" "$sysconf_manpage" 134 | do 135 | $man -w "$manpage" &>/dev/null || die "invalid manpage: $manpage" 136 | done 137 | 138 | pathconf_man_symbols=$($man "$pathconf_manpage" 2>/dev/null |\ 139 | egrep -o "\<_PC_[A-Z0-9_][A-Z0-9_]*" |\ 140 | sort -u) 141 | 142 | confstr_man_symbols=$($man "$pathconf_manpage" 2>/dev/null |\ 143 | egrep -o "\<_CS_[A-Z0-9_][A-Z0-9_]*" |\ 144 | sort -u) 145 | 146 | sysconf_man_symbols=$($man "$pathconf_manpage" 2>/dev/null |\ 147 | egrep -o "\<_SC_[A-Z0-9_][A-Z0-9_]*" |\ 148 | sort -u) 149 | 150 | include_symbols=$(egrep "#[ ]*define[ ]*\<(_CS_|_SC_|_PC_)[A-Z0-9][A-Z0-9]*" \ 151 | "$file" |\ 152 | awk '{print $2}' |\ 153 | sort -u) 154 | 155 | # Merge 156 | symbols=$(echo \ 157 | "$include_symbols" \ 158 | "$pathconf_man_symbols" \ 159 | "$sysconf_man_symbols" \ 160 | "$confstr_man_symbols" |\ 161 | tr ' ' '\n' |\ 162 | sort -u) 163 | 164 | echo "$symbols" 165 | } 166 | 167 | get_limits() 168 | { 169 | local file="/usr/include/bits/resource.h" 170 | local manpage='getrlimit(2)' 171 | 172 | local man_symbols 173 | local include_symbols 174 | local symbols 175 | 176 | [ -e "$file" ] || die "file does not exist: '$file'" 177 | $man -w "$manpage" &>/dev/null || die "invalid manpage: $manpage" 178 | 179 | man_symbols=$($man "$manpage" 2>/dev/null |\ 180 | egrep -o "\/dev/null |\ 184 | egrep "#[ ]*define[ ]*\" |\ 195 | egrep -v "\" |\ 196 | sort -u) 197 | 198 | echo "$symbols" 199 | } 200 | 201 | get_locale() 202 | { 203 | local file="/usr/include/locale.h" 204 | local manpage='locale(7)' 205 | 206 | local man_symbols 207 | local include_symbols 208 | local symbols 209 | local symbol 210 | 211 | [ -e "$file" ] || die "file does not exist: '$file'" 212 | $man -w "$manpage" &>/dev/null || die "invalid manpage: $manpage" 213 | 214 | man_symbols=$($man "$manpage" 2>/dev/null |\ 215 | egrep -o "\/dev/null || die "invalid manpage: $manpage" 243 | 244 | man_symbols=$($man "$manpage" 2>/dev/null |\ 245 | egrep "\/dev/null || die "invalid manpage: $manpage" 277 | 278 | man_symbols=$($man "$manpage" 2>/dev/null |\ 279 | egrep -o "\" |\ 291 | egrep -v "\" |\ 292 | egrep -v "\|\" |\ 293 | sort -u) 294 | 295 | echo "$symbols" 296 | } 297 | 298 | check_symbols() 299 | { 300 | local name="${1:-}" 301 | local func="${2:-}" 302 | 303 | [ -z "$check" ] && die "need check name" 304 | [ -z "$func" ] && die "need check function" 305 | 306 | local symbols 307 | local symbol 308 | 309 | local source_dir='.' 310 | 311 | symbols=$($func) 312 | 313 | for symbol in $symbols 314 | do 315 | [ "$verbose" == 1 ] && info "checking $name symbol: '$symbol'" 316 | 317 | local found 318 | 319 | found=$(egrep -lr "\<${symbol}\>" \ 320 | "${source_dir}" |\ 321 | grep "\.[ch]$" || true) 322 | 323 | [ -z "$found" ] && die "$name symbol '$symbol' not referenced in source" || true 324 | done 325 | } 326 | 327 | run_checks() 328 | { 329 | local -A checks=( 330 | [capabilities]=get_caps 331 | [clocks]=get_clocks 332 | [confstr]=get_confstr 333 | [limits]=get_limits 334 | [locale]=get_locale 335 | [prctl]=get_prctls 336 | [signals]=get_signals 337 | ) 338 | 339 | local check 340 | 341 | local checks_sorted 342 | checks_sorted=$(echo "${!checks[@]}" |\ 343 | tr ' ' '\n' |\ 344 | sort -u | 345 | tr '\n' ' ') 346 | 347 | for check in $checks_sorted 348 | do 349 | local func="${checks[$check]}" 350 | 351 | info "checking '$check'" 352 | 353 | check_symbols "$check" "$func" 354 | done 355 | 356 | info "Checks complete" 357 | } 358 | 359 | handle_args() 360 | { 361 | local opt 362 | 363 | while getopts "dv" opt "$@" 364 | do 365 | case "$opt" in 366 | d) set -o xtrace ;; 367 | v) verbose=1 ;; 368 | esac 369 | done 370 | 371 | shift $[$OPTIND-1] 372 | 373 | run_checks 374 | } 375 | 376 | main() 377 | { 378 | handle_args "$@" 379 | } 380 | 381 | main "$@" 382 | -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------- 2 | # Copyright (c) 2021 James O. D. Hunt . 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | #-------------------------------------------------------------------- 6 | 7 | name: procenv 8 | adopt-info: procenv 9 | base: core18 10 | license: GPL-3.0 11 | summary: Utility to show process environment 12 | description: | 13 | Command-line tool that displays as much detail about itself and its 14 | environment as possible. It can be used as a test tool, to understand the 15 | type of environment a process runs in, and for comparing system 16 | environments. 17 | grade: stable 18 | type: app 19 | confinement: strict 20 | 21 | architectures: 22 | - build-on: amd64 23 | - build-on: arm64 24 | - build-on: armhf 25 | - build-on: i386 26 | - build-on: ppc64el 27 | - build-on: s390x 28 | 29 | environment: 30 | CFLAGS: '-fstack-protector-strong -Wformat -Werror=format-security' 31 | LDFLAGS: Wl,-z,relro 32 | 33 | parts: 34 | procenv: 35 | plugin: autotools 36 | source: https://github.com/jamesodhunt/procenv 37 | source-type: git 38 | build-environment: 39 | - CC: "$CC" 40 | build-packages: 41 | - autoconf 42 | - automake 43 | - check 44 | - expat 45 | - groff-base 46 | - libapparmor-dev 47 | - libcap-dev 48 | - libnuma-dev 49 | - libselinux1-dev 50 | - pkg-config 51 | override-build: | 52 | autoreconf -fi 53 | ./configure --prefix="${SNAPCRAFT_PART_INSTALL}/usr" 54 | make 55 | make check 56 | sudo make install 57 | stage-packages: 58 | - libapparmor1 59 | - libcap2 60 | - libnuma1 61 | - libselinux1 62 | override-pull: | 63 | snapcraftctl pull 64 | version=$(git describe @ --tags) 65 | snapcraftctl set-version "$version" 66 | 67 | apps: 68 | procenv: 69 | plugs: [hardware-observe, mount-observe, network-observe, system-observe] 70 | command: usr/bin/procenv 71 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------- 2 | # Copyright (c) 2012-2021 James O. D. Hunt . 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | #-------------------------------------------------------------------- 6 | 7 | AUTOMAKE_OPTIONS = subdir-objects 8 | 9 | AM_CFLAGS = \ 10 | -pedantic \ 11 | -std=gnu99 \ 12 | -Wall -Wunused 13 | 14 | 15 | # keep it tight 16 | AM_CFLAGS += -Werror 17 | 18 | bin_PROGRAMS = procenv 19 | 20 | procenv_SOURCES = \ 21 | procenv.c procenv.h \ 22 | pr_list.c pr_list.h \ 23 | pstring.c pstring.h \ 24 | string-util.c string-util.h \ 25 | output.c output.h \ 26 | util.c util.h \ 27 | types.h \ 28 | messages.h \ 29 | platform.h platform-headers.h \ 30 | platform/platform-generic.c platform/platform-generic.h 31 | 32 | # should really do this in configure.ac 33 | if PROCENV_PLATFORM_MINIX 34 | procenv_LDADD = -lc 35 | endif 36 | 37 | procenv_CPPFLAGS = 38 | procenv_CPPFLAGS += -I $(srcdir) -I $(srcdir)/platform 39 | 40 | if PROCENV_PLATFORM_DARWIN 41 | procenv_SOURCES += platform/darwin/platform.c platform/darwin/platform-darwin.h 42 | procenv_CPPFLAGS += -I $(srcdir)/platform/darwin -D PROCENV_PLATFORM_DARWIN 43 | endif 44 | 45 | if PROCENV_PLATFORM_LINUX 46 | procenv_SOURCES += platform/linux/platform.c platform/linux/platform-linux.h 47 | procenv_CPPFLAGS += -I $(srcdir)/platform/linux -D PROCENV_PLATFORM_LINUX 48 | endif 49 | 50 | if PROCENV_PLATFORM_MINIX 51 | procenv_SOURCES += platform/minix/platform.c platform/minix/platform-minix.h 52 | procenv_CPPFLAGS += \ 53 | -I $(srcdir)/platform/minix -D PROCENV_PLATFORM_MINIX 54 | endif 55 | 56 | if PROCENV_PLATFORM_HURD 57 | procenv_SOURCES += platform/hurd/platform.c platform/hurd/platform-hurd.h 58 | procenv_CPPFLAGS += -I $(srcdir)/platform/hurd -D PROCENV_PLATFORM_HURD 59 | endif 60 | 61 | if PROCENV_PLATFORM_FREEBSD 62 | procenv_SOURCES += platform/freebsd/platform.c platform/freebsd/platform-freebsd.h 63 | procenv_CPPFLAGS += -I $(srcdir)/platform/freebsd \ 64 | -D PROCENV_PLATFORM_FREEBSD \ 65 | -D PROCENV_PLATFORM_BSD 66 | endif 67 | 68 | if PROCENV_PLATFORM_NETBSD 69 | procenv_SOURCES += platform/netbsd/platform.c platform/netbsd/platform-netbsd.h 70 | procenv_CPPFLAGS += -I $(srcdir)/platform/netbsd \ 71 | -D PROCENV_PLATFORM_NETBSD \ 72 | -D PROCENV_PLATFORM_BSD 73 | endif 74 | 75 | if PROCENV_PLATFORM_OPENBSD 76 | procenv_SOURCES += platform/openbsd/platform.c platform/openbsd/platform-openbsd.h 77 | procenv_CPPFLAGS += -I $(srcdir)/platform/openbsd \ 78 | -D PROCENV_PLATFORM_OPENBSD \ 79 | -D PROCENV_PLATFORM_BSD 80 | endif 81 | 82 | if PROCENV_PLATFORM_GENERIC 83 | procenv_SOURCES += platform/unknown/platform.c platform/unknown/platform-unknown.h 84 | procenv_CPPFLAGS += -I $(srcdir)/platform/unknown -D PROCENV_PLATFORM_GENERIC 85 | endif 86 | 87 | if HAVE_SELINUX 88 | procenv_CPPFLAGS += -DHAVE_SELINUX 89 | endif 90 | 91 | if HAVE_APPARMOR 92 | procenv_CPPFLAGS += -DHAVE_APPARMOR 93 | endif 94 | 95 | if ENABLE_TESTS 96 | 97 | TESTS = 98 | CLEANFILES = 99 | 100 | TESTS += tests/show_machine_details 101 | 102 | check_all_args: tests/check_all_args.in 103 | sed -e 's|[@]builddir[@]|$(top_builddir)/$(subdir)|g' \ 104 | -e 's|[@]man_path[@]|$(top_srcdir)/man/procenv.1|g' \ 105 | -e 's|[@]package_url[@]|$(PACKAGE_URL)|g' \ 106 | -e 's|[@]package_url[@]|$(PACKAGE_URL)|g' \ 107 | -e 's|[@]procenv_platform[@]|$(procenv_platform)|g' \ 108 | $< > $@ 109 | chmod +x $@ 110 | 111 | if HAVE_CHECK 112 | TESTS += check_pr_list 113 | 114 | check_PROGRAMS = check_pr_list 115 | check_pr_list_SOURCES = tests/check_pr_list.c pr_list.c 116 | check_pr_list_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/src 117 | check_pr_list_LDADD = @CHECK_LIBS@ 118 | 119 | endif 120 | 121 | TESTS += check_all_args 122 | 123 | # Run built binary to ensure we can display all values 124 | TESTS += procenv 125 | 126 | CLEANFILES += check_all_args 127 | 128 | endif 129 | 130 | EXTRA_DIST = \ 131 | tests/show_compiler_details \ 132 | tests/show_machine_details \ 133 | tests/check_all_args.in \ 134 | tests/check_pr_list.c 135 | -------------------------------------------------------------------------------- /src/messages.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_MESSAGES_H 9 | #define _PROCENV_MESSAGES_H 10 | 11 | /* FIXME: gettext */ 12 | #define _(str) str 13 | 14 | #define YES_STR _("yes") 15 | #define NO_STR _("no") 16 | #define NON_STR _("non") 17 | #define NA_STR _("n/a") 18 | #define UNKNOWN_STR _("unknown") 19 | #define MAX_STR _(" (max)") 20 | #define DEFINED_STR _("defined") 21 | #define NOT_DEFINED_STR _("not defined") 22 | #define NOT_IMPLEMENTED_STR _("[not implemented]") 23 | #define BIG_STR _("big") 24 | #define LITTLE_STR _("little") 25 | #define PRIVILEGED_STR _("privileged") 26 | #define SUPPRESSED_STR _("[suppressed]") 27 | #define BUILD_TYPE_STD_STR _("standard") 28 | #define BUILD_TYPE_REPRODUCIBLE_STR _("reproducible") 29 | 30 | #endif /* _PROCENV_MESSAGES_H */ 31 | -------------------------------------------------------------------------------- /src/output.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_OUTPUT_H 9 | #define _PROCENV_OUTPUT_H 10 | 11 | #include "types.h" 12 | #include "pstring.h" 13 | 14 | #define show(...) _show ("", get_indent_amount (), __VA_ARGS__) 15 | 16 | /** 17 | * showi: 18 | * 19 | * @_indent: additional indent amount, 20 | * @fmt: printf-style format and optional arguments. 21 | * 22 | * Write indented message to appropriate output location. 23 | **/ 24 | #define showi(_indent, ...) \ 25 | _show ("", get_indent_amount() + _indent, __VA_ARGS__) 26 | 27 | /** 28 | * _message: 29 | * @prefix: Fixed message prefix, 30 | * @fmt: printf-style format and optional arguments. 31 | * 32 | * Write unindented message to appropriate output location. 33 | **/ 34 | #define _message(prefix, ...) _show (prefix, 0, __VA_ARGS__) 35 | 36 | #define warn(...) \ 37 | { \ 38 | _message ("WARNING", __VA_ARGS__); \ 39 | } 40 | 41 | #ifdef DEBUG 42 | /* for when running under GDB */ 43 | #define die_finalise() raise (SIGUSR1) 44 | #else 45 | #define die_finalise() exit (EXIT_FAILURE) 46 | #endif 47 | 48 | #define bug(...) \ 49 | { \ 50 | _show ("BUG", 0, __VA_ARGS__); \ 51 | exit (EXIT_FAILURE); \ 52 | } 53 | 54 | #define POINTER_SIZE (sizeof (void *)) 55 | 56 | #define die(...) \ 57 | { \ 58 | output = OUTPUT_STDERR; \ 59 | _message ("ERROR", __VA_ARGS__); \ 60 | cleanup (); \ 61 | die_finalise (); \ 62 | } 63 | 64 | #define common_assert() \ 65 | assert (doc); \ 66 | assert (get_indent_amount() >= 0) 67 | 68 | #define assert_not_reached() \ 69 | do { \ 70 | die ("%s:%d: Not reached assertion failed in %s", \ 71 | __FILE__, __LINE__, __func__); \ 72 | } while (0) 73 | 74 | typedef enum procenv_output { 75 | OUTPUT_FILE, 76 | OUTPUT_STDERR, 77 | OUTPUT_STDOUT, 78 | OUTPUT_SYSLOG, 79 | OUTPUT_TERM 80 | } Output; 81 | 82 | typedef enum { 83 | OUTPUT_FORMAT_TEXT, 84 | OUTPUT_FORMAT_CRUMB, 85 | OUTPUT_FORMAT_JSON, 86 | OUTPUT_FORMAT_XML 87 | } OutputFormat; 88 | 89 | typedef enum element_type { 90 | ELEMENT_TYPE_ENTRY, 91 | ELEMENT_TYPE_SECTION_OPEN, 92 | ELEMENT_TYPE_SECTION_CLOSE, 93 | ELEMENT_TYPE_CONTAINER_OPEN, 94 | ELEMENT_TYPE_CONTAINER_CLOSE, 95 | ELEMENT_TYPE_OBJECT_OPEN, 96 | ELEMENT_TYPE_OBJECT_CLOSE, 97 | ELEMENT_TYPE_NONE = -1 98 | } ElementType; 99 | 100 | /********************************************************************/ 101 | 102 | extern Output output; 103 | extern OutputFormat output_format; 104 | extern wchar_t wide_indent_char; 105 | 106 | void cleanup (void); 107 | 108 | /********************************************************************/ 109 | 110 | void output_init (void); 111 | void output_finalise (void); 112 | 113 | void header (const char *name); 114 | void footer (void); 115 | 116 | void master_header (pstring **doc); 117 | void master_footer (pstring **doc); 118 | 119 | void object_open (int retain); 120 | void object_close (int retain); 121 | 122 | void section_open (const char *name); 123 | void section_close (void); 124 | 125 | void container_open (const char *name); 126 | void container_close (void); 127 | 128 | void entry (const char *name, const char *fmt, ...); 129 | void _show (const char *prefix, int indent, const char *fmt, ...); 130 | void _show_output (const char *str); 131 | void _show_output_pstring (const pstring *pstr); 132 | 133 | void inc_indent (void); 134 | void dec_indent (void); 135 | void reset_indent (void); 136 | void add_indent (pstring **doc); 137 | 138 | void set_indent_amount (int amount); 139 | int get_indent_amount (void); 140 | const char *get_indent_char (void); 141 | 142 | void set_indent_char (const char *c); 143 | void handle_indent_char (void); 144 | 145 | void add_breadcrumb (const char *name); 146 | void remove_breadcrumb (void); 147 | void set_crumb_separator (const char *c); 148 | const char *get_crumb_separator (void); 149 | 150 | void set_output_file (const char *f); 151 | void set_output_file_append (void); 152 | 153 | void change_element (ElementType new); 154 | void format_element (void); 155 | 156 | void format_text_element (void); 157 | void format_json_element (void); 158 | void format_xml_element (void); 159 | 160 | void set_output_value (const char *name); 161 | void set_output_value_raw (Output o); 162 | void set_output_format (const char *name); 163 | const char *get_output_format_name (void); 164 | 165 | const char *get_text_separator (void); 166 | void set_text_separator (const char *s); 167 | 168 | #endif /* _PROCENV_OUTPUT_H */ 169 | -------------------------------------------------------------------------------- /src/platform-headers.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | /*-------------------------------------------------------------------- 9 | * Description: This file contains platform-specific system includes 10 | *-------------------------------------------------------------------- 11 | */ 12 | 13 | #ifndef _PROCENV_PLATFORM_HEADERS_H 14 | #define _PROCENV_PLATFORM_HEADERS_H 15 | 16 | /*------------------------------------------------------------------*/ 17 | 18 | #if defined (PROCENV_PLATFORM_DARWIN) 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define PROCENV_LINK_LEVEL_FAMILY AF_LINK 34 | #define PROCENV_CPU_TYPE int 35 | 36 | /* XXX: fake value as cpu set are not available on darwin */ 37 | #define PROCENV_CPU_SET_TYPE void 38 | 39 | #define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flags 40 | #define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsid.val 41 | 42 | #define PROCENV_STATFS_INT_TYPE uint64_t 43 | #define PROCENV_STATFS_INT_FMT PRIu64 44 | 45 | typedef struct statfs procenv_mnt_type; 46 | 47 | #endif /* PROCENV_PLATFORM_DARWIN*/ 48 | 49 | /*------------------------------------------------------------------*/ 50 | 51 | /* XXX: for now, let's assume "unknown" is similar to Linux :-) */ 52 | #if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_GENERIC) 53 | 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | 60 | #include 61 | 62 | #include 63 | #include 64 | #include 65 | #include 66 | 67 | #ifndef _SYS_PRCTL_H 68 | #include 69 | #endif 70 | 71 | #include 72 | 73 | /* Lucid provides prctl.h, but not securebits.h */ 74 | #if defined (PR_GET_SECUREBITS) && defined (HAVE_LINUX_SECUREBITS_H) 75 | #include 76 | #endif 77 | 78 | #include 79 | #include 80 | 81 | #if defined (HAVE_SYS_APPARMOR_H) 82 | #include 83 | #endif 84 | 85 | #if defined (HAVE_SELINUX_SELINUX_H) 86 | #include 87 | #endif 88 | 89 | #if defined (HAVE_SYS_CAPABILITY_H) 90 | #include 91 | #endif 92 | 93 | #if defined (__GLIBC__) 94 | #include 95 | #endif 96 | 97 | /* Network family for entries containing link-level interface 98 | * details. These entries will be cached to allow MAC addresses 99 | * to be extracted from them when displaying the corresponding 100 | * higher-level network family entries for the interface in 101 | * question. 102 | */ 103 | #define PROCENV_LINK_LEVEL_FAMILY AF_PACKET 104 | #define PROCENV_PTHREAD_GUARD_SIZE_TYPE size_t 105 | #define PROCENV_PTHREAD_GUARD_SIZE_FMT "%lu" 106 | 107 | #define PROCENV_CPU_SET_TYPE cpu_set_t 108 | #define PROCENV_CPU_TYPE int 109 | 110 | #endif /* PROCENV_PLATFORM_LINUX || PROCENV_PLATFORM_GENERIC */ 111 | 112 | /*------------------------------------------------------------------*/ 113 | 114 | #if defined (PROCENV_PLATFORM_MINIX) 115 | 116 | #include 117 | #include 118 | #include 119 | #include 120 | #include 121 | #include 122 | #include 123 | #include 124 | #include 125 | #include 126 | #include 127 | #include 128 | #include 129 | 130 | #define PROCENV_LINK_LEVEL_FAMILY AF_LINK 131 | #define PROCENV_PTHREAD_GUARD_SIZE_TYPE int 132 | #define PROCENV_PTHREAD_GUARD_SIZE_FMT "%u" 133 | #define PROCENV_CPU_TYPE cpuid_t 134 | #define PROCENV_CPU_SET_TYPE cpuset_t 135 | #define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flag 136 | #define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsidx.__fsid_val 137 | 138 | #define PROCENV_STATFS_INT_TYPE uint64_t 139 | #define PROCENV_STATFS_INT_FMT PRIu64 140 | 141 | typedef struct statvfs procenv_mnt_type; 142 | 143 | #endif /* PROCENV_PLATFORM_MINIX */ 144 | 145 | /*------------------------------------------------------------------*/ 146 | 147 | #if defined (PROCENV_PLATFORM_FREEBSD) 148 | 149 | #include 150 | #include 151 | #include 152 | #include 153 | #include 154 | #include 155 | #include 156 | #include 157 | #include 158 | #include 159 | #include 160 | #include 161 | 162 | #define PROCENV_LINK_LEVEL_FAMILY AF_LINK 163 | #define PROCENV_CPU_TYPE int 164 | #define PROCENV_CPU_SET_TYPE cpuset_t 165 | #define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flags 166 | #define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsid.val 167 | 168 | #define PROCENV_STATFS_INT_TYPE uint64_t 169 | #define PROCENV_STATFS_INT_FMT PRIu64 170 | 171 | typedef struct statfs procenv_mnt_type; 172 | 173 | #endif /* PROCENV_PLATFORM_FREEBSD*/ 174 | 175 | /*------------------------------------------------------------------*/ 176 | 177 | #if defined (PROCENV_PLATFORM_NETBSD) 178 | 179 | /* Required to access "struct kinfo_proc" (from sys/sysctl.h) */ 180 | #ifndef _KMEMUSER 181 | #define _KMEMUSER 182 | #endif 183 | 184 | #include 185 | #include 186 | #include 187 | #include 188 | #include 189 | #include 190 | #include 191 | #include 192 | #include 193 | #include 194 | #include 195 | #include 196 | #include 197 | #include 198 | 199 | #define PROCENV_LINK_LEVEL_FAMILY AF_LINK 200 | #define PROCENV_CPU_TYPE cpuid_t 201 | #define PROCENV_CPU_SET_TYPE cpuset_t 202 | #define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flag 203 | #define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsidx.__fsid_val 204 | 205 | #define PROCENV_STATFS_INT_TYPE uint64_t 206 | #define PROCENV_STATFS_INT_FMT PRIu64 207 | 208 | typedef struct statvfs procenv_mnt_type; 209 | 210 | #endif /* PROCENV_PLATFORM_NETBSD */ 211 | 212 | /*------------------------------------------------------------------*/ 213 | 214 | #if defined (PROCENV_PLATFORM_OPENBSD) 215 | 216 | #include 217 | #include 218 | #include 219 | #include 220 | #include 221 | 222 | #include 223 | #include 224 | #include 225 | #include 226 | #include 227 | #include 228 | #include 229 | #include 230 | 231 | #define PROCENV_LINK_LEVEL_FAMILY AF_LINK 232 | #define PROCENV_CPU_TYPE cpuid_t 233 | #define PROCENV_CPU_SET_TYPE struct cpuset 234 | #define PROCENV_MNT_GET_FLAGS(mnt) (mnt)->f_flags 235 | #define PROCENV_MNT_GET_FSID(mnt) (mnt)->f_fsid.val 236 | 237 | #define PROCENV_STATFS_INT_TYPE uint64_t 238 | #define PROCENV_STATFS_INT_FMT PRIu64 239 | 240 | typedef struct statfs procenv_mnt_type; 241 | 242 | #endif /* PROCENV_PLATFORM_OPENBSD */ 243 | 244 | /*------------------------------------------------------------------*/ 245 | 246 | #if defined (PROCENV_PLATFORM_HURD) 247 | 248 | #include 249 | #include 250 | #include 251 | #include 252 | #include 253 | #include 254 | 255 | #if defined (HAVE_SYS_CAPABILITY_H) 256 | #include 257 | #endif 258 | 259 | #define PROCENV_CPU_TYPE int 260 | #define PROCENV_CPU_SET_TYPE cpu_set_t 261 | 262 | #endif /* PROCENV_PLATFORM_HURD */ 263 | 264 | /*------------------------------------------------------------------*/ 265 | 266 | #if defined (PROCENV_PLATFORM_GENERIC) 267 | 268 | /* XXX: see above */ 269 | 270 | #endif /* PROCENV_PLATFORM_GENERIC */ 271 | 272 | /*------------------------------------------------------------------*/ 273 | 274 | #endif /* _PROCENV_PLATFORM_HEADERS_H */ 275 | 276 | /*------------------------------------------------------------------*/ 277 | -------------------------------------------------------------------------------- /src/platform.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_H 9 | #define _PROCENV_PLATFORM_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef PATH_MAX 18 | /* Hurd. Grrrr.... */ 19 | #define PATH_MAX _POSIX_PATH_MAX 20 | #endif 21 | 22 | #define PROCENV_SET_DRIVER(_name) \ 23 | { .name = #_name, .file = __FILE__, } 24 | 25 | #if defined (PROCENV_PLATFORM_FREEBSD) 26 | #include 27 | #define PROCENV_PR_GET_NAME_LEN (COMMLEN+1) 28 | #else 29 | #define PROCENV_PR_GET_NAME_LEN 16 30 | #endif 31 | 32 | extern struct procenv_user user; 33 | extern struct procenv_misc misc; 34 | extern struct procenv_priority priority_io; 35 | extern struct utsname uts; 36 | 37 | typedef enum { 38 | SHOW_ALL, 39 | SHOW_MOUNTS, 40 | SHOW_PATHCONF 41 | } ShowMountType; 42 | 43 | #include 44 | #include "platform-generic.h" 45 | #include "platform-headers.h" 46 | 47 | struct procenv_priority { 48 | int process; 49 | int pgrp; 50 | int user; 51 | }; 52 | 53 | struct procenv_user { 54 | struct passwd passwd; 55 | char proc_name[PROCENV_PR_GET_NAME_LEN]; 56 | char ctrl_terminal[L_ctermid]; 57 | 58 | char __padding[3]; 59 | 60 | pid_t pid; 61 | pid_t ppid; 62 | pid_t sid; 63 | 64 | char *login; 65 | 66 | pid_t pgroup; 67 | pid_t fg_pgroup; 68 | int tty_fd; 69 | 70 | uid_t uid; 71 | uid_t euid; 72 | uid_t suid; 73 | 74 | gid_t gid; 75 | gid_t egid; 76 | gid_t sgid; 77 | }; 78 | 79 | struct procenv_misc { 80 | char cwd[PATH_MAX]; 81 | char root[PATH_MAX]; 82 | mode_t umask_value; 83 | int cpu; 84 | #if defined (PROCENV_PLATFORM_FREEBSD) 85 | int in_jail; 86 | #endif 87 | }; 88 | 89 | struct procenv_driver 90 | { 91 | const char *name; 92 | const char *file; 93 | }; 94 | 95 | /* 96 | * - get_*() functions obtain information. 97 | * - show_*() functions display entries for a particular category of 98 | * information. 99 | * - handle_*() functions are similar to show_*() ones, except that they 100 | * also emit the appropriate heading/section/container entries and 101 | * corresponding footers. 102 | */ 103 | struct procenv_ops 104 | { 105 | struct procenv_driver driver; 106 | 107 | void (*init) (void); 108 | void (*cleanup) (void); 109 | 110 | const struct procenv_map *signal_map; 111 | const struct procenv_map *if_flag_map; 112 | const struct procenv_map *personality_map; 113 | const struct procenv_map *personality_flag_map; 114 | 115 | void (*get_user_misc) (struct procenv_user *user, 116 | struct procenv_misc *misc); 117 | 118 | void (*get_proc_name) (struct procenv_user *user); 119 | 120 | void (*get_io_priorities) (struct procenv_priority *iop); 121 | void (*get_tty_locked_status) (struct termios *lock_status); 122 | 123 | long (*get_kernel_bits) (void); 124 | int (*get_mtu) (const struct ifaddrs *ifaddr); 125 | bool (*get_time) (struct timespec *ts); 126 | 127 | void (*show_capabilities) (void); 128 | void (*show_cgroups) (void); 129 | void (*show_clocks) (void); 130 | void (*show_confstrs) (void); 131 | void (*show_cpu_affinities) (void); 132 | void (*show_cpu) (void); 133 | void (*show_extended_if_flags) (const char *interface, 134 | unsigned short *flags); 135 | void (*show_fd_capabilities) (int fd); 136 | void (*show_fds) (void); 137 | void (*show_io_priorities) (void); 138 | void (*show_mounts) (ShowMountType what); 139 | void (*show_msg_queues) (void); 140 | void (*show_namespaces) (void); 141 | void (*show_oom) (void); 142 | void (*show_prctl) (void); 143 | void (*show_rlimits) (void); 144 | void (*show_security_module) (void); 145 | void (*show_semaphores) (void); 146 | void (*show_shared_mem) (void); 147 | void (*show_timezone) (void); 148 | void (*show_libs) (void); 149 | 150 | void (*handle_memory) (void); 151 | void (*handle_numa_memory) (void); 152 | void (*handle_proc_branch) (void); 153 | void (*handle_scheduler_type) (void); 154 | 155 | PROCENV_CPU_SET_TYPE *(*get_cpuset) (void); 156 | void (*free_cpuset) (PROCENV_CPU_SET_TYPE *cs); 157 | bool (*cpuset_has_cpu) (const PROCENV_CPU_SET_TYPE *cs, 158 | PROCENV_CPU_TYPE cpu); 159 | 160 | bool (*in_vm) (void); 161 | }; 162 | 163 | #endif /* _PROCENV_PLATFORM_H */ 164 | -------------------------------------------------------------------------------- /src/platform/README.md: -------------------------------------------------------------------------------- 1 | # `procenv` drivers 2 | 3 | ## Overview 4 | 5 | `procenv` now supports platform drivers. These are simply translation 6 | units that are compiled only for a particular platform. They were 7 | introduced to combat the "`#ifdef` hell" of previous releases. 8 | 9 | ## Build Strategy 10 | 11 | ### `configure.ac` 12 | 13 | Used to identify the platform the build is run on, exporting 14 | `PROCENV_PLATFORM_` and `$procenv_platform"` to `src/Makefile.am`. 15 | 16 | ### `src/Makefile.am` 17 | 18 | - Defines `PROCENV_PLATFORM_` as a symbol to the compiler. 19 | 20 | - Adds platform driver (platform-specific) source files to the list of 21 | files to be built. 22 | 23 | To simplify the include policy, all platform-specific headers are added to the 24 | appropriate section in `platform-headers.h`. 25 | 26 | Additionally, one other object get built on *all* platforms: 27 | 28 | - `platform-generic` 29 | 30 | Provides generic Unix/Linux implementations of particular methods. 31 | 32 | Drivers are free to reference the functions from this translation unit. 33 | See below for details. 34 | 35 | The build uses some magic options so that although all possible 36 | implementations get built, *only those symbols actually referenced become part 37 | of the final binary* (meaning you don't end up with lots of generic functions 38 | linked into your binary if your driver doesn't use them :-) 39 | 40 | ## Implementing a new driver 41 | 42 | - `configure.ac`: 43 | - Update the `$target_to_consider` case logic for your platform. 44 | - Add an `AM_CONDITIONAL(PROCENV_PLATFORM_*, ...)`. 45 | 46 | - Create `src/platform/${platform}/platform.c` with an implementation of 47 | the global "`struct procenv_ops platform_ops`". 48 | 49 | For each `struct procenv_ops` function pointer, 50 | 51 | - If it doesn't make sense to define a particular function for the 52 | platform, simply omit specifying a function pointer. 53 | 54 | (Note that you could set the function pointer to `NULL`, but that 55 | isn't necessary given that the `platform_ops` symbol is global, and 56 | thus effectively all pointers not specified are already implicitly set 57 | to `NULL`). 58 | 59 | - If one of the generic implementations is suitable, set the function 60 | pointer to the corresponding `*_generic()` function in 61 | `platform-generic.c`. 62 | 63 | - If neither of the above options is suitable, define a static 64 | implementation in your `platform.c` (with the function name 65 | `*_`) file and set the corresponding function pointer to 66 | that function. 67 | 68 | - Create `src/platform/${platform}/platform-${platform}.h`. 69 | -------------------------------------------------------------------------------- /src/platform/android/platform.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "platform.h" 9 | 10 | struct procenv_ops platform_ops = 11 | { 12 | .driver = PROCENV_SET_DRIVER (android), 13 | 14 | // FIXME 15 | #if 0 16 | .init = NULL, 17 | .signal_map = &signal_map_linux, 18 | .get_time = get_time_generic, 19 | 20 | .show_clocks = show_clocks_generic, 21 | .show_fds = show_fds_linux, 22 | .show_namespaces = show_namespaces_linux, 23 | .show_cgroups = show_cgroups_linux, 24 | .show_oom = show_oom_linux, 25 | .show_timezone = show_timezone_linux, 26 | .show_capabilities = show_capabilities_linux, 27 | .show_security_module = show_security_module_linux, 28 | .show_security_module_context = show_security_module_context_linux, 29 | .show_prctl = show_prctl_linux, 30 | .show_cpu = show_cpu_linux, 31 | .show_proc_branch = show_proc_branch_linux, 32 | .show_shared_mem = show_shared_mem_linux, 33 | .show_semaphores = show_semaphores_linux, 34 | .show_msg_queues = show_msg_queues_linux, 35 | .show_io_priorities = show_io_priorities_linux, 36 | #endif 37 | }; 38 | -------------------------------------------------------------------------------- /src/platform/darwin/platform-darwin.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_DARWIN_H 9 | #define _PROCENV_PLATFORM_DARWIN_H 10 | 11 | #include "platform.h" 12 | #include "util.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define mib_len(mib) ((sizeof (mib) / sizeof(*mib)) - 1) 20 | 21 | #define mach_header_size(h) \ 22 | (((h)->magic == MH_MAGIC_64 || (h)->magic == MH_CIGAM_64) \ 23 | ? sizeof(struct mach_header_64) \ 24 | : sizeof(struct mach_header)) 25 | 26 | #endif /* _PROCENV_PLATFORM_DARWIN_H */ 27 | -------------------------------------------------------------------------------- /src/platform/darwin/platform.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "platform-darwin.h" 9 | 10 | static struct procenv_map signal_map_darwin[] = { 11 | 12 | mk_map_entry (SIGALRM), 13 | mk_map_entry (SIGBUS), 14 | mk_map_entry (SIGCONT), 15 | mk_map_entry (SIGFPE), 16 | mk_map_entry (SIGHUP), 17 | mk_map_entry (SIGILL), 18 | mk_map_entry (SIGINT), 19 | mk_map_entry (SIGKILL), 20 | mk_map_entry (SIGPIPE), 21 | mk_map_entry (SIGQUIT), 22 | mk_map_entry (SIGSEGV), 23 | mk_map_entry (SIGSTOP), 24 | mk_map_entry (SIGTERM), 25 | mk_map_entry (SIGTRAP), 26 | mk_map_entry (SIGTSTP), 27 | mk_map_entry (SIGTTIN), 28 | mk_map_entry (SIGTTOU), 29 | mk_map_entry (SIGUSR1), 30 | mk_map_entry (SIGUSR2), 31 | mk_map_entry (SIGXCPU), 32 | mk_map_entry (SIGXFSZ), 33 | mk_map_entry (SIGIOT), 34 | mk_map_entry (SIGPROF), 35 | mk_map_entry (SIGSYS), 36 | mk_map_entry (SIGURG), 37 | mk_map_entry (SIGVTALRM), 38 | 39 | #if defined (SIGIO) 40 | mk_map_entry (SIGIO), 41 | #endif 42 | 43 | #if defined (SIGWINCH) 44 | mk_map_entry (SIGWINCH), 45 | #endif 46 | 47 | #if defined (SIGINFO) 48 | mk_map_entry (SIGINFO), 49 | #endif 50 | 51 | #if defined (SIGPOLL) 52 | { "SIGPOLL|SIGEMT" , SIGPOLL }, 53 | #elif defined (SIGEMT) 54 | { "SIGPOLL|SIGEMT", SIGEMT }, 55 | #endif 56 | 57 | { "SIGCHLD|SIGCLD", SIGCHLD }, 58 | { "SIGABRT|SIGIOT", SIGABRT }, 59 | 60 | { NULL , 0 }, 61 | }; 62 | 63 | static struct procenv_map64 mntopt_map_darwin[] = { 64 | 65 | { "asynchronous" , MNT_ASYNC }, 66 | { "NFS-exported" , MNT_EXPORTED }, 67 | { "local" , MNT_LOCAL }, 68 | { "multilabel" , MNT_MULTILABEL }, 69 | { "noatime" , MNT_NOATIME }, 70 | { "noexec" , MNT_NOEXEC }, 71 | { "nosuid" , MNT_NOSUID }, 72 | { "with-quotas" , MNT_QUOTA }, 73 | { "read-only" , MNT_RDONLY }, 74 | { "synchronous" , MNT_SYNCHRONOUS }, 75 | { "union" , MNT_UNION }, 76 | 77 | { NULL , 0} 78 | }; 79 | 80 | static struct procenv_map if_flag_map_darwin[] = { 81 | mk_map_entry (IFF_UP), 82 | mk_map_entry (IFF_BROADCAST), 83 | mk_map_entry (IFF_DEBUG), 84 | mk_map_entry (IFF_LOOPBACK), 85 | mk_map_entry (IFF_POINTOPOINT), 86 | mk_map_entry (IFF_RUNNING), 87 | mk_map_entry (IFF_NOARP), 88 | mk_map_entry (IFF_PROMISC), 89 | mk_map_entry (IFF_ALLMULTI), 90 | mk_map_entry (IFF_SIMPLEX), 91 | mk_map_entry (IFF_MULTICAST), 92 | 93 | { NULL , 0 } 94 | }; 95 | 96 | static void 97 | show_cpu_darwin (void) 98 | { 99 | long max; 100 | 101 | max = get_sysconf (_SC_NPROCESSORS_ONLN); 102 | 103 | /* XXX: possible to determine current cpu? */ 104 | entry ("number", "%s of %lu", UNKNOWN_STR, max); 105 | } 106 | 107 | static bool 108 | get_time_darwin (struct timespec *ts) 109 | { 110 | clock_serv_t cs; 111 | mach_timespec_t mts; 112 | 113 | kern_return_t ret; 114 | 115 | ret = host_get_clock_service (mach_host_self(), CALENDAR_CLOCK, &cs); 116 | if (ret != KERN_SUCCESS) { 117 | return 1; 118 | } 119 | 120 | ret = clock_get_time (cs, &mts); 121 | if (ret != KERN_SUCCESS) { 122 | return 1; 123 | } 124 | 125 | mach_port_deallocate (mach_task_self(), cs); 126 | 127 | ts->tv_sec = mts.tv_sec; 128 | ts->tv_nsec = mts.tv_nsec; 129 | 130 | return 0; 131 | } 132 | 133 | static void 134 | handle_proc_branch_darwin (void) 135 | { 136 | struct kinfo_proc *procs = NULL; 137 | struct kinfo_proc *p; 138 | static const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; 139 | int ret; 140 | int done = false; 141 | size_t bytes; 142 | size_t count; 143 | size_t i; 144 | pid_t current; 145 | pid_t ultimate_parent = 0; 146 | char *str = NULL; 147 | 148 | /* arbitrary */ 149 | int attempts = 20; 150 | 151 | current = getpid (); 152 | 153 | /* XXX: This system interface seems horribly racy - what if the number of pids 154 | * XXX: changes between the 1st and 2nd call to sysctl() ??? 155 | */ 156 | while (! done) { 157 | attempts--; 158 | if (! attempts) 159 | return; 160 | 161 | /* determine how much space required to store details of all 162 | * processes. 163 | */ 164 | ret = sysctl ((int *)mib, mib_len (mib), NULL, &bytes, NULL, 0); 165 | if (ret < 0) 166 | return; 167 | 168 | count = bytes / sizeof (struct kinfo_proc); 169 | 170 | /* allocate space */ 171 | procs = calloc (count, sizeof (struct kinfo_proc)); 172 | if (! procs) 173 | return; 174 | 175 | /* request the details of the processes */ 176 | ret = sysctl ((int *)mib, mib_len (mib), procs, &bytes, NULL, 0); 177 | if (ret < 0) { 178 | free (procs); 179 | procs = NULL; 180 | if (errno != ENOMEM) { 181 | /* unknown error, so give up */ 182 | return; 183 | } 184 | } else { 185 | done = true; 186 | } 187 | } 188 | 189 | if (! done) 190 | goto out; 191 | 192 | /* reset */ 193 | done = false; 194 | 195 | /* Calculate the lowest PID number which gives us the ultimate 196 | * parent of all processes. 197 | */ 198 | p = &procs[0]; 199 | ultimate_parent = p->kp_proc.p_pid; 200 | 201 | for (i = 1; i < count; i++) { 202 | p = &procs[i]; 203 | if (p->kp_proc.p_pid < ultimate_parent) 204 | ultimate_parent = p->kp_proc.p_pid; 205 | } 206 | 207 | while (! done) { 208 | for (i = 0; i < count && !done; i++) { 209 | p = &procs[i]; 210 | 211 | if (p->kp_proc.p_pid == current) { 212 | 213 | if (! ultimate_parent && current == ultimate_parent) { 214 | 215 | /* Found the "last" PID so record it and hop out */ 216 | appendf (&str, "%d ('%s')", 217 | (int)current, p->kp_proc.p_comm); 218 | 219 | done = true; 220 | break; 221 | } else { 222 | /* Found a valid parent pid */ 223 | appendf (&str, "%d ('%s'), ", 224 | (int)current, p->kp_proc.p_comm); 225 | } 226 | 227 | /* Move on */ 228 | current = p->kp_eproc.e_ppid; 229 | } 230 | } 231 | } 232 | 233 | entry ("ancestry", "%s", str); 234 | 235 | out: 236 | free_if_set (str); 237 | free_if_set (procs); 238 | } 239 | 240 | 241 | static void 242 | show_mounts_darwin (ShowMountType what) 243 | { 244 | show_mounts_generic_bsd (what, mntopt_map_darwin); 245 | } 246 | 247 | static void 248 | show_memory_darwin (void) 249 | { 250 | size_t bytes; 251 | size_t len = sizeof(bytes); 252 | int ret; 253 | 254 | size_t vm_page_size; 255 | size_t total_ram; 256 | size_t used_ram; 257 | size_t free_ram; 258 | 259 | bytes = 0; 260 | ret = sysctlbyname("hw.memsize", &bytes, &len, NULL, 0); 261 | if (ret < 0) { 262 | return; 263 | } 264 | 265 | total_ram = bytes; 266 | 267 | /*------------------------------*/ 268 | 269 | bytes = 0; 270 | ret = sysctlbyname("vm.pagesize", &bytes, &len, NULL, 0); 271 | if (ret < 0) { 272 | return; 273 | } 274 | 275 | vm_page_size = bytes; 276 | 277 | /*------------------------------*/ 278 | 279 | bytes = 0; 280 | ret = sysctlbyname("vm.page_free_count", &bytes, &len, NULL, 0); 281 | if (ret < 0) { 282 | return; 283 | } 284 | 285 | used_ram = (bytes * vm_page_size); 286 | free_ram = total_ram - used_ram; 287 | 288 | /*------------------------------*/ 289 | 290 | mach_msg_type_number_t count; 291 | vm_statistics_data_t stats = { 0 }; 292 | 293 | count = HOST_VM_INFO_COUNT; 294 | ret = host_statistics(mach_host_self(), 295 | HOST_VM_INFO, 296 | (host_info_t)&stats, 297 | &count); 298 | if (ret != KERN_SUCCESS) { 299 | return; 300 | } 301 | 302 | size_t unused_vm_bytes = stats.free_count * vm_page_size; 303 | size_t active_bytes = stats.active_count * vm_page_size; 304 | size_t inactive_bytes = stats.inactive_count * vm_page_size; 305 | size_t wired_bytes = stats.wire_count * vm_page_size; 306 | 307 | /*------------------------------*/ 308 | 309 | section_open ("ram"); 310 | 311 | mk_mem_section ("total", total_ram); 312 | mk_mem_section ("free", free_ram); 313 | mk_mem_section ("wired", wired_bytes); 314 | mk_mem_section ("unused", unused_vm_bytes); 315 | mk_mem_section ("active", active_bytes); 316 | mk_mem_section ("inactive", inactive_bytes); 317 | 318 | section_close (); 319 | 320 | /*------------------------------*/ 321 | } 322 | 323 | static char * 324 | get_macho_version(uint32_t version) 325 | { 326 | char *str = NULL; 327 | 328 | if (version == (uint32_t)-1) { 329 | appendf(&str, "(%s)", UNKNOWN_STR); 330 | } else { 331 | /* Top 2 bytes (bits 16-31) */ 332 | uint32_t major = version >> 16; 333 | 334 | /* 2nd byte (bits 9-15) */ 335 | uint32_t minor = (version >> 8) & 0xff; 336 | 337 | /* 1st byte (bits 0->8) */ 338 | uint32_t patch = version & 0xff; 339 | 340 | appendf(&str, "%u.%u.%u", major, minor, patch); 341 | } 342 | 343 | return str; 344 | } 345 | 346 | static void 347 | handle_load_cmds(const struct mach_header *header) 348 | { 349 | if (! header) return; 350 | 351 | uint32_t cmds = header->ncmds; 352 | 353 | if (cmds == 0) return; 354 | 355 | /* The commands immediately follow the mach header, 356 | * but the size of the header varies depending on the platform! 357 | */ 358 | uintptr_t cmds_addr = (uintptr_t)header + mach_header_size(header); 359 | 360 | uintptr_t p = cmds_addr; 361 | 362 | for (uint32_t i = 0; i < cmds; i++) 363 | { 364 | struct load_command *lc = (struct load_command *)p; 365 | 366 | /* We only need to consider a subset of load commands 367 | * to determine which shared libraries are loaded. 368 | */ 369 | bool consider = lc->cmd == LC_ID_DYLIB || 370 | lc->cmd == LC_LOAD_DYLIB || 371 | lc->cmd == LC_LOAD_WEAK_DYLIB || 372 | lc->cmd == LC_REEXPORT_DYLIB || 373 | lc->cmd == LC_LOAD_UPWARD_DYLIB || 374 | lc->cmd == LC_LAZY_LOAD_DYLIB; 375 | 376 | if (consider) { 377 | struct dylib_command *dl = (struct dylib_command *)lc; 378 | 379 | struct dylib dylib = dl->dylib; 380 | 381 | // Determine shared library path 382 | char *path = (char *)lc + dylib.name.offset; 383 | 384 | char *tmp = strdup (path); 385 | char *name = basename (tmp); 386 | 387 | object_open (false); 388 | section_open (name); 389 | 390 | free (tmp); 391 | 392 | void *addr = dlopen(path, RTLD_LAZY); 393 | if (addr) { 394 | entry ("address", "%p", addr); 395 | dlclose (addr); 396 | } 397 | 398 | entry ("path", "%s", path); 399 | 400 | /*------------------------------*/ 401 | 402 | section_open ("versions"); 403 | 404 | char *current_version = get_macho_version(dylib.current_version); 405 | char *compat_version = get_macho_version(dylib.compatibility_version); 406 | 407 | if (current_version) { 408 | entry ("current", "%s", current_version); 409 | free (current_version); 410 | } 411 | 412 | if (compat_version) { 413 | entry ("compatibility", "%s", compat_version); 414 | free (compat_version); 415 | } 416 | 417 | section_close (); 418 | 419 | /*------------------------------*/ 420 | 421 | section_close (); 422 | object_close (false); 423 | } 424 | 425 | p += lc->cmdsize; 426 | } 427 | } 428 | 429 | static void 430 | show_libs_darwin(void) 431 | { 432 | /* First, determine the OSX name for this binary */ 433 | int ret; 434 | char path[PATH_MAX]; 435 | uint32_t size = (uint32_t)sizeof(path); 436 | 437 | ret = _NSGetExecutablePath(path, &size); 438 | if (ret != 0) return; 439 | 440 | int count = _dyld_image_count(); 441 | 442 | /* Now, look for the image relating to this program */ 443 | for (int i = 0; i < count; i++) { 444 | const char *name = _dyld_get_image_name(i); 445 | 446 | if (!name) { 447 | continue; 448 | } 449 | 450 | /* Only show dependencies for _ourself_ */ 451 | if (! strcmp(name, path)) { 452 | const struct mach_header *header = _dyld_get_image_header(i); 453 | 454 | handle_load_cmds(header); 455 | break; 456 | } 457 | } 458 | } 459 | 460 | /* Darwin lacks: 461 | * 462 | * - cpusets and cpu affinities. 463 | */ 464 | struct procenv_ops platform_ops = 465 | { 466 | .driver = PROCENV_SET_DRIVER (darwin), 467 | 468 | .signal_map = signal_map_darwin, 469 | .if_flag_map = if_flag_map_darwin, 470 | 471 | .get_time = get_time_darwin, 472 | .get_kernel_bits = get_kernel_bits_generic, 473 | .get_mtu = get_mtu_generic, 474 | 475 | .handle_proc_branch = handle_proc_branch_darwin, 476 | 477 | .show_confstrs = show_confstrs_generic, 478 | .show_cpu = show_cpu_darwin, 479 | .show_clocks = show_clocks_generic, 480 | .show_fds = show_fds_generic, 481 | .show_mounts = show_mounts_darwin, 482 | .show_rlimits = show_rlimits_generic, 483 | .show_timezone = show_timezone_generic, 484 | .show_libs = show_libs_darwin, 485 | 486 | .handle_memory = show_memory_darwin, 487 | }; 488 | -------------------------------------------------------------------------------- /src/platform/freebsd/platform-freebsd.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_FREEBSD_H 9 | #define _PROCENV_PLATFORM_FREEBSD_H 10 | 11 | #include "platform.h" 12 | #include "util.h" 13 | 14 | #if defined (HAVE_SYS_CAPSICUM_H) 15 | #include 16 | #else /* !HAVE_SYS_CAPSICUM_H */ 17 | #if defined (HAVE_SYS_CAPABILITY_H) 18 | #include 19 | #endif /* HAVE_SYS_CAPABILITY_H */ 20 | #endif /* HAVE_SYS_CAPSICUM_H */ 21 | 22 | #if defined (HAVE_SYS_CAPSICUM_H) || defined (HAVE_SYS_CAPABILITY_H) 23 | 24 | #if __FreeBSD__ == 9 25 | 26 | /* FreeBSD 9 introduced optional capabilities. FreeBSD enabled them by 27 | * default, changing some of the system calls in the process, so handle 28 | * the name changes. 29 | */ 30 | #define cap_rights_get(fd, rightsp) cap_getrights (fd, (rightsp)) 31 | #define cap_rights_is_set(rightsp, cap) ((*rightsp) & (cap)) 32 | 33 | #endif /* __FreeBSD__ == 9 */ 34 | 35 | #define show_capsicum_cap(rights, cap) \ 36 | entry (#cap, "%s", cap_rights_is_set ((&rights), cap) ? YES_STR : NO_STR) 37 | #endif /* HAVE_SYS_CAPSICUM_H || HAVE_SYS_CAPSICUM_H */ 38 | 39 | #endif /* _PROCENV_PLATFORM_FREEBSD_H */ 40 | -------------------------------------------------------------------------------- /src/platform/hurd/platform-hurd.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_HURD_H 9 | #define _PROCENV_PLATFORM_HURD_H 10 | 11 | #include "platform.h" 12 | #include "util.h" 13 | 14 | /* Seriously? */ 15 | #ifndef PATH_MAX 16 | #define PATH_MAX 4096 17 | #endif 18 | 19 | /* semctl(2) states that POSIX.1-2001 requires the caller define this! */ 20 | union semun { 21 | int val; 22 | struct semid_ds *buf; 23 | unsigned short int *array; 24 | struct seminfo *__buf; 25 | }; 26 | 27 | #endif /* _PROCENV_PLATFORM_HURD_H */ 28 | -------------------------------------------------------------------------------- /src/platform/hurd/platform.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "platform-hurd.h" 9 | 10 | static struct procenv_map signal_map_hurd[] = { 11 | 12 | mk_map_entry (SIGABRT), 13 | mk_map_entry (SIGALRM), 14 | mk_map_entry (SIGBUS), 15 | 16 | { "SIGCHLD|SIGCLD", SIGCHLD }, 17 | 18 | mk_map_entry (SIGCONT), 19 | mk_map_entry (SIGFPE), 20 | mk_map_entry (SIGHUP), 21 | mk_map_entry (SIGILL), 22 | mk_map_entry (SIGINT), 23 | mk_map_entry (SIGKILL), 24 | mk_map_entry (SIGPIPE), 25 | mk_map_entry (SIGQUIT), 26 | mk_map_entry (SIGSEGV), 27 | mk_map_entry (SIGSTOP), 28 | mk_map_entry (SIGTERM), 29 | mk_map_entry (SIGTRAP), 30 | mk_map_entry (SIGTSTP), 31 | mk_map_entry (SIGTTIN), 32 | mk_map_entry (SIGTTOU), 33 | mk_map_entry (SIGUSR1), 34 | mk_map_entry (SIGUSR2), 35 | mk_map_entry (SIGIO), 36 | mk_map_entry (SIGPROF), 37 | mk_map_entry (SIGSYS), 38 | mk_map_entry (SIGURG), 39 | mk_map_entry (SIGVTALRM), 40 | mk_map_entry (SIGWINCH), 41 | mk_map_entry (SIGXCPU), 42 | mk_map_entry (SIGXFSZ), 43 | mk_map_entry (SIGEMT), 44 | mk_map_entry (SIGINFO), 45 | mk_map_entry (SIGLOST), 46 | 47 | { NULL, 0 }, 48 | }; 49 | 50 | static struct procenv_map if_flag_map_hurd[] = { 51 | mk_map_entry (IFF_UP), 52 | mk_map_entry (IFF_BROADCAST), 53 | mk_map_entry (IFF_DEBUG), 54 | mk_map_entry (IFF_LOOPBACK), 55 | mk_map_entry (IFF_POINTOPOINT), 56 | mk_map_entry (IFF_RUNNING), 57 | mk_map_entry (IFF_NOARP), 58 | mk_map_entry (IFF_PROMISC), 59 | mk_map_entry (IFF_ALLMULTI), 60 | mk_map_entry (IFF_MULTICAST), 61 | 62 | { NULL, 0 }, 63 | }; 64 | 65 | struct procenv_ops platform_ops = 66 | { 67 | .driver = PROCENV_SET_DRIVER (hurd), 68 | 69 | .get_kernel_bits = get_kernel_bits_generic, 70 | .get_mtu = get_mtu_generic, 71 | .get_time = get_time_generic, 72 | 73 | .signal_map = signal_map_hurd, 74 | .if_flag_map = if_flag_map_hurd, 75 | 76 | .show_clocks = show_clocks_generic, 77 | .show_confstrs = show_confstrs_generic, 78 | .show_cpu_affinities = show_cpu_affinities_generic, 79 | .show_fds = show_fds_generic, 80 | .show_mounts = show_mounts_generic_linux, 81 | .show_rlimits = show_rlimits_generic, 82 | .show_libs = show_libs_generic, 83 | }; 84 | -------------------------------------------------------------------------------- /src/platform/linux/platform-linux.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_LINUX_H 9 | #define _PROCENV_PLATFORM_LINUX_H 10 | 11 | /* required for sched_getcpu() (from sched.h) */ 12 | #define _GNU_SOURCE 13 | 14 | #include "platform.h" 15 | #include "util.h" 16 | 17 | #define ROOT_PATH "/proc/self/root" 18 | 19 | /* Maximum length of a process name as shown by ps(1), 20 | * /proc/$pid/comm, etc. Requires since there appears to be 21 | * no standard userspace define for the TASK_COMM_LEN 22 | * kernel define. 23 | * 24 | * See: 25 | * 26 | * - PR_SET_NAME in prctl(2). 27 | * - pthread_setname_np(3). 28 | */ 29 | #define _PROCENV_TASK_COMM_LEN 16 30 | 31 | /* The usable amount of space for a process name 32 | * (1 byte required for terminating '\0') 33 | */ 34 | #define PROCENV_TASK_COMM_NAME_LEN (_PROCENV_TASK_COMM_LEN-1) 35 | 36 | #if defined (HAVE_NUMA_H) 37 | 38 | #include 39 | #include 40 | 41 | #if LIBNUMA_API_VERSION == 2 42 | #define PROCENV_NUMA_BITMASK_ISSET(mask, node) numa_bitmask_isbitset ((mask), (node)) 43 | #else 44 | #define PROCENV_NUMA_BITMASK_ISSET(mask, node) nodemask_isset (&(mask), (node)) 45 | #endif 46 | #endif /* HAVE_NUMA_H */ 47 | 48 | /** 49 | * LINUX_KERNEL_M: 50 | * @major: Linux major kernel version number. 51 | * 52 | * Returns: true if running Linux kernel is at least at version 53 | * specified by @major else false. 54 | **/ 55 | #define LINUX_KERNEL_M(major) \ 56 | (linux_kernel_version (major, -1, -1)) 57 | 58 | /** 59 | * LINUX_KERNEL_MM: 60 | * @major: Linux major kernel version number, 61 | * @minor: Linux minor kernel version number. 62 | * 63 | * Returns: true if running Linux kernel is at least at version 64 | * specified by (@major, @minor) else false. 65 | **/ 66 | #define LINUX_KERNEL_MM(major, minor) \ 67 | (linux_kernel_version (major, minor, -1)) 68 | 69 | /** 70 | * LINUX_KERNEL_MMR: 71 | * @major: Linux major kernel version number, 72 | * @minor: Linux minor kernel version number, 73 | * @revision: kernel revision version. 74 | * 75 | * Returns: true if running Linux kernel is at least at version 76 | * specified by (@major, @minor, @revision) else false. 77 | **/ 78 | #define LINUX_KERNEL_MMR(major, minor, revision) \ 79 | (linux_kernel_version (major, minor, revision)) 80 | 81 | /** 82 | * show_capability: 83 | * @caps: cap_t, 84 | * @cap: capability. 85 | * 86 | * Display specified capability, or NOT_DEFINED_STR if value is 87 | * unknown. 88 | **/ 89 | #ifdef PR_CAPBSET_READ 90 | #define show_capability(caps, cap) \ 91 | _show_capability (caps, cap, #cap) 92 | 93 | #define _show_capability(caps, cap, name) \ 94 | { \ 95 | int bound; \ 96 | int effective; \ 97 | int inheritable; \ 98 | int permitted; \ 99 | int ambient; \ 100 | \ 101 | bound = cap_get_bound (cap); \ 102 | \ 103 | ambient = get_ambient_capability (cap); \ 104 | effective = get_capability_by_flag_type (caps, CAP_EFFECTIVE, cap); \ 105 | inheritable = get_capability_by_flag_type (caps, CAP_INHERITABLE, cap); \ 106 | permitted = get_capability_by_flag_type (caps, CAP_PERMITTED, cap); \ 107 | \ 108 | section_open (name); \ 109 | \ 110 | entry ("number", "%d", cap); \ 111 | \ 112 | entry ("supported", "%s", \ 113 | CAP_IS_SUPPORTED (cap) \ 114 | ? YES_STR : NO_STR); \ 115 | \ 116 | entry ("in bounding set", "%s", \ 117 | bound < 0 \ 118 | ? UNKNOWN_STR \ 119 | : bound \ 120 | ? YES_STR \ 121 | : NO_STR); \ 122 | \ 123 | entry ("ambient", "%s", \ 124 | ambient < 0 \ 125 | ? NOT_DEFINED_STR \ 126 | : permitted == CAP_SET \ 127 | ? YES_STR \ 128 | : NO_STR); \ 129 | \ 130 | entry ("effective", "%s", \ 131 | effective < 0 \ 132 | ? NOT_DEFINED_STR \ 133 | : effective == CAP_SET \ 134 | ? YES_STR \ 135 | : NO_STR); \ 136 | \ 137 | entry ("inheritable", "%s", \ 138 | inheritable < 0 \ 139 | ? NOT_DEFINED_STR \ 140 | : inheritable == CAP_SET \ 141 | ? YES_STR \ 142 | : NO_STR); \ 143 | \ 144 | entry ("permitted", "%s", \ 145 | permitted < 0 \ 146 | ? NOT_DEFINED_STR \ 147 | : permitted == CAP_SET \ 148 | ? YES_STR \ 149 | : NO_STR); \ 150 | \ 151 | section_close (); \ 152 | } 153 | #else 154 | #define show_capability(caps, cap) 155 | #endif 156 | 157 | #if defined (HAVE_SYS_CAPABILITY_H) 158 | 159 | #ifndef CAP_IS_SUPPORTED 160 | 161 | static int cap_get_bound (cap_value_t cap) 162 | __attribute__((unused)); 163 | 164 | #define CAP_IS_SUPPORTED(cap) (cap_get_bound (cap) >= 0) 165 | #define PROCENV_NEED_LOCAL_CAP_GET_BOUND 166 | 167 | #endif /* CAP_IS_SUPPORTED */ 168 | 169 | #endif /* HAVE_SYS_CAPABILITY_H */ 170 | 171 | /* semctl(2) states that POSIX.1-2001 requires the caller define this! */ 172 | union semun { 173 | int val; 174 | struct semid_ds *buf; 175 | unsigned short int *array; 176 | struct seminfo *__buf; 177 | }; 178 | 179 | static bool linux_kernel_version (int major, int minor, int revision); 180 | 181 | #if defined (HAVE_SYS_CAPABILITY_H) 182 | static int get_capability_by_flag_type (cap_t cap_p, cap_flag_t type, cap_value_t cap) 183 | __attribute__((unused)); 184 | static int get_ambient_capability(cap_value_t cap) 185 | __attribute__((unused)); 186 | 187 | #endif /* HAVE_SYS_CAPABILITY_H */ 188 | 189 | #endif /* _PROCENV_PLATFORM_LINUX_H */ 190 | -------------------------------------------------------------------------------- /src/platform/minix/platform-minix.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_MINIX_H 9 | #define _PROCENV_PLATFORM_MINIX_H 10 | 11 | #include "platform.h" 12 | #include "util.h" 13 | 14 | #endif /* _PROCENV_PLATFORM_MINIX_H */ 15 | -------------------------------------------------------------------------------- /src/platform/minix/platform.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "platform-minix.h" 9 | 10 | static struct procenv_map signal_map_minix[] = { 11 | 12 | mk_map_entry (SIGABRT), 13 | mk_map_entry (SIGALRM), 14 | mk_map_entry (SIGBUS), 15 | 16 | { SIGCHLD, "SIGCHLD|SIGCLD" }, 17 | 18 | mk_map_entry (SIGCONT), 19 | mk_map_entry (SIGFPE), 20 | mk_map_entry (SIGHUP), 21 | mk_map_entry (SIGILL), 22 | mk_map_entry (SIGINT), 23 | mk_map_entry (SIGKILL), 24 | mk_map_entry (SIGPIPE), 25 | mk_map_entry (SIGQUIT), 26 | mk_map_entry (SIGSEGV), 27 | mk_map_entry (SIGSTOP), 28 | mk_map_entry (SIGTERM), 29 | mk_map_entry (SIGTRAP), 30 | mk_map_entry (SIGTSTP), 31 | mk_map_entry (SIGTTIN), 32 | mk_map_entry (SIGTTOU), 33 | mk_map_entry (SIGUSR1), 34 | mk_map_entry (SIGUSR2), 35 | mk_map_entry (SIGIO), 36 | mk_map_entry (SIGPROF), 37 | mk_map_entry (SIGSYS), 38 | mk_map_entry (SIGURG), 39 | mk_map_entry (SIGVTALRM), 40 | mk_map_entry (SIGWINCH), 41 | mk_map_entry (SIGXCPU), 42 | mk_map_entry (SIGXFSZ), 43 | mk_map_entry (SIGEMT), 44 | mk_map_entry (SIGINFO), 45 | mk_map_entry (SIGKMEM), 46 | mk_map_entry (SIGKMESS), 47 | mk_map_entry (SIGKSIG), 48 | mk_map_entry (SIGKSIGSM), 49 | mk_map_entry (SIGPWR), 50 | mk_map_entry (SIGSNDELAY), 51 | 52 | { 0, NULL }, 53 | }; 54 | 55 | static struct procenv_map64 mntopt_map_minix[] = { 56 | 57 | { MNT_ASYNC , "async" }, 58 | //{ MNT_AUTO , "auto" }, 59 | { MNT_DISCARD , "discard" }, 60 | { MNT_EXTATTR , "extattr" }, 61 | { MNT_FORCE , "force" }, 62 | { MNT_GETARGS , "getargs" }, 63 | //{ MNT_GROUPQUOTA , "groupquota" }, 64 | { MNT_IGNORE , "hidden" }, 65 | { MNT_LOG , "log" }, 66 | { MNT_NOATIME , "atime" }, 67 | { MNT_NOCOREDUMP , "coredump" }, 68 | { MNT_NODEV , "dev" }, 69 | { MNT_NODEVMTIME , "devmtime" }, 70 | { MNT_NOEXEC , "exec" }, 71 | { MNT_NOSUID , "suid" }, 72 | { MNT_RDONLY , "rdonly" }, 73 | { MNT_RELOAD , "reload" }, 74 | //{ MNT_RO , "ro" }, 75 | //{ MNT_RUMP , "rump" }, 76 | //{ MNT_RW , "rw" }, 77 | { MNT_SOFTDEP , "softdep" }, 78 | { MNT_SYMPERM , "symperm" }, 79 | //{ MNT_SYNC , "sync" }, 80 | { MNT_UNION , "union" }, 81 | { MNT_UPDATE , "update" }, 82 | //{ MNT_USERQUOTA , "userquota" }, 83 | 84 | { 0, NULL } 85 | }; 86 | 87 | static void 88 | show_mounts_minix (ShowMountType what) 89 | { 90 | show_mounts_generic_bsd (what, mntopt_map_minix); 91 | } 92 | 93 | static void 94 | handle_proc_branch_minix (void) 95 | { 96 | /* FIXME */ 97 | } 98 | 99 | struct procenv_ops platform_ops = 100 | { 101 | .driver = PROCENV_SET_DRIVER (minix), 102 | 103 | .get_kernel_bits = get_kernel_bits_generic, 104 | .get_time = get_time_generic, 105 | 106 | .signal_map = signal_map_minix, 107 | 108 | // FIXME: add show_sysconf (which will do sysctl!) 109 | 110 | .handle_proc_branch = handle_proc_branch_minix, 111 | 112 | .show_clocks = show_clocks_generic, 113 | .show_fds = show_fds_generic, 114 | 115 | .show_mounts = show_mounts_minix, 116 | .show_rlimits = show_rlimits_generic, 117 | }; 118 | -------------------------------------------------------------------------------- /src/platform/netbsd/platform-netbsd.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_NETBSD_H 9 | #define _PROCENV_PLATFORM_NETBSD_H 10 | 11 | #include "platform.h" 12 | #include "util.h" 13 | 14 | #endif /* _PROCENV_PLATFORM_NETBSD_H */ 15 | -------------------------------------------------------------------------------- /src/platform/netbsd/platform.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "platform-netbsd.h" 9 | 10 | static struct procenv_map signal_map_netbsd[] = { 11 | 12 | mk_map_entry (SIGABRT), 13 | mk_map_entry (SIGALRM), 14 | mk_map_entry (SIGBUS), 15 | 16 | { "SIGCHLD|SIGCLD", SIGCHLD }, 17 | 18 | mk_map_entry (SIGCONT), 19 | mk_map_entry (SIGFPE), 20 | mk_map_entry (SIGHUP), 21 | mk_map_entry (SIGILL), 22 | mk_map_entry (SIGINT), 23 | mk_map_entry (SIGKILL), 24 | mk_map_entry (SIGPIPE), 25 | mk_map_entry (SIGQUIT), 26 | mk_map_entry (SIGSEGV), 27 | mk_map_entry (SIGSTOP), 28 | mk_map_entry (SIGTERM), 29 | mk_map_entry (SIGTRAP), 30 | mk_map_entry (SIGTSTP), 31 | mk_map_entry (SIGTTIN), 32 | mk_map_entry (SIGUSR1), 33 | mk_map_entry (SIGUSR2), 34 | mk_map_entry (SIGIO), 35 | mk_map_entry (SIGPROF), 36 | mk_map_entry (SIGSYS), 37 | mk_map_entry (SIGURG), 38 | mk_map_entry (SIGVTALRM), 39 | mk_map_entry (SIGWINCH), 40 | mk_map_entry (SIGXCPU), 41 | mk_map_entry (SIGXFSZ), 42 | mk_map_entry (SIGEMT), 43 | mk_map_entry (SIGINFO), 44 | mk_map_entry (SIGPWR), 45 | 46 | { NULL, 0 }, 47 | }; 48 | 49 | static struct procenv_map64 mntopt_map[] = { 50 | 51 | { "asynchronous" , MNT_ASYNC }, 52 | { "NFS-exported" , MNT_EXPORTED }, 53 | { "local" , MNT_LOCAL }, 54 | { "noatime" , MNT_NOATIME }, 55 | { "noexec" , MNT_NOEXEC }, 56 | { "nosuid" , MNT_NOSUID }, 57 | { "with-quotas" , MNT_QUOTA }, 58 | { "read-only" , MNT_RDONLY }, 59 | { "soft-updates", MNT_SOFTDEP }, 60 | #if defined (MNT_SUJ) 61 | { "journaled-soft-updates", MNT_SUJ }, 62 | #endif 63 | { "synchronous", MNT_SYNCHRONOUS }, 64 | { "union", MNT_UNION }, 65 | 66 | { NULL, 0 }, 67 | }; 68 | 69 | static struct procenv_map if_flag_map_netbsd[] = { 70 | mk_map_entry (IFF_UP), 71 | mk_map_entry (IFF_BROADCAST), 72 | mk_map_entry (IFF_DEBUG), 73 | mk_map_entry (IFF_LOOPBACK), 74 | mk_map_entry (IFF_POINTOPOINT), 75 | mk_map_entry (IFF_RUNNING), 76 | mk_map_entry (IFF_NOARP), 77 | mk_map_entry (IFF_PROMISC), 78 | mk_map_entry (IFF_ALLMULTI), 79 | mk_map_entry (IFF_SIMPLEX), 80 | mk_map_entry (IFF_MULTICAST), 81 | 82 | { NULL, 0 }, 83 | }; 84 | 85 | static void 86 | show_mounts_netbsd (ShowMountType what) 87 | { 88 | show_mounts_generic_bsd (what, mntopt_map); 89 | } 90 | 91 | /* Who would have thought handling PIDs was so tricky? */ 92 | static void 93 | handle_proc_branch_netbsd (void) 94 | { 95 | int count = 0; 96 | int i; 97 | char errors[_POSIX2_LINE_MAX]; 98 | kvm_t *kvm; 99 | struct kinfo_proc2 *procs; 100 | struct kinfo_proc2 *p; 101 | pid_t current; 102 | int done = false; 103 | char *str = NULL; 104 | pid_t ultimate_parent = 0; 105 | 106 | common_assert (); 107 | 108 | current = getpid (); 109 | 110 | kvm = kvm_openfiles (NULL, NULL, NULL, KVM_NO_FILES, errors); 111 | if (! kvm) 112 | die ("unable to open kvm"); 113 | 114 | procs = kvm_getproc2 (kvm, KERN_PROC_ALL, 0, sizeof (struct kinfo_proc2), &count); 115 | if (! procs) 116 | die ("failed to get process info"); 117 | 118 | /* Calculate the lowest PID number which gives us the ultimate 119 | * parent of all processes. 120 | * 121 | * On NetBSD systems, PID 0 ('[system]') is the ultimate 122 | * parent rather than PID 1 ('init'). 123 | */ 124 | 125 | p = &procs[0]; 126 | ultimate_parent = p->p_pid; 127 | 128 | for (i = 1; i < count; i++) { 129 | p = &procs[i]; 130 | if (p->p_pid< ultimate_parent) 131 | ultimate_parent = p->p_pid; 132 | } 133 | 134 | while (! done) { 135 | for (i = 0; i < count && !done; i++) { 136 | p = &procs[i]; 137 | 138 | if (p->p_pid == current) { 139 | if (! ultimate_parent && current == ultimate_parent) { 140 | 141 | /* Found the "last" PID so record it and hop out */ 142 | appendf (&str, "%d ('%*s')", 143 | (int)current, 144 | KI_MAXCOMLEN, 145 | p->p_comm); 146 | done = true; 147 | break; 148 | } else { 149 | /* Found a valid parent pid */ 150 | appendf (&str, "%d ('%*s'), ", 151 | (int)current, 152 | KI_MAXCOMLEN, 153 | p->p_comm); 154 | } 155 | 156 | /* Move on */ 157 | current = p->p_ppid; 158 | } 159 | } 160 | } 161 | 162 | if (kvm_close (kvm) < 0) 163 | die ("failed to close kvm"); 164 | 165 | entry ("ancestry", "%s", str); 166 | free (str); 167 | } 168 | 169 | static PROCENV_CPU_SET_TYPE * 170 | get_cpuset_netbsd (void) 171 | { 172 | PROCENV_CPU_SET_TYPE *cs = NULL; 173 | int ret; 174 | 175 | cs = cpuset_create (); 176 | if (! cs) 177 | return NULL; 178 | 179 | ret = pthread_getaffinity_np (pthread_self (), cpuset_size (cs), cs); 180 | if (ret) { 181 | cpuset_destroy (cs); 182 | return NULL; 183 | } 184 | 185 | return cs; 186 | } 187 | 188 | static void 189 | free_cpuset_netbsd (PROCENV_CPU_SET_TYPE *cs) 190 | { 191 | cpuset_destroy (cs); 192 | } 193 | 194 | bool cpuset_has_cpu_netbsd (const PROCENV_CPU_SET_TYPE *cs, 195 | PROCENV_CPU_TYPE cpu) 196 | { 197 | return cpuset_isset (cpu, cs); 198 | } 199 | 200 | /* XXX:Notes: 201 | * 202 | * - show_cpu : it doesn't appear you can query the CPU of the 203 | * current process on NetBSD :-( 204 | */ 205 | struct procenv_ops platform_ops = 206 | { 207 | .driver = PROCENV_SET_DRIVER (netbsd), 208 | 209 | .get_kernel_bits = get_kernel_bits_generic, 210 | .get_mtu = get_mtu_generic, 211 | .get_time = get_time_generic, 212 | 213 | .get_cpuset = get_cpuset_netbsd, 214 | .free_cpuset = free_cpuset_netbsd, 215 | .cpuset_has_cpu = cpuset_has_cpu_netbsd, 216 | 217 | .signal_map = signal_map_netbsd, 218 | .if_flag_map = if_flag_map_netbsd, 219 | 220 | .show_clocks = show_clocks_generic, 221 | .show_confstrs = show_confstrs_generic, 222 | .show_cpu_affinities = show_cpu_affinities_generic, 223 | .show_fds = show_fds_generic, 224 | .show_mounts = show_mounts_netbsd, 225 | .show_rlimits = show_rlimits_generic, 226 | .show_timezone = show_timezone_generic, 227 | .show_libs = show_libs_generic, 228 | 229 | .handle_proc_branch = handle_proc_branch_netbsd, 230 | }; 231 | -------------------------------------------------------------------------------- /src/platform/openbsd/platform-openbsd.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_OPENBSD_H 9 | #define _PROCENV_PLATFORM_OPENBSD_H 10 | 11 | #include "platform.h" 12 | #include "util.h" 13 | 14 | #endif /* _PROCENV_PLATFORM_OPENBSD_H */ 15 | -------------------------------------------------------------------------------- /src/platform/openbsd/platform.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "platform-openbsd.h" 9 | 10 | static struct procenv_map signal_map_openbsd[] = { 11 | 12 | { SIGABRT, "SIGABRT|SIGIOT" }, 13 | 14 | mk_map_entry (SIGALRM), 15 | mk_map_entry (SIGBUS), 16 | 17 | { "SIGCHLD|SIGCLD", SIGCHLD }, 18 | 19 | mk_map_entry (SIGCONT), 20 | mk_map_entry (SIGFPE), 21 | mk_map_entry (SIGHUP), 22 | mk_map_entry (SIGILL), 23 | mk_map_entry (SIGINT), 24 | mk_map_entry (SIGKILL), 25 | mk_map_entry (SIGPIPE), 26 | mk_map_entry (SIGQUIT), 27 | mk_map_entry (SIGSEGV), 28 | mk_map_entry (SIGSTOP), 29 | mk_map_entry (SIGTERM), 30 | mk_map_entry (SIGTRAP), 31 | mk_map_entry (SIGTSTP), 32 | mk_map_entry (SIGTTIN), 33 | mk_map_entry (SIGUSR1), 34 | mk_map_entry (SIGUSR2), 35 | mk_map_entry (SIGIO), 36 | mk_map_entry (SIGPROF), 37 | mk_map_entry (SIGSYS), 38 | mk_map_entry (SIGURG), 39 | mk_map_entry (SIGVTALRM), 40 | mk_map_entry (SIGWINCH), 41 | mk_map_entry (SIGXCPU), 42 | mk_map_entry (SIGXFSZ), 43 | mk_map_entry (SIGEMT), 44 | mk_map_entry (SIGINFO), 45 | mk_map_entry (SIGTHR), 46 | mk_map_entry (SIGTTOU), 47 | 48 | { NULL, 0 }, 49 | }; 50 | 51 | static struct procenv_map64 mntopt_map[] = { 52 | 53 | { "asynchronous" , MNT_ASYNC }, 54 | { "NFS-exported" , MNT_EXPORTED }, 55 | { "local" , MNT_LOCAL }, 56 | { "noatime" , MNT_NOATIME }, 57 | { "noexec" , MNT_NOEXEC }, 58 | { "nosuid" , MNT_NOSUID }, 59 | { "with-quotas" , MNT_QUOTA }, 60 | { "read-only" , MNT_RDONLY }, 61 | { "synchronous" , MNT_SYNCHRONOUS }, 62 | 63 | #if defined (MNT_SUJ) 64 | { "journaled-soft-updates", MNT_SUJ }, 65 | #endif 66 | { "synchronous", MNT_SYNCHRONOUS }, 67 | 68 | { NULL, 0 } 69 | }; 70 | 71 | static struct procenv_map if_flag_map_openbsd[] = { 72 | mk_map_entry (IFF_UP), 73 | mk_map_entry (IFF_BROADCAST), 74 | mk_map_entry (IFF_DEBUG), 75 | mk_map_entry (IFF_LOOPBACK), 76 | mk_map_entry (IFF_POINTOPOINT), 77 | mk_map_entry (IFF_RUNNING), 78 | mk_map_entry (IFF_NOARP), 79 | mk_map_entry (IFF_PROMISC), 80 | mk_map_entry (IFF_ALLMULTI), 81 | mk_map_entry (IFF_SIMPLEX), 82 | mk_map_entry (IFF_MULTICAST), 83 | 84 | { NULL, 0 } 85 | }; 86 | 87 | static void 88 | show_mounts_openbsd (ShowMountType what) 89 | { 90 | show_mounts_generic_bsd (what, mntopt_map); 91 | } 92 | 93 | /* Who would have thought handling PIDs was so tricky? */ 94 | static void 95 | handle_proc_branch_openbsd (void) 96 | { 97 | int count = 0; 98 | int i; 99 | char errors[_POSIX2_LINE_MAX]; 100 | kvm_t *kvm; 101 | struct kinfo_proc *procs; 102 | struct kinfo_proc *p; 103 | pid_t current; 104 | int done = false; 105 | char *str = NULL; 106 | pid_t ultimate_parent = 0; 107 | 108 | common_assert (); 109 | 110 | current = getpid (); 111 | 112 | kvm = kvm_openfiles (NULL, NULL, NULL, KVM_NO_FILES, errors); 113 | if (! kvm) 114 | die ("unable to open kvm"); 115 | 116 | procs = kvm_getprocs (kvm, KERN_PROC_ALL, 0, sizeof (struct kinfo_proc), &count); 117 | if (! procs) 118 | die ("failed to get process info"); 119 | 120 | /* Calculate the lowest PID number which gives us the ultimate 121 | * parent of all processes. 122 | * 123 | * OpenBSD has init as PID 1. 124 | */ 125 | 126 | p = &procs[0]; 127 | ultimate_parent = p->p_pid; 128 | 129 | for (i = 1; i < count; i++) { 130 | p = &procs[i]; 131 | if (p->p_pid< ultimate_parent) 132 | ultimate_parent = p->p_pid; 133 | } 134 | 135 | while (! done) { 136 | for (i = 0; i < count && !done; i++) { 137 | p = &procs[i]; 138 | 139 | if (p->p_pid == current) { 140 | if (ultimate_parent == 1 && current == ultimate_parent) { 141 | /* Found the "last" PID so record it and hop out */ 142 | appendf (&str, "%d ('%s')", 143 | (int)current, 144 | p->p_comm); 145 | done = true; 146 | break; 147 | } else { 148 | /* Found a valid parent pid */ 149 | appendf (&str, "%d ('%s'), ", 150 | (int)current, 151 | p->p_comm); 152 | } 153 | 154 | /* Move on */ 155 | current = p->p_ppid; 156 | } 157 | } 158 | } 159 | 160 | if (kvm_close (kvm) < 0) 161 | die ("failed to close kvm"); 162 | 163 | entry ("ancestry", "%s", str); 164 | free (str); 165 | } 166 | 167 | /* XXX:Notes: 168 | * 169 | * - show_cpu : it doesn't appear you can query the CPU of the 170 | * current process on OpenBSD :-( 171 | */ 172 | struct procenv_ops platform_ops = 173 | { 174 | .driver = PROCENV_SET_DRIVER (openbsd), 175 | 176 | .get_kernel_bits = get_kernel_bits_generic, 177 | .get_mtu = get_mtu_generic, 178 | .get_time = get_time_generic, 179 | 180 | .signal_map = signal_map_openbsd, 181 | .if_flag_map = if_flag_map_openbsd, 182 | 183 | .show_clocks = show_clocks_generic, 184 | .show_confstrs = show_confstrs_generic, 185 | .show_cpu_affinities = show_cpu_affinities_generic, 186 | .show_fds = show_fds_generic, 187 | .show_mounts = show_mounts_openbsd, 188 | .show_rlimits = show_rlimits_generic, 189 | .show_timezone = show_timezone_generic, 190 | .show_libs = show_libs_generic, 191 | 192 | .handle_proc_branch = handle_proc_branch_openbsd, 193 | }; 194 | -------------------------------------------------------------------------------- /src/platform/platform-generic.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_GENERIC_H 9 | #define _PROCENV_PLATFORM_GENERIC_H 10 | 11 | #include "types.h" 12 | 13 | void show_fds_generic (void); 14 | void show_rlimits_generic (void); 15 | void show_confstrs_generic (void); 16 | long get_kernel_bits_generic (void); 17 | void show_human_size_entry (size_t value); 18 | 19 | #if !defined (PROCENV_PLATFORM_MINIX) 20 | int get_mtu_generic (const struct ifaddrs *ifaddr); 21 | #endif 22 | 23 | #if defined (PROCENV_PLATFORM_LINUX) || \ 24 | defined (PROCENV_PLATFORM_BSD) || \ 25 | defined (PROCENV_PLATFORM_HURD) || \ 26 | defined (PROCENV_PLATFORM_MINIX) 27 | 28 | void show_cpu_affinities_generic (void); 29 | 30 | #endif 31 | 32 | #if defined (PROCENV_PLATFORM_LINUX) || \ 33 | defined (PROCENV_PLATFORM_BSD) || \ 34 | defined (PROCENV_PLATFORM_HURD) || \ 35 | defined (PROCENV_PLATFORM_MINIX) || \ 36 | defined (PROCENV_PLATFORM_DARWIN) 37 | 38 | void show_pathconfs (ShowMountType what, const char *dir); 39 | 40 | #endif 41 | 42 | #if defined (PROCENV_PLATFORM_BSD) || \ 43 | defined (PROCENV_PLATFORM_MINIX) || \ 44 | defined (PROCENV_PLATFORM_DARWIN) 45 | 46 | char *get_mount_opts_generic_bsd (const struct procenv_map64 *opts, uint64_t flags); 47 | void show_mounts_generic_bsd (ShowMountType what, 48 | const struct procenv_map64 *mntopt_map); 49 | 50 | #endif 51 | 52 | #if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_HURD) 53 | 54 | void show_mounts_generic_linux (ShowMountType what); 55 | int get_canonical_generic_linux (const char *path, char *canonical, size_t len); 56 | 57 | #endif /* PROCENV_PLATFORM_LINUX || PROCENV_PLATFORM_HURD */ 58 | 59 | #if !defined (PROCENV_PLATFORM_DARWIN) 60 | bool get_time_generic (struct timespec *ts); 61 | void show_memory_generic (void); 62 | #endif 63 | 64 | void show_clocks_generic (void); 65 | 66 | #if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_BSD) || defined (PROCENV_PLATFORM_DARWIN) 67 | 68 | void show_timezone_generic (void); 69 | 70 | #endif 71 | 72 | #if ! defined (PROCENV_PLATFORM_ANDROID) && ! defined (PROCENV_PLATFORM_DARWIN) 73 | 74 | void show_libs_generic(void); 75 | 76 | #endif 77 | 78 | #endif /* _PROCENV_PLATFORM_GENERIC_H */ 79 | -------------------------------------------------------------------------------- /src/platform/unknown/platform-unknown.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PLATFORM_UNKNOWN_H 9 | #define _PROCENV_PLATFORM_UNKNOWN_H 10 | 11 | #include "platform.h" 12 | #include "util.h" 13 | 14 | #endif /* _PROCENV_PLATFORM_UNKNOWN_H */ 15 | -------------------------------------------------------------------------------- /src/platform/unknown/platform.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "platform-unknown.h" 9 | 10 | static struct procenv_map signal_map_generic[] = { 11 | 12 | mk_map_entry (SIGABRT), 13 | mk_map_entry (SIGALRM), 14 | mk_map_entry (SIGBUS), 15 | 16 | { "SIGCHLD|SIGCLD", SIGCHLD }, 17 | 18 | mk_map_entry (SIGCONT), 19 | 20 | #if defined SIGEMT 21 | mk_map_entry (SIGEMT), 22 | #endif 23 | 24 | mk_map_entry (SIGFPE), 25 | mk_map_entry (SIGHUP), 26 | mk_map_entry (SIGILL), 27 | 28 | #if defined SIGINFO 29 | mk_map_entry (SIGINFO), 30 | #endif 31 | 32 | mk_map_entry (SIGINT), 33 | 34 | #if defined SIGIO 35 | mk_map_entry (SIGIO), 36 | #endif 37 | 38 | #if defined SIGIOT 39 | mk_map_entry (SIGIOT), 40 | #endif 41 | 42 | mk_map_entry (SIGKILL), 43 | mk_map_entry (SIGPIPE), 44 | mk_map_entry (SIGPOLL), 45 | mk_map_entry (SIGPROF), 46 | 47 | #if defined SIGPWR 48 | mk_map_entry (SIGPWR), 49 | #endif 50 | 51 | mk_map_entry (SIGQUIT), 52 | mk_map_entry (SIGSEGV), 53 | mk_map_entry (SIGSTOP), 54 | mk_map_entry (SIGSYS), 55 | mk_map_entry (SIGTERM), 56 | mk_map_entry (SIGTRAP), 57 | mk_map_entry (SIGTSTP), 58 | mk_map_entry (SIGTTIN), 59 | mk_map_entry (SIGTTOU), 60 | mk_map_entry (SIGURG), 61 | mk_map_entry (SIGUSR1), 62 | mk_map_entry (SIGUSR2), 63 | mk_map_entry (SIGVTALRM), 64 | mk_map_entry (SIGWINCH), 65 | mk_map_entry (SIGXCPU), 66 | mk_map_entry (SIGXFSZ), 67 | 68 | { NULL, 0 }, 69 | }; 70 | 71 | struct procenv_ops platform_ops = 72 | { 73 | .driver = PROCENV_SET_DRIVER (unknown), 74 | 75 | .get_time = get_time_generic, 76 | 77 | .signal_map = signal_map_generic, 78 | .show_fds = show_fds_generic, 79 | .show_clocks = show_clocks_generic, 80 | }; 81 | -------------------------------------------------------------------------------- /src/pr_list.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2012-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | * Description: Generic list handling routines. 7 | *-------------------------------------------------------------------- 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | /** 15 | * pr_list_new: 16 | * 17 | * @data: data pointer to store in node. 18 | * 19 | * Create a new list entry. 20 | * 21 | * Returns: New PRList or NULL on error. 22 | **/ 23 | PRList * 24 | pr_list_new (void *data) 25 | { 26 | PRList *list; 27 | 28 | list = (PRList *)calloc (1, sizeof (PRList)); 29 | 30 | if (! list) 31 | return NULL; 32 | 33 | list->next = list->prev = list; 34 | 35 | list->data = data; 36 | 37 | return list; 38 | } 39 | 40 | int 41 | pr_list_empty(PRList *list) 42 | { 43 | assert (list); 44 | 45 | return list->next == list && list->prev == list; 46 | } 47 | 48 | /** 49 | * pr_list_append: 50 | * 51 | * @list: list to operate on, 52 | * @entry: new PRList to add. 53 | * 54 | * Add @entry after @list entry. 55 | * 56 | * Returns: Newly-added entry. 57 | **/ 58 | PRList * 59 | pr_list_append (PRList *list, PRList *entry) 60 | { 61 | assert (list); 62 | assert (entry); 63 | 64 | entry->next = list->next; 65 | entry->prev = list; 66 | 67 | list->next->prev = entry; 68 | list->next = entry; 69 | 70 | return entry; 71 | } 72 | 73 | /** 74 | * pr_list_append_str: 75 | * 76 | * @list: list to operate on, 77 | * @str: string value to add to new entry. 78 | * 79 | * Create entry containing @str and add it after @list. 80 | * 81 | * Returns: New entry. 82 | **/ 83 | PRList * 84 | pr_list_append_str (PRList *list, const char *str) 85 | { 86 | size_t len; 87 | 88 | assert (list); 89 | assert (str); 90 | 91 | len = strlen (str); 92 | 93 | return pr_list_appendn_str (list, str, len); 94 | } 95 | 96 | /** 97 | * pr_list_appendn_str: 98 | * 99 | * @list: list to operate on, 100 | * @str: string value to add to new entry, 101 | * @len: length of @str to add to entry. 102 | * 103 | * Create entry containing @str and add it after @list. 104 | * 105 | * Returns: New entry. 106 | **/ 107 | PRList * 108 | pr_list_appendn_str (PRList *list, const char *str, size_t len) 109 | { 110 | char *s; 111 | PRList *entry; 112 | 113 | assert (list); 114 | assert (str); 115 | 116 | s = strndup (str, 1+len); 117 | assert (s); 118 | 119 | entry = pr_list_new (s); 120 | assert (entry); 121 | 122 | pr_list_append (list, entry); 123 | 124 | return entry; 125 | } 126 | 127 | /** 128 | * pr_list_prepend: 129 | * 130 | * @list: list to operate on, 131 | * @entry: new PRList to add. 132 | * 133 | * Add @entry before @list entry. 134 | * 135 | * Returns: Newly-added entry. 136 | **/ 137 | PRList * 138 | pr_list_prepend (PRList *list, PRList *entry) 139 | { 140 | assert (list); 141 | assert (entry); 142 | 143 | entry->next = list; 144 | entry->prev = list->prev; 145 | 146 | list->prev->next = entry; 147 | list->prev = entry; 148 | 149 | return entry; 150 | } 151 | 152 | /** 153 | * pr_list_prepend_str: 154 | * 155 | * @list: list to operate on, 156 | * @str: string value to add to new entry. 157 | * 158 | * Create entry containing @str and add it before @list. 159 | * 160 | * Returns: New entry. 161 | **/ 162 | PRList * 163 | pr_list_prepend_str (PRList *list, const char *str) 164 | { 165 | size_t len; 166 | 167 | assert (list); 168 | assert (str); 169 | 170 | len = strlen (str); 171 | 172 | return pr_list_prependn_str (list, str, len); 173 | } 174 | 175 | /** 176 | * pr_list_prependn_str: 177 | * 178 | * @list: list to operate on, 179 | * @str: string value to add to new entry, 180 | * @len: length of @str to add to entry. 181 | * 182 | * Create entry containing @str and add it before @list. 183 | * 184 | * Returns: New entry. 185 | **/ 186 | PRList * 187 | pr_list_prependn_str (PRList *list, const char *str, size_t len) 188 | { 189 | char *s; 190 | PRList *entry; 191 | 192 | assert (list); 193 | assert (str); 194 | 195 | s = strndup (str, 1+len); 196 | assert (s); 197 | 198 | entry = pr_list_new (s); 199 | assert (entry); 200 | 201 | pr_list_prepend (list, entry); 202 | 203 | return entry; 204 | } 205 | 206 | int 207 | pr_list_cmp_str(PRList *la, PRList *lb) 208 | { 209 | const char *a, *b; 210 | 211 | assert (la); 212 | assert (lb); 213 | 214 | a = (const char *)la->data; 215 | b = (const char *)lb->data; 216 | 217 | if (!a && !b) { 218 | return 0; 219 | } else if (!a && b) { 220 | return -1; 221 | } else if (a && !b) { 222 | return 1; 223 | } else { 224 | int ret = strcmp(a, b); 225 | return ret; 226 | } 227 | } 228 | 229 | #define pr_list_next(list, direction) \ 230 | direction > 0 ? (list)->next : (list)->prev 231 | 232 | static PRList * 233 | pr_list_add_sorted_internal(PRList *list, 234 | PRList *entry, 235 | PRListCmp cmp, 236 | int prepend) 237 | { 238 | PRList *p; 239 | PRList *start; 240 | int direction; 241 | 242 | assert (list); 243 | assert (entry); 244 | assert (cmp); 245 | 246 | PRList *(*handler)(PRList *list, PRList *entry); 247 | 248 | handler = prepend ? pr_list_prepend : pr_list_append; 249 | 250 | /* 1 being forwards, -1 backwards */ 251 | direction = prepend ? 1 : -1; 252 | 253 | if (direction > 0) { 254 | start = list->next; 255 | } else { 256 | start = list->prev; 257 | } 258 | 259 | for (p = start; p != list; p = pr_list_next(p, direction)) { 260 | if (cmp (entry, p) < 0) 261 | return handler(p, entry); 262 | } 263 | 264 | return handler(list, entry); 265 | } 266 | 267 | PRList * 268 | pr_list_prepend_sorted(PRList *list, 269 | PRList *entry, 270 | PRListCmp cmp) 271 | { 272 | return pr_list_add_sorted_internal (list, entry, cmp, 1); 273 | } 274 | 275 | PRList * 276 | pr_list_append_sorted(PRList *list, 277 | PRList *entry, 278 | PRListCmp cmp) 279 | { 280 | return pr_list_add_sorted_internal (list, entry, cmp, 0); 281 | } 282 | 283 | PRList * 284 | pr_list_prepend_str_sorted(PRList *list, 285 | PRList *entry) 286 | { 287 | return pr_list_prepend_sorted(list, entry, pr_list_cmp_str); 288 | } 289 | 290 | PRList * 291 | pr_list_append_str_sorted(PRList *list, 292 | PRList *entry) 293 | { 294 | return pr_list_append_sorted(list, entry, pr_list_cmp_str); 295 | } 296 | 297 | /** 298 | * pr_list_remove: 299 | * 300 | * @list: list to operate on. 301 | * 302 | * Remove @entry from its containing list. 303 | * 304 | * Returns: Removed entry. 305 | **/ 306 | PRList * 307 | pr_list_remove (PRList *entry) 308 | { 309 | assert (entry); 310 | 311 | entry->prev->next = entry->next; 312 | entry->next->prev = entry->prev; 313 | 314 | /* No longer attached to list */ 315 | entry->next = entry->prev = entry; 316 | 317 | return entry; 318 | } 319 | 320 | /** 321 | * pr_list_foreach_visit: 322 | * 323 | * @list: list to operate on, 324 | * @visitor: function to run on every element on @list. 325 | * 326 | * Visit every entry in @list passing them to @visitor. 327 | **/ 328 | void 329 | pr_list_foreach_visit (PRList *list, PRListVisitor visitor) 330 | { 331 | PRList *p; 332 | 333 | assert (list); 334 | 335 | p = list; 336 | 337 | do { 338 | if (visitor) 339 | visitor (p); 340 | 341 | p = p->next; 342 | } while (p != list); 343 | } 344 | 345 | /** 346 | * pr_list_foreach_rev_visit: 347 | * 348 | * @list: list to operate on, 349 | * @visitor: function to run on every element on @list. 350 | * 351 | * Visit every entry in @list in reverse passing them to @visitor. 352 | **/ 353 | void 354 | pr_list_foreach_rev_visit (PRList *list, PRListVisitor visitor) 355 | { 356 | PRList *p; 357 | 358 | assert (list); 359 | 360 | p = list->prev; 361 | 362 | do { 363 | if (visitor) 364 | visitor (p); 365 | 366 | p = p->prev; 367 | } while (p != list->prev); 368 | } 369 | 370 | /** 371 | * pr_list_visitor_str: 372 | * 373 | * @entry: list entry to operate on. 374 | * 375 | * Display data in @entry as a string. 376 | **/ 377 | void 378 | pr_list_visitor_str (PRList *entry) 379 | { 380 | assert (entry); 381 | 382 | printf ("entry: addr=%p, prev=%p, next=%p, data=%p ('%s')\n", 383 | (void *)entry, 384 | (void *)entry->prev, 385 | (void *)entry->next, 386 | (void *)entry->data, 387 | entry->data ? (char *)entry->data : ""); 388 | fflush (NULL); 389 | } 390 | -------------------------------------------------------------------------------- /src/pr_list.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2012-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | * Description: Generic list handling header. 7 | *-------------------------------------------------------------------- 8 | */ 9 | 10 | #ifndef _PROCENV_LIST 11 | #define _PROCENV_LIST 12 | 13 | #ifdef HAVE_CONFIG_H 14 | # include 15 | #endif /* HAVE_CONFIG_H */ 16 | 17 | #include 18 | #include 19 | 20 | /* Double-linked list structure with no terminal node - a list of a 21 | * single item has next and prev pointers pointing "back round" to 22 | * itself. 23 | */ 24 | typedef struct list { 25 | void *data; 26 | struct list *next; 27 | struct list *prev; 28 | } PRList; 29 | 30 | typedef void (*PRListVisitor) (PRList *entry); 31 | 32 | typedef int (*PRListCmp) (PRList *a, PRList *b); 33 | 34 | PRList *pr_list_new (void *data); 35 | 36 | PRList *pr_list_append (PRList *list, PRList *entry); 37 | PRList *pr_list_append_str (PRList *list, const char *str); 38 | PRList *pr_list_appendn_str (PRList *list, const char *str, size_t len); 39 | 40 | PRList *pr_list_prepend (PRList *list, PRList *entry); 41 | PRList *pr_list_prepend_str (PRList *list, const char *str); 42 | PRList *pr_list_prependn_str (PRList *list, const char *str, size_t len); 43 | 44 | PRList *pr_list_prepend_str_sorted(PRList *list, PRList *entry); 45 | PRList *pr_list_prepend_sorted(PRList *list, PRList *entry, PRListCmp cmp); 46 | 47 | PRList *pr_list_append_str_sorted(PRList *list, PRList *entry); 48 | PRList *pr_list_append_sorted(PRList *list, PRList *entry, PRListCmp cmp); 49 | 50 | PRList *pr_list_remove (PRList *entry); 51 | 52 | void pr_list_foreach_visit (PRList *list, PRListVisitor visitor); 53 | void pr_list_foreach_rev_visit (PRList *list, PRListVisitor visitor); 54 | 55 | void pr_list_visitor_str (PRList *entry); 56 | 57 | #define PR_LIST_FOREACH(list, iter) \ 58 | for (PRList *iter = (list)->next; iter != (list); iter = iter->next) 59 | 60 | #define PR_LIST_FOREACH_SAFE(list, iter) \ 61 | for (PRList *iter = (list)->next, *tmp = iter->next; \ 62 | iter != (list); \ 63 | iter = tmp, tmp = iter->next) 64 | 65 | #define PR_LIST_FOREACH_REV(list, iter) \ 66 | for (PRList *iter = (list)->prev; iter != (list); iter = iter->prev) 67 | 68 | #define PR_LIST_FOREACH_STR(list) \ 69 | pr_list_foreach_visit (list, pr_list_visitor_str) 70 | 71 | #define PR_LIST_FOREACH_REV_STR(list) \ 72 | pr_list_foreach_rev_visit (list, pr_list_visitor_str) 73 | 74 | #endif /* _PROCENV_LIST */ 75 | -------------------------------------------------------------------------------- /src/procenv.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2012-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef PROCENV_H 9 | #define PROCENV_H 10 | 11 | /* for dl_iterate_phdr(3) */ 12 | #ifndef _GNU_SOURCE 13 | #define _GNU_SOURCE 14 | #endif 15 | 16 | #ifdef HAVE_CONFIG_H 17 | # include 18 | #endif /* HAVE_CONFIG_H */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | /* XXX: must come before sched.h on Minix! */ 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | 70 | #if !defined (PROCENV_PLATFORM_DARWIN) 71 | #include 72 | #endif 73 | 74 | #include "util.h" 75 | #include "string-util.h" 76 | #include "pr_list.h" 77 | #include "output.h" 78 | #include "platform.h" 79 | 80 | #include "platform-headers.h" 81 | 82 | /*********************************************************************/ 83 | // FIXME: ANDROID - need to auto-generate values!! 84 | 85 | #if defined PROCENV_PLATFORM_ANDROID 86 | 87 | #ifndef PACKAGE_NAME 88 | #define PACKAGE_NAME "procenv" 89 | #endif 90 | 91 | #ifndef PACKAGE_VERSION 92 | #define PACKAGE_VERSION "0.24" 93 | #endif 94 | 95 | #ifndef PACKAGE_STRING 96 | #define PACKAGE_STRING PACKAGE_NAME 97 | #endif 98 | 99 | #endif /* PROCENV_PLATFORM_ANDROID */ 100 | 101 | /*********************************************************************/ 102 | 103 | /** 104 | * PROCENV_FORMAT_VERSION: 105 | * 106 | * Version of output format. 107 | * 108 | * XXX: must be updated for every change. 109 | * 110 | * VERSION 1: 111 | * - Original format (up to procenv 0.27). 112 | * VERSION 2: 113 | * - Added --memory. 114 | * - Expanded --cpu. 115 | * - Added missing --cpu to default output. 116 | * - Moved memory page size from --misc to --memory. 117 | * VERSION 3: 118 | * - --fds: Added Capsicum capabilities for FreeBSD (alas this version 119 | * is a NOP for non-BSD platforms). 120 | * VERSION 4: 121 | * - Added "symbolic" values to --range output. 122 | * VERSION 5: 123 | * - Capabilities output changed on linux to show not just the 124 | * bounding set, but also permitted, inheritable and enabled values 125 | * along with the numeric value of the define. 126 | * VERSION 6: 127 | * - --misc: Added personality. 128 | * VERSION 7: 129 | * - --confstr and pathconf values in --mount now show 130 | * NA_STR rather than UNKNOWN_STR. --sysconf now shows NA_STR rather 131 | * than -1. 132 | * VERSION 8: 133 | * - --memory: Added NUMA API version. 134 | * - --shared-memory: Added swap_attempts and swap_successes. 135 | * VERSION 9: 136 | * - --meta now includes a 'build-type' field. 137 | * VERSION 10: 138 | * - Output is now sorted correctly (again - previously show_misc() 139 | * and show_libc() were being called in the wrong order). 140 | * VERSION 11: 141 | * - Added --namespaces. 142 | * VERSION 12: 143 | * - Change format of --namespaces output. 144 | * VERSION 13: 145 | * - Added I/O priority to --cpu. 146 | * VERSION 14: 147 | * - Added driver to --meta. 148 | * VERSION 15: 149 | * - Renamed "linux security module" to "security" module in --misc. 150 | * - Added procenv driver details to --meta. 151 | * VERSION 16: 152 | * - Sort feature-test macros. 153 | * VERSION 17: 154 | * - Added 'vm' to --misc output. 155 | * VERSION 18: 156 | * - Added 'ambient' to --capabilities output. 157 | * VERSION 19: 158 | * - Added more details to --memory and new capabilities to --capabilities. 159 | * VERSION 20: 160 | * - More --memory details for Darwin. 161 | * VERSION 21: 162 | * - Added `CLOCK_BOOTTIME_ALARM`, `CLOCK_PROCESS_CPUTIME_ID` 163 | * and `CLOCK_REALTIME_ALARM` to --clocks output and supported --timezone 164 | * on Darwin. 165 | * VERSION 22: 166 | * - Supported --libs on Darwin. 167 | * VERSION 23: 168 | * - Changed output order of --sysconf and --confstr, added various new 169 | * sysconf values, plus changed output format of --namespaces. 170 | * VERSION 24: 171 | * - Changed format of --fds. 172 | * Previously the 'device' value showed the path/name of the device 173 | * represented by the file descriptor. 174 | * Now, 'device' is a container showing the name, permissions, 175 | * major/minor numbers and owner of the file represented by the file 176 | * descriptor (assuming it isn't a pipe). 177 | **/ 178 | #define PROCENV_FORMAT_VERSION 24 179 | 180 | #if defined (PROCENV_PLATFORM_LINUX) || defined (PROCENV_PLATFORM_HURD) 181 | 182 | #if ! defined (_LINUX_CAPABILITY_VERSION_3) && ! defined (CAP_LAST_CAP) 183 | /* Ugh */ 184 | #define CAP_LAST_CAP 30 185 | #endif 186 | 187 | #endif /* PROCENV_PLATFORM_LINUX || PROCENV_PLATFORM_HURD */ 188 | 189 | /* Environment Variables */ 190 | #define PROCENV_OUTPUT_ENV "PROCENV_OUTPUT" 191 | #define PROCENV_FORMAT_ENV "PROCENV_FORMAT" 192 | #define PROCENV_FILE_ENV "PROCENV_FILE" 193 | #define PROCENV_FILE_APPEND_ENV "PROCENV_FILE_APPEND" 194 | #define PROCENV_EXEC_ENV "PROCENV_EXEC" 195 | #define PROCENV_INDENT_ENV "PROCENV_INDENT" 196 | #define PROCENV_INDENT_CHAR_ENV "PROCENV_INDENT_CHAR" 197 | #define PROCENV_SEPARATOR_ENV "PROCENV_SEPARATOR" 198 | #define PROCENV_CRUMB_SEPARATOR_ENV "PROCENV_CRUMB_SEPARATOR" 199 | 200 | #define PROCENV_BUFFER 1024 201 | 202 | /* FIXME: explain! */ 203 | #define CTIME_BUFFER 32 204 | 205 | #include "messages.h" 206 | 207 | /* Size of blocks we will show the user (as df(1) does) */ 208 | #define DF_BLOCK_SIZE 1024 209 | 210 | #define PROGRAM_AUTHORS "James O. D. Hunt " 211 | 212 | #define type_hex_width(type) \ 213 | (sizeof (type) * 2) 214 | 215 | #define show_clock_res(clock) \ 216 | { \ 217 | struct timespec res; \ 218 | section_open (#clock); \ 219 | if (clock_getres (clock, &res) < 0) \ 220 | entry ("resolution", "%s", UNKNOWN_STR); \ 221 | else \ 222 | entry ("resolution", "%ld.%09lds", res.tv_sec, res.tv_nsec); \ 223 | section_close (); \ 224 | } 225 | 226 | #define show_const(t, flag, constant) \ 227 | object_open (false); \ 228 | entry (#constant, "%d", !!(t.flag & constant)); \ 229 | object_close (false) 230 | 231 | /** 232 | * Show a terminal special characters attribute. 233 | * 234 | * t: struct termios, 235 | * elem: element of c_cc array, 236 | * lock_status: struct termios representing lock status of @t. 237 | **/ 238 | #define show_cc_tty(t, elem, lock_status) \ 239 | entry (#elem, "0x%x%s", \ 240 | t.c_cc[elem], \ 241 | lock_status.c_cc[elem] ? " (locked)" : ""); 242 | 243 | /** 244 | * Show a terminal attribute constant value. 245 | * 246 | * t: struct termios, 247 | * flag: name of attribute, 248 | * constant: value of @flag, 249 | * lock_status: struct termios representing lock status of @t. 250 | **/ 251 | #define show_const_tty(t, flag, constant, lock_status) \ 252 | entry (#constant, \ 253 | "%d%s", \ 254 | !!(t.flag & constant), \ 255 | !!(lock_status.flag) ? " (locked)" : "") 256 | 257 | #define show_pathconf(what, path, name) \ 258 | { \ 259 | long conf; \ 260 | errno = 0; \ 261 | conf = pathconf (path, name); \ 262 | if (conf == -1 && errno == 0) { \ 263 | entry (#name, "%s", NA_STR); \ 264 | } else { \ 265 | entry (#name, "%d", conf); \ 266 | } \ 267 | } 268 | 269 | #define SPEED(s) \ 270 | {#s, s} 271 | 272 | #define mk_map_entry(s) \ 273 | {#s, s} 274 | 275 | #define show_confstr(s) \ 276 | { \ 277 | _show_confstr (s, #s); \ 278 | } 279 | 280 | #define _show_confstr(s, name) \ 281 | { \ 282 | size_t len; \ 283 | char *buffer; \ 284 | \ 285 | errno = 0; \ 286 | len = confstr(s, NULL, 0); \ 287 | if (len && errno == 0) { \ 288 | \ 289 | buffer = calloc (1, len); \ 290 | if (! buffer) { \ 291 | die ("failed to allocate space for confstr"); \ 292 | } \ 293 | \ 294 | assert (confstr (s, buffer, len) == len); \ 295 | \ 296 | /* Convert multi-line values to multi-field */ \ 297 | for (size_t i = 0; i < len; i++) { \ 298 | if (buffer[i] == '\n') buffer[i] = ' '; \ 299 | } \ 300 | \ 301 | entry (name, "%s%s%s", \ 302 | buffer && buffer[0] ? "'" : "", \ 303 | buffer && buffer[0] ? buffer : NA_STR, \ 304 | buffer && buffer[0] ? "'" : ""); \ 305 | \ 306 | free (buffer); \ 307 | } \ 308 | } 309 | 310 | /* Note: param is ignored */ 311 | #define limit_max(l) \ 312 | ((unsigned long int)-1) 313 | 314 | #define show_limit(limit) \ 315 | { \ 316 | struct rlimit tmp; \ 317 | \ 318 | if (getrlimit (limit, &tmp) < 0) { \ 319 | die ("failed to query rlimit '%s'", #limit); \ 320 | } \ 321 | \ 322 | section_open (#limit); \ 323 | \ 324 | section_open ("soft"); \ 325 | entry ("current", "%lu", (unsigned long int)tmp.rlim_cur); \ 326 | entry ("max", "%lu", limit_max (limit)); \ 327 | section_close (); \ 328 | \ 329 | section_open ("hard"); \ 330 | entry ("current", "%lu", (unsigned long int)tmp.rlim_max); \ 331 | entry ("max", "%lu", limit_max (limit)); \ 332 | section_close (); \ 333 | \ 334 | section_close (); \ 335 | } 336 | 337 | #define show_usage(rusage, name) \ 338 | entry (#name, "%lu", rusage.name) 339 | 340 | #define get_sysconf(s) \ 341 | sysconf (s) 342 | 343 | #define mk_sysconf_map_entry(name) \ 344 | {#name, name } 345 | 346 | #define show_sizeof_type(type) \ 347 | entry (#type, "%lu byte%s", \ 348 | (unsigned long int)sizeof (type), \ 349 | sizeof (type) == 1 ? "" : "s") 350 | 351 | 352 | #define show_size(type) \ 353 | entry ("size", "%lu byte%s", \ 354 | (unsigned long int)sizeof (type), \ 355 | sizeof (type) == 1 ? "" : "s") 356 | 357 | #define free_if_set(ptr) \ 358 | if (ptr) free (ptr) 359 | 360 | char *get_path (const char *argv0); 361 | char *get_personality_flags (unsigned int flags); 362 | const char *get_arch (void); 363 | const char *get_group_name (gid_t gid); 364 | const char *get_os (void); 365 | const char *get_personality_name (unsigned int domain); 366 | const char *get_signal_name (int signum); 367 | const char *get_thread_scheduler_name (int sched); 368 | const char *get_user_name (gid_t gid); 369 | int get_major_minor (const char *path, unsigned int *_major, unsigned int *_minor); 370 | long get_kernel_bits (void); 371 | void get_priorities (void); 372 | void get_uname (void); 373 | 374 | void show_all_groups (void); 375 | void show_capabilities (void); 376 | void show_cgroups (void); 377 | void show_clocks (void); 378 | void show_compiler (void); 379 | void show_confstrs (void); 380 | void show_data_model (void); 381 | void show_libc (void); 382 | void show_libs (void); 383 | void show_locale (void); 384 | void show_mounts (ShowMountType what); 385 | void show_misc (void); 386 | void show_msg_queues (void); 387 | void show_network (void); 388 | void show_oom (void); 389 | void show_ranges (void); 390 | void show_rlimits (void); 391 | void show_semaphores (void); 392 | void show_shared_mem (void); 393 | void show_sizeof (void); 394 | void show_threads (void); 395 | void show_time (void); 396 | void show_timezone (void); 397 | void show_tty_attrs (void); 398 | void show_uname (void); 399 | void show_version (void); 400 | 401 | void handle_proc_branch (void); 402 | 403 | char *format_perms (mode_t mode); 404 | void format_time (const time_t *t, char *buffer, size_t len); 405 | void restore_locale (void); 406 | int qsort_compar (const void *a, const void *b); 407 | 408 | extern char **environ; 409 | 410 | extern Output output; 411 | extern pstring *doc; 412 | 413 | #endif /* PROCENV_H */ 414 | -------------------------------------------------------------------------------- /src/pstring.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2012-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "pstring.h" 9 | 10 | #include 11 | #include 12 | 13 | extern wchar_t wide_indent_char; 14 | 15 | wchar_t * 16 | char_to_wchar (const char *str) 17 | { 18 | const char *p; 19 | wchar_t *wstr = NULL; 20 | size_t len; 21 | size_t bytes; 22 | 23 | assert (str); 24 | 25 | mbstate_t ps; 26 | 27 | memset(&ps, 0, sizeof (ps)); 28 | 29 | errno = 0; 30 | len = mbsrtowcs (NULL, &str, 0, &ps); 31 | if (len == 0) { 32 | return NULL; 33 | } 34 | 35 | if (len == (size_t)-1 || errno == EILSEQ) { 36 | return NULL; 37 | } 38 | 39 | /* Another possible error state. 40 | * See mbsrtowcs(3). 41 | */ 42 | if (str == NULL) { 43 | return NULL; 44 | } 45 | 46 | /* include space for terminator */ 47 | bytes = (1 + len) * sizeof (wchar_t); 48 | 49 | wstr = malloc (bytes); 50 | if (! wstr) 51 | return NULL; 52 | 53 | p = str; 54 | 55 | memset(&ps, 0, sizeof (ps)); 56 | 57 | if (mbsrtowcs (wstr, &p, len, &ps) != len) 58 | goto error; 59 | 60 | /* ensure it's terminated */ 61 | wstr[len] = L'\0'; 62 | 63 | return wstr; 64 | 65 | error: 66 | free (wstr); 67 | return NULL; 68 | } 69 | 70 | char * 71 | wchar_to_char (const wchar_t *wstr) 72 | { 73 | char *str = NULL; 74 | size_t len; 75 | size_t bytes; 76 | size_t ret; 77 | 78 | assert (wstr); 79 | 80 | len = wcslen (wstr); 81 | 82 | /* determine number of MBS (char) bytes requires to hold the 83 | * wchar_t string. 84 | */ 85 | bytes = wcstombs (NULL, wstr, len); 86 | if (! bytes) 87 | return NULL; 88 | 89 | str = calloc (bytes + 1, sizeof (char)); 90 | if (! str) 91 | return NULL; 92 | 93 | /* actually perform the conversion */ 94 | ret = wcstombs (str, wstr, bytes); 95 | 96 | if (! ret) 97 | goto error; 98 | 99 | return str; 100 | 101 | error: 102 | free (str); 103 | return NULL; 104 | } 105 | 106 | pstring * 107 | pstring_new (void) 108 | { 109 | pstring *pstr = NULL; 110 | 111 | pstr = calloc (1, sizeof (pstring)); 112 | if (! pstr) 113 | return NULL; 114 | 115 | pstr->len = 0; 116 | pstr->size = 0; 117 | pstr->buf = NULL; 118 | 119 | return pstr; 120 | } 121 | 122 | pstring * 123 | pstring_create (const wchar_t *str) 124 | { 125 | pstring *pstr = NULL; 126 | 127 | assert (str); 128 | 129 | pstr = pstring_new (); 130 | 131 | if (! pstr) 132 | return NULL; 133 | 134 | pstr->buf = wcsdup (str); 135 | if (! pstr->buf) { 136 | pstring_free (pstr); 137 | return NULL; 138 | } 139 | 140 | /* include the L'\0' terminator */ 141 | pstr->len = 1 + wcslen (pstr->buf); 142 | 143 | pstr->size = pstr->len * sizeof (wchar_t); 144 | 145 | return pstr; 146 | } 147 | 148 | void 149 | pstring_free (pstring *str) 150 | { 151 | assert (str); 152 | 153 | if (str->buf) 154 | free (str->buf); 155 | 156 | free (str); 157 | } 158 | 159 | pstring * 160 | char_to_pstring (const char *str) 161 | { 162 | pstring *pstr = NULL; 163 | wchar_t *s; 164 | 165 | assert (str); 166 | 167 | s = char_to_wchar (str); 168 | if (! s) 169 | return NULL; 170 | 171 | pstr = pstring_create (s); 172 | 173 | free (s); 174 | 175 | return pstr; 176 | } 177 | 178 | char * 179 | pstring_to_char (const pstring *str) 180 | { 181 | assert (str); 182 | 183 | return wchar_to_char (str->buf); 184 | } 185 | 186 | /** 187 | * pstring_chomp: 188 | * 189 | * Remove trailing extraneous newlines and indent_chars from @str. 190 | **/ 191 | void 192 | pstring_chomp (pstring *str) 193 | { 194 | size_t len; 195 | int removable = 0; 196 | wchar_t *p; 197 | 198 | assert (str); 199 | 200 | /* Unable to add '\n' in this scenario */ 201 | if (str->len < 2) 202 | return; 203 | 204 | for (p = str->buf+str->len-1; 205 | *p == L'\n' || *p == wide_indent_char; 206 | p--, removable++) 207 | ; 208 | 209 | /* Chop string at the appropriate place after first adding a new 210 | * newline. 211 | */ 212 | if (removable > 1) { 213 | len = str->len - (removable-1); 214 | str->buf[len-1] = L'\n'; 215 | str->buf[len] = L'\0'; 216 | str->len = len; 217 | } 218 | } 219 | 220 | /** 221 | * pstring_compress: 222 | * 223 | * Remove lines composed entirely of whitespace from @str. 224 | * 225 | * This is required specifically for '--output=text' which in some 226 | * scenarios generates lines comprising pure whitespace. This is 227 | * unnecessary and results from the fact that when an 228 | * ELEMENT_TYPE_OBJECT_* is encountered, formatting is applied for the 229 | * previously seen element, but sometimes such "objects" should be 230 | * invisible. 231 | **/ 232 | void 233 | pstring_compress (pstring **wstr, wchar_t remove_char) 234 | { 235 | wchar_t *from; 236 | wchar_t *to; 237 | wchar_t *p; 238 | wchar_t *start; 239 | size_t count = 0; 240 | size_t blanks = 0; 241 | size_t new_len; 242 | size_t bytes; 243 | 244 | assert (wstr); 245 | 246 | to = from = (*wstr)->buf; 247 | assert (from); 248 | 249 | while (to && *to) { 250 | again: 251 | while (*to == L'\n' && *(to+1) == L'\n') { 252 | /* skip over blank lines */ 253 | to++; 254 | blanks++; 255 | } 256 | 257 | start = to; 258 | 259 | while (*to == remove_char) { 260 | /* skip runs of contiguous characters */ 261 | to++; 262 | count++; 263 | } 264 | 265 | if (to != start) { 266 | /* Only start consuming NLs at the end of a 267 | * contiguous run *iff* there was more than a 268 | * single removed char. This is a heuristic to 269 | * avoid removing valid entries for example env 270 | * vars that are set to nul are shown as: 271 | * 272 | * 'var: ' 273 | * 274 | * Shudder. 275 | */ 276 | if (*to == L'\n' && to != start+1) { 277 | while (*to == L'\n') { 278 | /* consume the NL at the end of the contiguous run */ 279 | to++; 280 | } 281 | 282 | /* check to ensure that we haven't entered a new line 283 | * containing another block of chars to remove. 284 | */ 285 | if (*to == remove_char) 286 | goto again; 287 | 288 | blanks++; 289 | 290 | } else { 291 | /* not a full line so backtrack */ 292 | to = start; 293 | count = 0; 294 | } 295 | } 296 | 297 | *from++ = *to++; 298 | } 299 | 300 | /* terminate */ 301 | *from = L'\0'; 302 | 303 | if (blanks || count) { 304 | new_len = (*wstr)->len - (blanks + count); 305 | 306 | bytes = new_len * sizeof (wchar_t); 307 | 308 | p = realloc ((*wstr)->buf, bytes); 309 | assert (p); 310 | 311 | (*wstr)->buf = p; 312 | 313 | (*wstr)->buf[new_len-1] = L'\0'; 314 | 315 | (*wstr)->len = new_len; 316 | (*wstr)->size = bytes; 317 | } 318 | } 319 | 320 | -------------------------------------------------------------------------------- /src/pstring.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_PSTRING_H 9 | #define _PROCENV_PSTRING_H 10 | 11 | /* for wcsdup(3) */ 12 | #ifndef _GNU_SOURCE 13 | #define _GNU_SOURCE 14 | #endif 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /** 22 | * @buf: string, 23 | * @len: number of _characters_ (*NOT* bytes!) in @buf, 24 | * @size: allocated size of @buf in bytes. 25 | **/ 26 | typedef struct procenv_string { 27 | wchar_t *buf; 28 | size_t len; 29 | size_t size; 30 | } pstring; 31 | 32 | pstring *pstring_new (void); 33 | pstring *pstring_create (const wchar_t *str); 34 | pstring *char_to_pstring (const char *str); 35 | char *pstring_to_char (const pstring *str); 36 | void pstring_chomp (pstring *str); 37 | void pstring_compress (pstring **wstr, wchar_t remove_char); 38 | void pstring_free (pstring *str); 39 | int encode_string (pstring **pstr); 40 | 41 | wchar_t *char_to_wchar (const char *str); 42 | char *wchar_to_char (const wchar_t *wstr); 43 | 44 | #endif /* _PROCENV_PSTRING_H */ 45 | -------------------------------------------------------------------------------- /src/string-util.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "string-util.h" 9 | 10 | /* append @src to @dest */ 11 | void 12 | append (char **dest, const char *src) 13 | { 14 | size_t len; 15 | 16 | assert (dest); 17 | assert (src); 18 | 19 | len = strlen (src); 20 | 21 | appendn (dest, src, len); 22 | } 23 | 24 | /* Version of append() that operates on a wide string @dest and @src */ 25 | void 26 | wappend (pstring **dest, const wchar_t *src) 27 | { 28 | size_t len; 29 | 30 | assert (dest); 31 | assert (src); 32 | 33 | len = wcslen (src); 34 | 35 | wappendn (dest, src, len); 36 | } 37 | 38 | /* Version of append() that operates on a wide string @dest 39 | * and multi-byte @src. 40 | */ 41 | void 42 | wmappend (pstring **dest, const char *src) 43 | { 44 | wchar_t *wide_src = NULL; 45 | 46 | assert (dest); 47 | assert (src); 48 | 49 | wide_src = char_to_wchar (src); 50 | if (! wide_src) 51 | die ("failed to allocate space for wide string"); 52 | 53 | wappend (dest, wide_src); 54 | 55 | free (wide_src); 56 | } 57 | 58 | /** 59 | * appendn: 60 | * 61 | * @dest: [output] string to append to, 62 | * @src: string to append to @dest, 63 | * @len: length of @new. 64 | * 65 | * Append first @len bytes of @new to @str, 66 | * ensuring result is nul-terminated. 67 | **/ 68 | void 69 | appendn (char **dest, const char *src, size_t len) 70 | { 71 | size_t total; 72 | 73 | assert (dest); 74 | assert (src); 75 | 76 | if (! len) 77 | return; 78 | 79 | if (! *dest) 80 | *dest = strdup (""); 81 | if (! *dest) 82 | die ("failed to allocate space for string"); 83 | 84 | /* +1 for terminating nul */ 85 | total = strlen (*dest) + 1; 86 | 87 | total += len; 88 | 89 | *dest = realloc (*dest, total); 90 | assert (*dest); 91 | 92 | if (! *dest) { 93 | /* string is empty, so initialise the memory to avoid 94 | * surprises with strncat() being unable to find the 95 | * terminator! 96 | */ 97 | memset (*dest, '\0', total); 98 | } 99 | 100 | strncat (*dest, src, len); 101 | 102 | assert ((*dest)[total-1] == '\0'); 103 | } 104 | 105 | /* Version of appendn() that operates on a wide string @dest and @src */ 106 | void 107 | wappendn (pstring **dest, const wchar_t *src, size_t len) 108 | { 109 | wchar_t *p; 110 | size_t total; 111 | size_t bytes; 112 | 113 | assert (dest); 114 | assert (src); 115 | 116 | if (! len) 117 | return; 118 | 119 | if (! *dest) 120 | *dest = pstring_new (); 121 | if (! *dest) 122 | die ("failed to allocate space for pstring"); 123 | 124 | total = (*dest)->len + len; 125 | 126 | /* +1 for terminating nul */ 127 | bytes = (1 + total) * sizeof (wchar_t); 128 | 129 | p = realloc ((*dest)->buf, bytes); 130 | 131 | /* FIXME: turn into die() [all occurrences!] */ 132 | assert (p); 133 | 134 | (*dest)->buf = p; 135 | 136 | if (! (*dest)->len) { 137 | /* pstring is empty, so initialise the memory to avoid 138 | * surprises with wcsncat() being unable to find the 139 | * terminator! 140 | */ 141 | memset ((*dest)->buf, 0, bytes); 142 | } 143 | 144 | /* Used to check for overrun */ 145 | (*dest)->buf[total] = L'\0'; 146 | 147 | wcsncat ((*dest)->buf + (*dest)->len, src, len); 148 | 149 | /* update */ 150 | (*dest)->len = total; 151 | (*dest)->size = bytes; 152 | 153 | /* check for overrun */ 154 | assert ((*dest)->buf[total] == L'\0'); 155 | } 156 | 157 | /* Version of appendn() that operates on a wide string @dest and 158 | * multi-byte @src. 159 | */ 160 | void 161 | wmappendn (pstring **dest, const char *src, size_t len) 162 | { 163 | wchar_t *wide_src = NULL; 164 | 165 | assert (dest); 166 | assert (src); 167 | 168 | if (! len) 169 | return; 170 | 171 | wide_src = char_to_wchar (src); 172 | if (! wide_src) 173 | die ("failed to allocate space for wide string"); 174 | 175 | wappendn (dest, wide_src, wcslen (wide_src)); 176 | 177 | free (wide_src); 178 | } 179 | 180 | /* append @fmt and args to @dest */ 181 | void 182 | appendf (char **dest, const char *fmt, ...) 183 | { 184 | va_list ap; 185 | 186 | assert (dest); 187 | assert (fmt); 188 | 189 | va_start (ap, fmt); 190 | 191 | appendva (dest, fmt, ap); 192 | 193 | va_end (ap); 194 | } 195 | 196 | /* Version of appendf() that operates on a wide string @dest 197 | * and @fmt. 198 | */ 199 | void 200 | wappendf (pstring **dest, const wchar_t *fmt, ...) 201 | { 202 | va_list ap; 203 | 204 | assert (dest); 205 | assert (fmt); 206 | 207 | va_start (ap, fmt); 208 | 209 | wappendva (dest, fmt, ap); 210 | 211 | va_end (ap); 212 | } 213 | 214 | /* Version of appendf() that operates on a wide string @dest 215 | * and multi-byte @fmt. 216 | */ 217 | void 218 | wmappendf (pstring **dest, const char *fmt, ...) 219 | { 220 | wchar_t *wide_fmt = NULL; 221 | va_list ap; 222 | 223 | assert (dest); 224 | assert (fmt); 225 | 226 | wide_fmt = char_to_wchar (fmt); 227 | if (! wide_fmt) 228 | die ("failed to allocate memory for wide format"); 229 | 230 | va_start (ap, fmt); 231 | 232 | wappendva (dest, wide_fmt, ap); 233 | 234 | va_end (ap); 235 | 236 | free (wide_fmt); 237 | } 238 | 239 | /* append @fmt and args to @dest */ 240 | void 241 | appendva (char **dest, const char *fmt, va_list ap) 242 | { 243 | int ret; 244 | char *new = NULL; 245 | char *p; 246 | size_t bytes; 247 | 248 | /* Start with a guess for how big we think the buffer needs to 249 | * be. 250 | */ 251 | size_t len = DEFAULT_ALLOC_GUESS_SIZE; 252 | 253 | assert (dest); 254 | assert (fmt); 255 | 256 | bytes = (1 + len) * sizeof (char); 257 | 258 | /* we could use vasprintf(3), but that's GNU-specific and hence 259 | * not available everywhere we need it. 260 | */ 261 | new = malloc (bytes); 262 | if (! new) 263 | die ("failed to allocate space for string"); 264 | 265 | memset (new, '\0', bytes); 266 | 267 | /* keep on increasing size of buffer until the translation 268 | * succeeds. 269 | */ 270 | while (true) { 271 | va_list ap_copy; 272 | 273 | va_copy (ap_copy, ap); 274 | ret = vsnprintf (new, len, fmt, ap_copy); 275 | va_end (ap_copy); 276 | 277 | if (ret < 0) 278 | die ("failed to format string"); 279 | 280 | if ((size_t)ret < len) { 281 | /* now we have sufficient space */ 282 | break; 283 | } 284 | 285 | /* Bump to allow one char to be written */ 286 | len++; 287 | 288 | /* recalculate number of bytes */ 289 | bytes = (1 + len) * sizeof (char); 290 | 291 | p = realloc (new, bytes); 292 | if (! p) 293 | die ("failed to allocate space for string"); 294 | 295 | new = p; 296 | } 297 | 298 | if (*dest) { 299 | append (dest, new); 300 | free (new); 301 | } else { 302 | *dest = new; 303 | } 304 | } 305 | 306 | /* Version of appendva() that operates on a wide string @dest 307 | * and @fmt. 308 | */ 309 | void 310 | wappendva (pstring **dest, const wchar_t *fmt, va_list ap) 311 | { 312 | int ret; 313 | wchar_t *new = NULL; 314 | wchar_t *p; 315 | size_t bytes; 316 | va_list ap_copy; 317 | 318 | /* Start with a guess for how big we think the buffer needs to 319 | * be. 320 | */ 321 | size_t len = DEFAULT_ALLOC_GUESS_SIZE; 322 | 323 | assert (dest); 324 | assert (fmt); 325 | 326 | bytes = (1 + len) * sizeof (wchar_t); 327 | 328 | new = malloc (bytes); 329 | if (! new) 330 | die ("failed to allocate space for wide string"); 331 | 332 | memset (new, '\0', bytes); 333 | 334 | /* keep on increasing size of buffer until the translation 335 | * succeeds. 336 | */ 337 | while (true) { 338 | va_copy (ap_copy, ap); 339 | ret = vswprintf (new, len, fmt, ap_copy); 340 | va_end (ap_copy); 341 | 342 | if ((size_t)ret < len) { 343 | /* now we have sufficient space, so update for 344 | * actual number of bytes used (including the 345 | * terminator!) 346 | * 347 | * Note that, conveniently, if the string is 348 | * zero-characters long (ie ""), ret will be -1 349 | * which we correct to 0. 350 | */ 351 | len = ret + 1; 352 | 353 | break; 354 | } 355 | 356 | /* Bump to allow one more wide-char to be written */ 357 | len++; 358 | 359 | /* recalculate number of bytes */ 360 | bytes = (1 + len) * sizeof (wchar_t); 361 | 362 | p = realloc (new, bytes); 363 | if (! p) 364 | die ("failed to allocate space for string"); 365 | 366 | new = p; 367 | 368 | memset (new, '\0', bytes); 369 | } 370 | 371 | if (*dest) { 372 | wappend (dest, new); 373 | free (new); 374 | } else { 375 | wchar_t *n; 376 | 377 | /* recalculate number of bytes */ 378 | bytes = (1 + len) * sizeof (wchar_t); 379 | 380 | /* compress */ 381 | n = realloc (new, bytes); 382 | 383 | if (! n) 384 | die ("failed to reallocate space"); 385 | 386 | new = n; 387 | 388 | (*dest) = pstring_new (); 389 | assert (*dest); 390 | (*dest)->buf = new; 391 | (*dest)->len = len; 392 | (*dest)->size = bytes; 393 | } 394 | } 395 | 396 | /* Version of appendva() that operates on a wide string @dest 397 | * and multi-byte @fmt. 398 | */ 399 | void 400 | wmappendva (pstring **dest, const char *fmt, va_list ap) 401 | { 402 | wchar_t *wide_fmt = NULL; 403 | va_list ap_copy; 404 | 405 | assert (dest); 406 | assert (fmt); 407 | 408 | wide_fmt = char_to_wchar (fmt); 409 | if (! wide_fmt) 410 | die ("failed to allocate memory for wide format"); 411 | 412 | va_copy (ap_copy, ap); 413 | wappendva (dest, wide_fmt, ap_copy); 414 | va_end (ap_copy); 415 | 416 | free (wide_fmt); 417 | } 418 | 419 | /* 420 | * Append @src onto the end of @dest. 421 | */ 422 | void 423 | pappend (pstring **dest, const pstring *src) 424 | { 425 | size_t total; 426 | size_t bytes; 427 | wchar_t *p; 428 | 429 | assert (dest); 430 | assert (src); 431 | 432 | if (! src->len) 433 | return; 434 | 435 | if (! *dest) 436 | *dest = pstring_new (); 437 | if (! *dest) 438 | die ("failed to allocate space for pstring"); 439 | 440 | total = (*dest)->len + src->len; 441 | 442 | /* adjust since we only store _one_ of the string terminators 443 | * from @dest and @src. 444 | */ 445 | total--; 446 | 447 | /* +1 for terminating nul */ 448 | bytes = (1 + total) * sizeof (wchar_t); 449 | 450 | p = realloc ((*dest)->buf, bytes); 451 | 452 | /* FIXME: turn into die() [all occurrences!] */ 453 | assert (p); 454 | 455 | (*dest)->buf = p; 456 | 457 | wcsncat ((*dest)->buf + (*dest)->len, src->buf, src->len); 458 | 459 | /* update */ 460 | (*dest)->len = total; 461 | (*dest)->size = bytes; 462 | 463 | /* Used to check for overrun */ 464 | (*dest)->buf[total] = L'\0'; 465 | } 466 | 467 | /** 468 | * @string: input, 469 | * @delimiter: field delimiter, 470 | * @compress: if true, ignore repeated contiguous delimiter characters, 471 | * @array: [output] array of fields, which this function will allocate. 472 | * 473 | * Notes: it is the callers responsibility to free @array 474 | * if the returned value is >0. 475 | * 476 | * Returns: number of fields in @string. 477 | **/ 478 | size_t 479 | split_fields (const char *string, char delimiter, int compress, char ***array) 480 | { 481 | const char *p = NULL; 482 | const char *start = NULL; 483 | size_t count = 0; 484 | char *elem; 485 | char **new; 486 | 487 | assert (string); 488 | assert (delimiter); 489 | assert (array); 490 | 491 | *array = NULL; 492 | 493 | new = realloc ((*array), sizeof (char *) * (1+count)); 494 | assert (new); 495 | 496 | new[0] = NULL; 497 | *array = new; 498 | 499 | p = string; 500 | 501 | while (p && *p) { 502 | /* skip leading prefix */ 503 | while (compress && p && *p == delimiter) 504 | p++; 505 | 506 | if (! *p) 507 | break; 508 | 509 | /* found a field */ 510 | count++; 511 | 512 | if (! compress) 513 | p++; 514 | 515 | /* skip over the field */ 516 | start = p; 517 | while (p && *p && *p != delimiter) 518 | p++; 519 | 520 | elem = strndup (start, p-start); 521 | assert (elem); 522 | 523 | new = realloc ((*array), sizeof (char *) * (1+count)); 524 | assert (new); 525 | 526 | new[count-1] = elem; 527 | *array = new; 528 | } 529 | 530 | return count; 531 | } 532 | 533 | -------------------------------------------------------------------------------- /src/string-util.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_STRING_UTIL_H 9 | #define _PROCENV_STRING_UTIL_H 10 | 11 | /* for strndup(3) */ 12 | #ifndef _GNU_SOURCE 13 | #define _GNU_SOURCE 14 | #endif 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "pstring.h" 22 | #include "output.h" 23 | #include "util.h" 24 | 25 | #define DEFAULT_ALLOC_GUESS_SIZE 8 26 | 27 | /* operate on multi-bytes */ 28 | void append (char **dest, const char *src); 29 | void appendn (char **dest, const char *src, size_t len); 30 | void appendf (char **dest, const char *fmt, ...); 31 | void appendva (char **dest, const char *fmt, va_list ap); 32 | 33 | /* operate on pure wide-characters */ 34 | void wappend (pstring **dest, const wchar_t *src); 35 | void wappendn (pstring **dest, const wchar_t *src, size_t len); 36 | void wappendf (pstring **dest, const wchar_t *fmt, ...); 37 | void wappendva (pstring **dest, const wchar_t *fmt, va_list ap); 38 | 39 | /* operate on wide-characters, but using multi-byte formats */ 40 | void wmappend (pstring **dest, const char *src); 41 | void wmappendn (pstring **dest, const char *src, size_t len); 42 | void wmappendf (pstring **dest, const char *fmt, ...); 43 | void wmappendva (pstring **dest, const char *fmt, va_list ap); 44 | 45 | void pappend (pstring **dest, const pstring *src); 46 | size_t split_fields (const char *string, char delimiter, 47 | int compress, char ***array); 48 | 49 | #endif /* _PROCENV_STRING_UTIL_H */ 50 | -------------------------------------------------------------------------------- /src/tests/show_compiler_details: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #--------------------------------------------------------------------- 3 | # Copyright (c) 2012-2021 James O. D. Hunt . 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-or-later 6 | #--------------------------------------------------------------------- 7 | 8 | #--------------------------------------------------------------------- 9 | # Description: Script to dump preprocessor/compiler/linker details. 10 | # Notes: Tested with gcc and clang. 11 | #--------------------------------------------------------------------- 12 | 13 | CC=${CC:-cc} 14 | CPP=${CPP:-cpp} 15 | LD=${LD:-ld} 16 | 17 | # handle strange environments 18 | command -v gcpp >/dev/null 2>&1 && CPP=gcpp 19 | command -v gcc >/dev/null 2>&1 && CC=gcc 20 | 21 | echo "XXX:--------------------------------------------------" 22 | echo "XXX: $0: preprocessor ('$CPP') version" 23 | echo 24 | $CPP --version &1 43 | echo 44 | 45 | echo "XXX:--------------------------------------------------" 46 | echo "XXX: $0: preprocessor ('$CPP') pre-defined symbols" 47 | echo 48 | $CPP -dM < /dev/null 2>&1 49 | echo 50 | 51 | echo "XXX:--------------------------------------------------" 52 | echo "XXX: $0: compiler ('$CC') features" 53 | echo 54 | $CC -v -E &1 55 | echo 56 | 57 | echo "XXX:--------------------------------------------------" 58 | echo "XXX: $0: compiler ('$CC') search paths" 59 | echo 60 | $CC -print-search-dirs &1 61 | echo 62 | echo "XXX:--------------------------------------------------" 63 | -------------------------------------------------------------------------------- /src/tests/show_machine_details: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | #--------------------------------------------------------------------- 3 | # Copyright (c) 2016-2021 James O. D. Hunt . 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-or-later 6 | #--------------------------------------------------------------------- 7 | 8 | #--------------------------------------------------------------------- 9 | # Description: Script to dump machine details, to help debug build 10 | # errors. 11 | #--------------------------------------------------------------------- 12 | 13 | export LANG=C 14 | export LC_ALL=C 15 | 16 | readonly script_name=${0##*/} 17 | 18 | set -o errexit 19 | set -o nounset 20 | 21 | [ -n "${BASH_VERSION:-}" ] && set -o errtrace 22 | [ -n "${DEBUG:-}" ] && set -o xtrace 23 | 24 | info() 25 | { 26 | local msg="$*" 27 | echo "INFO: $script_name: $msg" 28 | } 29 | 30 | show_generic() 31 | { 32 | info "# Generic system details" 33 | 34 | local file 35 | 36 | for file in \ 37 | "/etc/issue" \ 38 | "/etc/lsb-release" \ 39 | "/etc/os-release" 40 | do 41 | [ ! -s "$file" ] && continue 42 | 43 | info "## File '$file'" 44 | cat "$file" 2>/dev/null || true 45 | done 46 | 47 | info "## uname" 48 | uname -a 49 | 50 | info "## ulimit" 51 | ulimit -a 52 | } 53 | 54 | show_compiler() 55 | { 56 | info "# Compiler details" 57 | 58 | local cc 59 | 60 | for cc in \ 61 | "clang" \ 62 | "gcc" 63 | do 64 | command -v $cc >/dev/null 2>&1 || continue 65 | 66 | info "## '$cc' compiler" 67 | $cc --version 68 | done 69 | } 70 | 71 | show_linux() 72 | { 73 | info "# Linux details" 74 | 75 | info "## Memory details" 76 | cat /proc/meminfo 77 | echo 78 | 79 | info "## CPU count" 80 | grep -c ^processor /proc/cpuinfo 81 | echo 82 | 83 | info "## CPU details" 84 | 85 | # show first CPU only 86 | awk 'BEGIN { RS=""; } { printf ("%s\n", $0); exit (0); }' \ 87 | /proc/cpuinfo 88 | echo 89 | 90 | kvm=$(cat /sys/module/kvm_intel/parameters/nested 2>/dev/null \ 91 | || echo N) 92 | 93 | info "## Nested KVM support" 94 | echo "$kvm" 95 | echo 96 | 97 | info "## Kernel modules" 98 | lsmod | sort 99 | } 100 | 101 | show_darwin() 102 | { 103 | info "# Darwin/Mac OSX details" 104 | 105 | info "## Host information" 106 | hostinfo 107 | } 108 | 109 | show_bsd() 110 | { 111 | info "# *BSD details" 112 | 113 | info "## File 'rc.conf'" 114 | grep -Ev "^(#|$)" /etc/rc.conf | sort 115 | } 116 | 117 | show_hurd() 118 | { 119 | info "# Hurd details" 120 | 121 | # FIXME: What to do? 122 | true 123 | } 124 | 125 | main() 126 | { 127 | local system=$(uname -s|tr '[A-Z]' '[a-z]') 128 | 129 | info "# System type: '$system'" 130 | 131 | show_generic 132 | 133 | show_compiler 134 | 135 | case "$system" in 136 | 137 | *bsd) show_bsd ;; 138 | darwin) show_darwin ;; 139 | gnu) show_hurd ;; 140 | linux) show_linux ;; 141 | 142 | esac 143 | } 144 | 145 | main "$@" 146 | -------------------------------------------------------------------------------- /src/types.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_TYPES_H 9 | #define _PROCENV_TYPES_H 10 | 11 | #include 12 | 13 | struct procenv_map { 14 | const char *name; 15 | unsigned int num; 16 | }; 17 | 18 | struct procenv_map64 { 19 | const char *name; 20 | uint64_t num; 21 | }; 22 | 23 | #endif /* _PROCENV_TYPES_H */ 24 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #include "util.h" 9 | 10 | #if defined(PROCENV_PLATFORM_LINUX) || defined(PROCENV_PLATFORM_ANDROID) 11 | #include 12 | #endif 13 | 14 | // FIXME 15 | extern struct procenv_user user; 16 | extern struct procenv_misc misc; 17 | 18 | struct baud_speed 19 | { 20 | char *name; 21 | speed_t speed; 22 | }; 23 | 24 | /** 25 | * fd_valid: 26 | * @fd: file descriptor. 27 | * 28 | * Return 1 if @fd is valid, else 0. 29 | **/ 30 | int 31 | fd_valid (int fd) 32 | { 33 | int flags = 0; 34 | 35 | if (fd < 0) 36 | return 0; 37 | 38 | errno = 0; 39 | flags = fcntl (fd, F_GETFL); 40 | 41 | if (flags < 0) 42 | return 0; 43 | 44 | /* redundant really */ 45 | if (errno == EBADF) 46 | return 0; 47 | 48 | return 1; 49 | } 50 | 51 | #if !defined (PROCENV_PLATFORM_HURD) && \ 52 | !defined (PROCENV_PLATFORM_MINIX) && \ 53 | !defined (PROCENV_PLATFORM_DARWIN) 54 | 55 | /** 56 | * is_console: 57 | * @fd: open file descriptor. 58 | * 59 | * Check if specified file descriptor is attached to a _console_ 60 | * device (physical or virtual). 61 | * 62 | * Notes: 63 | * - ptys are NOT consoles :) 64 | * - running inside screen/tmux will report not running on console. 65 | * 66 | * Returns: true if @fd is attached to a console, else false. 67 | **/ 68 | int 69 | is_console (int fd) 70 | { 71 | struct vt_mode vt; 72 | int ret; 73 | 74 | ret = ioctl (fd, VT_GETMODE, &vt); 75 | 76 | return !ret; 77 | } 78 | #endif 79 | 80 | /** 81 | * is_big_endian: 82 | * 83 | * Returns: true if system is big-endian, else false. 84 | **/ 85 | bool 86 | is_big_endian (void) 87 | { 88 | int x = 1; 89 | 90 | if (*(char *)&x == 1) 91 | return false; 92 | 93 | return true; 94 | } 95 | 96 | bool 97 | has_ctty (void) 98 | { 99 | int fd; 100 | fd = open ("/dev/tty", O_RDONLY | O_NOCTTY); 101 | 102 | if (fd < 0) 103 | return false; 104 | 105 | close (fd); 106 | 107 | return true; 108 | } 109 | 110 | bool 111 | uid_match (uid_t uid) 112 | { 113 | return uid == getuid (); 114 | } 115 | 116 | /** 117 | * in_container: 118 | * 119 | * Determine if running inside a container. 120 | * 121 | * Returns: Name of container type, or NO_STR. 122 | **/ 123 | const char * 124 | container_type (void) 125 | { 126 | struct stat statbuf; 127 | char buffer[1024]; 128 | FILE *f; 129 | #if defined (PROCENV_PLATFORM_LINUX) 130 | dev_t expected; 131 | 132 | expected = makedev (5, 1); 133 | #endif 134 | 135 | if (stat ("/dev/console", &statbuf) < 0) 136 | goto out; 137 | 138 | #if defined (PROCENV_PLATFORM_FREEBSD) 139 | if (misc.in_jail) 140 | return "jail"; 141 | #endif 142 | 143 | /* LXC's /dev/console is actually a pty */ 144 | #if defined (PROCENV_PLATFORM_LINUX) 145 | if (major (statbuf.st_rdev) != major (expected) 146 | || (minor (statbuf.st_rdev)) != minor (expected)) 147 | return "lxc"; 148 | #endif 149 | 150 | if (! stat ("/proc/vz", &statbuf) && stat ("/proc/bc", &statbuf) < 0) 151 | return "openvz"; 152 | 153 | f = fopen ("/proc/self/status", "r"); 154 | if (! f) 155 | goto out; 156 | 157 | while (fgets (buffer, sizeof (buffer), f)) { 158 | size_t len = strlen (buffer); 159 | buffer[len-1] = '\0'; 160 | 161 | if (strstr (buffer, "VxID") == buffer) { 162 | fclose (f); 163 | return "vserver"; 164 | } 165 | } 166 | 167 | fclose (f); 168 | 169 | out: 170 | return NO_STR; 171 | } 172 | 173 | /** 174 | * in_chroot: 175 | * 176 | * Determine if running inside a chroot environment. 177 | * 178 | * Failures are fatal. 179 | * 180 | * Returns true if within a chroot, else false. 181 | **/ 182 | // FIXME: add different implementations? 183 | bool 184 | in_chroot (void) 185 | { 186 | struct stat st; 187 | int i; 188 | int root_inode, self_inode; 189 | char root[] = "/"; 190 | char self[] = "/proc/self/root"; 191 | char bsd_self[] = "/proc/curproc"; 192 | char *dir = NULL; 193 | 194 | i = stat (root, &st); 195 | if (i != 0) { 196 | dir = root; 197 | goto error; 198 | } 199 | 200 | root_inode = st.st_ino; 201 | 202 | /* 203 | * Inode 2 is the root inode for most filesystems. However, XFS 204 | * uses 128 for root. 205 | */ 206 | if (root_inode != 2 && root_inode != 128) 207 | return true; 208 | 209 | i = stat (bsd_self, &st); 210 | if (i == 0) { 211 | /* Give up here if running on BSD */ 212 | return false; 213 | } 214 | 215 | i = stat (self, &st); 216 | if (i != 0) 217 | return false; 218 | 219 | self_inode = st.st_ino; 220 | 221 | if (root_inode == self_inode) 222 | return false; 223 | 224 | return true; 225 | 226 | error: 227 | die ("cannot stat '%s'", dir); 228 | 229 | /* compiler appeasement */ 230 | return false; 231 | } 232 | 233 | /* detect if setsid(2) has been called */ 234 | bool 235 | is_session_leader (void) 236 | { 237 | return user.sid == user.pid; 238 | } 239 | 240 | /* detect if setpgrp(2)/setpgid(2) (or setsid(2)) has been called */ 241 | bool 242 | is_process_group_leader (void) 243 | { 244 | return user.pgroup == user.pid; 245 | } 246 | 247 | static struct baud_speed baud_speeds[] = { 248 | SPEED (B0), 249 | SPEED (B50), 250 | SPEED (B75), 251 | SPEED (B110), 252 | SPEED (B134), 253 | SPEED (B150), 254 | SPEED (B200), 255 | SPEED (B300), 256 | SPEED (B600), 257 | SPEED (B1200), 258 | SPEED (B1800), 259 | SPEED (B2400), 260 | SPEED (B4800), 261 | SPEED (B9600), 262 | SPEED (B19200), 263 | SPEED (B38400), 264 | SPEED (B57600), 265 | SPEED (B115200), 266 | SPEED (B230400), 267 | 268 | /* terminator */ 269 | { NULL, 0 } 270 | }; 271 | 272 | const char * 273 | get_speed (speed_t speed) 274 | { 275 | struct baud_speed *s; 276 | 277 | for (s = baud_speeds; s && s->name; s++) { 278 | if (speed == s->speed) 279 | return s->name; 280 | } 281 | 282 | return NULL; 283 | } 284 | 285 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | * Copyright (c) 2016-2021 James O. D. Hunt . 3 | * 4 | * SPDX-License-Identifier: GPL-3.0-or-later 5 | *-------------------------------------------------------------------- 6 | */ 7 | 8 | #ifndef _PROCENV_UTIL_H 9 | #define _PROCENV_UTIL_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #if defined (PROCENV_PLATFORM_LINUX) 23 | #include 24 | #endif /* PROCENV_PLATFORM_LINUX */ 25 | 26 | #if defined (PROCENV_PLATFORM_FREEBSD) 27 | #include 28 | #endif 29 | 30 | #include "platform.h" 31 | 32 | bool has_ctty (void); 33 | bool in_chroot (void); 34 | bool is_big_endian (void); 35 | bool is_process_group_leader (void); 36 | bool is_session_leader (void); 37 | bool uid_match (uid_t uid); 38 | const char *container_type (void); 39 | const char *get_speed (speed_t speed); 40 | int fd_valid (int fd); 41 | 42 | #if !defined (PROCENV_PLATFORM_HURD) && \ 43 | !defined (PROCENV_PLATFORM_MINIX) && \ 44 | !defined (PROCENV_PLATFORM_DARWIN) 45 | int is_console (int fd); 46 | #endif 47 | 48 | #if !defined (PROCENV_PLATFORM_HURD) 49 | 50 | #define mk_mem_section(name, value) \ 51 | { \ 52 | section_open (name); \ 53 | entry ("bytes", "%lu", value); \ 54 | show_human_size_entry (value); \ 55 | section_close (); \ 56 | } 57 | 58 | #endif /* !PROCENV_PLATFORM_HURD */ 59 | 60 | #endif /* _PROCENV_UTIL_H */ 61 | --------------------------------------------------------------------------------