Commit | Line | Data |
---|---|---|
2044012d FF |
1 | #include <fcntl.h> |
2 | #include <sys/ioctl.h> | |
3 | #include <sys/param.h> | |
4 | #include <sys/types.h> | |
5 | #include <stdlib.h> | |
6 | #include <termios.h> | |
7 | #include <unistd.h> | |
8 | ||
9 | ||
10 | int openpty(int* amaster, int* aslave, char* name, struct termios* termp, struct winsize* winp) | |
11 | { | |
12 | char buf[512]; | |
13 | ||
14 | int master = open("/dev/ptmx", O_RDWR); | |
15 | if (master == -1) return -1; | |
16 | if (grantpt(master) || unlockpt(master) || ptsname_r(master, buf, sizeof buf)) goto fail; | |
17 | ||
18 | int slave = open(buf, O_RDWR | O_NOCTTY); | |
19 | if (slave == -1) goto fail; | |
20 | ||
21 | /* XXX Should we ignore errors here? */ | |
22 | if (termp) tcsetattr(slave, TCSAFLUSH, termp); | |
23 | if (winp) ioctl(slave, TIOCSWINSZ, winp); | |
24 | ||
25 | *amaster = master; | |
26 | *aslave = slave; | |
27 | if (name != NULL) strcpy(name, buf); | |
28 | return 0; | |
29 | ||
30 | fail: | |
31 | close(master); | |
32 | return -1; | |
33 | } | |
34 | ||
35 | ||
36 | int login_tty(int fd) | |
37 | { | |
38 | setsid(); | |
39 | if (ioctl(fd, TIOCSCTTY, NULL) == -1) return -1; | |
40 | dup2(fd, 0); | |
41 | dup2(fd, 1); | |
42 | dup2(fd, 2); | |
43 | if (fd > 2) close(fd); | |
44 | return 0; | |
45 | } | |
46 | ||
47 | ||
48 | int forkpty(int* amaster, char* name, struct termios* termp, struct winsize* winp) | |
49 | { | |
50 | int master, slave; | |
51 | if (openpty(&master, &slave, name, termp, winp) == -1) { | |
52 | return -1; | |
53 | } | |
54 | ||
55 | int pid; | |
56 | switch (pid = fork()) { | |
57 | case -1: | |
58 | return -1; | |
59 | case 0: | |
60 | close(master); | |
61 | if (login_tty(slave)) _exit(1); | |
62 | return 0; | |
63 | default: | |
64 | *amaster = master; | |
65 | close (slave); | |
66 | return pid; | |
67 | } | |
68 | } |