Skip to content

Import shuf utility from OpenBSD - #444

Merged
laffer1 merged 2 commits into
masterfrom
feature/import-shuf
Jul 10, 2026
Merged

laffer1 merged 2 commits into
masterfrom
feature/import-shuf

Conversation

@laffer1

@laffer1 laffer1 commented Jul 9, 2026 •

Copy link
Copy Markdown
Member

This PR imports the shuf (random permutation) utility from Brian Callahan's OpenBSD implementation.

Source

Features

shuf outputs a random permutation of its input lines. By default, it reads from stdin and outputs to stdout.

Options:

  • -e: Use a space-separated list of command-line arguments as input
  • -i lo-hi: Use the range of unsigned integers from lo to hi as input
  • -n count: Print at most count lines
  • -o file: Write output to file instead of stdout
  • -r: Do not permute; instead choose lines at random with replacement (repeats indefinitely without -n)
  • -z: Delineate lines with NUL character instead of newline
  • -h: Print usage
  • -v: Print version

Examples:

Shuffle lines from stdin, shuffle command-line arguments, select random numbers from a range.

MidnightBSD-specific changes

  1. Changed __dead to __dead2 (MidnightBSD convention)
  2. Added forward declarations for all static functions
  3. Removed OpenBSD-specific pledge() calls, replaced with Capsicum support using caph_enter() from capsicum_helpers.h
  4. All required functions (arc4random_uniform, reallocarray, strtonum, getprogname) are already present in MidnightBSD libc

Files Added

  • usr.bin/shuf/shuf.c: Main source code
  • usr.bin/shuf/Makefile: Build configuration
  • usr.bin/shuf/shuf.1: Manual page
  • aitools.md: Documentation of GNU coreutils compatibility for AI agents

Testing

Verified all major features: usage, version, stdin shuffling, -e flag, -i flag, -n flag, -r flag, man page.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe vibe@mistral.ai

Summary by Sourcery

Import the OpenBSD shuf utility into MidnightBSD, providing a random line permutation tool compatible with GNU coreutils expectations and documenting AI-oriented tooling differences.

New Features:

  • Add the shuf command to generate random permutations of input lines, including argument list and integer range modes with support for output limiting, random-with-replacement, NUL delimiters, and file output.
  • Provide a shuf(1) manual page describing usage, options, examples, and caveats for the new utility.

Build:

  • Add build configuration for the shuf utility under usr.bin.

Documentation:

  • Add aitools.md documenting MidnightBSD vs GNU coreutils compatibility, focusing on utilities and flags important for AI automation workflows.

