diff: prefer posix_spawn over pdfork/execl

MFC After:		1 week
Reviewed by:		kib
Differential Revision:	https://reviews.freebsd.org/D56076
This commit is contained in:
Baptiste Daroussin
2026-03-25 11:22:02 +01:00
parent 5f7f0efe8e
commit 6d8b2ac449
+39 -23
View File
@@ -29,8 +29,10 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <signal.h>
#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -41,6 +43,8 @@
#define _PATH_PR "/usr/bin/pr"
extern char **environ;
struct pr *
start_pr(char *file1, char *file2)
{
@@ -48,6 +52,9 @@ start_pr(char *file1, char *file2)
pid_t pid;
char *header;
struct pr *pr;
posix_spawn_file_actions_t fa;
posix_spawnattr_t sa;
int error;
pr = xcalloc(1, sizeof(*pr));
@@ -56,32 +63,41 @@ start_pr(char *file1, char *file2)
fflush(stdout);
if (pipe(pfd) == -1)
err(2, "pipe");
switch ((pid = pdfork(&pr->procd, PD_CLOEXEC))) {
case -1:
err(2, "No more processes");
case 0:
/* child */
if (pfd[0] != STDIN_FILENO) {
dup2(pfd[0], STDIN_FILENO);
close(pfd[0]);
if ((error = posix_spawnattr_init(&sa)) != 0)
errc(2, error, "posix_spawnattr_init");
if ((error = posix_spawn_file_actions_init(&fa)) != 0)
errc(2, error, "posix_spawn_file_actions_init");
posix_spawnattr_setprocdescp_np(&sa, &pr->procd, 0);
if (pfd[0] != STDIN_FILENO) {
posix_spawn_file_actions_adddup2(&fa, pfd[0], STDIN_FILENO);
posix_spawn_file_actions_addclose(&fa, pfd[0]);
}
posix_spawn_file_actions_addclose(&fa, pfd[1]);
char *argv[] = { __DECONST(char *, _PATH_PR),
__DECONST(char *, "-h"), header, NULL };
error = posix_spawn(&pid, _PATH_PR, &fa, &sa, argv, environ);
if (error != 0)
errc(2, error, "could not spawn pr");
posix_spawn_file_actions_destroy(&fa);
posix_spawnattr_destroy(&sa);
/* parent */
if (pfd[1] == STDOUT_FILENO) {
pr->ostdout = STDOUT_FILENO;
} else {
if ((pr->ostdout = dup(STDOUT_FILENO)) < 0 ||
dup2(pfd[1], STDOUT_FILENO) < 0) {
err(2, "stdout");
}
close(pfd[1]);
execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0);
_exit(127);
default:
/* parent */
if (pfd[1] == STDOUT_FILENO) {
pr->ostdout = STDOUT_FILENO;
} else {
if ((pr->ostdout = dup(STDOUT_FILENO)) < 0 ||
dup2(pfd[1], STDOUT_FILENO) < 0) {
err(2, "stdout");
}
close(pfd[1]);
}
close(pfd[0]);
free(header);
}
close(pfd[0]);
free(header);
return (pr);
}