= jexecした環境でsudoが動かない件 = jexecした環境でsudoを実行しようとすると {{{ sudo: no tty present and no askpass program specified }}} と言われる件。 nest上に [[http://www.mail-archive.com/freebsd-jail@freebsd.org/msg01584.html]] のパッチを当てて`jexec+tty`コマンドを湧かせた。一応本来の`jexec`はそのまま残しておく。 {{{ diff -Naru usr.sbin/jexec/Makefile usr.sbin/jexec+tty/Makefile --- usr.sbin/jexec/Makefile 2011-03-05 12:40:17.888811727 +0900 +++ usr.sbin/jexec+tty/Makefile 2011-11-22 19:00:35.201362880 +0900 @@ -1,6 +1,7 @@ # $FreeBSD: src/usr.sbin/jexec/Makefile,v 1.5.2.1.6.1 2010/12/21 17:09:25 kensmith Exp $ -PROG= jexec +PROG= jexec+tty +SRCS= jexec.c MAN= jexec.8 DPADD= ${LIBJAIL} ${LIBUTIL} LDADD= -ljail -lutil diff -Naru usr.sbin/jexec/jexec.c usr.sbin/jexec+tty/jexec.c --- usr.sbin/jexec/jexec.c 2011-03-05 12:40:17.890810865 +0900 +++ usr.sbin/jexec+tty/jexec.c 2011-11-22 19:01:44.961332469 +0900 @@ -37,16 +37,20 @@ #include #include +#include #include #include +#include #include #include #include #include +#include #include #include static void usage(void); +static void newpty(void); #define GET_USER_INFO do { \ pwd = getpwnam(username); \ @@ -71,17 +75,17 @@ login_cap_t *lcap = NULL; struct passwd *pwd = NULL; gid_t *groups = NULL; - int ch, ngroups, uflag, Uflag; + int ch, ngroups, uflag, Uflag, tflag; long ngroups_max; char *username; - ch = uflag = Uflag = 0; + ch = uflag = Uflag = tflag = 0; username = NULL; ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) err(1, "malloc"); - while ((ch = getopt(argc, argv, "nu:U:")) != -1) { + while ((ch = getopt(argc, argv, "nu:U:t")) != -1) { switch (ch) { case 'n': /* Specified name, now unused */ @@ -94,6 +98,9 @@ username = optarg; Uflag = 1; break; + case 't': + tflag = 1; + break; default: usage(); } @@ -125,6 +132,8 @@ err(1, "setusercontext"); login_close(lcap); } + if (tflag) + newpty(); if (execvp(argv[1], argv + 1) == -1) err(1, "execvp(): %s", argv[1]); exit(0); @@ -135,6 +144,68 @@ { fprintf(stderr, "%s\n", - "usage: jexec [-u username | -U username] jail command ..."); + "usage: jexec+tty [-u username | -U username] [-t] jail command ..."); exit(1); } + +static void +newpty(void) +{ + int master, slave, child, n, cc; + fd_set rfd; + struct termios tt, rtt; + struct winsize win; + char obuf[BUFSIZ]; + char ibuf[BUFSIZ]; + + if (tcgetattr(STDIN_FILENO, &tt) == -1) + err(1, "tcgetattr"); + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1) + err(1, "ioctl"); + if (openpty(&master, &slave, NULL, &tt, &win) == -1) + err(1, "openpty"); + rtt = tt; + cfmakeraw(&rtt); + rtt.c_lflag &= ~ECHO; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt); + + child = fork(); + if (child < 0) + err(1, "fork"); + if (child == 0) { + close(master); + login_tty(slave); + dup2(slave, STDIN_FILENO); + dup2(slave, STDOUT_FILENO); + dup2(slave, STDERR_FILENO); + close(slave); + return; + } + FD_ZERO(&rfd); + for (;;) { + FD_SET(master, &rfd); + FD_SET(STDIN_FILENO, &rfd); + n = select(master + 1, &rfd, 0, 0, NULL); + if (n < 0 && errno != EINTR) + break; + if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) { + cc = read(STDIN_FILENO, ibuf, BUFSIZ); + if (cc < 0) + break; + if (cc == 0) + write(master, ibuf, 0); + if (cc > 0) { + write(master, ibuf, cc); + } + } + if (n > 0 && FD_ISSET(master, &rfd)) { + cc = read(master, obuf, sizeof (obuf)); + if (cc <= 0) + break; + write(STDOUT_FILENO, obuf, cc); + } + } + tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt); + exit(0); +} + }}}