Skip to content

Commit 9aceaee

Browse files
nmeumnavi-desu
authored andcommitted
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=
1 parent ab07655 commit 9aceaee

7 files changed

Lines changed: 63 additions & 10 deletions

File tree

man/openrc-run.8

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,18 +158,23 @@ use this to change the user id, and optionally group id, before
158158
or
159159
.Xr supervise-daemon 8
160160
launches the daemon.
161-
.It Ar output_log
162-
This is the path to a file or named pipe where the standard output from
163-
the service will be redirected. If you are starting this service with
161+
.It Ar input_file
162+
This is the path to a file or named pipe to which the standard input of the
163+
service will be redirected to. If you are starting this service with
164164
.Xr start-stop-daemon 8 ,
165165
, you must set
166166
.Pa command_background
167167
to true. Keep in mind that this path will be inside the chroot if the
168168
.Pa chroot
169-
variable is set.
169+
variable is set. Contrary to output and error redirection, input redirection
170+
assumes that the file exists already.
171+
.It Ar output_log
172+
The same thing as
173+
.Pa input_file
174+
but for the standard output.
170175
.It Ar error_log
171176
The same thing as
172-
.Pa output_log
177+
.Pa input_file
173178
but for the standard error output.
174179
.It Ar output_logger
175180
This is a process which will be used to log the standard output from the

man/start-stop-daemon.8

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ on POSIX systems and, additionally, batch and idle on Linux. If
143143
is an integer, it is passed directly to pthread_setschedparam(3).
144144
.It Fl -scheduler-priority Ar priority
145145
Sets the priority parameter of the scheduling policy of the daemon. See sched(7) for details.
146+
.It Fl 0 , -stdin Ar file
147+
Redirect the standard input of the process to file when started with
148+
.Fl background .
149+
The file Must be an absolute pathname, but relative to the path
150+
optionally given with
151+
.Fl r , -chroot .
152+
The file can also be a named pipe. The file must exist, otherwise an error is emitted.
146153
.It Fl 1 , -stdout Ar logfile
147154
Redirect the standard output of the process to logfile when started with
148155
.Fl background .

man/supervise-daemon.8

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ servicename
5050
.Ar chrootpath
5151
.Fl u , -user
5252
.Ar user
53+
.Fl 0 , -stdin
54+
.Ar file
5355
.Fl 1 , -stdout
5456
.Ar logfile
5557
.Fl 2 , -stderr
@@ -154,11 +156,20 @@ process to communicate with is determined by the name of the service
154156
taken from the RC_SVCNAME environment variable.
155157
.It Fl u , -user Ar user
156158
Start the daemon as the specified user.
157-
.It Fl 1 , -stdout Ar logfile
158-
Redirect the standard output of the process to logfile.
159+
.It Fl 0 , -stdin Ar file
160+
Redirect the standard input of the process to file.
159161
Must be an absolute pathname, but relative to the path optionally given with
160162
.Fl r , -chroot .
161-
The logfile can also be a named pipe.
163+
The file can also be a named pipe. Input redirection assumes that the file
164+
exists already while output redirection via
165+
.Fl 1 , -stdout
166+
or
167+
.Fl 1 , -stderr
168+
creates it, if it doesn't.
169+
.It Fl 1 , -stdout Ar logfile
170+
The same thing as
171+
.Fl 0 , -stdin
172+
but with the standard output.
162173
.It Fl 2 , -stderr Ar logfile
163174
The same thing as
164175
.Fl 1 , -stdout

