Skip to content

Commit

Permalink
tty: add cli options
Browse files Browse the repository at this point in the history
It is now possible to set via the --tty switch options on the inner pty
termios, including control characters.
  • Loading branch information
Snaipe committed Aug 14, 2021
1 parent 960e577 commit 6a1e4f9
Show file tree
Hide file tree
Showing 10 changed files with 393 additions and 79 deletions.
6 changes: 3 additions & 3 deletions enter.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ int enter(struct entry_settings *opts)
if (parentSock >= 0) {
/* tty_parent_setup handles SIGWINCH to resize the pty */
sigdelset(&mask, SIGWINCH);
tty_parent_setup(epollfd, parentSock);
tty_parent_setup(&opts->ttyopts, epollfd, parentSock);
}
sig_setup(epollfd, &mask, outer_helper.pid, sig_handler);

Expand Down Expand Up @@ -672,9 +672,9 @@ int enter(struct entry_settings *opts)
}

if (childSock >= 0) {
tty_child(childSock);
tty_child(&opts->ttyopts, childSock);
}

if (opts->init != NULL && opts->init[0] != '\0') {

if (!pid_unshare && prctl(PR_SET_CHILD_SUBREAPER, 1) == -1) {
Expand Down
2 changes: 2 additions & 0 deletions enter.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# include "ns.h"
# include "timens.h"
# include "userns.h"
# include "tty.h"

struct limit {
bool present;
Expand Down Expand Up @@ -84,6 +85,7 @@ struct entry_settings {
const char *pidfile;

bool tty;
struct tty_opts ttyopts;

int no_copy_hard_limits;
int no_fake_devtmpfs;
Expand Down
5 changes: 5 additions & 0 deletions kvlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

void kvlist_parse(char *in, struct kvlist *out, size_t len, char **rest)
{
memset(out, 0, sizeof (out) * len);
if (in == NULL) {
return;
}

char *end = in + strlen(in);
char *save = NULL;
char *tok = strtok_r(in, ",", &save);
Expand Down
18 changes: 15 additions & 3 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ int main(int argc, char *argv[], char *envp[])
{ "pidfile", required_argument, NULL, OPTION_PIDFILE },
{ "ip", required_argument, NULL, OPTION_IP },
{ "route", required_argument, NULL, OPTION_ROUTE },
{ "tty", no_argument, NULL, OPTION_TTY },
{ "tty", optional_argument, NULL, OPTION_TTY },

/* Opt-out feature flags */
{ "no-copy-hard-limits", no_argument, NULL, OPTION_NO_COPY_HARD_LIMITS },
Expand Down Expand Up @@ -665,8 +665,20 @@ int main(int argc, char *argv[], char *envp[])
break;

case OPTION_TTY:
opts.tty = 1;
break;
{
opts.tty = 1;
opts.ttyopts.ptmx = tty_default_ptmx;

/* 128 is enough to support everything */
struct kvlist kvlist[128];
size_t nopts = sizeof (kvlist) / sizeof (*kvlist);
kvlist_parse(optarg, kvlist, nopts, NULL);

for (size_t i = 0; i < nopts && kvlist[i].key != NULL; ++i) {
tty_opt_parse(&opts.ttyopts, kvlist[i].key, kvlist[i].value);
}
break;
}

case 'r':
opts.root = optarg;
Expand Down
40 changes: 34 additions & 6 deletions man/bst.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,40 @@ _VAR=value_ before the executable to run.
To avoid lock races with other processes sharing a common pidfile path, the
file is never removed.

\--tty[=<options>]
Allocate a pty for the process.

_--tty_ optionally takes a list of flags or key=value pairs to set specific
termios options and control characters for the newly allocated pty.

Options take no value and can be negated by prepending _'-'_ to the option
name (e.g. _-echo_). Supported options are: *brkint*, *clocal*, *cmspar*,
*cr0*, *cr1*, *cr2*, *cr3*, *cread*, *crtscts*, *cstopb*, *echo*, *echoctl*,
*echoe*, *echok*, *echoke*, *echonl*, *echoprt*, *extproc*, *ff0*, *ff1*,
*flusho*, *hupcl*, *icanon*, *icrnl*, *iexten*, *ignbrk*, *igncr*, *ignpar*,
*inlcr*, *inpck*, *isig*, *istrip*, *iuclc*, *iutf8*, *ixany*, *ixoff*,
*ixon*, *nl0*, *nl1*, *noflsh*, *ocrnl*, *ofill*, *olcuc*, *onlcr*, *onlret*,
*onocr*, *opost*, *parenb*, *parmrk*, *parodd*, *tab0*, *tab1*, *tab2*,
*tab3*, *tostop*, *vt0*, and *vt1*.

Control characters are specified as a key-value pair, _<cc>=<val>_. Values
can be specified using the caret notation, or a backslash-escaped octal
(\\nnn) or hexadecimal (\\xnn) value. Supported control characters are: *veof*,
*veol*, *veol2*, *verase*, *vintr*, *vkill*, *vlnext*, *vquit*, *vreprint*,
*vstart*, *vstop*, *vsusp*, and *vwerase*.

A comprehensive description of what these options and control characters do
can be found in the *termios*(3) manual.

Other bst-specific options are:

- *ptmx*=<path>: use the specified ptmx device (relative to the target root)
to allocated the pty.

By default bst inherits the parent's terminal device (or lack thereof). Use
the --tty option to allocate a new pty for the child process.


\--no-copy-hard-limits
Do not copy hard limit values to soft limits for all resources mentioned above.

Expand Down Expand Up @@ -328,12 +362,6 @@ _VAR=value_ before the executable to run.
the spacetime process. This can cause issues for environment variables like
PATH if the rootfs layout is different than the host.

\--tty
Allocate a pty for the process.

By default bst inherits the parent's terminal device (or lack thereof). Use
the --tty option to allocate a new pty for the child process.

# PRIVILEGE MODEL

*bst* strives to be runnable by unprivileged users. However, some code paths
Expand Down
53 changes: 43 additions & 10 deletions test/tty.t
Original file line number Diff line number Diff line change
@@ -1,23 +1,56 @@
#!/usr/bin/env cram.sh

Allocate a PTY for the spacetime
$ bst --tty --mount devpts,/dev/pts,devpts,mode=620,ptmxmode=666 tty
/dev/pts/0

$ bst --tty --mount devpts,/dev/pts,devpts,mode=620,ptmxmode=666 tty | cat -e
/dev/pts/0^M$

$ bst --tty=ptmx=/dev/pts/ptmx --mount devpts,/dev/pts,devpts,mode=620,ptmxmode=666 tty | cat -e
/dev/pts/0^M$

$ </dev/null bst --tty stty -a | cat -e
speed 38400 baud; rows 0; columns 0; line = 0;^M$
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;^M$
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;^M$
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;^M$
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts^M$
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff^M$
-iuclc -ixany -imaxbel -iutf8^M$
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0^M$
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt^M$
echoctl echoke -flusho -extproc^M$

Check that redirections still work

$ echo hello | bst --tty cat
hello
hello
$ echo hello | bst --tty=-echo,-onlcr cat
hello

$ bst --tty=-onlcr echo bonjour | cat
bonjour

Change flags and control characters

$ bst --tty echo hello | cat
hello
$ bst --tty='-echo,-onlcr,-icanon,veof=^B,vintr=\4,vquit=\x10' stty
speed 38400 baud; line = 0;
intr = ^D; quit = ^P; eof = ^B; min = 1; time = 0;
-brkint -imaxbel
-onlcr
-icanon -echo

Ensure we send the correct VEOF control character

$ yes '' | head -c 32768 | timeout 1 bst --tty sh -c 'stty eof ^B && cat' >/dev/null
$ yes '' | head -c 32768 | timeout 1 bst --tty=veof=^B cat >/dev/null

$ yes '' | head -c 32768 | timeout 1 bst --tty sh -c 'head -c 1 && stty eof ^B && cat' >/dev/null

Ensure that we send VEOF twice in case there is pending input in the pty buffer

$ echo -n hello | bst --tty cat
hellohello
$ echo -n hola | bst --tty=-echo,-onlcr cat
hola

Inner PTYs should inherit their parent termios:

$ bst --tty sh -c '[ "$(stty -a)" = "$(bst --tty stty -a | tr -d "\r")" ]'

$ raw=-ignbrk,-brkint,-ignpar,-parmrk,-inpck,-istrip,-inlcr,-igncr,-icrnl,-ixon,-ixoff,-icanon,-opost,-isig,-iuclc,-ixany
> [ "$(bst --tty=$raw stty -a)" = "$(bst --tty=$raw bst --tty stty -a)" ]
Loading

0 comments on commit 6a1e4f9

Please sign in to comment.