2 * pty.c - pseudo-terminal handling
\r
5 #define _XOPEN_SOURCE
\r
6 #include <features.h>
\r
15 #include <termios.h>
\r
16 #include <sys/ioctl.h>
\r
17 #include <sys/types.h>
\r
23 static char ptyname[FILENAME_MAX];
\r
26 void pty_preinit(void)
\r
31 master = open("/dev/ptmx", O_RDWR);
\r
33 perror("/dev/ptmx: open");
\r
37 if (grantpt(master) < 0) {
\r
42 if (unlockpt(master) < 0) {
\r
48 void pty_resize(int w, int h)
\r
52 assert(master >= 0);
\r
56 sz.ws_xpixel = sz.ws_ypixel = 0;
\r
57 ioctl(master, TIOCSWINSZ, &sz);
\r
60 int run_program_in_pty(const struct shell_data *shdata,
\r
61 char *directory, char **program_args)
\r
64 char *fallback_args[2];
\r
66 assert(master >= 0);
\r
68 ptyname[FILENAME_MAX-1] = '\0';
\r
69 strncpy(ptyname, ptsname(master), FILENAME_MAX-1);
\r
77 * FIXME: think up some good defaults here
\r
80 if (!ioctl(0, TIOCGWINSZ, &ws))
\r
81 ioctl(master, TIOCSWINSZ, &ws);
\r
82 if (!tcgetattr(0, &ts))
\r
83 tcsetattr(master, TCSANOW, &ts);
\r
87 slave = open(ptyname, O_RDWR | O_NOCTTY);
\r
89 perror("slave pty: open");
\r
94 * Fork and execute the command.
\r
106 * We are the child.
\r
110 fcntl(slave, F_SETFD, 0); /* don't close on exec */
\r
113 if (slave != 0 && slave != 1)
\r
120 if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
\r
121 ioctl(fd, TIOCNOTTY, &i);
\r
126 ioctl(0, TIOCSCTTY, &i);
\r
128 tcsetpgrp(0, getpgrp());
\r
130 for (i = 0; i < shdata->nenvvars; i++)
\r
131 putenv(shdata->envvars[i]);
\r
132 if (shdata->termtype)
\r
133 putenv(shdata->termtype);
\r
139 * Use the provided shell program name, if the user gave
\r
140 * one. Failing that, use $SHELL; failing that, look up
\r
141 * the user's default shell in the password file; failing
\r
142 * _that_, revert to the bog-standard /bin/sh.
\r
144 if (!program_args) {
\r
147 shell = getenv("SHELL");
\r
151 struct passwd *pwd;
\r
154 * For maximum generality in the face of multiple
\r
155 * /etc/passwd entries with different login names and
\r
156 * shells but a shared uid, we start by using
\r
157 * getpwnam(getlogin()) if it's available - but we
\r
158 * insist that its uid must match our real one, or we
\r
159 * give up and fall back to getpwuid(getuid()).
\r
162 login = getlogin();
\r
163 if (login && (pwd = getpwnam(login)) && pwd->pw_uid == uid)
\r
164 shell = pwd->pw_shell;
\r
165 else if ((pwd = getpwuid(uid)))
\r
166 shell = pwd->pw_shell;
\r
171 fallback_args[0] = shell;
\r
172 fallback_args[1] = NULL;
\r
173 program_args = fallback_args;
\r
176 execv(program_args[0], program_args);
\r
179 * If we're here, exec has gone badly foom.
\r