sh/start-stop-daemon.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ ssd_start()
4545
--exec $command \
4646
${chroot:+--chroot} $chroot \
4747
${directory:+--chdir} $directory \
48+
${input_file+--stdin} $input_file \
4849
${output_log+--stdout} $output_log \
4950
${error_log+--stderr} $error_log \
5051
${output_logger:+--stdout-logger \"$output_logger\"} \

sh/supervise-daemon.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ supervise_start()
2828
${retry:+--retry} $retry \
2929
${directory:+--chdir} $directory \
3030
${chroot:+--chroot} $chroot \
31+
${input_file+--stdin} $input_file \
3132
${output_log+--stdout} ${output_log} \
3233
${error_log+--stderr} $error_log \
3334
${output_logger:+--stdout-logger \"$output_logger\"} \

src/start-stop-daemon/start-stop-daemon.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ enum {
9494

9595
const char *applet = NULL;
9696
const char *extraopts = NULL;
97-
const char getoptstring[] = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \
97+
const char getoptstring[] = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:0:1:2:3:4:" \
9898
getoptstring_COMMON;
9999
const struct option longopts[] = {
100100
{ "capabilities", 1, NULL, LONGOPT_CAPABILITIES},
@@ -124,6 +124,7 @@ const struct option longopts[] = {
124124
{ "chroot", 1, NULL, 'r'},
125125
{ "wait", 1, NULL, 'w'},
126126
{ "exec", 1, NULL, 'x'},
127+
{ "stdin", 1, NULL, '0'},
127128
{ "stdout", 1, NULL, '1'},
128129
{ "stderr", 1, NULL, '2'},
129130
{ "stdout-logger",1, NULL, '3'},
@@ -162,6 +163,7 @@ const char * const longopts_help[] = {
162163
"Chroot to this directory",
163164
"Milliseconds to wait for daemon start",
164165
"Binary to start/stop",
166+
"Redirect stdin to file",
165167
"Redirect stdout to file",
166168
"Redirect stderr to file",
167169
"Redirect stdout to process",
@@ -318,6 +320,7 @@ int main(int argc, char **argv)
318320
gid_t gid = 0;
319321
char *home = NULL;
320322
int tid = 0;
323+
char *redirect_stdin = NULL;
321324
char *redirect_stderr = NULL;
322325
char *redirect_stdout = NULL;
323326
char *stderr_process = NULL;
@@ -601,6 +604,10 @@ int main(int argc, char **argv)
601604
exec = optarg;
602605
break;
603606

607+
case '0': /* --stdin /path/to/stdin.input-file */
608+
redirect_stdin = optarg;
609+
break;
610+
604611
case '1': /* --stdout /path/to/stdout.lgfile */
605612
redirect_stdout = optarg;
606613
break;
@@ -1071,6 +1078,13 @@ int main(int argc, char **argv)
10711078
stdin_fd = devnull_fd;
10721079
stdout_fd = devnull_fd;
10731080
stderr_fd = devnull_fd;
1081+
if (redirect_stdin) {
1082+
if ((stdin_fd = open(redirect_stdin,
1083+
O_RDONLY)) == -1)
1084+
eerrorx("%s: unable to open the input file"
1085+
" for stdin `%s': %s",
1086+
applet, redirect_stdin, strerror(errno));
1087+
}
10741088
if (redirect_stdout) {
10751089
if ((stdout_fd = open(redirect_stdout,
10761090
O_WRONLY | O_CREAT | O_APPEND,

src/supervise-daemon/supervise-daemon.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ enum {
8787

8888
const char *applet = NULL;
8989
const char *extraopts = NULL;
90-
const char getoptstring[] = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:s:Su:1:2:3" \
90+
const char getoptstring[] = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:s:Su:0:1:2:3" \
9191
getoptstring_COMMON;
9292
const struct option longopts[] = {
9393
{ "healthcheck-timer", 1, NULL, 'a'},
@@ -112,6 +112,7 @@ const struct option longopts[] = {
112112
{ "signal", 1, NULL, 's'},
113113
{ "start", 0, NULL, 'S'},
114114
{ "user", 1, NULL, 'u'},
115+
{ "stdin", 1, NULL, '0'},
115116
{ "stdout", 1, NULL, '1'},
116117
{ "stderr", 1, NULL, '2'},
117118
{ "stdout-logger",1, NULL, LONGOPT_STDOUT_LOGGER},
@@ -143,6 +144,7 @@ const char * const longopts_help[] = {
143144
"Send a signal to the daemon",
144145
"Start daemon",
145146
"Change the process user",
147+
"Redirect stdin to file",
146148
"Redirect stdout to file",
147149
"Redirect stderr to file",
148150
"Redirect stdout to process",
@@ -168,6 +170,7 @@ static int stdin_fd;
168170
static int stdout_fd;
169171
static int stderr_fd;
170172
static struct ready ready;
173+
static char *redirect_stdin = NULL;
171174
static char *redirect_stderr = NULL;
172175
static char *redirect_stdout = NULL;
173176
static char *stderr_process = NULL;
@@ -554,6 +557,13 @@ RC_NORETURN static void child_process(char *exec, char **argv)
554557
stdin_fd = devnull_fd;
555558
stdout_fd = devnull_fd;
556559
stderr_fd = devnull_fd;
560+
if (redirect_stdin) {
561+
if ((stdin_fd = open(redirect_stdin,
562+
O_RDONLY)) == -1)
563+
eerrorx("%s: unable to open the input file"
564+
" for stdin `%s': %s",
565+
applet, redirect_stdin, strerror(errno));
566+
}
557567
if (redirect_stdout) {
558568
if ((stdout_fd = open(redirect_stdout,
559569
O_WRONLY | O_CREAT | O_APPEND,
@@ -1057,6 +1067,10 @@ int main(int argc, char **argv)
10571067
}
10581068
break;
10591069

1070+
case '0': /* --stdin /path/to/stdin.input-file */
1071+
redirect_stdin = optarg;
1072+
break;
1073+
10601074
case '1': /* --stdout /path/to/stdout.lgfile */
10611075
redirect_stdout = optarg;
10621076
break;

0 commit comments

Comments
 (0)