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 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