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