diff --git a/Makefile b/Makefile index e1c3ea1..761e4f7 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,8 @@ RUSTLIBS = --extern getopt=build/o/libgetopt.rlib \ CFLAGS += -I$(SYSEXITS) .PHONY: all -all: dj false fop hru intcmp mm npc pschdir retval rpn scrut str strcmp swab true +all: dj false fop hru intcmp mm npc pschdir retval rpn scrut simexec str \ + strcmp swab true # keep build/include until bindgen(1) has stdin support # https://github.com/rust-lang/rust-bindgen/issues/2703 @@ -142,6 +143,11 @@ scrut: build/bin/scrut build/bin/scrut: src/scrut.c build $(CC) $(CFLAGS) -o $@ src/scrut.c +.PHONY: simexec +simexec: build/bin/simexec +build/bin/simexec: src/simexec.c build + $(CC) $(CFLAGS) -o $@ src/simexec.c + .PHONY: str str: build/bin/str build/bin/str: src/str.c build diff --git a/docs/simexec.1 b/docs/simexec.1 new file mode 100644 index 0000000..794b972 --- /dev/null +++ b/docs/simexec.1 @@ -0,0 +1,79 @@ +.\" Copyright (c) 2022–2024 DTB +.\" +.\" This work is licensed under CC BY-SA 4.0. To see a copy of this license, +.\" visit . +.\" +.TH SIMEXEC 1 2024-07-23 "Harakit-overgrown X.X.X" +.SH NAME +simexec \(en execute a program with argv +.\" +.SH SYNOPSIS + +simexec +.B binary argv... +.SH DESCRIPTION +Execute a binary with a certain argv. +.SH CAVEATS + +Non-binary programs cannot be executed on their own. The PATH environment +variable is not used and a valid pathname (relative or absolute) must be +specified. + +.BR simexec (1) +requires caution. +.B argv +are not just the operands for the binary but in fact the direct +.B argv +it will receive in runtime; +the first argv entry is the program\(cqs name, and omitting this, though valid +use of +.BR simexec (1), +can break false assumptions made by programmers. +for example, the +.BR true (1) +implementation in the GNU coreutils project suffers a segmentation fault it is +given no argv[0]. + +While POSIX.1-2017 doesn't mandate there being an argv[0] per se, a Strictly +Conforming POSIX Application must pass an argv[0]. It has also been said that +those who do not pass an argv[0] are mean and nasty and smell of elderberries. + +.BR simexec (1) +directly uses the +.BR execv (3p) +library function. It cannot execute shell scripts intelligently (via shebang). +It is inadviseable to use +.BR simexec (1) +to simply execute a program when other methods would suffice. +.\" +.SH DIAGNOSTICS + +.BR simexec (1) +exits with the returned value of +.BR execv (3p), +which will be 255 if an error occurs in execution, such as the binary not being +found. +This is indistinguishable from the executed binary exiting with the same +status. + +Simexec will print a error message and return the proper +.BR sysexits.h (3) +value if invoked in an invalid manner. +.\" +.SH AUTHOR + +Written by DTB +.MT trinity@trinity.moe +.ME . +.\" +.SH COPYRIGHT +.\" +Copyright \(co 2022–2024 DTB. License AGPLv3+: GNU AGPL version 3 or later +. +.\" +.SH SEE ALSO +.BR execv (3p) + +The C89 standard's draft, section 2.1.2.2: "Hosted environment". + +POSIX.1-2017 System Interfaces: execv. Particularly under the RATIONALE section header. diff --git a/src/simexec.c b/src/simexec.c new file mode 100644 index 0000000..6441bdb --- /dev/null +++ b/src/simexec.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022–2024 DTB + * SPDX-License-Identifier: AGPL-3.0-or-later + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +#include /* fprintf(3), NULL */ +#include /* execv(3), */ +#include /* EX_USAGE */ + +char *program_name = "simexec"; + +int main(int argc, char *argv[]){ + if (argc < 2) { + fprintf(stderr, "Usage: %s binary argv...\n", + argv[0] == NULL ? program_name : argv[0] + ); + return EX_USAGE; + } + + execv(argv[1], &argv[2]); +}