#include <sys/cdefs.h>
__RCSID("$NetBSD: t_execve.c,v 1.4 2025/03/13 12:48:22 riastradh Exp $");
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include "h_macros.h"
ATF_TC(t_execve_null);
ATF_TC_HEAD(t_execve_null, tc)
{
atf_tc_set_md_var(tc, "descr",
"Tests an empty execve(2) executing");
}
ATF_TC_BODY(t_execve_null, tc)
{
int err;
err = execve(NULL, NULL, NULL);
ATF_REQUIRE(err == -1);
ATF_REQUIRE_MSG(errno == EFAULT,
"wrong error returned %d instead of %d", errno, EFAULT);
}
ATF_TC(t_execve_sig);
ATF_TC_HEAD(t_execve_sig, tc)
{
atf_tc_set_md_var(tc, "descr",
"Checks that execve does not drop pending signals");
}
ATF_TC_BODY(t_execve_sig, tc)
{
const char *srcdir = atf_tc_get_config_var(tc, "srcdir");
char h_execsig[PATH_MAX];
time_t start;
snprintf(h_execsig, sizeof(h_execsig), "%s/../h_execsig", srcdir);
REQUIRE_LIBC(signal(SIGPIPE, SIG_IGN), SIG_ERR);
for (start = time(NULL); time(NULL) - start <= 10;) {
int fd[2];
char *const argv[] = {h_execsig, NULL};
pid_t pid;
int status;
RL(pipe(fd));
RL(pid = vfork());
if (pid == 0) {
if (dup2(fd[0], STDIN_FILENO) == -1)
_exit(1);
(void)execve(argv[0], argv, NULL);
_exit(2);
}
RL(close(fd[0]));
RL(kill(pid, SIGTERM));
if (write(fd[1], (char[]){0}, 1) == -1 && errno != EPIPE)
atf_tc_fail("write failed: %s", strerror(errno));
RL(waitpid(pid, &status, 0));
ATF_REQUIRE_MSG(WIFSIGNALED(status),
"child exited with status 0x%x", status);
ATF_REQUIRE_EQ_MSG(WTERMSIG(status), SIGTERM,
"child exited on signal %d (%s)",
WTERMSIG(status), strsignal(WTERMSIG(status)));
RL(close(fd[1]));
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, t_execve_null);
ATF_TP_ADD_TC(tp, t_execve_sig);
return atf_no_error();
}