1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "forkpty"
18
19 #include <utils/Log.h>
20
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/ioctl.h>
25 #include <termios.h>
26 #include <unistd.h>
27
28 #include "forkpty.h"
29
forkpty(int * master,int * slave,const struct termios * termp,const struct winsize * winp)30 pid_t forkpty(int *master, int *slave, const struct termios *termp,
31 const struct winsize *winp) {
32 int ptm = open("/dev/ptmx", O_RDWR);
33 if (ptm < 0) {
34 ALOGE("cannot open /dev/ptmx - %s", strerror(errno));
35 return -1;
36 }
37 fcntl(ptm, F_SETFD, FD_CLOEXEC);
38
39 char *devname;
40 if (grantpt(ptm) || unlockpt(ptm) || ((devname = (char *) ptsname(ptm)) == 0)) {
41 ALOGE("error opening pty - %s", strerror(errno));
42 return -1;
43 }
44
45 int pts = open(devname, O_RDWR);
46 if (pts < 0) {
47 ALOGE("unable to open slave pty - %s", strerror(errno));
48 return -1;
49 }
50
51 if (termp) {
52 tcsetattr(pts, TCSAFLUSH, termp);
53 }
54
55 if (winp) {
56 ioctl(pts, TIOCSWINSZ, winp);
57 }
58
59 pid_t pid = fork();
60
61 if (pid < 0) {
62 ALOGE("fork failed - %s", strerror(errno));
63 return -1;
64 }
65
66 if (pid == 0) {
67 setsid();
68 if (ioctl(pts, TIOCSCTTY, (char *)NULL) == -1) exit(-1);
69 dup2(pts, STDIN_FILENO);
70 dup2(pts, STDOUT_FILENO);
71 dup2(pts, STDERR_FILENO);
72 if (pts > 2) {
73 close(pts);
74 }
75 } else {
76 *master = ptm;
77 if (slave) {
78 *slave = pts;
79 }
80 }
81 return pid;
82 }
83
84