xref: /haiku/src/libs/bsd/pty.cpp (revision 61ce1824dfdea15a581a1e54b92dc06aadf418c5)
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
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 		// TODO we should either close master and slaves and return -1
36 		// 		or we do nothing!
37 		close(slave);
38 		close(master);
39 	}
40 
41 	*_master = master;
42 	*_slave = slave;
43 
44 	if (name != NULL)
45 		strcpy(name, ttyName);
46 
47 	return 0;
48 }
49 
50 
51 int
52 login_tty(int fd)
53 {
54 	setsid();
55 
56 	if (ioctl(fd, TIOCSCTTY, NULL) != 0)
57 		return -1;
58 
59 	dup2(fd, 0);
60 	dup2(fd, 1);
61 	dup2(fd, 2);
62 
63 	close(fd);
64 	return 0;
65 }
66 
67 
68 pid_t
69 forkpty(int* _master, char* name, struct termios* termAttrs,
70 	struct winsize* windowSize)
71 {
72 	int master, slave;
73 	if (openpty(&master, &slave, name, termAttrs, windowSize) != 0)
74 		return -1;
75 
76 	int pid = fork();
77 	if (pid < 0) {
78 		close(master);
79 		close(slave);
80 		return -1;
81 	}
82 	// child
83 	if (pid == 0) {
84 		close(master);
85 		return login_tty(slave);
86 	}
87 
88 	// parent
89 	close (slave);
90 	*_master = master;
91 	return pid;
92 }
93