Handle stdout and stderr separately

This commit is contained in:
Radon Rosborough 2021-08-15 14:46:34 -07:00
parent 02ff4aaaef
commit 570060ae9c
2 changed files with 31 additions and 16 deletions

View File

@ -32,13 +32,14 @@ while read -t2 -r cmdline; do
fi fi
uuid="${cmd[1]}" uuid="${cmd[1]}"
args=("${cmd[@]:2}") args=("${cmd[@]:2}")
input="/var/cache/riju/share/cmd-${uuid}-input" stdin="/var/cache/riju/share/cmd-${uuid}-stdin"
output="/var/cache/riju/share/cmd-${uuid}-output" stdout="/var/cache/riju/share/cmd-${uuid}-stdout"
stderr="/var/cache/riju/share/cmd-${uuid}-stderr"
status="/var/cache/riju/share/cmd-${uuid}-status" status="/var/cache/riju/share/cmd-${uuid}-status"
mkfifo "${input}" "${output}" "${status}" mkfifo "${stdin}" "${stdout}" "${stderr}" "${status}"
( (
set +e set +e
runuser -u riju -- bash -c "exec ${maybe_pty:-} \"\$@\"" -- "${args[@]}" < "${input}" &> "${output}" runuser -u riju -- bash -c "exec ${maybe_pty:-} \"\$@\"" -- "${args[@]}" < "${stdin}" > "${stdout}" 2> "${stderr}"
echo "$?" > "${status}" echo "$?" > "${status}"
) & ) &
fi fi

View File

@ -286,16 +286,18 @@ void exec(char *uuid, int argc, char **cmdline, bool pty)
{ {
if (setvbuf(stdout, NULL, _IONBF, 0) != 0) if (setvbuf(stdout, NULL, _IONBF, 0) != 0)
die("setvbuf failed"); die("setvbuf failed");
char *share, *ctlFIFO, *inputFIFO, *outputFIFO, *statusFIFO, *ctlCmd, char *share, *ctlFIFO, *stdinFIFO, *stdoutFIFO, *stderrFIFO, *statusFIFO,
*dataFIFO; *ctlCmd, *dataFIFO;
if (asprintf(&share, "/var/cache/riju/shares/%s", uuid) < 0) if (asprintf(&share, "/var/cache/riju/shares/%s", uuid) < 0)
die("asprintf failed"); die("asprintf failed");
if (asprintf(&ctlFIFO, "%s/control", share) < 0) if (asprintf(&ctlFIFO, "%s/control", share) < 0)
die("asprintf failed"); die("asprintf failed");
char *procUUID = getUUID(); char *procUUID = getUUID();
if (asprintf(&inputFIFO, "%s/cmd-%s-input", share, procUUID) < 0) if (asprintf(&stdinFIFO, "%s/cmd-%s-stdin", share, procUUID) < 0)
die("asprintf failed"); die("asprintf failed");
if (asprintf(&outputFIFO, "%s/cmd-%s-output", share, procUUID) < 0) if (asprintf(&stdoutFIFO, "%s/cmd-%s-stdout", share, procUUID) < 0)
die("asprintf failed");
if (asprintf(&stderrFIFO, "%s/cmd-%s-stderr", share, procUUID) < 0)
die("asprintf failed"); die("asprintf failed");
if (asprintf(&statusFIFO, "%s/cmd-%s-status", share, procUUID) < 0) if (asprintf(&statusFIFO, "%s/cmd-%s-status", share, procUUID) < 0)
die("asprintf failed"); die("asprintf failed");
@ -328,7 +330,7 @@ void exec(char *uuid, int argc, char **cmdline, bool pty)
die("prctl failed"); die("prctl failed");
if (getppid() != orig_ppid) if (getppid() != orig_ppid)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
dataFIFO = inputFIFO; dataFIFO = stdinFIFO;
} else { } else {
pid = fork(); pid = fork();
if (pid < 0) if (pid < 0)
@ -338,9 +340,20 @@ void exec(char *uuid, int argc, char **cmdline, bool pty)
die("prctl failed"); die("prctl failed");
if (getppid() != orig_ppid) if (getppid() != orig_ppid)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
dataFIFO = outputFIFO; dataFIFO = stdoutFIFO;
} else { } else {
dataFIFO = statusFIFO; pid = fork();
if (pid < 0)
die("fork failed");
else if (pid == 0) {
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
die("prctl failed");
if (getppid() != orig_ppid)
exit(EXIT_FAILURE);
dataFIFO = stderrFIFO;
} else {
dataFIFO = statusFIFO;
}
} }
} }
if (dataFIFO != statusFIFO) { if (dataFIFO != statusFIFO) {
@ -349,7 +362,7 @@ void exec(char *uuid, int argc, char **cmdline, bool pty)
alarm(1); alarm(1);
} }
while (1) { while (1) {
int mode = dataFIFO == inputFIFO ? O_WRONLY : O_RDONLY; int mode = dataFIFO == stdinFIFO ? O_WRONLY : O_RDONLY;
fd = open(dataFIFO, mode); fd = open(dataFIFO, mode);
if (fd >= 0) if (fd >= 0)
break; break;
@ -362,7 +375,7 @@ void exec(char *uuid, int argc, char **cmdline, bool pty)
if (signal(SIGALRM, SIG_IGN) == SIG_ERR) if (signal(SIGALRM, SIG_IGN) == SIG_ERR)
die("signal failed"); die("signal failed");
char buf[1024]; char buf[1024];
if (dataFIFO == inputFIFO) { if (dataFIFO == stdinFIFO) {
if (close(STDOUT_FILENO) < 0) if (close(STDOUT_FILENO) < 0)
die("close failed"); die("close failed");
while ((len = read(STDIN_FILENO, buf, 1024)) > 0) { while ((len = read(STDIN_FILENO, buf, 1024)) > 0) {
@ -377,12 +390,13 @@ void exec(char *uuid, int argc, char **cmdline, bool pty)
} }
if (len < 0) if (len < 0)
die("read failed"); die("read failed");
} else if (dataFIFO == outputFIFO) { } else if (dataFIFO == stdoutFIFO || dataFIFO == stderrFIFO) {
FILE *output = dataFIFO == stdoutFIFO ? stdout : stderr;
if (close(STDIN_FILENO) < 0) if (close(STDIN_FILENO) < 0)
die("close failed"); die("close failed");
while ((len = read(fd, buf, 1024)) > 0) { while ((len = read(fd, buf, 1024)) > 0) {
fwrite(buf, 1, len, stdout); fwrite(buf, 1, len, output);
if (ferror(stdout)) if (ferror(output))
die("fwrite failed"); die("fwrite failed");
if (feof(stdout)) if (feof(stdout))
break; break;