main/openrc: backport support for input redirection

This commit is contained in:
Sören Tempel 2025-03-28 19:27:00 +01:00 committed by Natanael Copa
parent af5e38371d
commit 3e33dfd01d
2 changed files with 266 additions and 1 deletions

View File

@ -0,0 +1,263 @@
From 9aceaee18f8849655ee5cbd5c4326b8aa702b301 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B6ren=20Tempel?= <soeren+git@soeren-tempel.net>
Date: Tue, 18 Mar 2025 07:43:48 +0100
Subject: [PATCH] openrc-run: Support standard input redirection too
OpenRC already supports redirecting standard output/error of services.
This patch adds support for redirecting standard input as well. I
encountered the lack of this feature while working on a user service for
a Wayland compositor status bar which reads status text to be displayed
from stdin. Input redirection allows me to connect this user services to
another user service providing the status text via a named pipe.
Note that input redirection is also supported by SystemD (and
potentially other service supervisors) through the `StandardInput=`
directive [1].
[1]: https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#StandardInput=
---
man/openrc-run.8 | 15 ++++++++++-----
man/start-stop-daemon.8 | 7 +++++++
man/supervise-daemon.8 | 17 ++++++++++++++---
sh/start-stop-daemon.sh | 1 +
sh/supervise-daemon.sh | 1 +
src/start-stop-daemon/start-stop-daemon.c | 16 +++++++++++++++-
src/supervise-daemon/supervise-daemon.c | 16 +++++++++++++++-
7 files changed, 63 insertions(+), 10 deletions(-)
diff --git a/man/openrc-run.8 b/man/openrc-run.8
index c7476728..e0255943 100644
--- a/man/openrc-run.8
+++ b/man/openrc-run.8
@@ -158,18 +158,23 @@ use this to change the user id, and optionally group id, before
or
.Xr supervise-daemon 8
launches the daemon.
-.It Ar output_log
-This is the path to a file or named pipe where the standard output from
-the service will be redirected. If you are starting this service with
+.It Ar input_file
+This is the path to a file or named pipe to which the standard input of the
+service will be redirected to. If you are starting this service with
.Xr start-stop-daemon 8 ,
, you must set
.Pa command_background
to true. Keep in mind that this path will be inside the chroot if the
.Pa chroot
-variable is set.
+variable is set. Contrary to output and error redirection, input redirection
+assumes that the file exists already.
+.It Ar output_log
+The same thing as
+.Pa input_file
+but for the standard output.
.It Ar error_log
The same thing as
-.Pa output_log
+.Pa input_file
but for the standard error output.
.It Ar output_logger
This is a process which will be used to log the standard output from the
diff --git a/man/start-stop-daemon.8 b/man/start-stop-daemon.8
index b6d62ff0..32103a37 100644
--- a/man/start-stop-daemon.8
+++ b/man/start-stop-daemon.8
@@ -143,6 +143,13 @@ on POSIX systems and, additionally, batch and idle on Linux. If
is an integer, it is passed directly to pthread_setschedparam(3).
.It Fl -scheduler-priority Ar priority
Sets the priority parameter of the scheduling policy of the daemon. See sched(7) for details.
+.It Fl 0 , -stdin Ar file
+Redirect the standard input of the process to file when started with
+.Fl background .
+The file Must be an absolute pathname, but relative to the path
+optionally given with
+.Fl r , -chroot .
+The file can also be a named pipe. The file must exist, otherwise an error is emitted.
.It Fl 1 , -stdout Ar logfile
Redirect the standard output of the process to logfile when started with
.Fl background .
diff --git a/man/supervise-daemon.8 b/man/supervise-daemon.8
index 5fa226e9..7abb034b 100644
--- a/man/supervise-daemon.8
+++ b/man/supervise-daemon.8
@@ -50,6 +50,8 @@ servicename
.Ar chrootpath
.Fl u , -user
.Ar user
+.Fl 0 , -stdin
+.Ar file
.Fl 1 , -stdout
.Ar logfile
.Fl 2 , -stderr
@@ -154,11 +156,20 @@ process to communicate with is determined by the name of the service
taken from the RC_SVCNAME environment variable.
.It Fl u , -user Ar user
Start the daemon as the specified user.
-.It Fl 1 , -stdout Ar logfile
-Redirect the standard output of the process to logfile.
+.It Fl 0 , -stdin Ar file
+Redirect the standard input of the process to file.
Must be an absolute pathname, but relative to the path optionally given with
.Fl r , -chroot .
-The logfile can also be a named pipe.
+The file can also be a named pipe. Input redirection assumes that the file
+exists already while output redirection via
+.Fl 1 , -stdout
+or
+.Fl 1 , -stderr
+creates it, if it doesn't.
+.It Fl 1 , -stdout Ar logfile
+The same thing as
+.Fl 0 , -stdin
+but with the standard output.
.It Fl 2 , -stderr Ar logfile
The same thing as
.Fl 1 , -stdout
diff --git a/sh/start-stop-daemon.sh b/sh/start-stop-daemon.sh
index 1f9dfa5a..ba90bb47 100644
--- a/sh/start-stop-daemon.sh
+++ b/sh/start-stop-daemon.sh
@@ -45,6 +45,7 @@ ssd_start()
--exec $command \
${chroot:+--chroot} $chroot \
${directory:+--chdir} $directory \
+ ${input_file+--stdin} $input_file \
${output_log+--stdout} $output_log \
${error_log+--stderr} $error_log \
${output_logger:+--stdout-logger \"$output_logger\"} \
diff --git a/sh/supervise-daemon.sh b/sh/supervise-daemon.sh
index 8cdde18b..7a6b4674 100644
--- a/sh/supervise-daemon.sh
+++ b/sh/supervise-daemon.sh
@@ -28,6 +28,7 @@ supervise_start()
${retry:+--retry} $retry \
${directory:+--chdir} $directory \
${chroot:+--chroot} $chroot \
+ ${input_file+--stdin} $input_file \
${output_log+--stdout} ${output_log} \
${error_log+--stderr} $error_log \
${output_logger:+--stdout-logger \"$output_logger\"} \
diff --git a/src/start-stop-daemon/start-stop-daemon.c b/src/start-stop-daemon/start-stop-daemon.c
index a04e0119..d9a9a0f5 100644
--- a/src/start-stop-daemon/start-stop-daemon.c
+++ b/src/start-stop-daemon/start-stop-daemon.c
@@ -94,7 +94,7 @@ enum {
const char *applet = NULL;
const char *extraopts = NULL;
-const char getoptstring[] = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \
+const char getoptstring[] = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:0:1:2:3:4:" \
getoptstring_COMMON;
const struct option longopts[] = {
{ "capabilities", 1, NULL, LONGOPT_CAPABILITIES},
@@ -124,6 +124,7 @@ const struct option longopts[] = {
{ "chroot", 1, NULL, 'r'},
{ "wait", 1, NULL, 'w'},
{ "exec", 1, NULL, 'x'},
+ { "stdin", 1, NULL, '0'},
{ "stdout", 1, NULL, '1'},
{ "stderr", 1, NULL, '2'},
{ "stdout-logger",1, NULL, '3'},
@@ -162,6 +163,7 @@ const char * const longopts_help[] = {
"Chroot to this directory",
"Milliseconds to wait for daemon start",
"Binary to start/stop",
+ "Redirect stdin to file",
"Redirect stdout to file",
"Redirect stderr to file",
"Redirect stdout to process",
@@ -318,6 +320,7 @@ int main(int argc, char **argv)
gid_t gid = 0;
char *home = NULL;
int tid = 0;
+ char *redirect_stdin = NULL;
char *redirect_stderr = NULL;
char *redirect_stdout = NULL;
char *stderr_process = NULL;
@@ -601,6 +604,10 @@ int main(int argc, char **argv)
exec = optarg;
break;
+ case '0': /* --stdin /path/to/stdin.input-file */
+ redirect_stdin = optarg;
+ break;
+
case '1': /* --stdout /path/to/stdout.lgfile */
redirect_stdout = optarg;
break;
@@ -1071,6 +1078,13 @@ int main(int argc, char **argv)
stdin_fd = devnull_fd;
stdout_fd = devnull_fd;
stderr_fd = devnull_fd;
+ if (redirect_stdin) {
+ if ((stdin_fd = open(redirect_stdin,
+ O_RDONLY)) == -1)
+ eerrorx("%s: unable to open the input file"
+ " for stdin `%s': %s",
+ applet, redirect_stdin, strerror(errno));
+ }
if (redirect_stdout) {
if ((stdout_fd = open(redirect_stdout,
O_WRONLY | O_CREAT | O_APPEND,
diff --git a/src/supervise-daemon/supervise-daemon.c b/src/supervise-daemon/supervise-daemon.c
index 179a7f79..445a4cda 100644
--- a/src/supervise-daemon/supervise-daemon.c
+++ b/src/supervise-daemon/supervise-daemon.c
@@ -87,7 +87,7 @@ enum {
const char *applet = NULL;
const char *extraopts = NULL;
-const char getoptstring[] = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:s:Su:1:2:3" \
+const char getoptstring[] = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:s:Su:0:1:2:3" \
getoptstring_COMMON;
const struct option longopts[] = {
{ "healthcheck-timer", 1, NULL, 'a'},
@@ -112,6 +112,7 @@ const struct option longopts[] = {
{ "signal", 1, NULL, 's'},
{ "start", 0, NULL, 'S'},
{ "user", 1, NULL, 'u'},
+ { "stdin", 1, NULL, '0'},
{ "stdout", 1, NULL, '1'},
{ "stderr", 1, NULL, '2'},
{ "stdout-logger",1, NULL, LONGOPT_STDOUT_LOGGER},
@@ -143,6 +144,7 @@ const char * const longopts_help[] = {
"Send a signal to the daemon",
"Start daemon",
"Change the process user",
+ "Redirect stdin to file",
"Redirect stdout to file",
"Redirect stderr to file",
"Redirect stdout to process",
@@ -168,6 +170,7 @@ static int stdin_fd;
static int stdout_fd;
static int stderr_fd;
static struct ready ready;
+static char *redirect_stdin = NULL;
static char *redirect_stderr = NULL;
static char *redirect_stdout = NULL;
static char *stderr_process = NULL;
@@ -554,6 +557,13 @@ RC_NORETURN static void child_process(char *exec, char **argv)
stdin_fd = devnull_fd;
stdout_fd = devnull_fd;
stderr_fd = devnull_fd;
+ if (redirect_stdin) {
+ if ((stdin_fd = open(redirect_stdin,
+ O_RDONLY)) == -1)
+ eerrorx("%s: unable to open the input file"
+ " for stdin `%s': %s",
+ applet, redirect_stdin, strerror(errno));
+ }
if (redirect_stdout) {
if ((stdout_fd = open(redirect_stdout,
O_WRONLY | O_CREAT | O_APPEND,
@@ -1057,6 +1067,10 @@ int main(int argc, char **argv)
}
break;
+ case '0': /* --stdin /path/to/stdin.input-file */
+ redirect_stdin = optarg;
+ break;
+
case '1': /* --stdout /path/to/stdout.lgfile */
redirect_stdout = optarg;
break;

View File

@ -2,7 +2,7 @@
pkgname=openrc
pkgver=0.60.1
_ver=${pkgver/_git*/}
pkgrel=2
pkgrel=3
pkgdesc="OpenRC manages the services, startup and shutdown of a host"
url="https://github.com/OpenRC/openrc"
arch="all"
@ -35,6 +35,7 @@ source="$pkgname-$pkgver.tar.gz::https://github.com/OpenRC/openrc/archive/$pkgve
0008-bootmisc-switch-wipe_tmp-setting-to-no-by-default.patch
0009-Based-on-the-vrf-patch-it-adds-support-to-run-servic.patch
0010-openrc-run-Fix-loading-of-user-configs-for-system-su.patch
0011-openrc-run-Support-standard-input-redirection-too.patch
supervise-daemon-defaults.patch
sysctl-readme.patch
@ -239,6 +240,7 @@ aa44e62392c47c5f20a66072574ae452be0c1b0c4914bb58fa35b6ecc3e2a75c7a2d6245198e30a8
475f4ea63b9b5d7eb9c623e96b6cc3d3072abcb7194d0045b84e0688836c8514fccfc68b0eae0b4bee60878cdea8042c3ce7e48406ee7a2f0e4a3e128a153468 0008-bootmisc-switch-wipe_tmp-setting-to-no-by-default.patch
d7b8b1facd7fb9a6a8350912644cce3956947bcaa8bcb645f9c26a2bb0d062970efaa14bd66a7987f0748daff7b5a8e701b45b3fcca7c7c7e393ac262728f1a6 0009-Based-on-the-vrf-patch-it-adds-support-to-run-servic.patch
1fa65d7b692a5647cc2db61506f2801a874e7bebec8b4380929431e13a0b32bd76ec892ef818b0de6765a7297e75e64eccfea0a210166ee4d5b97e419a636555 0010-openrc-run-Fix-loading-of-user-configs-for-system-su.patch
30183429c98be9ee3f0cc3ce2d3e8a17592ec4a9500ac9c020630242146fe6af1ea9f865859b91fce58bf78eddf749cb295f7c75d783317ce882d1ec8d14016c 0011-openrc-run-Support-standard-input-redirection-too.patch
86a2fb1564b8537f5dd7e06587a572ebefd110bf8bea049bc2254d4008ed3fed2296b4e9fde793ddbed7a66f70335b6c228f0b10fc0a6e7d106d3ad226fc0ba4 supervise-daemon-defaults.patch
903ff555275a67ff08da91badb55d9fa6c6a2901e8ef09ca8366bd74d69757491c8336347f04551268ecf053c8ae974f50decd869926894dd94e382008e3e925 sysctl-readme.patch
12bb6354e808fbf47bbab963de55ee7901738b4a912659982c57ef2777fff9a670e867fcb8ec316a76b151032c92dc89a950d7d1d835ef53f753a8f3b41d2cec openrc.logrotate