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
15int
16openpty(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
50int
51login_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
67pid_t
68forkpty(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