buildPkillShim function

String buildPkillShim({
  1. required String realPkill,
  2. required String realPgrep,
})

The pkill PATH shim: expands the match with the REAL pgrep (the same selection engine and flags), filters the protected pids, the invoking shell (PPID) and the shim itself, then signals the rest with the requested signal (default SIGTERM). Selection shapes the shim models: signal forms (-9, -SIGTERM, --signal[=]), the value-taking selection flags in split form (-u <uid>, -t <tty>, …) and glued form (-urot), and plain selection flags (-f, -x, …). Everything else — output modes (-c, -v, -l, -a, --count, any other long option), a signal spelled after the pattern, extra operands, or a selection pgrep rejects — execs the real pkill (honest behavior over silent guessing): outside the shim the harness chain is NOT protected.

Implementation

String buildPkillShim({required String realPkill, required String realPgrep}) =>
    r'''#!/bin/sh
# fa bash-guard shim for pkill (gh-1763): never signals the harness or its
# ancestor chain, the invoking shell, or itself.
set -u
FA_REAL_PKILL='__FA_REAL_PKILL__'
FA_REAL_PGREP='__FA_REAL_PGREP__'

sig=''
sel=''
fa_dd=0
# Flags that would corrupt the victim set never enter the guarded path —
# the real pkill decides:
# - output modes (c = count prints a number the victim loop would read as
#   a pid, v = negated match, l/a = list modes the real pkill rejects with
#   a usage error — their pgrep output is "pid name" rows, not a pid list);
# - any other long option (only --signal/--signal=<sig> is modeled).
for a in "$@"; do
  case "$a" in
    --|--signal|--signal=*) continue ;;
    --*) exec "$FA_REAL_PKILL" "$@" ;;
    -[a-zA-Z]*)
      fa_body="${a#-}"
      case "$fa_body" in
        [0-9]*|[Ss][Ii][Gg]*|[A-Z]*) continue ;;
      esac
      fa_rest="$fa_body"
      while [ -n "$fa_rest" ]; do
        fa_c="${fa_rest%"${fa_rest#?}"}"
        case "$fa_c" in
          [cval]) exec "$FA_REAL_PKILL" "$@" ;;
        esac
        fa_rest="${fa_rest#?}"
      done
      ;;
  esac
done
while [ $# -gt 0 ]; do
  case "$1" in
    --signal)
      if [ "$#" -ge 2 ]; then sig="$2"; shift 2
      else exec "$FA_REAL_PKILL" "$@"; fi
      ;;
    --signal=*) sig="${1#--signal=}"; shift ;;
    --) fa_dd=1; shift; break ;;
    -[0-9]*) sig="$1"; shift ;;
    -[Ss][Ii][Gg][A-Za-z]*|-[A-Z][A-Z]*) sig="$1"; shift ;;
    # Value-taking selection flags (procps: -u -U -g -s -t -P -G -r -O -q
    # -F): the value may ride the next argv item (split form, e.g.
    # `pkill -u "$(id -u)" -f <pat>`). Consume both into the selection so
    # the guarded path still runs — execing the real, unshimed pkill here
    # would leave the harness unprotected (the gh-1763 crash shape). The
    # glued forms (-urot) ride the generic case below.
    -u|-U|-g|-s|-t|-P|-G|-r|-O|-q|-F)
      if [ "$#" -ge 2 ]; then
        sel="$sel $1 $2"
        shift 2
      else
        exec "$FA_REAL_PKILL" "$@"
      fi
      ;;
    -*) sel="$sel $1"; shift ;;
    *) break ;;
  esac
done
# Exactly one operand (the pattern) must remain; anything else — unknown
# flags interleaved with it, extra operands — is the real pkill's call.
if [ "$#" -ne 1 ]; then
  if [ "$fa_dd" = 1 ]; then exec "$FA_REAL_PKILL" -- "$@"; fi
  exec "$FA_REAL_PKILL" "$@"
fi

# The selection flags ride along: pgrep shares pkill's selection engine.
pids=$("$FA_REAL_PGREP" $sel "$@" 2>/dev/null)
rc=$?
if [ "$rc" -ge 2 ]; then
  # pgrep rejected the selection (a flag it does not share): the real
  # pkill decides, semantics stay honest. A consumed `--` is re-emitted
  # so the surviving operands stay operands (`pkill -- -<pat>`).
  if [ "$fa_dd" = 1 ]; then exec "$FA_REAL_PKILL" -- "$@"; fi
  exec "$FA_REAL_PKILL" "$@"
fi
[ "$rc" -eq 0 ] || exit 1
# Output modes never reach this pgrep call (they exec the real pkill
# above), so pgrep prints bare pids; the cut is belt-and-braces — list
# rows like "pid name" would turn the name column into a phantom kill
# target.
pids=$(printf '%s\n' "$pids" | cut -d' ' -f1)
# --signal/--signal= store the NAME without the leading dash; normalize
# so `kill "$sig" <pid>` works for TERM, KILL and 9 alike.
case "$sig" in -*) ;; ?*) sig="-$sig" ;; esac

self=$$
parent="${PPID:-}"
out=0
for p in $pids; do
  case " ${FA_PROTECTED_PIDS:-} " in *" $p "*) continue ;; esac
  if [ "$p" = "$parent" ] || [ "$p" = "$self" ]; then continue; fi
  if [ -n "$sig" ]; then
    kill "$sig" "$p" 2>/dev/null && out=1
  else
    kill -TERM "$p" 2>/dev/null && out=1
  fi
done
[ "$out" -eq 1 ] && exit 0
exit 1
'''
        .replaceAll('__FA_REAL_PKILL__', realPkill)
        .replaceAll('__FA_REAL_PGREP__', realPgrep);