This file collects per-utility POSIX conformance audits for the system-information
utilities crate. Each audit follows the playbook in audits.md.
The sys/ crate ships six POSIX utilities: getconf, ipcrm, ipcs, ps
(with platform back-ends pslinux.rs / psmacos.rs), uname, and who.
Audit method: static spec-vs-code against the sliced POSIX.1-2024 tree
(~/tmp/posix.2024/sliced/), with every Critical/Major "absent" or
"miscompiles" claim confirmed by reading the cited code + spec lines (and the
libc-0.2.180 crate source for portability claims). Several agent-proposed
findings were refuted on verification and are recorded inline.
Date: 2026-06-18
Every actionable finding has since been fixed across 11 themed phases on the
sys-audit branch (one or two utilities per phase), each independently committed
with regression tests and gated on cargo build/clippy --all-targets/fmt.
Both Critical defects (ipcs MODE octal-parse #IS1; ps etime time-base #P1) and
every Major/Minor item are closed; the headline ps time fixes and ipcs MODE
fix were behaviorally cross-checked against the system ps/ipcs, and the
macOS-only ps/ipcs changes (#P2/#P8/#P13/#IS7) were verified to compile and
lint cleanly via cargo check/clippy --target x86_64-apple-darwin (runtime
macOS verification pending CI). New deterministic unit tests cover the pure
helpers (mode/time/limit/key formatters); the crate previously had zero unit
tests. Refuted on verification: getconf macOS build-break (#G2-era libc claim),
ps -o all-null header and args CMD header (#P12), who extra-operand
(#W3). Dispositioned WON'T-FIX / deferred: _CS_POSIX_V8_* confstr and the
pure-header limit macros (#G3 / #G2 tail — not exposed by libc), the macOS
SysV message-queue omission (#IR3 — platform limitation), and the crate-wide
.mo translation catalogs (#IR4/#IS8/#P14/#U3/#W8 — tree-wide i18n decision,
consistent with dev/). All six utilities are promoted to README
Stage 6 — Audited.
Four patterns recur across the crate and are not repeated in every section:
- Locale init is wired everywhere, translations are not. All six utilities
call
setlocale(LC_ALL, "")+textdomain("posixutils-rs")+bind_textdomain_codesetinmainand wrap user-facing strings ingettext(). But the crate ships no.mocatalogs, soLANG/LC_ALL/LC_MESSAGESselect a non-existent catalog and diagnostics stay English. This is the same "diag plumbing in place; string-level catalogs deferred" status as thedev/audit — recorded once here, Minor per utility. - Time/locale honoring is incidental, not deliberate.
ipcs/whoformat timestamps throughchrono::Local/ libcstrftime, which transitively honorTZ(and partlyLC_TIME) because they calllocaltime_r.psdoes not — its time code is hand-rolled and ignoresTZ/LC_TIMEentirely. - The Linux/
/procvs macOS/syscall split is real and uneven.ipcsandpscarry separate back-ends;ipcrmandwhorely on libc. The audits flag back-end divergences (e.g.psstart_timeunits differ between platforms). - i18n category coverage is structurally complete (every var the spec lists
is reachable through
setlocale); the gaps are catalog content, not wiring.
Implementation: sys/getconf.rs (767 lines)
Tests: sys/tests/getconf/mod.rs
Spec: POSIX.1-2024 (IEEE Std 1003.1-2024), Vol. 3 §3
Reference slice: ~/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/getconf.md
Date: 2026-06-18
The golden path — getconf VAR and getconf PATH_VAR pathname for sysconf /
confstr / pathconf names — works and is well-mapped (both Linux and macOS
confstr tables are #[cfg]-branched). The conformance gaps are coverage and
currency: the -v specification gate only accepts the obsolescent POSIX_V6_*
/ POSIX_V7_* names and rejects the POSIX.1-2024 POSIX_V8_* names the spec
now mandates (Issue 8 / Austin Group Defect 1330), the <limits.h>
Maximum/Minimum compile-time constants (LONG_BIT, MB_LEN_MAX, NL_*, …) are
not accepted as operands at all, and confstr results are passed through
.trim_end() which can corrupt a value the spec says to print verbatim.
- #G1 —
-v POSIX_V8_*specifications are rejected.sys/getconf.rs:544-556(is_valid_specification). Thematches!arm listed onlyPOSIX_V6_*andPOSIX_V7_*. The spec (CHANGE HISTORY 99566–99571: Austin Group Defect 1330,_V7_→_V8_) makes the fourPOSIX_V8_*names the current-vset. ✓ fixed in Phase 10 — added the four V8 arms (legacy V6/V7 kept). Behaviorally verifiedgetconf -v POSIX_V8_LP64_OFF64 ARG_MAX→ 3200000. Unit testv8_specifications_accepted. - #G2 —
<limits.h>Maximum/Minimum value names not accepted as operands. Spec 99441–99455. ✓ fixed in Phase 10 (partial, by design) — newlookup_limit_constant, dispatched inmainbefore the confstr/sysconf path, returns the portably-derivableLONG_BITandWORD_BIT(c_long::BITS/c_int::BITS); behaviorallygetconf LONG_BIT→ 64 == system. The utility-limit values (LINE_MAX,RE_DUP_MAX,COLL_WEIGHTS_MAX,BC_*,EXPR_NEST_MAX) were already covered via the sysconf map. Deferred: the remaining pure-header macros (MB_LEN_MAX,NL_ARGMAX/NL_*,NZERO,CHARCLASS_NAME_MAX) are not exposed by thelibccrate on Linux/macOS and are not hardcoded, since their per-platform values can't be runtime-verified from this host. - #G3 —
POSIX_V8_*confstr entries missing on both platforms.sys/getconf.rs(load_confstr_mapping). Deferred / WON'T-FIX (Phase 10). Thelibccrate defines no_CS_POSIX_V8_*constants for Linux or macOS (grep-confirmed), and neither glibc nor the macOS SDK exposes the Issue-8 V8 confstr names yet; hardcoding speculative integers for aconfstr(3)query would be unverifiable and risk wrong output. Revisit when libc/the C libraries gain_CS_POSIX_V8_*.
- #G4 —
confstrvalue passed through.trim_end().sys/getconf.rs:140. ✓ fixed in Phase 10 — now strips only the NUL terminator (.trim_end_matches('\0')); significant trailing whitespace is preserved per the"%s\n"format. - #G5 — Several POSIX.1-2024 sysconf names absent.
sys/getconf.rs(load_sysconf_mapping). ✓ fixed in Phase 10 — added the Issue-8_SC_NPROCESSORS_CONF/_SC_NPROCESSORS_ONLN(Defect 339) plus_SC_BARRIERS,_SC_CLOCK_SELECTION,_SC_CPUTIME,_SC_MONOTONIC_CLOCK,_SC_READER_WRITER_LOCKS,_SC_SPIN_LOCKS,_SC_SPORADIC_SERVER,_SC_THREAD_CPUTIME,_SC_TIMEOUTS,_SC_TYPED_MEMORY_OBJECTS,_SC_TRACE,_SC_XOPEN_REALTIME,_SC_XOPEN_REALTIME_THREADS(all verified present inlibcfor both Linux and macOS viacargo check --target). Behaviorallygetconf NPROCESSORS_ONLN== system. Unit testnprocessors_mapped. (The_SC_V7_*/_SC_V8_*programming-env query variables are not in libc — deferred with #G3.) - #G6 — A few pathconf names absent.
sys/getconf.rs(load_pathconf_mapping). ✓ fixed in Phase 10 — addedPOSIX2_SYMLINKS/_PC_2_SYMLINKS(present on both targets); behaviorallygetconf POSIX2_SYMLINKS /→ 1, unit testposix2_symlinks_mapped. Deferred:_PC_SYNC_IO(not defined for linux-gnu/musl inlibc) and_PC_TIMESTAMP_RESOLUTION(not defined for Linux or macOS inlibc).
-
getconf [-v spec] system_varandgetconf [-v spec] path_var pathnameforms —getconf.rs:24-36, 752. CONFORMS. -
--end-of-options handled by clap. CONFORMS. -
-vaccepts V6/V7/V8 (#G1 ✓ Phase 10).getconf.rs:544-556. -
pathnameoperand passed topathconfviaCString—getconf.rs:164. CONFORMS.
- None used. CONFORMS / N/A.
-
LANG/LC_ALL/LC_CTYPE/LC_MESSAGES/NLSPATHreachable viasetlocale(LC_ALL,"")+ textdomain —getconf.rs:735-737. CONFORMS (catalog content deferred, see cross-cutting).
- Numeric vars
"%d\n", undefined →undefined\n, invalid → nothing on stdout + stderr diagnostic + exit 1 —getconf.rs:77/85/113/141/171. CONFORMS. - confstr verbatim (NUL-only strip) (#G4 ✓ Phase 10) —
getconf.rs:140.
- 0 on success (incl. valid-but-
undefined→ exit 0 per RATIONALE 99532–99535); >0 on any error viaprocess::exit(1). CONFORMS —getconf.rs:77/113/171(undefined), error paths.
- i18n wiring present (
getconf.rs:735-737); catalogs deferred (Minor, crate-wide). - Portability: confstr tables are
#[cfg(target_os)]-branched (getconf.rs:187,305); sysconf/pathconf maps are shared but use only constants present on both platforms.
-
"Refuted 2026-06-18. Verified inlibc::_SC_PASS_MAX(getconf.rs:581) andlibc::_PC_FILESIZEBITS(getconf.rs:725) are Linux-only → macOS build break (proposed Critical)."libc-0.2.180/src/unix/bsd/apple/mod.rs:_PC_FILESIZEBITS = 18(line 1962) and_SC_PASS_MAX = 131(line 3117) are both defined for Apple targets. The shared maps compile on macOS; no build break.
Not covered:
-
getconf -v POSIX_V8_*acceptance (#G1) —v8_specifications_accepted(Phase 10). -
<limits.h>constant operands (#G2) —limit_constants(Phase 10; LONG_BIT/WORD_BIT). - confstr trailing-whitespace preservation (#G4) — behavioral (Phase 10).
-
NPROCESSORS_CONF/NPROCESSORS_ONLN(#G5) —nprocessors_mapped+ behavioral (Phase 10).
Implementation: sys/ipcrm.rs (319 lines)
Tests: sys/tests/ipcrm/mod.rs
Spec: POSIX.1-2024 (IEEE Std 1003.1-2024), Vol. 3 §3, pp. 3059–3061
Reference slice: ~/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/ipcrm.md
Date: 2026-06-18
The cleanest utility in the crate. All six options (-q -Q -s -S -m -M) accept
repetition (ArgAction::Append), removal routes to the correct *ctl(IPC_RMID)
syscall, per-operand errors set exit 1 but continue (correct CONSEQUENCES-OF-
ERRORS behavior), and macOS's lack of SysV message queues is handled with a
#[cfg] guard + runtime error. The only real divergences are minor: a
fixed internal processing order that ignores argv order (Guideline 11), and
decimal key parsing capped at signed i32.
- #IR1 — Options processed in fixed internal order, not argv order.
sys/ipcrm.rs:192-306. XBD 12.2 Guideline 11 says repeated option/option-argument pairs should be interpreted in the order specified. ✓ fixed in Phase 11 —mainnow reads clap value indices (ArgMatches::indices_of) for all six options, builds a singleVec<(index, Op)>, sorts by argv index, and processes in that order. Behaviorally verified:ipcrm -s 991 -m 992 -s 993reports the three in command-line order. - #IR2 — Decimal keys limited to signed
i32range.sys/ipcrm.rs:31. A decimal key > 2147483647 failed to parse while the same value in hex succeeded. ✓ fixed in Phase 11 —parse_ipc_keyfalls back tou32(cast toi32, matching the hex path) for out-of-i32-range decimals. Behaviorallyipcrm -S 3000000000parses to0xb2d05e00. Unit testparse_keys. - #IR3 — macOS message-queue support omitted wholesale.
sys/ipcrm.rs.-q/-Qon macOS print an error and exit 1. WON'T-FIX (documented platform limitation): macOS does not provide working SysV message queues (msggetis effectively stubbed), so erroring is the correct behavior; the-q/-Qoptions remain accepted per the POSIX SYNOPSIS. - #IR4 — No
.mocatalogs (crate-wide).LC_MESSAGEShas no runtime effect. Deferred — thesetlocale+gettextwiring is present; shipping translation catalogs is a tree-wide decision, consistent with thedev/audit and the rest of the repo. See cross-cutting / PR I.
-
-q msgid/-m shmid/-s semid(by id) →*ctl(IPC_RMID)—ipcrm.rs:169-180and per-type loops. CONFORMS (msg: Linux-only). -
-Q msgkey/-M shmkey/-S semkey(by key) → key lookup then remove —ipcrm.rskey-lookup helpers. CONFORMS (msg: Linux-only). - argv-order processing (#IR1 ✓ Phase 11); full decimal key range (#IR2 ✓ Phase 11).
- None accepted / used. CONFORMS.
-
LANG/LC_ALL/LC_CTYPE/LC_MESSAGES/NLSPATHreachable viasetlocale—ipcrm.rs:310-312. CONFORMS (catalogs deferred).
- Default; no stdout. CONFORMS.
- Diagnostics to stderr only; exit 0/1 via accumulator; per-operand continue-on-error —
ipcrm.rs:189-318. CONFORMS.
- Portability: msg-queue paths
#[cfg(not(target_os="macos"))]; sem/shm portable.semctl(IPC_RMID, semun{val:0})portable. CONFORMS.
Not covered:
- argv-order processing (#IR1) — behavioral (Phase 11).
- large decimal key parsing (#IR2) —
parse_keysunit test (Phase 11).
Implementation: sys/ipcs.rs (755 lines)
Tests: sys/tests/ipcs/mod.rs
Spec: POSIX.1-2024 (IEEE Std 1003.1-2024), Vol. 3 §3, pp. 3062–3068
Reference slice: ~/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/ipcs.md
Date: 2026-06-18
The option surface (-q -m -s selectors; -a/-bcopt modifiers), the title
line, facility ordering, OWNER/GROUP truncation, and the T/KEY columns are
correct. But the permission MODE column is wrong on every Linux invocation:
the kernel prints the mode field in /proc/sysvipc/* as octal (%4o) and the
implementation parses it with decimal .parse(), so the displayed rwx bits
are garbage. Two further golden-path columns never carry real data — message-
queue QBYTES always prints -, and the MODE status flags (S/R waiters,
C = SHM_DEST) are hard-coded -. I/O errors reading /proc are silently
swallowed (unwrap_or_default()), so a permission failure yields empty output
with exit 0 instead of a diagnostic.
- #IS1 —
/proc/sysvipc/*mode field parsed as decimal, but the kernel writes it in octal.sys/ipcs.rs:228, 262, 296(theperms: fields[2].parse().unwrap_or(0)sites for msg/shm/sem). The Linux kernel's*_proc_showroutines print theipc_perm.modefield with%4o. Parsing"644"as decimal yields644(0o1204), soformat_mode(ipcs.rs:118-138) reads the wrong bits and the MODE column is incorrect on every run. Fix:u16::from_str_radix(fields[2], 8). ✓ fixed in Phase 1 — all threeread_proc_*sites now parse base 8; behaviorally verified against/usr/bin/ipcs(0640→-rw-r-----, 0600→-rw-------, 0644→-rw-r--r--); unit testproc_mode_field_is_octal.
- #IS2 — Message-queue
QBYTESalways prints-.sys/ipcs.rs:548-550(acknowledged in a code comment).q_qbytesis not in/proc/sysvipc/msg; obtaining it needsmsgctl(msqid, IPC_STAT, &buf). Spec (the-bcolumn for message queues) requires the value. Fix: callmsgctl(IPC_STAT)per entry. ✓ fixed in Phase 2 — newget_msg_qbytes()helper +MsgQueueInfo.qbytes: Option<u64>; renders-only when the stat fails. Behaviorally verified (ipcs -q -bshows 16384, themsgmnbdefault). - #IS3 — MODE status flags never set + wrong char count.
sys/ipcs.rs:118-123(c1/c2hard-coded-). ✓ fixed in Phase 1. Re-reading the spec (IEEE Std 1003.1-2024, ipcs MODE column 100916–100940) corrected the finding: POSIX mandates 11 characters — a single leading flag char (Cif a shared memory segment is marked for clearing/SHM_DEST, else-), then 9 permission chars, then 1 ACL char. There is noS/Rmsgsnd/msgrcv flag in POSIX.1-2024 (that is a historical SysV-ism), and there is no/procdata source for waiters anyway. The old code emitted 12 chars (two bogus-flags) — itself a divergence.format_modenow returns the 11-char form and sets theCflag fromSHM_DEST; unit testsmode_string_is_eleven_chars_and_decodes_perms+shm_dest_sets_c_flag. - #IS4 —
-ttime column zero-pads the hour; spec format is%d:%2.2d:%2.2d.sys/ipcs.rs:165. Uses%H:%M:%S(e.g.09:30:00); spec 100977–100985 mandates an unpadded hour (9:30:00). Fix: use%-H:%M:%S. ✓ fixed in Phase 2; unit testtime_no_entry_and_format. - #IS5 —
/procread errors silently swallowed; "facility not in system" never emitted on Linux for shm/sem.sys/ipcs.rs:500, 579, 653(.unwrap_or_default()). If a facility is compiled out (file missing) or unreadable (EACCES), the code emits a header with no rows and exits 0, instead of"%s facility not in system.\n"(spec 100886–100889) or a stderr diagnostic + non-zero exit. Fix: branch on theErrfromread_proc_*; emit the not-in-system line for missing facilities and a diagnostic for hard errors. ✓ fixed in Phase 2 —display_*now returnio::Result<()>;NotFound(and an empty facility, per the spec's "not used since the last reboot") emits the singular"<facility> facility not in system."; any other error propagates tomain(diagnostic + non-zero exit). Behaviorally verified on a clean host (all three report "not in system").
- #IS6 —
get_current_datefallback uses%zinstead of%Z.sys/ipcs.rs:185, 200. The primarystrftimepath correctly uses%a %b %e %H:%M:%S %Z %Y; only the chrono fallback (used whenlocaltime_r/strftimefail) emits numeric%z. Fix: change the fallback format to%Z. ✓ fixed in Phase 2 (both fallback format strings). - #IS7 — macOS slot iteration capped at 256.
sys/ipcs.rs(MAX_IPC_SLOTS_TO_CHECK = 256). IDs beyond slot 256 are missed on busy systems. Fix: drive the bound fromkern.sysv.shmmni/semmni. ✓ fixed in Phase 2 (macOS, code-only — compiled, not run on this Linux host): the slot dimension is now bounded byMACOS_MAX_SLOTS(2048), separate from the per-slot sequence probeMACOS_SEQ_PROBE;read_macos_semno longer caps slots at the sequence budget. Documented as a best-effort heuristic (macOS lacks an IPC-enumeration API). - #IS8 — No
.mocatalogs (crate-wide). Deferred (tree-wide i18n; see cross-cutting / PR I).
-
-q -m -sselectors; default = all three;-a=-bcopt;-b -c -o -p -tmodifiers —ipcs.rs:24-48, 742-749. CONFORMS. - No operands; stdin unused. CONFORMS.
-
LANG/LC_ALL/LC_CTYPE/LC_MESSAGES/NLSPATHviasetlocale—ipcs.rs:735-737. CONFORMS. -
TZhonored incidentally (localtime_rvia chrono/strftime) —ipcs.rs:164,189. CONFORMS. -
-thour format (#IS4 ✓ Phase 2 — unpadded hour per%d:%2.2d:%2.2d).LC_TIME-localized digits remain a deferred crate-wide i18n item.
- Title line
IPC status from <source> as of <date>—ipcs.rs:719. CONFORMS. - Facility order msg→shm→sem;
T/KEY/OWNER/GROUP columns —ipcs.rs:721-731, truncationipcs.rs:98. CONFORMS. - MODE octal-parse bug (#IS1 ✓ Phase 1); MODE flags / 11-char form (#IS3 ✓ Phase 1); QBYTES (#IS2 ✓ Phase 2); shm/sem "not in system" (#IS5 ✓ Phase 2).
- Errors propagated (not swallowed) (#IS5 ✓ Phase 2).
- 0 success / non-zero on hard
/procerrors (#IS5 ✓ Phase 2 —display_*propagateio::Resulttomain;NotFound/empty → "not in system" at exit 0).
- Portability: Linux
/proc/sysvipc; macOSshmctl/semctl(IPC_STAT)slot scan (#IS7 cap raised, Phase 2); msg queues "not in system" on macOS. CONFORMS.
Tests are structural smoke tests. Not covered:
- MODE string correctness (#IS1, #IS3) — unit tests + behavioral cross-check (Phase 1).
- QBYTES value (#IS2) — gated real-IPC test + behavioral check (Phase 2).
-
-thour format (#IS4) — unit testtime_no_entry_and_format(Phase 2). - facility-not-in-system path (#IS5) — behavioral check on a clean host (Phase 2).
Implementation: sys/ps.rs (776) + sys/pslinux.rs (169) + sys/psmacos.rs (189)
Tests: sys/tests/ps/mod.rs
Spec: POSIX.1-2024 (IEEE Std 1003.1-2024), Vol. 3 §3, pp. 3... (slice lines 112432–112719)
Reference slice: ~/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/ps.md
Date: 2026-06-18
The selection options (-A -a -d -e -g -G -p -t -u -U), the -l long format,
and the -o format engine (field=header overrides, multiple -o, all-null
header suppression) are largely correct. But etime is wrong on every Linux
run — format_etime subtracts the process start_time (clock-ticks-since-
boot on Linux) from the current Unix epoch seconds, mixing incommensurable
units; the code comment even calls itself "a simplified version". CPU/elapsed
time also hardcodes 100 ticks/second instead of sysconf(_SC_CLK_TCK), the
macOS PID enumeration uses a fixed 1024-entry buffer that silently truncates the
process list, and the SYNOPSIS options -w and -n (plus the COLUMNS env
var) are absent. TZ/LC_TIME are ignored for all time output.
- #P1 —
etimemixes time bases (always wrong on Linux).sys/ps.rs:491-517(format_etime) computesnow_epoch_secs - start_time, butpslinux.rs:28documentsstart_timeas "clock ticks since boot". The subtraction is meaningless; the in-code comment admits "proper implementation would need boot time". Fix: read boot time (/proc/statbtimeor/proc/uptime), convertstart_time / CLK_TCKto an epoch instant, then take the delta. ✓ fixed in Phase 3 —pslinux.rsreads/proc/statbtimeonce and normalizesstart_timeto epoch seconds;format_etime(start_epoch, now_epoch)is now pure (nowinjected frommain) andsaturating_subs for skew. Behaviorally verified:ps -p 1 -o etime==/usr/bin/ps(2-12:52:14). Unit testformat_etime_elapsed. - #P2 — macOS PID buffer fixed at 1024 → silent process-list truncation.
sys/psmacos.rs:40(let mut pids = vec![0; 1024];).proc_listallpidswith an undersized buffer returns a truncated list with no error. Fix: callproc_listallpids(NULL, 0)to get the count, then allocate. ✓ fixed in Phase 7 (macOS, code-only) — count-then-allocate with +64 slack. Verified viacargo check/clippy --target x86_64-apple-darwin; runtime macOS verification pending CI.
- #P3 — CPU/elapsed time hardcodes 100 ticks/second.
sys/ps.rs:474-488(format_time:ticks / 100). POSIX requiressysconf(_SC_CLK_TCK); LinuxCONFIG_HZmay be 250/1000. Fix: divide bysysconf(_SC_CLK_TCK). ✓ fixed in Phase 3 — the Linux backend dividesutime+stimebysysconf(_SC_CLK_TCK)(read once);format_timenow takes whole seconds. Behaviorally verifiedTIME==/usr/bin/ps(00:00:38for PID 1). Unit testformat_time_seconds. - #P4 —
-woption andCOLUMNSenv var absent; output never width-limited.sys/ps.rs:92-144(no-wfield);COLUMNSnever read. Spec 112481–112498 require lines to contain no more than the greater of{LINE_MAX}andCOLUMNSbytes; a single-wbehaves as ifCOLUMNS≥ 132; repeated-wremoves the limit. ✓ fixed in Phase 5 — added-w(repeatableCount);resolve_line_limitreads_SC_LINE_MAX+COLUMNS; each row/header is clipped bytruncate_lineat a UTF-8 boundary. Behaviorally verified: a 3041-byte argv caps at 2048 by default, full under-ww, andCOLUMNSraises the cap. Unit testline_limit_and_truncation. - #P5 —
-n namelistoption absent.sys/ps.rs:92-144. In the SYNOPSIS (XSI); the namelist format is "unspecified", so a parsed no-op is conforming. ✓ fixed in Phase 5 — added-n namelist, accepted and ignored (this implementation reads live state). Integration testps_namelist_accepted. - #P6 —
stimecolumn always-in-flisting.sys/ps.rs:573. The-ffull format mandates STIME; the field returned"-". ✓ fixed in Phase 4 — new pureformat_stime(start_epoch, now_epoch, tz)rendersHH:MMif started today elseMmmDD(matching historicalps),"-"when the start time is unknown. Behaviorally verifiedps -p 1 -o stime==/usr/bin/ps(Jun15). Unit testformat_stime_today_vs_date. - #P7 —
TZ/LC_TIMEignored for all time output.sys/ps.rs:474-517. ✓ fixed in Phase 4 — the only absolute-time field (stime) now formats throughchrono::Local, which honors$TZ(verified:TZ=UTC→10:16vsTZ=America/New_York→06:16).etime/timeare elapsed durations (timezone-independent by definition).LC_TIME-localized month/digit glyphs remain a deferred crate-wide i18n item. - #P8 — macOS
argsis the executable path, not argv; no bracketed fallback.sys/psmacos.rs:171. Spec 112547–112549: under-f, reconstruct argv, else write[comm]in brackets. Linux does this (pslinux.rs:146); macOS setargs = full_pathalways. Fix: usesysctl KERN_PROCARGS2to reconstruct argv; bracket kernel/threadless procs. ✓ fixed in Phase 7 (macOS, code-only) — newget_process_argsparses theKERN_PROCARGS2[argc][exec_path][argv...]buffer; falls back to[comm]when unavailable.cargo check/clippy --target x86_64-apple-darwinclean; runtime macOS verification pending CI.
- #P9 —
start_timesemantics diverge between back-ends.pslinux.rs:28(ticks since boot) vspsmacos.rs(epoch seconds). The sharedformat_etimecannot be correct for both. Fix: normalize both back-ends to epoch seconds before handing tops.rs. ✓ fixed in Phase 3 — theProcessInfocontract is now documented asstart_time= epoch seconds,time= whole CPU seconds; Linux converts (ticks→seconds, +btime) and macOS converts CPU ns→seconds (start_timealready epoch). The shared formatters are unit-agnostic. - #P10 — Defunct (zombie) processes not marked
<defunct>. No marking anywhere. Spec 112545–112546. Fix: append<defunct>toargs/commwhen state ==Z. ✓ fixed in Phase 6 —mark_defunct()appends<defunct>to the command column for stateZ. Behaviorally verified against a real zombie (perl <defunct>). Unit testdefunct_marking. - #P11 — Controlling-terminal detection via
isatty(STDIN); TTY match by substring.sys/ps.rs:521-537(uses stdin, breaks under redirected stdin) andps.rs:714-717(contains()sopts/0spuriously matchespts/00). ✓ fixed in Phase 6 —get_current_ttynow probes stdin→stdout→stderr (a redirected stdin no longer hides the terminal); the default filter compares TTY names by equality (ptty == ctty). -
#P12 —Refuted (Phase 6). Re-reading the spec: line 112543 makes-fargs header isCMD; spec default header forargsisCOMMAND.CMDthe command-column header for the full/long listing (-f/-l), while line 112604 maps only the-o args/-o commformat specifiers to the default headerCOMMAND. The code already matches both (get_full_fields→CMD;get_posix_fieldsargs/comm→COMMAND). No change needed. - #P13 — macOS
get_tty_namescans all of/devper process; notty_dev==0guard.sys/psmacos.rs:176-189. O(procs × /dev). Fix: build a one-timedev→namemap; guardtty_dev==0 → None. ✓ fixed in Phase 7 (macOS, code-only) —build_dev_name_mapruns once;get_tty_nameis now a map lookup that returns None fore_tdev0/NODEV.cargo check/clippy --target x86_64-apple-darwinclean. - #P14 — No
.mocatalogs (crate-wide). Deferred (tree-wide i18n; see cross-cutting / PR I).
| Opt | Status | Notes (file:line) |
|---|---|---|
-A / -e |
CONFORMS | ps.rs:94,98. |
-a |
PARTIAL | ps.rs:103 selects tty-bearing procs; optional session-leader exclusion not done (XSI "may"). |
-d |
CONFORMS | ps.rs:106, pid==sid check ps.rs:702. |
-f |
CONFORMS | login-name UID OK; stime ✓ Phase 4 (#P6); args header CMD is correct per spec 112543 (#P12 refuted). |
-g |
CONFORMS | filters by session id — ps.rs:118,656. |
-G / -U / -u / -p |
CONFORMS | ps.rs:122,138,134,127. |
-l |
CONFORMS | F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD — ps.rs:398-471. |
-o |
CONFORMS | append + name=header + null-header suppression — ps.rs:260-319, 739. |
-t |
PARTIAL | substring match; XSI two-form (tty04/04) not handled — ps.rs:131. |
-n namelist |
CONFORMS | accepted no-op (#P5 ✓ Phase 5). |
-w |
CONFORMS | -w/-ww + COLUMNS line limit (#P4 ✓ Phase 5). |
- None accepted / used. CONFORMS.
-
COLUMNSread for line limit (#P4 ✓ Phase 5).TZhonored forstime(#P7 ✓ Phase 4). -
LANG/LC_*/NLSPATHviasetlocale—ps.rs:580-584. CONFORMS (catalogs deferred).
- Default columns PID TTY TIME CMD (default format unspecified by spec) —
ps.rs:326-349. CONFORMS. -
-oall-null-header suppression correct (any(non-empty)) —ps.rs:739. CONFORMS (agent's "inverted logic" claim self-refuted; verified correct). -
etime/CLK_TCK (#P1/#P3 ✓ Phase 3);stime/TZ (#P6/#P7 ✓ Phase 4).
- 0 / 1 via
ExitCode—ps.rs:592,728. CONFORMS.
- Back-end divergences resolved:
start_time/timeunits (#P9 ✓ Phase 3), macOSargs(#P8 ✓ Phase 7), macOS PID buffer (#P2 ✓ Phase 7), macOS/devscan (#P13 ✓ Phase 7).
Not covered:
-
etimenumeric correctness (#P1) — unit testformat_etime_elapsed+ behavioral cross-check vs/usr/bin/ps(Phase 3). -
COLUMNS/-wtruncation (#P4) — unit test + behavioral 3041-byte argv check (Phase 5). -
-naccepted (#P5, Phase 5); defunct marking (#P10 — unit test + real-zombie check, Phase 6). [ ] header suppression content (ps_empty_headeronly checks exit).
Implementation: sys/uname.rs (89 lines)
Tests: sys/tests/uname/mod.rs
Spec: POSIX.1-2024 (IEEE Std 1003.1-2024), Vol. 3 §3 (slice lines 119026–119120)
Reference slice: ~/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/uname.md
Date: 2026-06-18
Conforming. All six options (-a -m -n -r -s -v), the default-to--s behavior,
the fixed -a field order (sysname, nodename, release, version, machine) with
trailing-blank suppression, exit status, and locale init are correct. The
uname = "0.1" crate wraps libc utsname and exposes all five fields on both
Linux and macOS. No Critical or Major defects. Only Minor notes are clap-
extension hygiene (non-POSIX long options) and the unmaintained dependency.
- #U1 — Non-POSIX long options exposed in
--help.sys/uname.rs:17-33. clap exposes--all/--machine/… and the awkward--osversion. POSIX defines only the short letters. Harmless extensions. ✓ addressed in Phase 11 — retained as intentional GNU-style convenience extensions (removing them would breakuname --alletc.), now documented with a code comment explaining the--osversion/--versionclash. No behavioral change (matches the finding's "acceptable, document" recommendation). - #U2 — Unmaintained
uname = "0.1"dependency.sys/Cargo.toml:15. ✓ fixed in Phase 11 — replaced with a directlibc::uname()call (get_uname+field_to_string); theunamecrate is dropped fromCargo.toml. Output is byte-for-byte unchanged (verified against the systemuname, 5 POSIX fields); compiles on both Linux and macOS targets. - #U3 — No
.mocatalogs (crate-wide). Deferred (tree-wide i18n; see cross-cutting / PR I). uname field values are implementation-defined and legitimately not translated.
-
-a -m -n -r -s -vpresent;-a=-mnrsv; default =-s—uname.rs:17-33, 42-55, 68-76. CONFORMS. - No operands; stdin/files unused. CONFORMS.
-
LANG/LC_ALL/LC_CTYPE/LC_MESSAGES/NLSPATHviasetlocale—uname.rs:62-64. CONFORMS.
- Default
"%s\n"sysname;-afive-field space-separated; partial-option ordering with no trailing blanks —uname.rs:42-58. CONFORMS. - Errors to stderr —
uname.rs:83. CONFORMS.
- 0 / 1 via
process::exit—uname.rs:78,85,88. CONFORMS.
-
libc::utsnameprovides all five fields on Linux and macOS. CONFORMS.
Covered well (option order, five-field output). No gaps mapping to actionable findings.
Implementation: sys/who.rs (380 lines) + plib/src/utmpx.rs
Tests: sys/tests/who/mod.rs
Spec: POSIX.1-2024 (IEEE Std 1003.1-2024), Vol. 3 §3 (slice lines 122888–122992)
Reference slice: ~/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/who.md
Date: 2026-06-18
The option surface (-a -b -d -H -l -m -p -q -r -s -t -T -u), the am i operand
form, -T writable markers (+/-/?), -q count format, -b "system boot"
line, default and -T output formats, utmpx access (libc setutxent/
getutxent/utmpxname, portable to Linux and macOS), and exit status are
correct. Gaps: the Utmpx struct omits ut_exit, so the -d <exit> field is
never printed; -l prints the record's name instead of the literal LOGIN; and
extra operands beyond file are silently ignored rather than diagnosed.
- #W1 —
-d<exit>field never emitted.plib/src/utmpx.rs:15-23(struct had no exit field) +sys/who.rs:247. Spec 122908–122910 requires the termination/exit values column for dead processes. ✓ fixed in Phase 8 — addedUtmpx.exit_status: Option<(i16,i16)>populated fromut_exit.e_termination/.e_exit(#[cfg(not(macos))];Noneon macOS, which lacksut_exit);whoemits aterm=<t> exit=<e>field forDEAD_PROCESS. Unit testdead_process_exit_field. - #W2 —
-ldoes not print the literalLOGINas<name>.sys/who.rs:248+ print functions. Spec 122912–122914 mandates the name field beLOGINfor login lines; the code printedentry.user. ✓ fixed in Phase 8 —display_name()substitutes"LOGIN"whentyp == LOGIN_PROCESS. Unit testlogin_process_name_is_login. -
#W3 — Extra operands beyondRefuted (Phase 8). Behaviorally tested:filesilently ignored.who foo bar bazalready exits 2 with clap'serror: unexpected argument 'bar'— the singlefile: Option<PathBuf>positional rejects a second operand. Thewho am i/am Iform is intercepted before clap. No code change needed.
- #W4 —
LC_TIMEnot honored for time rendering.sys/who.rs:69-76.dt.format("%b %e %H:%M")was the hardcoded POSIX-locale shape; month names didn't localize. ✓ fixed in Phase 9 —fmt_timestampnow callsplib::locale::strftime("%b %e %H:%M", …), which formats via libclocaltime_r+strftimeso bothLC_TIME(month/day names) andTZtake effect. - #W5 —
--userprocinternal flag leaks into--help.sys/who.rs:58-59. Non-POSIX; an implementation detail for the defaultUSER_PROCESScase. ✓ fixed in Phase 9 — marked#[arg(hide = true)]so it no longer appears in--help(verified) while remaining functional for the internal default-selection logic. - #W6 — Negative idle time possible on clock skew.
sys/who.rs:111.idle_secswas not clamped at 0. ✓ fixed in Phase 9 —(now - atime).max(0). - #W7 —
-s/-Tclap group is fragile.sys/who.rs:49,55.-shaddefault_value_t=true(always-on, unread) conflicting with-T's group. ✓ fixed in Phase 9 — removeddefault_value_t;-sis now a normal opt-in flag (short remains the default; the output dispatch keys offterminals). The-s/-Tmutual exclusion is preserved (behaviorally verified:who -s -Texits 2). - #W8 — No
.mocatalogs (crate-wide). Deferred (tree-wide i18n; see cross-cutting / PR I).
| Opt | Status | Notes (file:line) |
|---|---|---|
-a |
PARTIAL | expands to sub-flags — who.rs:359-371. |
-b |
CONFORMS | "system boot" — who.rs:245,262. |
-d |
CONFORMS | <exit> field term=N exit=M (#W1 ✓ Phase 8). |
-H |
CONFORMS | localized headings — who.rs:274-313. |
-l |
CONFORMS | name forced to LOGIN (#W2 ✓ Phase 8). |
-m / am i |
CONFORMS | who.rs:230-242, 349-354. |
-p / -r / -t |
CONFORMS | who.rs:250,249,251-252. |
-q |
CONFORMS | names + # users=N — who.rs:326-341. |
-s |
CONFORMS | opt-in flag, mutually exclusive with -T (#W7 ✓ Phase 9). |
-T |
CONFORMS | +/-/? via group-write bit 0o020 — who.rs:180-216. |
-u |
CONFORMS | idle from /dev/<line> atime; <pid> column; idle clamped at 0 (#W6 ✓ Phase 9). |
-
am i/am I→-m;fileoperand viautmpxname—who.rs:349-354,317. CONFORMS. - Extra operands diagnosed (#W3 refuted — clap exits 2 on a second operand).
- Default db path via libc (
/var/run/utmpLinux,/var/run/utmpxmacOS). CONFORMS (portable; macOS db may be sparse at runtime — data issue, not a bug).
-
LANG/LC_ALL/LC_CTYPE/LC_MESSAGES/NLSPATHviasetlocale—who.rs:344-346. CONFORMS. -
TZhonored (chronoLocal). CONFORMS. -
LC_TIME/TZhonored viaplib::locale::strftime(#W4 ✓ Phase 9).
- Default/
-T/-q/-b/-Hformats —who.rs:171,209,326-341,262,274-313. CONFORMS. -
-d<exit>(#W1 ✓ Phase 8);-lLOGIN (#W2 ✓ Phase 8). - 0 / non-zero via
?. CONFORMS.
- utmpx functions present on glibc, musl (
plib/src/platform.rsextern block), and Apple targets. CONFORMS.
Most tests check exit code only. Not covered:
-
-dexit field (#W1) +-lname=LOGIN(#W2) — unit tests (Phase 8); extra-operand rejection (#W3 — behavioral, exit 2). [ ]-Tstate chars,-b"system boot" content.
Ordered roughly by user-visible impact. Each is a small, themed unit.
- PR A — "ipcs: correct the MODE/permission display": #IS1 (octal parse — the headline correctness bug), #IS3 (status flags
S/R/C). Both touch the mode pipeline. - PR B — "ps: fix elapsed/CPU time": #P1 (etime time-base), #P3 (
_SC_CLK_TCK), #P6 (stime), #P9 (normalize back-endstart_time). The Critical cluster. - PR C — "ps: macOS back-end robustness": #P2 (PID buffer count-then-alloc), #P8 (argv reconstruction), #P13 (
/devmap + tty guard). - PR D — "ps: width control + missing SYNOPSIS options": #P4 (
-w/COLUMNS), #P5 (-n), #P11 (controlling-tty detection), #P12 (COMMANDheader). - PR E — "ipcs: error propagation + facility reporting": #IS2 (
QBYTESviamsgctl), #IS5 (don't swallow/procerrors; emit "facility not in system"), #IS4/#IS6 (time format), #IS7 (macOS slot cap). - PR F — "who: dead/login record fields": #W1 (
ut_exit), #W2 (LOGIN), #W3 (extra-operand diagnostic). - PR G — "getconf: POSIX.1-2024 currency": #G1 (
-v POSIX_V8_*), #G3 (V8 confstr), #G2 (<limits.h>constants), #G5/#G6 (sysconf/pathconf coverage). - PR H — "getconf/who/ipcrm small fixes": #G4 (confstr trim), #W4/#W6/#W7 (who locale/clamp/group), #IR1/#IR2 (ipcrm order + key range).
- PR I — "crate-wide i18n catalogs": the deferred
.mo-catalog item shared by all six utilities (#G-/#IR4/#IS8/#P14/#U3/#W8). Mirrors thedev/audit's "string-level gettext deferred" status — wire actual catalogs or document the gap. - PR J — "uname hygiene (optional)": #U1 (long-option surface), #U2 (drop unmaintained dep).