mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
run: add a new "-t" mode for invoking a binary on an allocated TTY
This commit is contained in:
@@ -225,10 +225,16 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="user-system-options.xml" xpointer="user" />
|
||||
<xi:include href="user-system-options.xml" xpointer="system" />
|
||||
<xi:include href="user-system-options.xml" xpointer="host" />
|
||||
<xi:include href="user-system-options.xml" xpointer="machine" />
|
||||
<varlistentry>
|
||||
<term><option>--pty</option></term>
|
||||
<term><option>-t</option></term>
|
||||
|
||||
<listitem><para>When invoking a command as service connects
|
||||
its standard input and output to the invoking tty via a
|
||||
pseudo TTY device. This allows invoking binaries as services
|
||||
that expect interactive user input, such as an interactive
|
||||
command shells.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--on-active=</option></term>
|
||||
@@ -278,6 +284,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
<command>set-property</command> command.</para> </listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="user-system-options.xml" xpointer="user" />
|
||||
<xi:include href="user-system-options.xml" xpointer="system" />
|
||||
<xi:include href="user-system-options.xml" xpointer="host" />
|
||||
<xi:include href="user-system-options.xml" xpointer="machine" />
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
</variablelist>
|
||||
@@ -333,6 +344,13 @@ Dec 08 20:44:38 container systemd[1]: Started /bin/touch /tmp/foo.
|
||||
-- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. --
|
||||
Dec 08 20:44:48 container systemd[1]: Starting /bin/touch /tmp/foo...
|
||||
Dec 08 20:44:48 container systemd[1]: Started /bin/touch /tmp/foo.</programlisting>
|
||||
|
||||
<para>The following command invokes <filename>/bin/bash</filename>
|
||||
as a service passing its standard input, output and error to
|
||||
the calling TTY.</para>
|
||||
|
||||
<programlisting># systemd-run -t /bin/bash</programlisting>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
@@ -31,11 +31,12 @@
|
||||
#include "strv.h"
|
||||
#include "fileio.h"
|
||||
#include "execute.h"
|
||||
#include "dbus-execute.h"
|
||||
#include "capability.h"
|
||||
#include "env-util.h"
|
||||
#include "af-list.h"
|
||||
#include "namespace.h"
|
||||
#include "path-util.h"
|
||||
#include "dbus-execute.h"
|
||||
|
||||
#ifdef HAVE_SECCOMP
|
||||
#include "seccomp-util.h"
|
||||
@@ -845,6 +846,92 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "TTYPath")) {
|
||||
const char *tty;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &tty);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(tty))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY device not absolute path");
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
char *t;
|
||||
|
||||
t = strdup(tty);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
free(c->tty_path);
|
||||
c->tty_path = t;
|
||||
|
||||
unit_write_drop_in_private_format(u, mode, name, "TTYPath=%s\n", tty);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "StandardInput")) {
|
||||
const char *s;
|
||||
ExecInput p;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = exec_input_from_string(s);
|
||||
if (p < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
c->std_input = p;
|
||||
|
||||
unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s\n", exec_input_to_string(p));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
} else if (streq(name, "StandardOutput")) {
|
||||
const char *s;
|
||||
ExecOutput p;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = exec_output_from_string(s);
|
||||
if (p < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
c->std_output = p;
|
||||
|
||||
unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s\n", exec_output_to_string(p));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "StandardError")) {
|
||||
const char *s;
|
||||
ExecOutput p;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = exec_output_from_string(s);
|
||||
if (p < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
c->std_error = p;
|
||||
|
||||
unit_write_drop_in_private_format(u, mode, name, "StandardError=%s\n", exec_output_to_string(p));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "Environment")) {
|
||||
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
|
||||
@@ -1178,7 +1178,7 @@ static int login_machine(int argc, char *argv[], void *userdata) {
|
||||
sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
|
||||
sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
|
||||
|
||||
r = pty_forward_new(event, master, &forward);
|
||||
r = pty_forward_new(event, master, true, &forward);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create PTY forwarder: %m");
|
||||
|
||||
|
||||
@@ -3519,7 +3519,7 @@ int main(int argc, char *argv[]) {
|
||||
/* simply exit on sigchld */
|
||||
sd_event_add_signal(event, NULL, SIGCHLD, NULL, NULL);
|
||||
|
||||
r = pty_forward_new(event, master, &forward);
|
||||
r = pty_forward_new(event, master, true, &forward);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to create PTY forwarder: %m");
|
||||
goto finish;
|
||||
|
||||
431
src/run/run.c
431
src/run/run.c
File diff suppressed because it is too large
Load Diff
@@ -53,6 +53,11 @@ struct PTYForward {
|
||||
bool master_writable:1;
|
||||
bool master_hangup:1;
|
||||
|
||||
bool repeat:1;
|
||||
|
||||
bool last_char_set:1;
|
||||
char last_char;
|
||||
|
||||
char in_buffer[LINE_MAX], out_buffer[LINE_MAX];
|
||||
size_t in_buffer_full, out_buffer_full;
|
||||
|
||||
@@ -169,11 +174,12 @@ static int shovel(PTYForward *f) {
|
||||
* might be cause by vhangup() or
|
||||
* temporary closing of everything on
|
||||
* the other side, we treat it like
|
||||
* EAGAIN here and try again. */
|
||||
* EAGAIN here and try again, unless
|
||||
* repeat is off. */
|
||||
|
||||
if (errno == EAGAIN || errno == EIO)
|
||||
if (errno == EAGAIN || (errno == EIO && f->repeat))
|
||||
f->master_readable = false;
|
||||
else if (errno == EPIPE || errno == ECONNRESET) {
|
||||
else if (errno == EPIPE || errno == ECONNRESET || errno == EIO) {
|
||||
f->master_readable = f->master_writable = false;
|
||||
f->master_hangup = true;
|
||||
|
||||
@@ -203,6 +209,12 @@ static int shovel(PTYForward *f) {
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (k > 0) {
|
||||
f->last_char = f->out_buffer[k-1];
|
||||
f->last_char_set = true;
|
||||
}
|
||||
|
||||
assert(f->out_buffer_full >= (size_t) k);
|
||||
memmove(f->out_buffer, f->out_buffer + k, f->out_buffer_full - k);
|
||||
f->out_buffer_full -= k;
|
||||
@@ -285,7 +297,7 @@ static int on_sigwinch_event(sd_event_source *e, const struct signalfd_siginfo *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pty_forward_new(sd_event *event, int master, PTYForward **ret) {
|
||||
int pty_forward_new(sd_event *event, int master, bool repeat, PTYForward **ret) {
|
||||
_cleanup_(pty_forward_freep) PTYForward *f = NULL;
|
||||
struct winsize ws;
|
||||
int r;
|
||||
@@ -294,6 +306,8 @@ int pty_forward_new(sd_event *event, int master, PTYForward **ret) {
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
f->repeat = repeat;
|
||||
|
||||
if (event)
|
||||
f->event = sd_event_ref(event);
|
||||
else {
|
||||
@@ -388,3 +402,14 @@ PTYForward *pty_forward_free(PTYForward *f) {
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pty_forward_last_char(PTYForward *f, char *ch) {
|
||||
assert(f);
|
||||
assert(ch);
|
||||
|
||||
if (!f->last_char_set)
|
||||
return -ENXIO;
|
||||
|
||||
*ch = f->last_char;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
|
||||
typedef struct PTYForward PTYForward;
|
||||
|
||||
int pty_forward_new(sd_event *event, int master, PTYForward **f);
|
||||
int pty_forward_new(sd_event *event, int master, bool repeat, PTYForward **f);
|
||||
PTYForward *pty_forward_free(PTYForward *f);
|
||||
|
||||
int pty_forward_last_char(PTYForward *f, char *ch);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free);
|
||||
|
||||
Reference in New Issue
Block a user