aboutsummaryrefslogtreecommitdiff
path: root/bin/pkill/tests
diff options
context:
space:
mode:
Diffstat (limited to 'bin/pkill/tests')
-rw-r--r--bin/pkill/tests/Makefile42
-rw-r--r--bin/pkill/tests/Makefile.depend13
-rw-r--r--bin/pkill/tests/pgrep-_f_test.sh23
-rw-r--r--bin/pkill/tests/pgrep-_g_test.sh37
-rw-r--r--bin/pkill/tests/pgrep-_lf_test.sh40
-rw-r--r--bin/pkill/tests/pgrep-_p_test.sh21
-rw-r--r--bin/pkill/tests/pgrep-_s_test.sh21
-rw-r--r--bin/pkill/tests/pgrep-_u_test.sh37
-rw-r--r--bin/pkill/tests/pgrep-f_test.sh57
-rw-r--r--bin/pkill/tests/pgrep-g_test.sh36
-rw-r--r--bin/pkill/tests/pgrep-i_test.sh23
-rw-r--r--bin/pkill/tests/pgrep-j_test.sh116
-rw-r--r--bin/pkill/tests/pgrep-l_test.sh19
-rw-r--r--bin/pkill/tests/pgrep-n_test.sh23
-rw-r--r--bin/pkill/tests/pgrep-o_test.sh23
-rw-r--r--bin/pkill/tests/pgrep-q_test.sh37
-rw-r--r--bin/pkill/tests/pgrep-s_test.sh36
-rw-r--r--bin/pkill/tests/pgrep-t_test.sh36
-rw-r--r--bin/pkill/tests/pgrep-v_test.sh24
-rw-r--r--bin/pkill/tests/pgrep-x_test.sh35
-rw-r--r--bin/pkill/tests/pkill-_f_test.sh26
-rw-r--r--bin/pkill/tests/pkill-_g_test.sh41
-rw-r--r--bin/pkill/tests/pkill-_lf_test.sh42
-rw-r--r--bin/pkill/tests/pkill-_p_test.sh24
-rw-r--r--bin/pkill/tests/pkill-_u_test.sh41
-rw-r--r--bin/pkill/tests/pkill-g_test.sh40
-rw-r--r--bin/pkill/tests/pkill-i_test.sh25
-rw-r--r--bin/pkill/tests/pkill-j_test.sh122
-rw-r--r--bin/pkill/tests/pkill-s_test.sh40
-rw-r--r--bin/pkill/tests/pkill-t_test.sh44
-rw-r--r--bin/pkill/tests/pkill-x_test.sh43
-rw-r--r--bin/pkill/tests/spin_helper.c123
32 files changed, 1310 insertions, 0 deletions
diff --git a/bin/pkill/tests/Makefile b/bin/pkill/tests/Makefile
new file mode 100644
index 000000000000..aaf165521304
--- /dev/null
+++ b/bin/pkill/tests/Makefile
@@ -0,0 +1,42 @@
+.include <bsd.own.mk>
+
+PACKAGE= tests
+
+PROGS+= spin_helper
+BINDIR= ${TESTSDIR}
+
+TAP_TESTS_SH= pgrep-_f_test
+TAP_TESTS_SH+= pgrep-_lf_test
+TAP_TESTS_SH+= pgrep-_p_test
+TAP_TESTS_SH+= pgrep-_u_test
+TAP_TESTS_SH+= pgrep-_g_test
+TAP_TESTS_SH+= pgrep-_s_test
+TAP_TESTS_SH+= pgrep-g_test
+TAP_TESTS_SH+= pgrep-i_test
+TAP_TESTS_SH+= pgrep-f_test
+TAP_TESTS_SH+= pgrep-j_test
+TEST_METADATA.pgrep-j_test+= required_user="root"
+TEST_METADATA.pgrep-j_test+= required_programs="jail jls"
+TAP_TESTS_SH+= pgrep-l_test
+TAP_TESTS_SH+= pgrep-n_test
+TAP_TESTS_SH+= pgrep-o_test
+TAP_TESTS_SH+= pgrep-q_test
+TAP_TESTS_SH+= pgrep-s_test
+TAP_TESTS_SH+= pgrep-t_test
+TAP_TESTS_SH+= pgrep-v_test
+TAP_TESTS_SH+= pgrep-x_test
+TAP_TESTS_SH+= pkill-_f_test
+TAP_TESTS_SH+= pkill-_lf_test
+TAP_TESTS_SH+= pkill-_p_test
+TAP_TESTS_SH+= pkill-_u_test
+TAP_TESTS_SH+= pkill-_g_test
+TAP_TESTS_SH+= pkill-g_test
+TAP_TESTS_SH+= pkill-i_test
+TAP_TESTS_SH+= pkill-j_test
+TEST_METADATA.pkill-j_test+= required_user="root"
+TEST_METADATA.pkill-j_test+= required_programs="jail jls"
+TAP_TESTS_SH+= pkill-s_test
+TAP_TESTS_SH+= pkill-t_test
+TAP_TESTS_SH+= pkill-x_test
+
+.include <bsd.test.mk>
diff --git a/bin/pkill/tests/Makefile.depend b/bin/pkill/tests/Makefile.depend
new file mode 100644
index 000000000000..8e1db63914e6
--- /dev/null
+++ b/bin/pkill/tests/Makefile.depend
@@ -0,0 +1,13 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/bin/pkill/tests/pgrep-_f_test.sh b/bin/pkill/tests/pgrep-_f_test.sh
new file mode 100644
index 000000000000..41fcc9b678e5
--- /dev/null
+++ b/bin/pkill/tests/pgrep-_f_test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pgrep -F <pidfile>"
+pidfile=$(pwd)/pidfile.txt
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+echo $chpid > $pidfile
+pid=`pgrep -f -F $pidfile $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok - $name"
+else
+ echo "not ok - $name"
+fi
+kill "$chpid"
+rm -f $pidfile
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-_g_test.sh b/bin/pkill/tests/pgrep-_g_test.sh
new file mode 100644
index 000000000000..65ad5f5c579b
--- /dev/null
+++ b/bin/pkill/tests/pgrep-_g_test.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pgrep -G <gid>"
+rgid=`id -gr`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -G $rgid $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+kill $chpid
+rm -f $sleep
+
+name="pgrep -G <group>"
+rgid=`id -grn`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -G $rgid $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+kill $chpid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-_lf_test.sh b/bin/pkill/tests/pgrep-_lf_test.sh
new file mode 100644
index 000000000000..a9b4b8f08a74
--- /dev/null
+++ b/bin/pkill/tests/pgrep-_lf_test.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pgrep -LF <pidfile>"
+pidfile=$(pwd)/pidfile.txt
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+daemon -p $pidfile $sleep 5
+sleep 0.3
+chpid=`cat $pidfile`
+pid=`pgrep -f -L -F $pidfile $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+kill "$chpid"
+
+# Be sure we cannot find process which pidfile is not locked.
+$sleep 5 &
+sleep 0.3
+chpid=$!
+echo $chpid > $pidfile
+pgrep -f -L -F $pidfile $sleep 2>/dev/null
+ec=$?
+case $ec in
+0)
+ echo "not ok 2 - $name"
+ ;;
+*)
+ echo "ok 2 - $name"
+ ;;
+esac
+
+kill "$chpid"
+rm -f $pidfile
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-_p_test.sh b/bin/pkill/tests/pgrep-_p_test.sh
new file mode 100644
index 000000000000..e38e490d5f88
--- /dev/null
+++ b/bin/pkill/tests/pgrep-_p_test.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pgrep -P <ppid>"
+ppid=$$
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -P $ppid $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok - $name"
+else
+ echo "not ok - $name"
+fi
+kill $chpid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-_s_test.sh b/bin/pkill/tests/pgrep-_s_test.sh
new file mode 100644
index 000000000000..d151ce51018f
--- /dev/null
+++ b/bin/pkill/tests/pgrep-_s_test.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+exp_pid="$(ps ax | grep '\[idle\]' | awk '{print $1}')"
+
+name="pgrep -S"
+pid=`pgrep -Sx idle`
+if [ "$pid" = "$exp_pid" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+pid=`pgrep -x idle`
+if [ "$pid" != "$exp_pid" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
diff --git a/bin/pkill/tests/pgrep-_u_test.sh b/bin/pkill/tests/pgrep-_u_test.sh
new file mode 100644
index 000000000000..96e34b7e3666
--- /dev/null
+++ b/bin/pkill/tests/pgrep-_u_test.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pgrep -U <uid>"
+ruid=`id -ur`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -U $ruid $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+kill $chpid
+rm -f $sleep
+
+name="pgrep -U <user>"
+ruid=`id -urn`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -U $ruid $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+kill $chpid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-f_test.sh b/bin/pkill/tests/pgrep-f_test.sh
new file mode 100644
index 000000000000..e92e09ebde0c
--- /dev/null
+++ b/bin/pkill/tests/pgrep-f_test.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+: ${ARG_MAX:=524288}
+base=$(dirname $(realpath "$0"))
+
+echo "1..2"
+
+waitfor() {
+ flagfile=$1
+
+ iter=0
+
+ while [ ! -f ${flagfile} ] && [ ${iter} -lt 50 ]; do
+ sleep 0.10
+ iter=$((iter + 1))
+ done
+
+ if [ ! -f ${flagfile} ]; then
+ return 1
+ fi
+}
+
+sentinel="findme=test-$$"
+sentinelsz=$(printf "${sentinel}" | wc -c | tr -d '[[:space:]]')
+name="pgrep -f"
+spin="${base}/spin_helper"
+flagfile="pgrep_f_short.flag"
+
+${spin} --short ${flagfile} ${sentinel} &
+chpid=$!
+if ! waitfor ${flagfile}; then
+ echo "not ok - $name"
+else
+ pid=$(pgrep -f ${sentinel})
+ if [ "$pid" = "$chpid" ]; then
+ echo "ok - $name"
+ else
+ echo "not ok - $name"
+ fi
+fi
+kill $chpid
+
+name="pgrep -f long args"
+flagfile="pgrep_f_long.flag"
+${spin} --long ${flagfile} ${sentinel} &
+chpid=$!
+if ! waitfor ${flagfile}; then
+ echo "not ok - $name"
+else
+ pid=$(pgrep -f ${sentinel})
+ if [ "$pid" = "$chpid" ]; then
+ echo "ok - $name"
+ else
+ echo "not ok - $name"
+ fi
+fi
+kill $chpid
diff --git a/bin/pkill/tests/pgrep-g_test.sh b/bin/pkill/tests/pgrep-g_test.sh
new file mode 100644
index 000000000000..b4cb7ffa4137
--- /dev/null
+++ b/bin/pkill/tests/pgrep-g_test.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pgrep -g <pgrp>"
+pgrp=`ps -o tpgid -p $$ | tail -1`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -g $pgrp $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+kill $chpid
+rm -f $sleep
+
+name="pgrep -g 0"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -g 0 $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+kill $chpid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-i_test.sh b/bin/pkill/tests/pgrep-i_test.sh
new file mode 100644
index 000000000000..902a4c0ef045
--- /dev/null
+++ b/bin/pkill/tests/pgrep-i_test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pgrep -i"
+sleep=$(pwd)/sleep.txt
+usleep="${sleep}XXX"
+touch $usleep
+lsleep="${sleep}xxx"
+ln -sf /bin/sleep $usleep
+$usleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -i $lsleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok - $name"
+else
+ echo "not ok - $name"
+fi
+kill $chpid
+rm -f $sleep $usleep
diff --git a/bin/pkill/tests/pgrep-j_test.sh b/bin/pkill/tests/pgrep-j_test.sh
new file mode 100644
index 000000000000..cbeb417f6769
--- /dev/null
+++ b/bin/pkill/tests/pgrep-j_test.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+jail_name_to_jid()
+{
+ local check_name="$1"
+ jls -j "$check_name" -s | tr ' ' '\n' | grep jid= | sed -e 's/.*=//g'
+}
+
+base=pgrep_j_test
+
+if [ "$(id -u)" -ne 0 ]; then
+ echo "1..0 # skip Test needs uid 0."
+ exit 0
+fi
+
+echo "1..4"
+
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+
+name="pgrep -j <jid>"
+sleep_amount=15
+jail -c path=/ name=${base}_1_1 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_1_1.pid $sleep $sleep_amount &
+
+jail -c path=/ name=${base}_1_2 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_1_2.pid $sleep $sleep_amount &
+sleep 0.5
+
+for i in $(seq 1 10); do
+ jid1=$(jail_name_to_jid ${base}_1_1)
+ jid2=$(jail_name_to_jid ${base}_1_2)
+ jid="${jid1},${jid2}"
+ case "$jid" in
+ [0-9]*,[0-9]*)
+ break
+ ;;
+ esac
+ sleep 0.1
+done
+sleep 0.5
+
+pid1="$(pgrep -f -x -j "$jid" "$sleep $sleep_amount" | sort)"
+pid2=$(printf "%s\n%s" "$(cat ${PWD}/${base}_1_1.pid)" \
+ "$(cat ${PWD}/${base}_1_2.pid)" | sort)
+if [ "$pid1" = "$pid2" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name # pgrep output: '$pid1', pidfile output: '$pid2'"
+fi
+[ -f ${PWD}/${base}_1_1.pid ] && kill "$(cat ${PWD}/${base}_1_1.pid)"
+[ -f ${PWD}/${base}_1_2.pid ] && kill "$(cat ${PWD}/${base}_1_2.pid)"
+wait
+
+name="pgrep -j any"
+sleep_amount=16
+jail -c path=/ name=${base}_2_1 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_2_1.pid $sleep $sleep_amount &
+
+jail -c path=/ name=${base}_2_2 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_2_2.pid $sleep $sleep_amount &
+
+sleep 2
+pid1="$(pgrep -f -x -j any "$sleep $sleep_amount" | sort)"
+pid2=$(printf "%s\n%s" "$(cat ${PWD}/${base}_2_1.pid)" \
+ "$(cat ${PWD}/${base}_2_2.pid)" | sort)
+if [ "$pid1" = "$pid2" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name # pgrep output: '$pid1', pidfile output: '$pid2'"
+fi
+[ -f ${PWD}/${base}_2_1.pid ] && kill "$(cat ${PWD}/${base}_2_1.pid)"
+[ -f ${PWD}/${base}_2_2.pid ] && kill "$(cat ${PWD}/${base}_2_2.pid)"
+wait
+
+name="pgrep -j none"
+sleep_amount=17
+daemon -p ${PWD}/${base}_3_1.pid $sleep $sleep_amount &
+jail -c path=/ name=${base}_3_2 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_3_2.pid $sleep $sleep_amount &
+sleep 2
+pid="$(pgrep -f -x -j none "$sleep $sleep_amount")"
+if [ "$pid" = "$(cat ${PWD}/${base}_3_1.pid)" ]; then
+ echo "ok 3 - $name"
+else
+ echo "not ok 3 - $name # pgrep output: '$pid1', pidfile output: '$pid2'"
+fi
+[ -f ${PWD}/${base}_3_1.pid ] && kill "$(cat $PWD/${base}_3_1.pid)"
+[ -f ${PWD}/${base}_3_2.pid ] && kill "$(cat $PWD/${base}_3_2.pid)"
+wait
+
+# test 4 is like test 1 except with jname instead of jid.
+name="pgrep -j <jname>"
+sleep_amount=18
+jail -c path=/ name=${base}_4_1 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_4_1.pid $sleep $sleep_amount &
+
+jail -c path=/ name=${base}_4_2 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_4_2.pid $sleep $sleep_amount &
+
+sleep 0.5
+
+jname="${base}_4_1,${base}_4_2"
+pid1="$(pgrep -f -x -j "$jname" "$sleep $sleep_amount" | sort)"
+pid2=$(printf "%s\n%s" "$(cat ${PWD}/${base}_4_1.pid)" \
+ "$(cat ${PWD}/${base}_4_2.pid)" | sort)
+if [ "$pid1" = "$pid2" ]; then
+ echo "ok 4 - $name"
+else
+ echo "not ok 4 - $name # pgrep output: '$(echo $pid1)', pidfile output: '$(echo $pid2)'"
+fi
+[ -f ${PWD}/${base}_4_1.pid ] && kill "$(cat ${PWD}/${base}_4_1.pid)"
+[ -f ${PWD}/${base}_4_2.pid ] && kill "$(cat ${PWD}/${base}_4_2.pid)"
+wait
+
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-l_test.sh b/bin/pkill/tests/pgrep-l_test.sh
new file mode 100644
index 000000000000..65e9727aead8
--- /dev/null
+++ b/bin/pkill/tests/pgrep-l_test.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pgrep -l"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pid=$!
+if [ "$pid $sleep 5" = "`pgrep -f -l $sleep`" ]; then
+ echo "ok - $name"
+else
+ echo "not ok - $name"
+fi
+kill $pid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-n_test.sh b/bin/pkill/tests/pgrep-n_test.sh
new file mode 100644
index 000000000000..578b76b3af91
--- /dev/null
+++ b/bin/pkill/tests/pgrep-n_test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pgrep -n"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+oldpid=$!
+$sleep 5 &
+sleep 0.3
+newpid=$!
+pid=`pgrep -f -n $sleep`
+if [ "$pid" = "$newpid" ]; then
+ echo "ok - $name"
+else
+ echo "not ok - $name"
+fi
+kill $oldpid
+kill $newpid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-o_test.sh b/bin/pkill/tests/pgrep-o_test.sh
new file mode 100644
index 000000000000..d5d95d6ab00b
--- /dev/null
+++ b/bin/pkill/tests/pgrep-o_test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pgrep -o"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+oldpid=$!
+$sleep 5 &
+sleep 0.3
+newpid=$!
+pid=`pgrep -f -o $sleep`
+if [ "$pid" = "$oldpid" ]; then
+ echo "ok - $name"
+else
+ echo "not ok - $name"
+fi
+kill $oldpid
+kill $newpid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-q_test.sh b/bin/pkill/tests/pgrep-q_test.sh
new file mode 100644
index 000000000000..e42acf11a053
--- /dev/null
+++ b/bin/pkill/tests/pgrep-q_test.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..4"
+
+name="pgrep -q"
+sleep0=$(pwd)/sleep0.txt
+sleep1=$(pwd)/sleep1.txt
+ln -sf /bin/sleep $sleep0
+$sleep0 5 &
+sleep 0.3
+pid=$!
+out="`pgrep -q -f $sleep0 2>&1`"
+if [ $? -eq 0 ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+if [ -z "${out}" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+out="`pgrep -q -f $sleep1 2>&1`"
+if [ $? -ne 0 ]; then
+ echo "ok 3 - $name"
+else
+ echo "not ok 3 - $name"
+fi
+if [ -z "${out}" ]; then
+ echo "ok 4 - $name"
+else
+ echo "not ok 4 - $name"
+fi
+kill $pid
+rm -f $sleep0 $sleep1
diff --git a/bin/pkill/tests/pgrep-s_test.sh b/bin/pkill/tests/pgrep-s_test.sh
new file mode 100644
index 000000000000..9a6d503347b8
--- /dev/null
+++ b/bin/pkill/tests/pgrep-s_test.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pgrep -s <sid>"
+sid=`ps -o tsid -p $$ | tail -1`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -s $sid $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+kill $chpid
+rm -f $sleep
+
+name="pgrep -s 0"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -s 0 $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+kill $chpid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-t_test.sh b/bin/pkill/tests/pgrep-t_test.sh
new file mode 100644
index 000000000000..304cc51bbeaf
--- /dev/null
+++ b/bin/pkill/tests/pgrep-t_test.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pgrep -t <tty>"
+tty=`ps -x -o tty -p $$ | tail -1`
+if [ "$tty" = "??" -o "$tty" = "-" ]; then
+ tty="-"
+ ttyshort="-"
+else
+ case $tty in
+ pts/*) ttyshort=`echo $tty | cut -c 5-` ;;
+ *) ttyshort=`echo $tty | cut -c 4-` ;;
+ esac
+fi
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+chpid=$!
+pid=`pgrep -f -t $tty $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+pid=`pgrep -f -t $ttyshort $sleep`
+if [ "$pid" = "$chpid" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+kill $chpid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-v_test.sh b/bin/pkill/tests/pgrep-v_test.sh
new file mode 100644
index 000000000000..8dce1d37d0c3
--- /dev/null
+++ b/bin/pkill/tests/pgrep-v_test.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pgrep -v"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pid=$!
+if [ -z "`pgrep -f -v $sleep | egrep '^'"$pid"'$'`" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+if [ ! -z "`pgrep -f -v -x x | egrep '^'"$pid"'$'`" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+kill $pid
+rm -f $sleep
diff --git a/bin/pkill/tests/pgrep-x_test.sh b/bin/pkill/tests/pgrep-x_test.sh
new file mode 100644
index 000000000000..10a865aeafdf
--- /dev/null
+++ b/bin/pkill/tests/pgrep-x_test.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..4"
+
+name="pgrep -x"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pid=$!
+if [ ! -z "`pgrep -x sleep | egrep '^'"$pid"'$'`" ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+if [ -z "`pgrep -x slee | egrep '^'"$pid"'$'`" ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+name="pgrep -x -f"
+if [ ! -z "`pgrep -x -f ''"$sleep"' 5' | egrep '^'"$pid"'$'`" ]; then
+ echo "ok 3 - $name"
+else
+ echo "not ok 3 - $name"
+fi
+if [ -z "`pgrep -x -f ''"$sleep"' ' | egrep '^'"$pid"'$'`" ]; then
+ echo "ok 4 - $name"
+else
+ echo "not ok 4 - $name"
+fi
+kill $pid
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-_f_test.sh b/bin/pkill/tests/pkill-_f_test.sh
new file mode 100644
index 000000000000..c19d3807deb3
--- /dev/null
+++ b/bin/pkill/tests/pkill-_f_test.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pkill -F <pidfile>"
+pidfile=$(pwd)/pidfile.txt
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+echo $! > $pidfile
+pkill -f -F $pidfile $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok - $name"
+ ;;
+*)
+ echo "not ok - $name"
+ ;;
+esac
+
+rm -f $pidfile
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-_g_test.sh b/bin/pkill/tests/pkill-_g_test.sh
new file mode 100644
index 000000000000..34a1edbd0dee
--- /dev/null
+++ b/bin/pkill/tests/pkill-_g_test.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pkill -G <gid>"
+rgid=`id -gr`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -G $rgid $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 1 - $name"
+ ;;
+*)
+ echo "not ok 1 - $name"
+ ;;
+esac
+rm -f $sleep
+
+name="pkill -G <group>"
+rgid=`id -grn`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -G $rgid $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 2 - $name"
+ ;;
+*)
+ echo "not ok 2 - $name"
+ ;;
+esac
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-_lf_test.sh b/bin/pkill/tests/pkill-_lf_test.sh
new file mode 100644
index 000000000000..38bddbcf81df
--- /dev/null
+++ b/bin/pkill/tests/pkill-_lf_test.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pkill -LF <pidfile>"
+pidfile=$(pwd)/pidfile.txt
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+daemon -p $pidfile $sleep 5
+sleep 0.3
+pkill -f -L -F $pidfile $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 1 - $name"
+ ;;
+*)
+ echo "not ok 1 - $name"
+ ;;
+esac
+
+# Be sure we cannot kill process which pidfile is not locked.
+$sleep 5 &
+sleep 0.3
+chpid=$!
+echo $chpid > $pidfile
+pkill -f -L -F $pidfile $sleep 2>/dev/null
+ec=$?
+case $ec in
+0)
+ echo "not ok 2 - $name"
+ ;;
+*)
+ echo "ok 2 - $name"
+ ;;
+esac
+
+kill "$chpid"
+rm -f $pidfile
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-_p_test.sh b/bin/pkill/tests/pkill-_p_test.sh
new file mode 100644
index 000000000000..7fb46c5c5407
--- /dev/null
+++ b/bin/pkill/tests/pkill-_p_test.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pkill -P <ppid>"
+ppid=$$
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -P $ppid $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok - $name"
+ ;;
+*)
+ echo "not ok - $name"
+ ;;
+esac
+
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-_u_test.sh b/bin/pkill/tests/pkill-_u_test.sh
new file mode 100644
index 000000000000..5ea4c7257437
--- /dev/null
+++ b/bin/pkill/tests/pkill-_u_test.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pkill -U <uid>"
+ruid=`id -ur`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -U $ruid $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 1 - $name"
+ ;;
+*)
+ echo "not ok 1 - $name"
+ ;;
+esac
+rm -f $sleep
+
+name="pkill -U <user>"
+ruid=`id -urn`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -U $ruid $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 2 - $name"
+ ;;
+*)
+ echo "not ok 2 - $name"
+ ;;
+esac
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-g_test.sh b/bin/pkill/tests/pkill-g_test.sh
new file mode 100644
index 000000000000..2148f4489f0a
--- /dev/null
+++ b/bin/pkill/tests/pkill-g_test.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pkill -g <pgrp>"
+pgrp=`ps -o tpgid -p $$ | tail -1`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -g $pgrp $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 1 - $name"
+ ;;
+*)
+ echo "not ok 1 - $name"
+ ;;
+esac
+rm -f $sleep
+
+name="pkill -g 0"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -g 0 $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 2 - $name"
+ ;;
+*)
+ echo "not ok 2 - $name"
+ ;;
+esac
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-i_test.sh b/bin/pkill/tests/pkill-i_test.sh
new file mode 100644
index 000000000000..ae9240596102
--- /dev/null
+++ b/bin/pkill/tests/pkill-i_test.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..1"
+
+name="pkill -i"
+sleep=$(pwd)/sleep.txt
+usleep="${sleep}XXX"
+touch $usleep
+lsleep="${sleep}xxx"
+ln -sf /bin/sleep $usleep
+$usleep 5 &
+sleep 0.3
+pkill -f -i $lsleep
+ec=$?
+case $ec in
+0)
+ echo "ok - $name"
+ ;;
+*)
+ echo "not ok - $name"
+ ;;
+esac
+rm -f $sleep $usleep
diff --git a/bin/pkill/tests/pkill-j_test.sh b/bin/pkill/tests/pkill-j_test.sh
new file mode 100644
index 000000000000..f279a3ede2f3
--- /dev/null
+++ b/bin/pkill/tests/pkill-j_test.sh
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+jail_name_to_jid()
+{
+ local check_name="$1"
+ jls -j "$check_name" -s | tr ' ' '\n' | grep jid= | sed -e 's/.*=//g'
+}
+
+base=pkill_j_test
+
+if [ "$(id -u)" -ne 0 ]; then
+ echo "1..0 # skip Test needs uid 0."
+ exit 0
+fi
+
+echo "1..4"
+
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+
+name="pkill -j <jid>"
+sleep_amount=15
+jail -c path=/ name=${base}_1_1 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_1_1.pid $sleep $sleep_amount &
+
+jail -c path=/ name=${base}_1_2 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_1_2.pid $sleep $sleep_amount &
+
+$sleep $sleep_amount &
+
+for i in $(seq 1 10); do
+ jid1=$(jail_name_to_jid ${base}_1_1)
+ jid2=$(jail_name_to_jid ${base}_1_2)
+ jid="${jid1},${jid2}"
+ case "$jid" in
+ [0-9]*,[0-9]*)
+ break
+ ;;
+ *)
+ echo "Did not match: '${jid}'" >&2
+ ;;
+ esac
+ sleep 0.1
+done
+sleep 0.5
+
+if pkill -f -j "$jid" $sleep && sleep 0.5 &&
+ ! test -f "${PWD}/${base}_1_1.pid" &&
+ ! test -f "${PWD}/${base}_1_2.pid" ; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi 2>/dev/null
+[ -f ${PWD}/${base}_1_1.pid ] && kill "$(cat ${PWD}/${base}_1_1.pid)"
+[ -f ${PWD}/${base}_1_2.pid ] && kill "$(cat ${PWD}/${base}_1_2.pid)"
+wait
+
+name="pkill -j any"
+sleep_amount=16
+jail -c path=/ name=${base}_2_1 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_2_1.pid $sleep $sleep_amount &
+
+jail -c path=/ name=${base}_2_2 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_2_2.pid $sleep $sleep_amount &
+
+$sleep $sleep_amount &
+chpid3=$!
+sleep 0.5
+if pkill -f -j any $sleep && sleep 0.5 &&
+ ! test -f ${PWD}/${base}_2_1.pid &&
+ ! test -f ${PWD}/${base}_2_2.pid && kill $chpid3; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi 2>/dev/null
+[ -f ${PWD}/${base}_2_1.pid ] && kill "$(cat ${PWD}/${base}_2_1.pid)"
+[ -f ${PWD}/${base}_2_2.pid ] && kill "$(cat ${PWD}/${base}_2_2.pid)"
+wait
+
+name="pkill -j none"
+sleep_amount=17
+daemon -p ${PWD}/${base}_3_1.pid $sleep $sleep_amount
+jail -c path=/ name=${base}_3_2 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_3_2.pid $sleep $sleep_amount &
+sleep 1
+if pkill -f -j none "$sleep $sleep_amount" && sleep 1 &&
+ [ ! -f ${PWD}/${base}_3_1.pid -a -f ${PWD}/${base}_3_2.pid ] ; then
+ echo "ok 3 - $name"
+else
+ ls ${PWD}/*.pid
+ echo "not ok 3 - $name"
+fi 2>/dev/null
+[ -f ${PWD}/${base}_3_1.pid ] && kill "$(cat ${base}_3_1.pid)"
+[ -f ${PWD}/${base}_3_2.pid ] && kill "$(cat ${base}_3_2.pid)"
+wait
+
+# test 4 is like test 1 except with jname instead of jid.
+name="pkill -j <jname>"
+sleep_amount=18
+jail -c path=/ name=${base}_4_1 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_4_1.pid $sleep $sleep_amount &
+
+jail -c path=/ name=${base}_4_2 ip4.addr=127.0.0.1 \
+ command=daemon -p ${PWD}/${base}_4_2.pid $sleep $sleep_amount &
+
+$sleep $sleep_amount &
+
+sleep 0.5
+
+jname="${base}_4_1,${base}_4_2"
+if pkill -f -j "$jname" $sleep && sleep 0.5 &&
+ ! test -f ${PWD}/${base}_4_1.pid &&
+ ! test -f ${PWD}/${base}_4_2.pid ; then
+ echo "ok 4 - $name"
+else
+ echo "not ok 4 - $name"
+fi 2>/dev/null
+[ -f ${PWD}/${base}_4_1.pid ] && kill "$(cat ${PWD}/${base}_4_1.pid)"
+[ -f ${PWD}/${base}_4_2.pid ] && kill "$(cat ${PWD}/${base}_4_2.pid)"
+wait
+
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-s_test.sh b/bin/pkill/tests/pkill-s_test.sh
new file mode 100644
index 000000000000..05b1fe3301f6
--- /dev/null
+++ b/bin/pkill/tests/pkill-s_test.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pkill -s <sid>"
+sid=`ps -o tsid -p $$ | tail -1`
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -s $sid $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 1 - $name"
+ ;;
+*)
+ echo "not ok 1 - $name"
+ ;;
+esac
+rm -f $sleep
+
+name="pkill -s 0"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -s 0 $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 2 - $name"
+ ;;
+*)
+ echo "not ok 2 - $name"
+ ;;
+esac
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-t_test.sh b/bin/pkill/tests/pkill-t_test.sh
new file mode 100644
index 000000000000..2be1089692e6
--- /dev/null
+++ b/bin/pkill/tests/pkill-t_test.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..2"
+
+name="pkill -t <tty>"
+tty=`ps -x -o tty -p $$ | tail -1`
+if [ "$tty" = "??" -o "$tty" = "-" ]; then
+ tty="-"
+ ttyshort="-"
+else
+ case $tty in
+ pts/*) ttyshort=`echo $tty | cut -c 5-` ;;
+ *) ttyshort=`echo $tty | cut -c 4-` ;;
+ esac
+fi
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -f -t $tty $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 1 - $name"
+ ;;
+*)
+ echo "not ok 1 - $name"
+ ;;
+esac
+$sleep 5 &
+sleep 0.3
+pkill -f -t $ttyshort $sleep
+ec=$?
+case $ec in
+0)
+ echo "ok 2 - $name"
+ ;;
+*)
+ echo "not ok 2 - $name"
+ ;;
+esac
+rm -f $sleep
diff --git a/bin/pkill/tests/pkill-x_test.sh b/bin/pkill/tests/pkill-x_test.sh
new file mode 100644
index 000000000000..5fe751f9ec72
--- /dev/null
+++ b/bin/pkill/tests/pkill-x_test.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+base=`basename $0`
+
+echo "1..4"
+
+name="pkill -x"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -P $$ -x slee
+if [ $? -ne 0 ]; then
+ echo "ok 1 - $name"
+else
+ echo "not ok 1 - $name"
+fi
+pkill -P $$ -x sleep
+if [ $? -eq 0 ]; then
+ echo "ok 2 - $name"
+else
+ echo "not ok 2 - $name"
+fi
+rm -f $sleep
+
+name="pkill -x -f"
+sleep=$(pwd)/sleep.txt
+ln -sf /bin/sleep $sleep
+$sleep 5 &
+sleep 0.3
+pkill -P $$ -x -f "$sleep "
+if [ $? -ne 0 ]; then
+ echo "ok 3 - $name"
+else
+ echo "not ok 3 - $name"
+fi
+pkill -P $$ -x -f "$sleep 5"
+if [ $? -eq 0 ]; then
+ echo "ok 4 - $name"
+else
+ echo "not ok 4 - $name"
+fi
+rm -f $sleep
diff --git a/bin/pkill/tests/spin_helper.c b/bin/pkill/tests/spin_helper.c
new file mode 100644
index 000000000000..10541ad12516
--- /dev/null
+++ b/bin/pkill/tests/spin_helper.c
@@ -0,0 +1,123 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Klara, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int
+exec_shortargs(char *argv[])
+{
+ char *flag_arg = argv[2];
+ char *sentinel = argv[3];
+ char * nargv[] = { argv[0], __DECONST(char *, "--spin"), flag_arg,
+ sentinel, NULL };
+ char * const nenvp[] = { NULL };
+
+ execve(argv[0], nargv, nenvp);
+ err(1, "execve");
+}
+
+static int
+exec_largeargs(char *argv[])
+{
+ char *flag_arg = argv[2];
+ char *sentinel = argv[3];
+ /*
+ * Account for each argument and their NUL terminator, as well as an
+ * extra NUL terminator.
+ */
+ size_t bufsz = ARG_MAX -
+ ((strlen(argv[0]) + 1) + sizeof("--spin") + (strlen(flag_arg) + 1) +
+ (strlen(sentinel) + 1) + 1);
+ char *s = NULL;
+ char * nargv[] = { argv[0], __DECONST(char *, "--spin"), flag_arg, NULL,
+ sentinel, NULL };
+ char * const nenvp[] = { NULL };
+
+ /*
+ * Our heuristic may or may not be accurate, we'll keep trying with
+ * smaller argument sizes as needed until we stop getting E2BIG.
+ */
+ do {
+ if (s == NULL)
+ s = malloc(bufsz + 1);
+ else
+ s = realloc(s, bufsz + 1);
+ if (s == NULL)
+ abort();
+ memset(s, 'x', bufsz);
+ s[bufsz] = '\0';
+ nargv[3] = s;
+
+ execve(argv[0], nargv, nenvp);
+ bufsz--;
+ } while (errno == E2BIG);
+ err(1, "execve");
+}
+
+int
+main(int argc, char *argv[])
+{
+
+ if (argc > 1 && strcmp(argv[1], "--spin") == 0) {
+ int fd;
+
+ if (argc < 4) {
+ fprintf(stderr, "usage: %s --spin flagfile ...\n", argv[0]);
+ return (1);
+ }
+
+ fd = open(argv[2], O_RDWR | O_CREAT, 0755);
+ if (fd < 0)
+ err(1, "%s", argv[2]);
+ close(fd);
+
+ for (;;) {
+ sleep(1);
+ }
+
+ return (1);
+ }
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s [--short | --long] flagfile sentinel\n",
+ argv[0]);
+ return (1);
+ }
+
+ if (strcmp(argv[1], "--short") == 0)
+ exec_shortargs(argv);
+ else
+ exec_largeargs(argv);
+}