mirror of
https://github.com/systemd/systemd.git
synced 2025-03-25 18:50:18 +03:00
Merge pull request #1496 from poettering/stdin-fd
allow passing in fds for stdin/stdout/stderr for transient services
This commit is contained in:
commit
ad86c1335a
@ -342,3 +342,7 @@
|
||||
- To determine the length of a constant string "foo", don't bother
|
||||
with sizeof("foo")-1, please use strlen("foo") directly. gcc knows
|
||||
strlen() anyway and turns it into a constant expression if possible.
|
||||
|
||||
- If you want to concatenate two or more strings, consider using
|
||||
strjoin() rather than asprintf(), as the latter is a lot
|
||||
slower. This matters particularly in inner loops.
|
||||
|
@ -26,7 +26,7 @@ __contains_word() {
|
||||
|
||||
__get_machines() {
|
||||
local a b
|
||||
(machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager) | \
|
||||
(machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; echo ".host") | \
|
||||
{ while read a b; do echo " $a"; done; } | sort -u;
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ _machinectl() {
|
||||
|
||||
local -A VERBS=(
|
||||
[STANDALONE]='list list-images pull-tar pull-raw pull-dkr import-tar import-raw export-tar export-raw list-transfers cancel-transfer'
|
||||
[MACHINES]='status show start login enable disable poweroff reboot terminate kill copy-to copy-from image-status show-image clone rename read-only remove set-limit'
|
||||
[MACHINES]='status show start login shell enable disable poweroff reboot terminate kill copy-to copy-from image-status show-image clone rename read-only remove set-limit'
|
||||
)
|
||||
|
||||
_init_completion || return
|
||||
|
@ -480,10 +480,6 @@ int acquire_terminal(
|
||||
|
||||
safe_close(notify);
|
||||
|
||||
r = reset_terminal_fd(fd, true);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to reset terminal: %m");
|
||||
|
||||
return fd;
|
||||
|
||||
fail:
|
||||
@ -539,8 +535,9 @@ int terminal_vhangup(const char *name) {
|
||||
}
|
||||
|
||||
int vt_disallocate(const char *name) {
|
||||
int fd, r;
|
||||
_cleanup_close_ int fd = -1;
|
||||
unsigned u;
|
||||
int r;
|
||||
|
||||
/* Deallocate the VT if possible. If not possible
|
||||
* (i.e. because it is the active one), at least clear it
|
||||
@ -562,8 +559,6 @@ int vt_disallocate(const char *name) {
|
||||
"\033[H" /* move home */
|
||||
"\033[2J", /* clear screen */
|
||||
10, false);
|
||||
safe_close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -583,7 +578,7 @@ int vt_disallocate(const char *name) {
|
||||
return fd;
|
||||
|
||||
r = ioctl(fd, VT_DISALLOCATE, u);
|
||||
safe_close(fd);
|
||||
fd = safe_close(fd);
|
||||
|
||||
if (r >= 0)
|
||||
return 0;
|
||||
@ -602,8 +597,6 @@ int vt_disallocate(const char *name) {
|
||||
"\033[H" /* move home */
|
||||
"\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */
|
||||
10, false);
|
||||
safe_close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -616,6 +609,10 @@ int make_console_stdio(void) {
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to acquire terminal: %m");
|
||||
|
||||
r = reset_terminal_fd(fd, true);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
|
||||
|
||||
r = make_stdio(fd);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to duplicate terminal fd: %m");
|
||||
@ -1054,6 +1051,33 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ptsname_malloc(int fd, char **ret) {
|
||||
size_t l = 100;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
for (;;) {
|
||||
char *c;
|
||||
|
||||
c = new(char, l);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
if (ptsname_r(fd, c, l) == 0) {
|
||||
*ret = c;
|
||||
return 0;
|
||||
}
|
||||
if (errno != ERANGE) {
|
||||
free(c);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
free(c);
|
||||
l *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
int ptsname_namespace(int pty, char **ret) {
|
||||
int no = -1, r;
|
||||
|
||||
@ -1072,3 +1096,104 @@ int ptsname_namespace(int pty, char **ret) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openpt_in_namespace(pid_t pid, int flags) {
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
siginfo_t si;
|
||||
pid_t child;
|
||||
int r;
|
||||
|
||||
assert(pid > 0);
|
||||
|
||||
r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
return -errno;
|
||||
|
||||
if (child == 0) {
|
||||
int master;
|
||||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
|
||||
if (master < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (unlockpt(master) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (send_one_fd(pair[1], master, 0) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate(child, &si);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
|
||||
return -EIO;
|
||||
|
||||
return receive_one_fd(pair[0], 0);
|
||||
}
|
||||
|
||||
int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
siginfo_t si;
|
||||
pid_t child;
|
||||
int r;
|
||||
|
||||
r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
return -errno;
|
||||
|
||||
if (child == 0) {
|
||||
int master;
|
||||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC);
|
||||
if (master < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (send_one_fd(pair[1], master, 0) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate(child, &si);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
|
||||
return -EIO;
|
||||
|
||||
return receive_one_fd(pair[0], 0);
|
||||
}
|
||||
|
@ -120,4 +120,8 @@ int get_ctty(pid_t, dev_t *_devnr, char **r);
|
||||
int getttyname_malloc(int fd, char **r);
|
||||
int getttyname_harder(int fd, char **r);
|
||||
|
||||
int ptsname_malloc(int fd, char **ret);
|
||||
int ptsname_namespace(int pty, char **ret);
|
||||
|
||||
int openpt_in_namespace(pid_t pid, int flags);
|
||||
int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
|
||||
|
@ -6087,86 +6087,6 @@ int free_and_strdup(char **p, const char *s) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ptsname_malloc(int fd, char **ret) {
|
||||
size_t l = 100;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
for (;;) {
|
||||
char *c;
|
||||
|
||||
c = new(char, l);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
if (ptsname_r(fd, c, l) == 0) {
|
||||
*ret = c;
|
||||
return 0;
|
||||
}
|
||||
if (errno != ERANGE) {
|
||||
free(c);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
free(c);
|
||||
l *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
int openpt_in_namespace(pid_t pid, int flags) {
|
||||
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
siginfo_t si;
|
||||
pid_t child;
|
||||
int r;
|
||||
|
||||
assert(pid > 0);
|
||||
|
||||
r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
return -errno;
|
||||
|
||||
if (child == 0) {
|
||||
int master;
|
||||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
|
||||
if (master < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (unlockpt(master) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (send_one_fd(pair[1], master, 0) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate(child, &si);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
|
||||
return -EIO;
|
||||
|
||||
return receive_one_fd(pair[0], 0);
|
||||
}
|
||||
|
||||
ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
|
||||
char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
@ -891,10 +891,6 @@ union inotify_event_buffer {
|
||||
|
||||
#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW)
|
||||
|
||||
int ptsname_malloc(int fd, char **ret);
|
||||
|
||||
int openpt_in_namespace(pid_t pid, int flags);
|
||||
|
||||
ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags);
|
||||
|
||||
int fd_setcrtime(int fd, usec_t usec);
|
||||
|
@ -774,8 +774,9 @@ static int automount_stop(Unit *u) {
|
||||
|
||||
static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
Automount *a = AUTOMOUNT(u);
|
||||
void *p;
|
||||
Iterator i;
|
||||
void *p;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(f);
|
||||
@ -790,15 +791,9 @@ static int automount_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
SET_FOREACH(p, a->expire_tokens, i)
|
||||
unit_serialize_item_format(u, f, "expire-token", "%u", PTR_TO_UINT(p));
|
||||
|
||||
if (a->pipe_fd >= 0) {
|
||||
int copy;
|
||||
|
||||
copy = fdset_put_dup(fds, a->pipe_fd);
|
||||
if (copy < 0)
|
||||
return copy;
|
||||
|
||||
unit_serialize_item_format(u, f, "pipe-fd", "%i", copy);
|
||||
}
|
||||
r = unit_serialize_item_fd(u, f, fds, "pipe-fd", a->pipe_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -656,6 +656,7 @@ static int busname_stop(Unit *u) {
|
||||
|
||||
static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
BusName *n = BUSNAME(u);
|
||||
int r;
|
||||
|
||||
assert(n);
|
||||
assert(f);
|
||||
@ -667,15 +668,9 @@ static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
if (n->control_pid > 0)
|
||||
unit_serialize_item_format(u, f, "control-pid", PID_FMT, n->control_pid);
|
||||
|
||||
if (n->starter_fd >= 0) {
|
||||
int copy;
|
||||
|
||||
copy = fdset_put_dup(fds, n->starter_fd);
|
||||
if (copy < 0)
|
||||
return copy;
|
||||
|
||||
unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
|
||||
}
|
||||
r = unit_serialize_item_fd(u, f, fds, "starter-fd", n->starter_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "async.h"
|
||||
#include "strv.h"
|
||||
#include "path-util.h"
|
||||
#include "unit.h"
|
||||
@ -120,6 +121,37 @@ static int bus_service_set_transient_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name,
|
||||
"StandardInputFileDescriptor",
|
||||
"StandardOutputFileDescriptor",
|
||||
"StandardErrorFileDescriptor")) {
|
||||
int fd;
|
||||
|
||||
r = sd_bus_message_read(message, "h", &fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
int copy;
|
||||
|
||||
copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
||||
if (copy < 0)
|
||||
return -errno;
|
||||
|
||||
if (streq(name, "StandardInputFileDescriptor")) {
|
||||
asynchronous_close(s->stdin_fd);
|
||||
s->stdin_fd = copy;
|
||||
} else if (streq(name, "StandardOutputFileDescriptor")) {
|
||||
asynchronous_close(s->stdout_fd);
|
||||
s->stdout_fd = copy;
|
||||
} else {
|
||||
asynchronous_close(s->stderr_fd);
|
||||
s->stderr_fd = copy;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "ExecStart")) {
|
||||
unsigned n = 0;
|
||||
|
||||
|
@ -359,12 +359,28 @@ static int fixup_output(ExecOutput std_output, int socket_fd) {
|
||||
return std_output;
|
||||
}
|
||||
|
||||
static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
|
||||
static int setup_input(
|
||||
const ExecContext *context,
|
||||
const ExecParameters *params,
|
||||
int socket_fd) {
|
||||
|
||||
ExecInput i;
|
||||
|
||||
assert(context);
|
||||
assert(params);
|
||||
|
||||
i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
|
||||
if (params->stdin_fd >= 0) {
|
||||
if (dup2(params->stdin_fd, STDIN_FILENO) < 0)
|
||||
return -errno;
|
||||
|
||||
/* Try to make this the controlling tty, if it is a tty, and reset it */
|
||||
(void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE);
|
||||
(void) reset_terminal_fd(STDIN_FILENO, true);
|
||||
|
||||
return STDIN_FILENO;
|
||||
}
|
||||
|
||||
i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin);
|
||||
|
||||
switch (i) {
|
||||
|
||||
@ -401,16 +417,40 @@ static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty
|
||||
}
|
||||
}
|
||||
|
||||
static int setup_output(Unit *unit, const ExecContext *context, int fileno, int socket_fd, const char *ident, bool apply_tty_stdin, uid_t uid, gid_t gid) {
|
||||
static int setup_output(
|
||||
Unit *unit,
|
||||
const ExecContext *context,
|
||||
const ExecParameters *params,
|
||||
int fileno,
|
||||
int socket_fd,
|
||||
const char *ident,
|
||||
uid_t uid, gid_t gid) {
|
||||
|
||||
ExecOutput o;
|
||||
ExecInput i;
|
||||
int r;
|
||||
|
||||
assert(unit);
|
||||
assert(context);
|
||||
assert(params);
|
||||
assert(ident);
|
||||
|
||||
i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
|
||||
if (fileno == STDOUT_FILENO && params->stdout_fd >= 0) {
|
||||
|
||||
if (dup2(params->stdout_fd, STDOUT_FILENO) < 0)
|
||||
return -errno;
|
||||
|
||||
return STDOUT_FILENO;
|
||||
}
|
||||
|
||||
if (fileno == STDERR_FILENO && params->stderr_fd >= 0) {
|
||||
if (dup2(params->stderr_fd, STDERR_FILENO) < 0)
|
||||
return -errno;
|
||||
|
||||
return STDERR_FILENO;
|
||||
}
|
||||
|
||||
i = fixup_input(context->std_input, socket_fd, params->apply_tty_stdin);
|
||||
o = fixup_output(context->std_output, socket_fd);
|
||||
|
||||
if (fileno == STDERR_FILENO) {
|
||||
@ -503,9 +543,9 @@ static int chown_terminal(int fd, uid_t uid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_confirm_stdio(int *_saved_stdin,
|
||||
int *_saved_stdout) {
|
||||
int fd = -1, saved_stdin, saved_stdout = -1, r;
|
||||
static int setup_confirm_stdio(int *_saved_stdin, int *_saved_stdout) {
|
||||
_cleanup_close_ int fd = -1, saved_stdin = -1, saved_stdout = -1;
|
||||
int r;
|
||||
|
||||
assert(_saved_stdin);
|
||||
assert(_saved_stdout);
|
||||
@ -515,10 +555,8 @@ static int setup_confirm_stdio(int *_saved_stdin,
|
||||
return -errno;
|
||||
|
||||
saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
|
||||
if (saved_stdout < 0) {
|
||||
r = errno;
|
||||
goto fail;
|
||||
}
|
||||
if (saved_stdout < 0)
|
||||
return -errno;
|
||||
|
||||
fd = acquire_terminal(
|
||||
"/dev/console",
|
||||
@ -526,39 +564,33 @@ static int setup_confirm_stdio(int *_saved_stdin,
|
||||
false,
|
||||
false,
|
||||
DEFAULT_CONFIRM_USEC);
|
||||
if (fd < 0) {
|
||||
r = fd;
|
||||
goto fail;
|
||||
}
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
r = chown_terminal(fd, getuid());
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
return r;
|
||||
|
||||
if (dup2(fd, STDIN_FILENO) < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
r = reset_terminal_fd(fd, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (dup2(fd, STDOUT_FILENO) < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
if (dup2(fd, STDIN_FILENO) < 0)
|
||||
return -errno;
|
||||
|
||||
if (dup2(fd, STDOUT_FILENO) < 0)
|
||||
return -errno;
|
||||
|
||||
if (fd >= 2)
|
||||
safe_close(fd);
|
||||
fd = -1;
|
||||
|
||||
*_saved_stdin = saved_stdin;
|
||||
*_saved_stdout = saved_stdout;
|
||||
|
||||
saved_stdin = saved_stdout = -1;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
safe_close(saved_stdout);
|
||||
safe_close(saved_stdin);
|
||||
safe_close(fd);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
_printf_(1, 2) static int write_confirm_message(const char *format, ...) {
|
||||
@ -578,9 +610,7 @@ _printf_(1, 2) static int write_confirm_message(const char *format, ...) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int restore_confirm_stdio(int *saved_stdin,
|
||||
int *saved_stdout) {
|
||||
|
||||
static int restore_confirm_stdio(int *saved_stdin, int *saved_stdout) {
|
||||
int r = 0;
|
||||
|
||||
assert(saved_stdin);
|
||||
@ -596,8 +626,8 @@ static int restore_confirm_stdio(int *saved_stdin,
|
||||
if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
|
||||
r = -errno;
|
||||
|
||||
safe_close(*saved_stdin);
|
||||
safe_close(*saved_stdout);
|
||||
*saved_stdin = safe_close(*saved_stdin);
|
||||
*saved_stdout = safe_close(*saved_stdout);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -1324,6 +1354,44 @@ static bool exec_needs_mount_namespace(
|
||||
return false;
|
||||
}
|
||||
|
||||
static int close_remaining_fds(
|
||||
const ExecParameters *params,
|
||||
ExecRuntime *runtime,
|
||||
int socket_fd,
|
||||
int *fds, unsigned n_fds) {
|
||||
|
||||
unsigned n_dont_close = 0;
|
||||
int dont_close[n_fds + 7];
|
||||
|
||||
assert(params);
|
||||
|
||||
if (params->stdin_fd >= 0)
|
||||
dont_close[n_dont_close++] = params->stdin_fd;
|
||||
if (params->stdout_fd >= 0)
|
||||
dont_close[n_dont_close++] = params->stdout_fd;
|
||||
if (params->stderr_fd >= 0)
|
||||
dont_close[n_dont_close++] = params->stderr_fd;
|
||||
|
||||
if (socket_fd >= 0)
|
||||
dont_close[n_dont_close++] = socket_fd;
|
||||
if (n_fds > 0) {
|
||||
memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
|
||||
n_dont_close += n_fds;
|
||||
}
|
||||
|
||||
if (params->bus_endpoint_fd >= 0)
|
||||
dont_close[n_dont_close++] = params->bus_endpoint_fd;
|
||||
|
||||
if (runtime) {
|
||||
if (runtime->netns_storage_socket[0] >= 0)
|
||||
dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
|
||||
if (runtime->netns_storage_socket[1] >= 0)
|
||||
dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
|
||||
}
|
||||
|
||||
return close_all_fds(dont_close, n_dont_close);
|
||||
}
|
||||
|
||||
static int exec_child(
|
||||
Unit *unit,
|
||||
ExecCommand *command,
|
||||
@ -1339,8 +1407,6 @@ static int exec_child(
|
||||
_cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
|
||||
_cleanup_free_ char *mac_selinux_context_net = NULL;
|
||||
const char *username = NULL, *home = NULL, *shell = NULL, *wd;
|
||||
unsigned n_dont_close = 0;
|
||||
int dont_close[n_fds + 4];
|
||||
uid_t uid = UID_INVALID;
|
||||
gid_t gid = GID_INVALID;
|
||||
int i, r;
|
||||
@ -1380,22 +1446,7 @@ static int exec_child(
|
||||
|
||||
log_forget_fds();
|
||||
|
||||
if (socket_fd >= 0)
|
||||
dont_close[n_dont_close++] = socket_fd;
|
||||
if (n_fds > 0) {
|
||||
memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
|
||||
n_dont_close += n_fds;
|
||||
}
|
||||
if (params->bus_endpoint_fd >= 0)
|
||||
dont_close[n_dont_close++] = params->bus_endpoint_fd;
|
||||
if (runtime) {
|
||||
if (runtime->netns_storage_socket[0] >= 0)
|
||||
dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
|
||||
if (runtime->netns_storage_socket[1] >= 0)
|
||||
dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
|
||||
}
|
||||
|
||||
r = close_all_fds(dont_close, n_dont_close);
|
||||
r = close_remaining_fds(params, runtime, socket_fd, fds, n_fds);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_FDS;
|
||||
return r;
|
||||
@ -1451,21 +1502,21 @@ static int exec_child(
|
||||
/* If a socket is connected to STDIN/STDOUT/STDERR, we
|
||||
* must sure to drop O_NONBLOCK */
|
||||
if (socket_fd >= 0)
|
||||
fd_nonblock(socket_fd, false);
|
||||
(void) fd_nonblock(socket_fd, false);
|
||||
|
||||
r = setup_input(context, socket_fd, params->apply_tty_stdin);
|
||||
r = setup_input(context, params, socket_fd);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_STDIN;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = setup_output(unit, context, STDOUT_FILENO, socket_fd, basename(command->path), params->apply_tty_stdin, uid, gid);
|
||||
r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, basename(command->path), uid, gid);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_STDOUT;
|
||||
return r;
|
||||
}
|
||||
|
||||
r = setup_output(unit, context, STDERR_FILENO, socket_fd, basename(command->path), params->apply_tty_stdin, uid, gid);
|
||||
r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, basename(command->path), uid, gid);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_STDERR;
|
||||
return r;
|
||||
|
@ -208,23 +208,22 @@ struct ExecContext {
|
||||
|
||||
struct ExecParameters {
|
||||
char **argv;
|
||||
char **environment;
|
||||
|
||||
int *fds;
|
||||
char **fd_names;
|
||||
unsigned n_fds;
|
||||
|
||||
char **environment;
|
||||
bool apply_permissions:1;
|
||||
bool apply_chroot:1;
|
||||
bool apply_tty_stdin:1;
|
||||
|
||||
bool apply_permissions;
|
||||
bool apply_chroot;
|
||||
bool apply_tty_stdin;
|
||||
|
||||
bool confirm_spawn;
|
||||
bool selinux_context_net;
|
||||
bool confirm_spawn:1;
|
||||
bool selinux_context_net:1;
|
||||
|
||||
bool cgroup_delegate:1;
|
||||
CGroupMask cgroup_supported;
|
||||
const char *cgroup_path;
|
||||
bool cgroup_delegate;
|
||||
|
||||
const char *runtime_prefix;
|
||||
|
||||
@ -234,6 +233,10 @@ struct ExecParameters {
|
||||
|
||||
char *bus_endpoint_path;
|
||||
int bus_endpoint_fd;
|
||||
|
||||
int stdin_fd;
|
||||
int stdout_fd;
|
||||
int stderr_fd;
|
||||
};
|
||||
|
||||
int exec_spawn(Unit *unit,
|
||||
|
@ -694,6 +694,9 @@ static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) {
|
||||
.apply_chroot = true,
|
||||
.apply_tty_stdin = true,
|
||||
.bus_endpoint_fd = -1,
|
||||
.stdin_fd = -1,
|
||||
.stdout_fd = -1,
|
||||
.stderr_fd = -1,
|
||||
};
|
||||
|
||||
assert(m);
|
||||
|
@ -108,6 +108,7 @@ static void service_init(Unit *u) {
|
||||
s->type = _SERVICE_TYPE_INVALID;
|
||||
s->socket_fd = -1;
|
||||
s->bus_endpoint_fd = -1;
|
||||
s->stdin_fd = s->stdout_fd = s->stderr_fd = -1;
|
||||
s->guess_main_pid = true;
|
||||
|
||||
RATELIMIT_INIT(s->start_limit, u->manager->default_start_limit_interval, u->manager->default_start_limit_burst);
|
||||
@ -271,11 +272,15 @@ static void service_release_resources(Unit *u) {
|
||||
|
||||
assert(s);
|
||||
|
||||
if (!s->fd_store)
|
||||
if (!s->fd_store && s->stdin_fd < 0 && s->stdout_fd < 0 && s->stderr_fd < 0)
|
||||
return;
|
||||
|
||||
log_unit_debug(u, "Releasing all resources.");
|
||||
|
||||
s->stdin_fd = safe_close(s->stdin_fd);
|
||||
s->stdout_fd = safe_close(s->stdout_fd);
|
||||
s->stderr_fd = safe_close(s->stderr_fd);
|
||||
|
||||
while (s->fd_store)
|
||||
service_fd_store_unlink(s->fd_store);
|
||||
|
||||
@ -1090,11 +1095,13 @@ static int service_spawn(
|
||||
pid_t pid;
|
||||
|
||||
ExecParameters exec_params = {
|
||||
.apply_permissions = apply_permissions,
|
||||
.apply_chroot = apply_chroot,
|
||||
.apply_tty_stdin = apply_tty_stdin,
|
||||
.bus_endpoint_fd = -1,
|
||||
.selinux_context_net = s->socket_fd_selinux_context_net
|
||||
.apply_permissions = apply_permissions,
|
||||
.apply_chroot = apply_chroot,
|
||||
.apply_tty_stdin = apply_tty_stdin,
|
||||
.bus_endpoint_fd = -1,
|
||||
.stdin_fd = -1,
|
||||
.stdout_fd = -1,
|
||||
.stderr_fd = -1,
|
||||
};
|
||||
|
||||
int r;
|
||||
@ -1236,8 +1243,12 @@ static int service_spawn(
|
||||
exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
|
||||
exec_params.watchdog_usec = s->watchdog_usec;
|
||||
exec_params.bus_endpoint_path = bus_endpoint_path;
|
||||
exec_params.selinux_context_net = s->socket_fd_selinux_context_net;
|
||||
if (s->type == SERVICE_IDLE)
|
||||
exec_params.idle_pipe = UNIT(s)->manager->idle_pipe;
|
||||
exec_params.stdin_fd = s->stdin_fd;
|
||||
exec_params.stdout_fd = s->stdout_fd;
|
||||
exec_params.stderr_fd = s->stderr_fd;
|
||||
|
||||
r = exec_spawn(UNIT(s),
|
||||
c,
|
||||
@ -2038,6 +2049,7 @@ _pure_ static bool service_can_reload(Unit *u) {
|
||||
static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
Service *s = SERVICE(u);
|
||||
ServiceFDStore *fs;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
assert(f);
|
||||
@ -2056,12 +2068,9 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
|
||||
unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good));
|
||||
|
||||
if (s->status_text) {
|
||||
_cleanup_free_ char *c = NULL;
|
||||
|
||||
c = cescape(s->status_text);
|
||||
unit_serialize_item(u, f, "status-text", strempty(c));
|
||||
}
|
||||
r = unit_serialize_item_escaped(u, f, "status-text", s->status_text);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* FIXME: There's a minor uncleanliness here: if there are
|
||||
* multiple commands attached here, we will start from the
|
||||
@ -2069,25 +2078,22 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
if (s->control_command_id >= 0)
|
||||
unit_serialize_item(u, f, "control-command", service_exec_command_to_string(s->control_command_id));
|
||||
|
||||
if (s->socket_fd >= 0) {
|
||||
int copy;
|
||||
r = unit_serialize_item_fd(u, f, fds, "stdin-fd", s->stdin_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = unit_serialize_item_fd(u, f, fds, "stdout-fd", s->stdout_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = unit_serialize_item_fd(u, f, fds, "stderr-fd", s->stderr_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
copy = fdset_put_dup(fds, s->socket_fd);
|
||||
if (copy < 0)
|
||||
return copy;
|
||||
|
||||
unit_serialize_item_format(u, f, "socket-fd", "%i", copy);
|
||||
}
|
||||
|
||||
if (s->bus_endpoint_fd >= 0) {
|
||||
int copy;
|
||||
|
||||
copy = fdset_put_dup(fds, s->bus_endpoint_fd);
|
||||
if (copy < 0)
|
||||
return copy;
|
||||
|
||||
unit_serialize_item_format(u, f, "endpoint-fd", "%i", copy);
|
||||
}
|
||||
r = unit_serialize_item_fd(u, f, fds, "socket-fd", s->socket_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = unit_serialize_item_fd(u, f, fds, "endpoint-fd", s->bus_endpoint_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(fd_store, fs, s->fd_store) {
|
||||
_cleanup_free_ char *c = NULL;
|
||||
@ -2116,8 +2122,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
if (dual_timestamp_is_set(&s->watchdog_timestamp))
|
||||
dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp);
|
||||
|
||||
if (s->forbid_restart)
|
||||
unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart));
|
||||
unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2288,6 +2293,33 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
|
||||
log_unit_debug(u, "Failed to parse forbid-restart value: %s", value);
|
||||
else
|
||||
s->forbid_restart = b;
|
||||
} else if (streq(key, "stdin-fd")) {
|
||||
int fd;
|
||||
|
||||
if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
|
||||
log_unit_debug(u, "Failed to parse stdin-fd value: %s", value);
|
||||
else {
|
||||
asynchronous_close(s->stdin_fd);
|
||||
s->stdin_fd = fdset_remove(fds, fd);
|
||||
}
|
||||
} else if (streq(key, "stdout-fd")) {
|
||||
int fd;
|
||||
|
||||
if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
|
||||
log_unit_debug(u, "Failed to parse stdout-fd value: %s", value);
|
||||
else {
|
||||
asynchronous_close(s->stdout_fd);
|
||||
s->stdout_fd = fdset_remove(fds, fd);
|
||||
}
|
||||
} else if (streq(key, "stderr-fd")) {
|
||||
int fd;
|
||||
|
||||
if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
|
||||
log_unit_debug(u, "Failed to parse stderr-fd value: %s", value);
|
||||
else {
|
||||
asynchronous_close(s->stderr_fd);
|
||||
s->stderr_fd = fdset_remove(fds, fd);
|
||||
}
|
||||
} else
|
||||
log_unit_debug(u, "Unknown serialization key: %s", key);
|
||||
|
||||
|
@ -195,6 +195,10 @@ struct Service {
|
||||
|
||||
char *usb_function_descriptors;
|
||||
char *usb_function_strings;
|
||||
|
||||
int stdin_fd;
|
||||
int stdout_fd;
|
||||
int stderr_fd;
|
||||
};
|
||||
|
||||
extern const UnitVTable service_vtable;
|
||||
|
@ -1505,6 +1505,9 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
|
||||
.apply_chroot = true,
|
||||
.apply_tty_stdin = true,
|
||||
.bus_endpoint_fd = -1,
|
||||
.stdin_fd = -1,
|
||||
.stdout_fd = -1,
|
||||
.stderr_fd = -1,
|
||||
};
|
||||
|
||||
assert(s);
|
||||
|
@ -597,6 +597,9 @@ static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) {
|
||||
.apply_chroot = true,
|
||||
.apply_tty_stdin = true,
|
||||
.bus_endpoint_fd = -1,
|
||||
.stdin_fd = -1,
|
||||
.stdout_fd = -1,
|
||||
.stderr_fd = -1,
|
||||
};
|
||||
|
||||
assert(s);
|
||||
|
@ -2624,6 +2624,62 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
|
||||
assert(u);
|
||||
assert(f);
|
||||
assert(key);
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
fputs(key, f);
|
||||
fputc('=', f);
|
||||
fputs(value, f);
|
||||
fputc('\n', f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value) {
|
||||
_cleanup_free_ char *c = NULL;
|
||||
|
||||
assert(u);
|
||||
assert(f);
|
||||
assert(key);
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
c = cescape(value);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
fputs(key, f);
|
||||
fputc('=', f);
|
||||
fputs(c, f);
|
||||
fputc('\n', f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd) {
|
||||
int copy;
|
||||
|
||||
assert(u);
|
||||
assert(f);
|
||||
assert(key);
|
||||
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
copy = fdset_put_dup(fds, fd);
|
||||
if (copy < 0)
|
||||
return copy;
|
||||
|
||||
fprintf(f, "%s=%i\n", key, copy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *format, ...) {
|
||||
va_list ap;
|
||||
|
||||
@ -2642,15 +2698,6 @@ void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *f
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) {
|
||||
assert(u);
|
||||
assert(f);
|
||||
assert(key);
|
||||
assert(value);
|
||||
|
||||
fprintf(f, "%s=%s\n", key, value);
|
||||
}
|
||||
|
||||
int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
ExecRuntime **rt = NULL;
|
||||
size_t offset;
|
||||
|
@ -533,11 +533,15 @@ char *unit_dbus_path(Unit *u);
|
||||
int unit_load_related_unit(Unit *u, const char *type, Unit **_found);
|
||||
|
||||
bool unit_can_serialize(Unit *u) _pure_;
|
||||
|
||||
int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
|
||||
void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_(4,5);
|
||||
void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
|
||||
int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
|
||||
|
||||
int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
|
||||
int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value);
|
||||
int unit_serialize_item_fd(Unit *u, FILE *f, FDSet *fds, const char *key, int fd);
|
||||
void unit_serialize_item_format(Unit *u, FILE *f, const char *key, const char *value, ...) _printf_(4,5);
|
||||
|
||||
int unit_add_node_link(Unit *u, const char *what, bool wants);
|
||||
|
||||
int unit_coldplug(Unit *u);
|
||||
|
@ -639,7 +639,7 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
_cleanup_free_ char *pty_name = NULL;
|
||||
_cleanup_bus_flush_close_unref_ sd_bus *allocated_bus = NULL;
|
||||
sd_bus *container_bus = NULL;
|
||||
_cleanup_close_ int master = -1;
|
||||
_cleanup_close_ int master = -1, slave = -1;
|
||||
_cleanup_strv_free_ char **env = NULL, **args = NULL;
|
||||
Machine *m = userdata;
|
||||
const char *p, *unit, *user, *path, *description, *utmp_id;
|
||||
@ -700,8 +700,11 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
return r;
|
||||
|
||||
p = path_startswith(pty_name, "/dev/pts/");
|
||||
if (!p)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
|
||||
assert(p);
|
||||
|
||||
slave = machine_open_terminal(m, pty_name, O_RDWR|O_NOCTTY|O_CLOEXEC);
|
||||
if (slave < 0)
|
||||
return slave;
|
||||
|
||||
utmp_id = path_startswith(pty_name, "/dev/");
|
||||
assert(utmp_id);
|
||||
@ -735,16 +738,14 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
|
||||
description = strjoina("Shell for User ", isempty(user) ? "root" : user);
|
||||
r = sd_bus_message_append(tm,
|
||||
"(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)",
|
||||
"(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)",
|
||||
"Description", "s", description,
|
||||
"StandardInput", "s", "tty",
|
||||
"StandardOutput", "s", "tty",
|
||||
"StandardError", "s", "tty",
|
||||
"TTYPath", "s", pty_name,
|
||||
"StandardInputFileDescriptor", "h", slave,
|
||||
"StandardOutputFileDescriptor", "h", slave,
|
||||
"StandardErrorFileDescriptor", "h", slave,
|
||||
"SendSIGHUP", "b", true,
|
||||
"IgnoreSIGPIPE", "b", false,
|
||||
"KillMode", "s", "mixed",
|
||||
"TTYVHangup", "b", true,
|
||||
"TTYReset", "b", true,
|
||||
"UtmpIdentifier", "s", utmp_id,
|
||||
"UtmpMode", "s", "user",
|
||||
@ -845,6 +846,8 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
slave = safe_close(slave);
|
||||
|
||||
r = sd_bus_message_new_method_return(message, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "machine.h"
|
||||
|
||||
extern const sd_bus_vtable machine_vtable[];
|
||||
|
||||
char *machine_bus_path(Machine *s);
|
||||
|
@ -19,23 +19,24 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "sd-messages.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "mkdir.h"
|
||||
#include "hashmap.h"
|
||||
#include "fileio.h"
|
||||
#include "special.h"
|
||||
#include "unit-name.h"
|
||||
#include "bus-util.h"
|
||||
#include "bus-error.h"
|
||||
#include "machine.h"
|
||||
#include "machine-dbus.h"
|
||||
#include "bus-util.h"
|
||||
#include "fileio.h"
|
||||
#include "formats-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "mkdir.h"
|
||||
#include "special.h"
|
||||
#include "terminal-util.h"
|
||||
#include "unit-name.h"
|
||||
#include "util.h"
|
||||
#include "machine-dbus.h"
|
||||
#include "machine.h"
|
||||
|
||||
Machine* machine_new(Manager *manager, MachineClass class, const char *name) {
|
||||
Machine *m;
|
||||
@ -571,6 +572,25 @@ int machine_openpt(Machine *m, int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
int machine_open_terminal(Machine *m, const char *path, int mode) {
|
||||
assert(m);
|
||||
|
||||
switch (m->class) {
|
||||
|
||||
case MACHINE_HOST:
|
||||
return open_terminal(path, mode);
|
||||
|
||||
case MACHINE_CONTAINER:
|
||||
if (m->leader <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
return open_terminal_in_namespace(m->leader, path, mode);
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
MachineOperation *machine_operation_unref(MachineOperation *o) {
|
||||
if (!o)
|
||||
return NULL;
|
||||
|
@ -123,3 +123,4 @@ const char *kill_who_to_string(KillWho k) _const_;
|
||||
KillWho kill_who_from_string(const char *s) _pure_;
|
||||
|
||||
int machine_openpt(Machine *m, int flags);
|
||||
int machine_open_terminal(Machine *m, const char *path, int mode);
|
||||
|
@ -1390,7 +1390,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
return process_forward(event, &forward, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, machine);
|
||||
return process_forward(event, &forward, master, 0, machine);
|
||||
}
|
||||
|
||||
static int remove_image(int argc, char *argv[], void *userdata) {
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "signal-util.h"
|
||||
#include "spawn-polkit-agent.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "unit-name.h"
|
||||
|
||||
static bool arg_ask_password = true;
|
||||
@ -62,7 +63,7 @@ static usec_t arg_on_boot = 0;
|
||||
static usec_t arg_on_startup = 0;
|
||||
static usec_t arg_on_unit_active = 0;
|
||||
static usec_t arg_on_unit_inactive = 0;
|
||||
static char *arg_on_calendar = NULL;
|
||||
static const char *arg_on_calendar = NULL;
|
||||
static char **arg_timer_property = NULL;
|
||||
static bool arg_quiet = false;
|
||||
|
||||
@ -181,7 +182,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
};
|
||||
|
||||
int r, c;
|
||||
CalendarSpec *spec = NULL;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
@ -335,16 +335,19 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
break;
|
||||
|
||||
case ARG_ON_CALENDAR:
|
||||
case ARG_ON_CALENDAR: {
|
||||
CalendarSpec *spec = NULL;
|
||||
|
||||
r = calendar_spec_from_string(optarg, &spec);
|
||||
if (r < 0) {
|
||||
log_error("Invalid calendar spec: %s", optarg);
|
||||
return r;
|
||||
}
|
||||
free(spec);
|
||||
|
||||
calendar_spec_free(spec);
|
||||
arg_on_calendar = optarg;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_TIMER_PROPERTY:
|
||||
|
||||
@ -389,6 +392,11 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg_pty && arg_transport == BUS_TRANSPORT_REMOTE) {
|
||||
log_error("--pty is only supported when connecting to the local system or containers.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg_scope && with_timer()) {
|
||||
log_error("Timer options are not supported in --scope mode.");
|
||||
return -EINVAL;
|
||||
@ -707,9 +715,9 @@ static int start_transient_service(
|
||||
_cleanup_bus_unref_ sd_bus *system_bus = NULL;
|
||||
const char *s;
|
||||
|
||||
r = sd_bus_open_system(&system_bus);
|
||||
r = sd_bus_default_system(&system_bus);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to connect to system bus: %m");
|
||||
return log_error_errno(r, "Failed to connect to system bus: %m");
|
||||
|
||||
r = sd_bus_call_method(system_bus,
|
||||
"org.freedesktop.machine1",
|
||||
@ -794,10 +802,8 @@ static int start_transient_service(
|
||||
polkit_agent_open_if_enabled();
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, &reply);
|
||||
if (r < 0) {
|
||||
log_error("Failed to start transient service unit: %s", bus_error_message(&error, -r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r));
|
||||
|
||||
if (w) {
|
||||
const char *object;
|
||||
|
@ -315,6 +315,10 @@ static int parse_password(const char *filename, char **wall) {
|
||||
tty_fd = acquire_terminal("/dev/console", false, false, false, USEC_INFINITY);
|
||||
if (tty_fd < 0)
|
||||
return log_error_errno(tty_fd, "Failed to acquire /dev/console: %m");
|
||||
|
||||
r = reset_terminal_fd(tty_fd, true);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
|
||||
}
|
||||
|
||||
r = ask_password_tty(message, NULL, not_after, echo ? ASK_PASSWORD_ECHO : 0, filename, &password);
|
||||
|
Loading…
x
Reference in New Issue
Block a user