diff options
Diffstat (limited to 'bin/pkill')
36 files changed, 253 insertions, 61 deletions
diff --git a/bin/pkill/Makefile b/bin/pkill/Makefile index bd755b822b7e..b4a8754d231f 100644 --- a/bin/pkill/Makefile +++ b/bin/pkill/Makefile @@ -1,5 +1,4 @@ # $NetBSD: Makefile,v 1.1 2002/03/01 11:21:58 ad Exp $ -# $FreeBSD$ .include <src.opts.mk> diff --git a/bin/pkill/Makefile.depend b/bin/pkill/Makefile.depend index 6f5a5f79bf30..73bd22d39dcc 100644 --- a/bin/pkill/Makefile.depend +++ b/bin/pkill/Makefile.depend @@ -1,14 +1,11 @@ -# $FreeBSD$ # Autogenerated - do NOT edit! DIRDEPS = \ - gnu/lib/csu \ include \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ lib/libcompiler_rt \ - lib/libelf \ lib/libjail \ lib/libkvm \ diff --git a/bin/pkill/pkill.1 b/bin/pkill/pkill.1 index db9283de26a3..40abbba96362 100644 --- a/bin/pkill/pkill.1 +++ b/bin/pkill/pkill.1 @@ -1,7 +1,5 @@ .\" $NetBSD: pkill.1,v 1.8 2003/02/14 15:59:18 grant Exp $ .\" -.\" $FreeBSD$ -.\" .\" Copyright (c) 2002 The NetBSD Foundation, Inc. .\" All rights reserved. .\" @@ -29,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 5, 2020 +.Dd June 24, 2025 .Dt PKILL 1 .Os .Sh NAME @@ -73,12 +71,17 @@ The .Nm pgrep command searches the process table on the running system and prints the process IDs of all processes that match the criteria given on the command -line. +line, excluding itself and all direct ancestors unless the +.Fl a +option is specified. .Pp The .Nm pkill command searches the process table on the running system and signals all -processes that match the criteria given on the command line. +processes that match the criteria given on the command line, excluding itself +and all direct ancestors unless the +.Fl a +option is specified. .Pp The following options are available: .Bl -tag -width ".Fl F Ar pidfile" @@ -132,6 +135,16 @@ or process and all of its ancestors are excluded (unless .Fl v is used). +Note that the +.Fl a +option will not +.Dq unhide +the +.Nm pgrep +or +.Nm pkill +process itself, even with +.Fl v . .It Fl c Ar class Restrict matches to processes running with specified login class .Ar class . diff --git a/bin/pkill/pkill.c b/bin/pkill/pkill.c index 0ffa5ababaac..4b894a986062 100644 --- a/bin/pkill/pkill.c +++ b/bin/pkill/pkill.c @@ -1,7 +1,7 @@ /* $NetBSD: pkill.c,v 1.16 2005/10/10 22:13:20 kleink Exp $ */ /*- - * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2002 The NetBSD Foundation, Inc. * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org> @@ -32,9 +32,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/types.h> #include <sys/param.h> #include <sys/sysctl.h> @@ -133,8 +130,9 @@ static int takepid(const char *, int); int main(int argc, char **argv) { - char buf[_POSIX2_LINE_MAX], *mstr, **pargv, *p, *q, *pidfile; + char *buf, *mstr, **pargv, *p, *q, *pidfile; const char *execf, *coref; + size_t bufsz; int ancestors, debug_opt, did_action; int i, ch, bestidx, rv, criteria, pidfromfile, pidfilelock; size_t jsz; @@ -177,6 +175,7 @@ main(int argc, char **argv) } } + buf = NULL; ancestors = 0; criteria = 0; debug_opt = 0; @@ -312,6 +311,31 @@ main(int argc, char **argv) mypid = getpid(); /* + * If we're not matching args, we only need a buffer large enough to + * hold some relatively short error strings. Otherwise, we have to + * assume we'll need up to ARG_MAX bytes for arguments. + */ + bufsz = _POSIX2_LINE_MAX; + if (matchargs) { + long arg_max; + + arg_max = sysconf(_SC_ARG_MAX); + if (arg_max == -1) + arg_max = ARG_MAX; + + /* + * The absolute worst case scenario is ARG_MAX single-byte + * arguments which we'll then separate with spaces and NUL + * terminate. + */ + bufsz = (arg_max * 2) + 1; + } + + buf = malloc(bufsz); + if (buf == NULL) + err(STATUS_ERROR, "malloc"); + + /* * Retrieve the list of running processes from the kernel. */ kd = kvm_openfiles(execf, coref, NULL, O_RDONLY, buf); @@ -346,7 +370,7 @@ main(int argc, char **argv) */ for (; *argv != NULL; argv++) { if ((rv = regcomp(®, *argv, cflags)) != 0) { - regerror(rv, ®, buf, sizeof(buf)); + regerror(rv, ®, buf, bufsz); errx(STATUS_BADUSAGE, "Cannot compile regular expression `%s' (%s)", *argv, buf); @@ -363,9 +387,9 @@ main(int argc, char **argv) if (matchargs && (pargv = kvm_getargv(kd, kp, 0)) != NULL) { jsz = 0; - while (jsz < sizeof(buf) && *pargv != NULL) { + while (jsz < bufsz && *pargv != NULL) { jsz += snprintf(buf + jsz, - sizeof(buf) - jsz, + bufsz - jsz, pargv[1] != NULL ? "%s " : "%s", pargv[0]); pargv++; @@ -384,7 +408,7 @@ main(int argc, char **argv) } else selected[i] = 1; } else if (rv != REG_NOMATCH) { - regerror(rv, ®, buf, sizeof(buf)); + regerror(rv, ®, buf, bufsz); errx(STATUS_ERROR, "Regular expression evaluation error (%s)", buf); @@ -576,6 +600,7 @@ main(int argc, char **argv) fprintf(stderr, "No matching processes belonging to you were found\n"); + free(buf); exit(rv ? STATUS_MATCH : STATUS_NOMATCH); } diff --git a/bin/pkill/tests/Makefile b/bin/pkill/tests/Makefile index be467074651f..aaf165521304 100644 --- a/bin/pkill/tests/Makefile +++ b/bin/pkill/tests/Makefile @@ -1,15 +1,19 @@ -# $FreeBSD$ - .include <bsd.own.mk> -TAP_TESTS_SH= pgrep-F_test -TAP_TESTS_SH+= pgrep-LF_test -TAP_TESTS_SH+= pgrep-P_test -TAP_TESTS_SH+= pgrep-U_test +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" @@ -21,10 +25,10 @@ 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-_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 diff --git a/bin/pkill/tests/Makefile.depend b/bin/pkill/tests/Makefile.depend index f80275d86ab1..8e1db63914e6 100644 --- a/bin/pkill/tests/Makefile.depend +++ b/bin/pkill/tests/Makefile.depend @@ -1,7 +1,9 @@ -# $FreeBSD$ # Autogenerated - do NOT edit! DIRDEPS = \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ .include <dirdeps.mk> diff --git a/bin/pkill/tests/pgrep-F_test.sh b/bin/pkill/tests/pgrep-_f_test.sh index 4d8feaa34eb2..41fcc9b678e5 100644 --- a/bin/pkill/tests/pgrep-F_test.sh +++ b/bin/pkill/tests/pgrep-_f_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-_g_test.sh b/bin/pkill/tests/pgrep-_g_test.sh index fbe7b08161a0..65ad5f5c579b 100644 --- a/bin/pkill/tests/pgrep-_g_test.sh +++ b/bin/pkill/tests/pgrep-_g_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-LF_test.sh b/bin/pkill/tests/pgrep-_lf_test.sh index 4818869d8d6e..a9b4b8f08a74 100644 --- a/bin/pkill/tests/pgrep-LF_test.sh +++ b/bin/pkill/tests/pgrep-_lf_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-P_test.sh b/bin/pkill/tests/pgrep-_p_test.sh index 5a5cdcf8e97c..e38e490d5f88 100644 --- a/bin/pkill/tests/pgrep-P_test.sh +++ b/bin/pkill/tests/pgrep-_p_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-_s_test.sh b/bin/pkill/tests/pgrep-_s_test.sh index ce0bde3d8d12..d151ce51018f 100644 --- a/bin/pkill/tests/pgrep-_s_test.sh +++ b/bin/pkill/tests/pgrep-_s_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-U_test.sh b/bin/pkill/tests/pgrep-_u_test.sh index 2e7f24d94659..96e34b7e3666 100644 --- a/bin/pkill/tests/pgrep-U_test.sh +++ b/bin/pkill/tests/pgrep-_u_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` 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 index 14149082338f..b4cb7ffa4137 100644 --- a/bin/pkill/tests/pgrep-g_test.sh +++ b/bin/pkill/tests/pgrep-g_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-i_test.sh b/bin/pkill/tests/pgrep-i_test.sh index b9ecfbc1511d..902a4c0ef045 100644 --- a/bin/pkill/tests/pgrep-i_test.sh +++ b/bin/pkill/tests/pgrep-i_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-j_test.sh b/bin/pkill/tests/pgrep-j_test.sh index 5f44109d41b3..cbeb417f6769 100644 --- a/bin/pkill/tests/pgrep-j_test.sh +++ b/bin/pkill/tests/pgrep-j_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ jail_name_to_jid() { diff --git a/bin/pkill/tests/pgrep-l_test.sh b/bin/pkill/tests/pgrep-l_test.sh index 49273b315b6c..65e9727aead8 100644 --- a/bin/pkill/tests/pgrep-l_test.sh +++ b/bin/pkill/tests/pgrep-l_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-n_test.sh b/bin/pkill/tests/pgrep-n_test.sh index 1b6fe8302867..578b76b3af91 100644 --- a/bin/pkill/tests/pgrep-n_test.sh +++ b/bin/pkill/tests/pgrep-n_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-o_test.sh b/bin/pkill/tests/pgrep-o_test.sh index 250f230ec84f..d5d95d6ab00b 100644 --- a/bin/pkill/tests/pgrep-o_test.sh +++ b/bin/pkill/tests/pgrep-o_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-q_test.sh b/bin/pkill/tests/pgrep-q_test.sh index 2626a5e6bbac..e42acf11a053 100644 --- a/bin/pkill/tests/pgrep-q_test.sh +++ b/bin/pkill/tests/pgrep-q_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-s_test.sh b/bin/pkill/tests/pgrep-s_test.sh index 82c1ef98ddb1..9a6d503347b8 100644 --- a/bin/pkill/tests/pgrep-s_test.sh +++ b/bin/pkill/tests/pgrep-s_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-t_test.sh b/bin/pkill/tests/pgrep-t_test.sh index a8527d5be611..304cc51bbeaf 100644 --- a/bin/pkill/tests/pgrep-t_test.sh +++ b/bin/pkill/tests/pgrep-t_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-v_test.sh b/bin/pkill/tests/pgrep-v_test.sh index b9835bc29f0e..8dce1d37d0c3 100644 --- a/bin/pkill/tests/pgrep-v_test.sh +++ b/bin/pkill/tests/pgrep-v_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pgrep-x_test.sh b/bin/pkill/tests/pgrep-x_test.sh index 1defde23d962..10a865aeafdf 100644 --- a/bin/pkill/tests/pgrep-x_test.sh +++ b/bin/pkill/tests/pgrep-x_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-F_test.sh b/bin/pkill/tests/pkill-_f_test.sh index 48ad47456839..c19d3807deb3 100644 --- a/bin/pkill/tests/pkill-F_test.sh +++ b/bin/pkill/tests/pkill-_f_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-_g_test.sh b/bin/pkill/tests/pkill-_g_test.sh index 1739ac88efa3..34a1edbd0dee 100644 --- a/bin/pkill/tests/pkill-_g_test.sh +++ b/bin/pkill/tests/pkill-_g_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-LF_test.sh b/bin/pkill/tests/pkill-_lf_test.sh index fcafd0a1ee2a..38bddbcf81df 100644 --- a/bin/pkill/tests/pkill-LF_test.sh +++ b/bin/pkill/tests/pkill-_lf_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-P_test.sh b/bin/pkill/tests/pkill-_p_test.sh index 2030710af659..7fb46c5c5407 100644 --- a/bin/pkill/tests/pkill-P_test.sh +++ b/bin/pkill/tests/pkill-_p_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-U_test.sh b/bin/pkill/tests/pkill-_u_test.sh index 04395e559387..5ea4c7257437 100644 --- a/bin/pkill/tests/pkill-U_test.sh +++ b/bin/pkill/tests/pkill-_u_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-g_test.sh b/bin/pkill/tests/pkill-g_test.sh index 29d6ab77b6ab..2148f4489f0a 100644 --- a/bin/pkill/tests/pkill-g_test.sh +++ b/bin/pkill/tests/pkill-g_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-i_test.sh b/bin/pkill/tests/pkill-i_test.sh index b9b8df8be459..ae9240596102 100644 --- a/bin/pkill/tests/pkill-i_test.sh +++ b/bin/pkill/tests/pkill-i_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-j_test.sh b/bin/pkill/tests/pkill-j_test.sh index 1710ca04f653..f279a3ede2f3 100644 --- a/bin/pkill/tests/pkill-j_test.sh +++ b/bin/pkill/tests/pkill-j_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ jail_name_to_jid() { diff --git a/bin/pkill/tests/pkill-s_test.sh b/bin/pkill/tests/pkill-s_test.sh index 0a9587ba6f16..05b1fe3301f6 100644 --- a/bin/pkill/tests/pkill-s_test.sh +++ b/bin/pkill/tests/pkill-s_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-t_test.sh b/bin/pkill/tests/pkill-t_test.sh index 07f511bd1ad7..2be1089692e6 100644 --- a/bin/pkill/tests/pkill-t_test.sh +++ b/bin/pkill/tests/pkill-t_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` diff --git a/bin/pkill/tests/pkill-x_test.sh b/bin/pkill/tests/pkill-x_test.sh index 5ff0d680a83a..5fe751f9ec72 100644 --- a/bin/pkill/tests/pkill-x_test.sh +++ b/bin/pkill/tests/pkill-x_test.sh @@ -1,5 +1,4 @@ #!/bin/sh -# $FreeBSD$ base=`basename $0` @@ -10,13 +9,13 @@ sleep=$(pwd)/sleep.txt ln -sf /bin/sleep $sleep $sleep 5 & sleep 0.3 -pkill -x slee -P $$ +pkill -P $$ -x slee if [ $? -ne 0 ]; then echo "ok 1 - $name" else echo "not ok 1 - $name" fi -pkill -x sleep -P $$ +pkill -P $$ -x sleep if [ $? -eq 0 ]; then echo "ok 2 - $name" else @@ -29,13 +28,13 @@ sleep=$(pwd)/sleep.txt ln -sf /bin/sleep $sleep $sleep 5 & sleep 0.3 -pkill -x -f "$sleep " -P $$ +pkill -P $$ -x -f "$sleep " if [ $? -ne 0 ]; then echo "ok 3 - $name" else echo "not ok 3 - $name" fi -pkill -x -f "$sleep 5" -P $$ +pkill -P $$ -x -f "$sleep 5" if [ $? -eq 0 ]; then echo "ok 4 - $name" else 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); +} |