Import the shuf (random permutation) utility from Brian Callahan's
OpenBSD implementation (https://github.com/ibara/shuf).

Features:
- Shuffle lines from stdin or a file
- -e flag: shuffle command-line arguments
- -i flag: shuffle a range of integers (lo-hi)
- -n flag: limit output to N lines
- -r flag: sample with replacement (repeat output)
- -z flag: null-delimited output
- -o flag: write to output file

MidnightBSD-specific changes:
- Use __dead2 instead of __dead for noreturn functions
- Added forward declarations for all functions
- Removed OpenBSD-specific pledge() calls
- Added Capsicum support using caph_enter() from capsicum_helpers.h
- All functions (arc4random_uniform, reallocarray, strtonum, getprogname)
  are already present in MidnightBSD libc

Also added aitools.md documenting GNU coreutils compatibility for AI agents.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Copilot AI review requested due to automatic review settings July 9, 2026 22:50
@sourcery-ai

sourcery-ai Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Imports the OpenBSD shuf utility into MidnightBSD, wiring it into the build, documenting GNU/coreutils compatibility for AI tools, and making minimal portability/security adjustments (Capsicum, attributes, prototypes) while preserving original behavior and interface.

Sequence diagram for shuf execution flow

sequenceDiagram
    actor User
    participant shuf_main as main
    participant Capsicum as caph_enter
    participant FS as fopen
    participant RNG as arc4random_uniform

    User->>shuf_main: invoke shuf [options]
    shuf_main->>Capsicum: caph_enter()
    Capsicum-->>shuf_main: capability mode enabled

    alt eflag set (-e)
        shuf_main->>shuf_main: parse argv as args
        alt rflag set (-r)
            shuf_main->>shuf_main: randomshuf(argc, argv)
            shuf_main->>RNG: arc4random_uniform(argn)
        else rflag not set
            shuf_main->>shuf_main: shuf(argc, argv)
            shuf_main->>RNG: arc4random_uniform(i + 1)
        end
    else iflag set (-i)
        shuf_main->>shuf_main: shufintegers(hi - lo + 1, lo)
        alt rflag set (-r)
            shuf_main->>RNG: arc4random_uniform(range)
        else rflag not set
            shuf_main->>RNG: arc4random_uniform(i + 1)
        end
    else file/stdin input
        shuf_main->>FS: fopen(file, "r")
        FS-->>shuf_main: ifile
        shuf_main->>shuf_main: read with fgetc(ifile)
        shuf_main->>shuf_main: shuffile(buf, argn, buflen)
        alt rflag set (-r)
            shuf_main->>shuf_main: randomshuf(argn, args)
            shuf_main->>RNG: arc4random_uniform(argn)
        else rflag not set
            shuf_main->>shuf_main: shuf(argn, args)
            shuf_main->>RNG: arc4random_uniform(i + 1)
        end
    end

    shuf_main-->>User: shuffled output via stdout or -o file
Loading

File-Level Changes

Change Details Files
Add shuf(1) implementation based on Brian Callahan's OpenBSD version, with MidnightBSD-specific portability and security adjustments.
  • Introduce shuf.c implementing random permutation of input with support for -e, -i lo-hi, -n count, -o file, -r, -z, -h, -v options.
  • Replace OpenBSD __dead attribute with MidnightBSD __dead2 and add forward declarations for all static functions.
  • Remove OpenBSD pledge() sandboxing and add Capsicum support via caph_enter() from capsicum_helpers.h.
  • Use existing MidnightBSD libc functions arc4random_uniform, reallocarray, strtonum, getprogname for randomness, allocation, and argument parsing.
  • Implement core shuf logic: Fisher–Yates shuffle for in-memory lines, random selection with replacement, integer-range shuffling, and line delimiting via configurable delimiter/NUL handling.
usr.bin/shuf/shuf.c
Wire shuf into the MidnightBSD build system as a standard usr.bin utility.
  • Create a Makefile for shuf using PROG=shuf and SRCS=shuf.c.
  • Include src.opts.mk and bsd.prog.mk to integrate with the existing build infrastructure.
usr.bin/shuf/Makefile
Add man page for shuf(1) documenting usage, options, examples, and caveats.
  • Import shuf.1 mdoc manpage from OpenBSD with licensing header preserved.
  • Document all supported flags, input modes (stdin, -e args, -i lo-hi), output control (-n, -o, -r, -z, -v, -h), and examples.
  • Note intentional omission of long options and the INT_MAX-1 limit for integer ranges.
usr.bin/shuf/shuf.1
Add AI tooling compatibility documentation to describe MidnightBSD vs GNU coreutils behavior and newly added shuf utility.
  • Create aitools.md summarizing missing GNU coreutils, differences in flags/behavior, and available BSD alternatives.
  • Explicitly document shuf as now imported and available in /usr/bin/shuf.
  • Highlight top missing features (e.g., sed -i, grep -P) and suggested workarounds for AI agents.
aitools.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

github-actions Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Claude finished @laffer1's task in 3m 27s —— View job


Claude finished @laffer1's task

  • Gather context (PR description, diff, files)
  • Review usr.bin/shuf/shuf.c (correctness, malloc/free, bounds checking, style(9), security)
  • Review usr.bin/shuf/Makefile
  • Review usr.bin/shuf/shuf.1
  • Review aitools.md
  • Post final review

Review

High-confidence bug: caph_enter() is called before the file opens it needs to protect, breaking -o and file-argument use

usr.bin/shuf/shuf.c:219 calls caph_enter() unconditionally at the top of main(), before the getopt loop runs. But the -o file output path (shuf.c:262) and the positional input file path (shuf.c:310) both call plain fopen() on a caller-supplied path after capability mode has already been entered.

Under Capsicum, once a process is in capability mode (cap_enter()), path-based syscalls like open(2)/fopen(3) on arbitrary filesystem paths are no longer permitted — only operations on already-open descriptors (or openat-style relative-to-capability opens) work. So as written, shuf -o out.txt and shuf somefile will fail (e.g. could not open ...: Not permitted in capability mode / ECAPMODE), while stdin/-e/-i usage (which never opens a new path) will keep working.

This matches the codebase's existing convention: other utilities here that combine Capsicum with path-based file args resolve/open the file(s) before entering capability mode, or use libcasper's fileargs_init()/fileargs_open()/fileargs_fopen() to keep opening files after caph_enter_casper() (see usr.bin/wc/wc.c:133,147 and usr.bin/head/head.c:128,134,143). shuf.c does neither — it uses a bare caph_enter() placed too early.

Notably, the PR description's testing list covers usage/version/stdin/-e/-i/-n/-r, but not -o or a named input file — consistent with this being an untested, broken path.

Suggested fix: move the caph_enter() call to right after both fopen() calls are resolved (i.e., after usr.bin/shuf/shuf.c:312, once ifile/ofile are known-good), since nothing past that point in main() opens a new path — only buffered reads/writes on already-open descriptors.

Fix this →

Minor nits (not blocking):

  • shuf.c:27-28, 92-93, 210-212: mixed space+tab in declarations (e.g. char \tdelimiter, int \t\t\ti = 0;) — inconsistent with style(9)/.clang-format tab alignment used elsewhere in the file.
  • shuf.c:214-217: the #ifdef HAVE_PLEDGE block is dead code — HAVE_PLEDGE is never defined anywhere in the MidnightBSD build for this program, so it can be dropped now that Capsicum replaces pledge.
  • aitools.md at the repo root is a one-off AI-agent compatibility note rather than code/docs infra — consider whether it belongs under share/doc/ or similar instead of the tree root, though this is a judgment call for the maintainers.

Other areas checked, no issues found:

  • shuffile()/shuf()/shufintegers() malloc/free are symmetric (each malloc/reallocarray has a matching free, including on the -e/-i and file-read paths).
  • The size_t inputlen decrement-on-empty pattern in shuffile() can technically wrap when a segment ends exactly at the buffer boundary, but argn (computed in main()) and the parsing in shuffile() use the same delimiter/buffer, so the outer i < argn bound always terminates the loop before the wrapped value is dereferenced in every case I traced (including no-trailing-delimiter and empty-line inputs). This logic is unchanged from upstream OpenBSD, not introduced by this PR.
  • Makefile and shuf.1 are straightforward and consistent with other usr.bin tools; no LIBADD needed since caph_enter() is a header-only inline in capsicum_helpers.h.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues, and left some high level feedback:

  • The Capsicum integration currently calls caph_enter() before opening any input/output files; consider moving capability mode entry until after all required file descriptors are opened and, if desired, using caph_limit_* helpers to more precisely constrain privileges.
  • The version() message string contains a stray quote and awkward line break around "AS IS" that makes the license text slightly malformed; tightening up that literal would improve the output and avoid confusion.
  • Some utility names and locations in aitools.md (e.g., checksum tools under /sbin, base64 helpers) should be cross-checked against the actual MidnightBSD base layout to ensure AI-facing compatibility notes accurately reflect the system.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The Capsicum integration currently calls caph_enter() before opening any input/output files; consider moving capability mode entry until after all required file descriptors are opened and, if desired, using caph_limit_* helpers to more precisely constrain privileges.
- The version() message string contains a stray quote and awkward line break around "AS IS" that makes the license text slightly malformed; tightening up that literal would improve the output and avoid confusion.
- Some utility names and locations in aitools.md (e.g., checksum tools under /sbin, base64 helpers) should be cross-checked against the actual MidnightBSD base layout to ensure AI-facing compatibility notes accurately reflect the system.

## Individual Comments

### Comment 1
<location path="usr.bin/shuf/shuf.c" line_range="219-220" />
<code_context>
+		err(1, "pledge");
+#endif
+
+	if (caph_enter() < 0)
+		err(1, "cap_enter");
+
+	while ((ch = getopt(argc, argv, "ehi:n:o:rvz")) != -1) {
</code_context>
<issue_to_address>
**issue (bug_risk):** Entering capsicum capability mode before opening files likely breaks -o and file input support

On Capsicum systems, entering capability mode before option parsing means the subsequent fopen calls for -o and non-stdin inputs will fail, since path-based opens are disallowed. Please move caph_enter() to after all required files are opened (post-getopt/fopen), and consider using caph_utility_* helpers to appropriately restrict rights on those descriptors once acquired.
</issue_to_address>

### Comment 2
<location path="usr.bin/shuf/shuf.c" line_range="186-199" />
<code_context>
+version(void)
+{
+
+	fputs("shuf 3.0\n"
+	      "Copyright (c) 2017-2020 Brian Callahan <bcallah@openbsd.org>\n"
+	      "\nPermission to use, copy, modify, and distribute this software"
+	      " for any\npurpose with or without fee is hereby granted, "
+	      "provided that the above\ncopyright notice and this permission "
+	      "notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED "
+	      " AS\nIS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES"
+	      " WITH REGARD TO\nTHIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF"
+	      "\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE "
</code_context>
<issue_to_address>
**suggestion (typo):** Version string appears to contain a quoting/spacing typo in the license text

The embedded license string currently shows `" AS
IS" AND`, which misquotes the "AS IS" wording and renders oddly. Please update this segment to match the license header exactly (including spaces, quotes, and newlines) so the user-facing text is correct.

```suggestion
	fputs("shuf 3.0\n"
	      "Copyright (c) 2017-2020 Brian Callahan <bcallah@openbsd.org>\n"
	      "\nPermission to use, copy, modify, and distribute this software"
	      " for any\npurpose with or without fee is hereby granted, "
	      "provided that the above\ncopyright notice and this permission "
	      "notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\""
	      " AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS "
	      "SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND "
	      "FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, "
	      "DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n"
	      "WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER "
	      "IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, "
	      "ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF "
	      "THIS SOFTWARE.\n", stderr);
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread usr.bin/shuf/shuf.c Resolved
Comment thread usr.bin/shuf/shuf.c Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces shuf(1) to MidnightBSD (imported from an OpenBSD implementation), adding a coreutils-compatible random-permutation utility along with its build integration, manual page, and an AI-oriented compatibility document.

Changes:

  • Add usr.bin/shuf implementation supporting -e, -i, -n, -o, -r, and -z.
  • Add shuf(1) manual page and Makefile to build/install the new utility.
  • Add aitools.md documenting MidnightBSD vs GNU coreutils differences for automation/agent workflows.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.

File Description
usr.bin/shuf/shuf.c New shuf implementation (random permutation / sampling) including Capsicum integration.
usr.bin/shuf/shuf.1 New manual page for shuf(1) usage, options, and examples.
usr.bin/shuf/Makefile Build rules for the new shuf utility under usr.bin.
aitools.md New documentation describing MidnightBSD vs GNU coreutils compatibility notes for AI/automation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread usr.bin/shuf/shuf.c Outdated
Comment on lines +219 to +220
if (caph_enter() < 0)
err(1, "cap_enter");
Comment thread usr.bin/shuf/shuf.c
Comment on lines +291 to +300
if (eflag) {
if (argc == 0)
goto out;
delimiter = '\0';
if (rflag)
randomshuf(argc, argv);
else
shuf(argc, argv);
goto out;
}
Comment thread usr.bin/shuf/shuf.c
Comment on lines +302 to +305
if (iflag) {
shufintegers(hi - lo + 1, lo);
goto out;
}
Comment thread usr.bin/shuf/shuf.c
Comment on lines +307 to +315
if (argc == 0 || (argv[0][0] == '-' && argv[0][1] == '\0')) {
ifile = stdin;
} else {
if ((ifile = fopen(*argv, "r")) == NULL)
err(1, "could not open %s", *argv);
}

if ((buf = malloc(bufsize)) == NULL)
err(1, "could not create initial shuffle buffer");
Comment thread aitools.md Resolved
Comment thread aitools.md Resolved
Comment thread usr.bin/shuf/shuf.c
Comment on lines +205 to +206
main(int argc, char *argv[])
{
Copilot AI review requested due to automatic review settings July 9, 2026 23:11
@laffer1

laffer1 commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

Thanks for the code review feedback! I have fixed the Capsicum issue in a follow-up commit. The issue was that caph_enter was called too early, before opening input files. The fix moves it to after all files are opened but before I/O operations.

Import the shuf (random permutation) utility from Brian Callahan's
OpenBSD implementation (https://github.com/ibara/shuf).

Features:
- Shuffle lines from stdin or a file
- -e flag: shuffle command-line arguments
- -i flag: shuffle a range of integers (lo-hi)
- -n flag: limit output to N lines
- -r flag: sample with replacement (repeat output)
- -z flag: null-delimited output
- -o flag: write output to file

MidnightBSD-specific changes:
- Use __dead2 instead of __dead for noreturn functions
- Added forward declarations for all static functions
- Removed OpenBSD-specific pledge() calls
- Added Capsicum support using caph_enter() from capsicum_helpers.h
- All functions (arc4random_uniform, reallocarray, strtonum, getprogname)
  are already present in MidnightBSD libc

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
@github-actions

github-actions Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Claude finished @laffer1's task in 1m 3s —— View job


Todo

  • Gather context (PR comments, prior review, fix commit)
  • Review the follow-up fix commit 19f00f31a5 (Capsicum ordering)
  • Check -e/-i paths no longer need caph_enter()
  • Check other flagged issues (version() string, style nits) status
  • Post final review

Review of follow-up commit 19f00f31a5

The core bug from the earlier review is fixed correctly: caph_enter() (usr.bin/shuf/shuf.c:308) now runs after both fopen() calls that need path access — the -o output file (shuf.c:254, opened during getopt) and the positional input file / stdin (shuf.c:300-305). Nothing after line 308 in that code path opens a new path, so shuf -o out.txt and shuf somefile should now work under Capsicum. The dead #ifdef HAVE_PLEDGE block was also removed as previously suggested.

Remaining issue: -e and -i code paths never call caph_enter() at all

Looking at main(), the -e branch (shuf.c:283-292) and -i branch (shuf.c:294-297) both goto out before reaching the caph_enter() call at line 308. Previously, caph_enter() ran unconditionally at the top of main(), so every mode was sandboxed (just with the file-open bug). After this fix, only the stdin/file-input code path enters capability mode — shuf -e a b c and shuf -i 1-100 now run with no Capsicum confinement whatsoever, including when combined with -o (which still writes through an already-open fd, so sandboxing wouldn't break it).

The commit message justifies this as "they don't do file I/O," which is true for reading, but capability mode is defense-in-depth against unrelated logic bugs (e.g., a future change or an argument-parsing bug reaching unexpected syscalls), not just a file-I/O guard. Since ofile/output is already resolved by the time -e/-i branch off (getopt has already run), it would be safe to call caph_enter() unconditionally right after the getopt loop / -o handling and before the -e/-i/file branches, rather than only in the stdin/file branch. That single relocation would restore full coverage without reintroducing the original bug.

This matches feedback independently raised by the Copilot review on this PR (comments on shuf.c:292 and shuf.c:297).

Still open from the original review (not in scope of this fix commit, unaddressed):

  • shuf.c:191-192 — the version() license string still has the " AS\nIS\" mis-quoting/line-break issue flagged by Sourcery; the text renders as THE SOFTWARE IS PROVIDED AS\nIS" AND ... instead of PROVIDED "AS IS" AND ....
  • Minor mixed space/tab alignment in declarations (e.g. shuf.c:210-212) — style(9)/.clang-format nit, not blocking.

Fix this →

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comment thread usr.bin/shuf/shuf.c
Comment on lines +98 to +122
while (i < argn) {
for (s = input; *s != delimiter; s++) {
if (inputlen-- == 0)
break;
}
len = s - input;

if ((args[i] = malloc(len + 1)) == NULL)
err(1, "could not create shuffile item buffer");
argt = args[i++];

while (len-- > 0)
*argt++ = *input++;
*argt++ = delimiter;

input++;
--inputlen;
}

most = (most < argn ? most : argn);

if (rflag)
randomshuf(argn, args);
else
shuf(argn, args);
Comment thread usr.bin/shuf/shuf.c
Comment on lines +307 to +310
/* Enter capability mode after all files are opened */
if (caph_enter() < 0)
err(1, "cap_enter");

Comment thread usr.bin/shuf/shuf.c
Comment on lines +186 to +202
fputs("shuf 3.0\n"
"Copyright (c) 2017-2020 Brian Callahan <bcallah@openbsd.org>\n"
"\nPermission to use, copy, modify, and distribute this software"
" for any\npurpose with or without fee is hereby granted, "
"provided that the above\ncopyright notice and this permission "
"notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED "
" AS\nIS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES"
" WITH REGARD TO\nTHIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF"
"\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE "
"LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL "
"DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, "
"DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE "
"OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION "
"WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n", stderr);

exit(1);
}
Comment thread aitools.md Outdated
Comment on lines +60 to +63
### `sed`
- ❌ `-i` - In-place file editing (not supported)
- ❌ `-i.bak` - In-place editing with backup (not supported)
- ✅ Standard stream editing (fully supported)
Copilot AI review requested due to automatic review settings July 9, 2026 23:37
@laffer1
laffer1 force-pushed the feature/import-shuf branch from 19f00f3 to caa5289 Compare July 9, 2026 23:37
@github-actions

github-actions Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Claude finished @laffer1's task in 1m 45s —— View job


Todo

  • Gather context (PR comments, prior reviews, latest commits)
  • Review latest diff on branch feature/import-shuf vs origin/master
  • Check whether caph_enter() placement issue is fully resolved (including -e/-i paths)
  • Check version() license string fix status
  • Check other outstanding review items
  • Post final review

Review

No new commits have landed since the last review — HEAD (caa528950b) is unchanged from what was already reviewed. Confirming current state of previously-raised issues:

✅ Fixed: The original Capsicum ordering bug is resolved. caph_enter() (usr.bin/shuf/shuf.c:308) now runs after the -o/input fopen() calls, so shuf -o out.txt and shuf somefile work correctly. The dead #ifdef HAVE_PLEDGE block was also removed.

❌ Still open — -e/-i paths never enter capability mode (shuf.c:283-297)
Both branches goto out (lines 285, 291, 296) before ever reaching caph_enter() at line 308. shuf -e a b c and shuf -i 1-100 run with zero Capsicum confinement, even though ofile is already resolved by the time these branches execute (getopt has finished). Moving caph_enter() to right after the getopt loop (before the -e/-i/file branches) would restore full coverage without reintroducing the original fopen-after-cap_enter bug, since no path-based open happens after that point in any branch.

❌ Still open — malformed license text in version() (shuf.c:186-199)
The embedded string still reads THE SOFTWARE IS PROVIDED AS\nIS" AND ... — a broken "AS IS" quoting/line-break, mismatched vs. the correct header text at the top of the file (shuf.c:8).

New/independently-flagged issue — version() behavior (shuf.c:182-202)
version() writes to stderr and calls exit(1). Printing -v/version output is normally a successful, informational operation — GNU coreutils and most BSD utilities print version text to stdout and exit 0. As written, shuf -v | head shows nothing (stderr isn't piped) and scripts checking $? after shuf -v see a failure. Suggest fputs(..., stdout) and exit(0).

Minor, non-blocking: mixed space+tab in a few declarations (shuf.c:27-28, 92-93, 210-212) still present — style(9)/.clang-format nit only.

Fix this →

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

Comment thread usr.bin/shuf/shuf.c
Comment on lines +98 to +115
while (i < argn) {
for (s = input; *s != delimiter; s++) {
if (inputlen-- == 0)
break;
}
len = s - input;

if ((args[i] = malloc(len + 1)) == NULL)
err(1, "could not create shuffile item buffer");
argt = args[i++];

while (len-- > 0)
*argt++ = *input++;
*argt++ = delimiter;

input++;
--inputlen;
}
Comment thread usr.bin/shuf/shuf.c
Comment on lines +237 to +240
if (lo >= hi)
errx(1, "lo is greater than or equal to hi");
if (hi == INT_MAX && lo == 0)
errx(1, "lo-hi range too large for -i option");
Comment thread usr.bin/shuf/shuf.c
Comment on lines +191 to +193
"notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED "
" AS\nIS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES"
" WITH REGARD TO\nTHIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF"
Comment thread usr.bin/shuf/shuf.c
"OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION "
"WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n", stderr);

exit(1);
Comment thread usr.bin/shuf/shuf.c
Comment on lines +307 to +310
/* Enter capability mode after all files are opened */
if (caph_enter() < 0)
err(1, "cap_enter");

Comment thread usr.bin/shuf/Makefile
Comment on lines +5 to +6
PROG= shuf
SRCS= shuf.c
Comment thread usr.bin/shuf/Makefile
@@ -0,0 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
@laffer1
laffer1 merged commit 7a337d1 into master Jul 10, 2026
12 of 18 checks passed
@laffer1
laffer1 deleted the feature/import-shuf branch July 10, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants