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