fix old nix manpages, strip priv esc

This commit is contained in:
atagen 2026-03-24 22:18:12 +11:00
parent bbd7c67d0c
commit 6da495dc59
2 changed files with 81 additions and 14 deletions

View file

@ -762,6 +762,50 @@ let fuzzy_score needle haystack =
) (0, 0, 0, -1) haystack_lc in
if ni = nlen then score else 0
(* known privilege-escalation wrappers. when one of these is the first token,
* we strip it (and its own options/arguments) before completing the real command.
* options that consume the next token as an argument are listed per-command so
* we don't accidentally treat the argument value as the real command name. *)
let elevation_commands =
["sudo"; "run0"; "doas"; "pkexec"; "su"; "calife"; "sux"; "sudoedit";
"please"; "super"; "priv"]
let elevation_opts_with_arg = function
| "sudo" -> ["-u"; "--user"; "-g"; "--group"; "-h"; "--host";
"-p"; "--prompt"; "-r"; "--role"; "-t"; "--type";
"-U"; "--other-user"; "-C"; "--close-from";
"-T"; "--command-timeout"; "-D"; "--chdir"]
| "run0" -> ["--unit"; "--property"; "--description"; "--slice";
"--user"; "--group"; "--nice"; "--chdir"; "--setenv";
"--background"; "--machine"]
| "doas" -> ["-C"; "-u"]
| "pkexec" -> ["--user"]
| "su" -> ["-c"; "-s"; "-g"; "-G"]
| _ -> []
(* strip the elevation command itself plus all its own flags/options from
* the span list, returning the spans for the real command (or [] if none).
* handles:
* --flag=value (value is part of the token no extra token consumed)
* --flag value (value is the next token consumed if flag is in the list)
* -- (end-of-options sentinel everything after is the command) *)
let strip_elevation cmd args =
let with_arg = elevation_opts_with_arg cmd in
let rec skip = function
| [] -> []
| "--" :: rest -> rest
| arg :: rest when String.length arg > 0 && arg.[0] = '-' ->
if List.mem arg with_arg then
(* option takes the next token as its argument — drop both *)
skip (match rest with _ :: tl -> tl | [] -> [])
else begin
(* boolean flag or --flag=value form — drop only this token *)
skip rest
end
| real_cmd -> real_cmd
in
skip args
(* "inshellah complete CMD [ARGS...]" — the nushell custom completer.
* this is the hot path called every time the user presses tab in nushell.
*
@ -785,6 +829,12 @@ let fuzzy_score needle haystack =
* prevents showing sibling subcommands when the user has already committed
* to a specific subcommand path. *)
let cmd_complete spans user_dir system_dirs =
(* if the command line starts with a privilege-escalation wrapper, strip the
* wrapper and all its own options so we complete the real command instead. *)
let spans = match spans with
| cmd :: rest when List.mem cmd elevation_commands ->
strip_elevation cmd rest
| _ -> spans in
match spans with
| [] -> print_string "[]\n"
| cmd_name :: rest ->