chiark / gitweb /
debianutils: Update from 4.8.3 to 4.8.4
[termux-packages] / packages / libutil / pty.c
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, const struct termios* termp, const 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, const struct termios* termp, const 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 }