1 /*
2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All rights reserved.
3 * Copyright 2010, Jérôme Duval, korli@users.berlios.de. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7 #include <pty.h>
8
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14
15 int
openpty(int * _master,int * _slave,char * name,struct termios * termAttrs,struct winsize * windowSize)16 openpty(int* _master, int* _slave, char* name, struct termios* termAttrs,
17 struct winsize* windowSize)
18 {
19 int master = posix_openpt(O_RDWR);
20 if (master < 0)
21 return -1;
22
23 int slave;
24 const char *ttyName;
25 if (grantpt(master) != 0 || unlockpt(master) != 0
26 || (ttyName = ptsname(master)) == NULL
27 || (slave = open(ttyName, O_RDWR | O_NOCTTY)) < 0) {
28 close(master);
29 return -1;
30 }
31
32 if ((termAttrs != NULL && tcsetattr(master, TCSANOW, termAttrs) != 0)
33 || (windowSize != NULL
34 && ioctl(master, TIOCSWINSZ, windowSize, sizeof(winsize)) != 0)) {
35 close(slave);
36 close(master);
37 return -1;
38 }
39
40 *_master = master;
41 *_slave = slave;
42
43 if (name != NULL)
44 strcpy(name, ttyName);
45
46 return 0;
47 }
48
49
50 int
login_tty(int fd)51 login_tty(int fd)
52 {
53 setsid();
54
55 if (ioctl(fd, TIOCSCTTY, NULL) != 0)
56 return -1;
57
58 dup2(fd, 0);
59 dup2(fd, 1);
60 dup2(fd, 2);
61
62 close(fd);
63 return 0;
64 }
65
66
67 pid_t
forkpty(int * _master,char * name,struct termios * termAttrs,struct winsize * windowSize)68 forkpty(int* _master, char* name, struct termios* termAttrs,
69 struct winsize* windowSize)
70 {
71 int master, slave;
72 if (openpty(&master, &slave, name, termAttrs, windowSize) != 0)
73 return -1;
74
75 int pid = fork();
76 if (pid < 0) {
77 close(master);
78 close(slave);
79 return -1;
80 }
81 // child
82 if (pid == 0) {
83 close(master);
84 return login_tty(slave);
85 }
86
87 // parent
88 close (slave);
89 *_master = master;
90 return pid;
91 }
92