mirror of
https://github.com/AuxXxilium/eudev.git
synced 2025-02-05 16:45:28 +07:00
core: make systemd.confirm_spawn=1 actually work
This adds a timeout if the TTY cannot be acquired and makes sure we always output the question to the console, never to the TTY of the respective service.
This commit is contained in:
parent
0c7f15b3a9
commit
af6da548aa
2
TODO
2
TODO
@ -25,6 +25,8 @@ Bugfixes:
|
|||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
|
* new dependency type to "group" services in a target
|
||||||
|
|
||||||
* add switch to journalctl to only show data from current boot
|
* add switch to journalctl to only show data from current boot
|
||||||
|
|
||||||
* change REquires=basic.target to RequisiteOverride=basic.target
|
* change REquires=basic.target to RequisiteOverride=basic.target
|
||||||
|
@ -293,7 +293,8 @@ static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty
|
|||||||
tty_path(context),
|
tty_path(context),
|
||||||
i == EXEC_INPUT_TTY_FAIL,
|
i == EXEC_INPUT_TTY_FAIL,
|
||||||
i == EXEC_INPUT_TTY_FORCE,
|
i == EXEC_INPUT_TTY_FORCE,
|
||||||
false)) < 0)
|
false,
|
||||||
|
(usec_t) -1)) < 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
if (fd != STDIN_FILENO) {
|
if (fd != STDIN_FILENO) {
|
||||||
@ -444,47 +445,45 @@ static int chown_terminal(int fd, uid_t uid) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setup_confirm_stdio(const ExecContext *context,
|
static int setup_confirm_stdio(int *_saved_stdin,
|
||||||
int *_saved_stdin,
|
|
||||||
int *_saved_stdout) {
|
int *_saved_stdout) {
|
||||||
int fd = -1, saved_stdin, saved_stdout = -1, r;
|
int fd = -1, saved_stdin, saved_stdout = -1, r;
|
||||||
|
|
||||||
assert(context);
|
|
||||||
assert(_saved_stdin);
|
assert(_saved_stdin);
|
||||||
assert(_saved_stdout);
|
assert(_saved_stdout);
|
||||||
|
|
||||||
/* This returns positive EXIT_xxx return values instead of
|
saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
|
||||||
* negative errno style values! */
|
if (saved_stdin < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
if ((saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3)) < 0)
|
saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
|
||||||
return EXIT_STDIN;
|
if (saved_stdout < 0) {
|
||||||
|
r = errno;
|
||||||
if ((saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3)) < 0) {
|
|
||||||
r = EXIT_STDOUT;
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fd = acquire_terminal(
|
fd = acquire_terminal(
|
||||||
tty_path(context),
|
"/dev/console",
|
||||||
context->std_input == EXEC_INPUT_TTY_FAIL,
|
false,
|
||||||
context->std_input == EXEC_INPUT_TTY_FORCE,
|
false,
|
||||||
false)) < 0) {
|
false,
|
||||||
r = EXIT_STDIN;
|
DEFAULT_CONFIRM_USEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
r = fd;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chown_terminal(fd, getuid()) < 0) {
|
r = chown_terminal(fd, getuid());
|
||||||
r = EXIT_STDIN;
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
|
|
||||||
if (dup2(fd, STDIN_FILENO) < 0) {
|
if (dup2(fd, STDIN_FILENO) < 0) {
|
||||||
r = EXIT_STDIN;
|
r = -errno;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dup2(fd, STDOUT_FILENO) < 0) {
|
if (dup2(fd, STDOUT_FILENO) < 0) {
|
||||||
r = EXIT_STDOUT;
|
r = -errno;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,50 +508,72 @@ fail:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int restore_confirm_stdio(const ExecContext *context,
|
static int write_confirm_message(const char *format, ...) {
|
||||||
int *saved_stdin,
|
int fd;
|
||||||
int *saved_stdout,
|
va_list ap;
|
||||||
bool *keep_stdin,
|
|
||||||
bool *keep_stdout) {
|
|
||||||
|
|
||||||
assert(context);
|
assert(format);
|
||||||
assert(saved_stdin);
|
|
||||||
assert(*saved_stdin >= 0);
|
|
||||||
assert(saved_stdout);
|
|
||||||
assert(*saved_stdout >= 0);
|
|
||||||
|
|
||||||
/* This returns positive EXIT_xxx return values instead of
|
fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
|
||||||
* negative errno style values! */
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
|
||||||
if (is_terminal_input(context->std_input)) {
|
va_start(ap, format);
|
||||||
|
vdprintf(fd, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
/* The service wants terminal input. */
|
close_nointr_nofail(fd);
|
||||||
|
|
||||||
*keep_stdin = true;
|
|
||||||
*keep_stdout =
|
|
||||||
context->std_output == EXEC_OUTPUT_INHERIT ||
|
|
||||||
context->std_output == EXEC_OUTPUT_TTY;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* If the service doesn't want a controlling terminal,
|
|
||||||
* then we need to get rid entirely of what we have
|
|
||||||
* already. */
|
|
||||||
|
|
||||||
if (release_terminal() < 0)
|
|
||||||
return EXIT_STDIN;
|
|
||||||
|
|
||||||
if (dup2(*saved_stdin, STDIN_FILENO) < 0)
|
|
||||||
return EXIT_STDIN;
|
|
||||||
|
|
||||||
if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
|
|
||||||
return EXIT_STDOUT;
|
|
||||||
|
|
||||||
*keep_stdout = *keep_stdin = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int restore_confirm_stdio(int *saved_stdin,
|
||||||
|
int *saved_stdout) {
|
||||||
|
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
assert(saved_stdin);
|
||||||
|
assert(saved_stdout);
|
||||||
|
|
||||||
|
release_terminal();
|
||||||
|
|
||||||
|
if (*saved_stdin >= 0)
|
||||||
|
if (dup2(*saved_stdin, STDIN_FILENO) < 0)
|
||||||
|
r = -errno;
|
||||||
|
|
||||||
|
if (*saved_stdout >= 0)
|
||||||
|
if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
|
||||||
|
r = -errno;
|
||||||
|
|
||||||
|
if (*saved_stdin >= 0)
|
||||||
|
close_nointr_nofail(*saved_stdin);
|
||||||
|
|
||||||
|
if (*saved_stdout >= 0)
|
||||||
|
close_nointr_nofail(*saved_stdout);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ask_for_confirmation(char *response, char **argv) {
|
||||||
|
int saved_stdout = -1, saved_stdin = -1, r;
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
r = setup_confirm_stdio(&saved_stdin, &saved_stdout);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
line = exec_command_line(argv);
|
||||||
|
if (!line)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = ask(response, "yns", "Execute %s? [Yes, No, Skip] ", line);
|
||||||
|
free(line);
|
||||||
|
|
||||||
|
restore_confirm_stdio(&saved_stdin, &saved_stdout);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
|
static int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
|
||||||
bool keep_groups = false;
|
bool keep_groups = false;
|
||||||
int r;
|
int r;
|
||||||
@ -952,7 +973,8 @@ int exec_spawn(ExecCommand *command,
|
|||||||
if (!argv)
|
if (!argv)
|
||||||
argv = command->argv;
|
argv = command->argv;
|
||||||
|
|
||||||
if (!(line = exec_command_line(argv))) {
|
line = exec_command_line(argv);
|
||||||
|
if (!line) {
|
||||||
r = -ENOMEM;
|
r = -ENOMEM;
|
||||||
goto fail_parent;
|
goto fail_parent;
|
||||||
}
|
}
|
||||||
@ -979,8 +1001,7 @@ int exec_spawn(ExecCommand *command,
|
|||||||
gid_t gid = (gid_t) -1;
|
gid_t gid = (gid_t) -1;
|
||||||
char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
|
char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
|
||||||
unsigned n_env = 0;
|
unsigned n_env = 0;
|
||||||
int saved_stdout = -1, saved_stdin = -1;
|
bool set_access = false;
|
||||||
bool keep_stdout = false, keep_stdin = false, set_access = false;
|
|
||||||
|
|
||||||
/* child */
|
/* child */
|
||||||
|
|
||||||
@ -1050,44 +1071,24 @@ int exec_spawn(ExecCommand *command,
|
|||||||
|
|
||||||
exec_context_tty_reset(context);
|
exec_context_tty_reset(context);
|
||||||
|
|
||||||
/* We skip the confirmation step if we shall not apply the TTY */
|
if (confirm_spawn) {
|
||||||
if (confirm_spawn &&
|
|
||||||
(!is_terminal_input(context->std_input) || apply_tty_stdin)) {
|
|
||||||
char response;
|
char response;
|
||||||
|
|
||||||
/* Set up terminal for the question */
|
err = ask_for_confirmation(&response, argv);
|
||||||
if ((r = setup_confirm_stdio(context,
|
if (err == -ETIMEDOUT)
|
||||||
&saved_stdin, &saved_stdout))) {
|
write_confirm_message("Confirmation question timed out, assuming positive response.\n");
|
||||||
err = -errno;
|
else if (err < 0)
|
||||||
goto fail_child;
|
write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-err));
|
||||||
}
|
else if (response == 's') {
|
||||||
|
write_confirm_message("Skipping execution.\n");
|
||||||
/* Now ask the question. */
|
|
||||||
if (!(line = exec_command_line(argv))) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
r = EXIT_MEMORY;
|
|
||||||
goto fail_child;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = ask(&response, "yns", "Execute %s? [Yes, No, Skip] ", line);
|
|
||||||
free(line);
|
|
||||||
|
|
||||||
if (r < 0 || response == 'n') {
|
|
||||||
err = -ECANCELED;
|
err = -ECANCELED;
|
||||||
r = EXIT_CONFIRM;
|
r = EXIT_CONFIRM;
|
||||||
goto fail_child;
|
goto fail_child;
|
||||||
} else if (response == 's') {
|
} else if (response == 'n') {
|
||||||
|
write_confirm_message("Failing execution.\n");
|
||||||
err = r = 0;
|
err = r = 0;
|
||||||
goto fail_child;
|
goto fail_child;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release terminal for the question */
|
|
||||||
if ((r = restore_confirm_stdio(context,
|
|
||||||
&saved_stdin, &saved_stdout,
|
|
||||||
&keep_stdin, &keep_stdout))) {
|
|
||||||
err = -errno;
|
|
||||||
goto fail_child;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a socket is connected to STDIN/STDOUT/STDERR, we
|
/* If a socket is connected to STDIN/STDOUT/STDERR, we
|
||||||
@ -1095,21 +1096,17 @@ int exec_spawn(ExecCommand *command,
|
|||||||
if (socket_fd >= 0)
|
if (socket_fd >= 0)
|
||||||
fd_nonblock(socket_fd, false);
|
fd_nonblock(socket_fd, false);
|
||||||
|
|
||||||
if (!keep_stdin) {
|
|
||||||
err = setup_input(context, socket_fd, apply_tty_stdin);
|
err = setup_input(context, socket_fd, apply_tty_stdin);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
r = EXIT_STDIN;
|
r = EXIT_STDIN;
|
||||||
goto fail_child;
|
goto fail_child;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!keep_stdout) {
|
|
||||||
err = setup_output(context, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
|
err = setup_output(context, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
r = EXIT_STDOUT;
|
r = EXIT_STDOUT;
|
||||||
goto fail_child;
|
goto fail_child;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
err = setup_error(context, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
|
err = setup_error(context, socket_fd, path_get_file_name(command->path), unit_id, apply_tty_stdin);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
@ -1439,12 +1436,6 @@ int exec_spawn(ExecCommand *command,
|
|||||||
strv_free(files_env);
|
strv_free(files_env);
|
||||||
strv_free(final_argv);
|
strv_free(final_argv);
|
||||||
|
|
||||||
if (saved_stdin >= 0)
|
|
||||||
close_nointr_nofail(saved_stdin);
|
|
||||||
|
|
||||||
if (saved_stdout >= 0)
|
|
||||||
close_nointr_nofail(saved_stdout);
|
|
||||||
|
|
||||||
_exit(r);
|
_exit(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ _noreturn_ static void crash(int sig) {
|
|||||||
else if (pid == 0) {
|
else if (pid == 0) {
|
||||||
int fd, r;
|
int fd, r;
|
||||||
|
|
||||||
if ((fd = acquire_terminal("/dev/console", false, true, true)) < 0)
|
if ((fd = acquire_terminal("/dev/console", false, true, true, (usec_t) -1)) < 0)
|
||||||
log_error("Failed to acquire terminal: %s", strerror(-fd));
|
log_error("Failed to acquire terminal: %s", strerror(-fd));
|
||||||
else if ((r = make_stdio(fd)) < 0)
|
else if ((r = make_stdio(fd)) < 0)
|
||||||
log_error("Failed to duplicate terminal fd: %s", strerror(-r));
|
log_error("Failed to duplicate terminal fd: %s", strerror(-r));
|
||||||
|
@ -2005,6 +2005,9 @@ void manager_check_finished(Manager *m) {
|
|||||||
/* Notify Type=idle units that we are done now */
|
/* Notify Type=idle units that we are done now */
|
||||||
close_pipe(m->idle_pipe);
|
close_pipe(m->idle_pipe);
|
||||||
|
|
||||||
|
/* Turn off confirm spawn now */
|
||||||
|
m->confirm_spawn = false;
|
||||||
|
|
||||||
if (dual_timestamp_is_set(&m->finish_timestamp))
|
if (dual_timestamp_is_set(&m->finish_timestamp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC)
|
#define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC)
|
||||||
#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC)
|
#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC)
|
||||||
|
#define DEFAULT_CONFIRM_USEC (30*USEC_PER_SEC)
|
||||||
|
|
||||||
#define DEFAULT_EXIT_USEC (5*USEC_PER_MINUTE)
|
#define DEFAULT_EXIT_USEC (5*USEC_PER_MINUTE)
|
||||||
|
|
||||||
|
@ -2305,12 +2305,14 @@ int open_terminal(const char *name, int mode) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((fd = open(name, mode)) >= 0)
|
fd = open(name, mode);
|
||||||
|
if (fd >= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (errno != EIO)
|
if (errno != EIO)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
/* Max 1s in total */
|
||||||
if (c >= 20)
|
if (c >= 20)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
@ -2321,7 +2323,8 @@ int open_terminal(const char *name, int mode) {
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if ((r = isatty(fd)) < 0) {
|
r = isatty(fd);
|
||||||
|
if (r < 0) {
|
||||||
close_nointr_nofail(fd);
|
close_nointr_nofail(fd);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
@ -2373,8 +2376,15 @@ int flush_fd(int fd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm) {
|
int acquire_terminal(
|
||||||
|
const char *name,
|
||||||
|
bool fail,
|
||||||
|
bool force,
|
||||||
|
bool ignore_tiocstty_eperm,
|
||||||
|
usec_t timeout) {
|
||||||
|
|
||||||
int fd = -1, notify = -1, r, wd = -1;
|
int fd = -1, notify = -1, r, wd = -1;
|
||||||
|
usec_t ts = 0;
|
||||||
|
|
||||||
assert(name);
|
assert(name);
|
||||||
|
|
||||||
@ -2391,27 +2401,35 @@ int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocst
|
|||||||
* on the same tty as an untrusted user this should not be a
|
* on the same tty as an untrusted user this should not be a
|
||||||
* problem. (Which he probably should not do anyway.) */
|
* problem. (Which he probably should not do anyway.) */
|
||||||
|
|
||||||
|
if (timeout != (usec_t) -1)
|
||||||
|
ts = now(CLOCK_MONOTONIC);
|
||||||
|
|
||||||
if (!fail && !force) {
|
if (!fail && !force) {
|
||||||
if ((notify = inotify_init1(IN_CLOEXEC)) < 0) {
|
notify = inotify_init1(IN_CLOEXEC | (timeout != (usec_t) -1 ? IN_NONBLOCK : 0));
|
||||||
|
if (notify < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((wd = inotify_add_watch(notify, name, IN_CLOSE)) < 0) {
|
wd = inotify_add_watch(notify, name, IN_CLOSE);
|
||||||
|
if (wd < 0) {
|
||||||
r = -errno;
|
r = -errno;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (notify >= 0)
|
if (notify >= 0) {
|
||||||
if ((r = flush_fd(notify)) < 0)
|
r = flush_fd(notify);
|
||||||
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* We pass here O_NOCTTY only so that we can check the return
|
/* We pass here O_NOCTTY only so that we can check the return
|
||||||
* value TIOCSCTTY and have a reliable way to figure out if we
|
* value TIOCSCTTY and have a reliable way to figure out if we
|
||||||
* successfully became the controlling process of the tty */
|
* successfully became the controlling process of the tty */
|
||||||
if ((fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
|
fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
/* First, try to get the tty */
|
/* First, try to get the tty */
|
||||||
@ -2440,9 +2458,29 @@ int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocst
|
|||||||
ssize_t l;
|
ssize_t l;
|
||||||
struct inotify_event *e;
|
struct inotify_event *e;
|
||||||
|
|
||||||
if ((l = read(notify, inotify_buffer, sizeof(inotify_buffer))) < 0) {
|
if (timeout != (usec_t) -1) {
|
||||||
|
usec_t n;
|
||||||
|
|
||||||
if (errno == EINTR)
|
n = now(CLOCK_MONOTONIC);
|
||||||
|
if (ts + timeout < n) {
|
||||||
|
r = -ETIMEDOUT;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fd_wait_for_event(fd, POLLIN, ts + timeout - n);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
r = -ETIMEDOUT;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l = read(notify, inotify_buffer, sizeof(inotify_buffer));
|
||||||
|
if (l < 0) {
|
||||||
|
|
||||||
|
if (errno == EINTR || errno == EAGAIN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = -errno;
|
r = -errno;
|
||||||
|
@ -321,7 +321,7 @@ int reset_terminal_fd(int fd, bool switch_to_text);
|
|||||||
int reset_terminal(const char *name);
|
int reset_terminal(const char *name);
|
||||||
|
|
||||||
int open_terminal(const char *name, int mode);
|
int open_terminal(const char *name, int mode);
|
||||||
int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm);
|
int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocstty_eperm, usec_t timeout);
|
||||||
int release_terminal(void);
|
int release_terminal(void);
|
||||||
|
|
||||||
int flush_fd(int fd);
|
int flush_fd(int fd);
|
||||||
|
@ -368,7 +368,7 @@ static int parse_password(const char *filename, char **wall) {
|
|||||||
char *password;
|
char *password;
|
||||||
|
|
||||||
if (arg_console)
|
if (arg_console)
|
||||||
if ((tty_fd = acquire_terminal("/dev/console", false, false, false)) < 0) {
|
if ((tty_fd = acquire_terminal("/dev/console", false, false, false, (usec_t) -1)) < 0) {
|
||||||
r = tty_fd;
|
r = tty_fd;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user