1 /* Assign a given terminal as controlling terminal and as standard input, 2 standard output, standard error of the current process. 3 Copyright (C) 2010-2021 Free Software Foundation, Inc. 4 5 This file is free software: you can redistribute it and/or modify 6 it under the terms of the GNU Lesser General Public License as 7 published by the Free Software Foundation; either version 3 of the 8 License, or (at your option) any later version. 9 10 This file is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public License 16 along with this program. If not, see <https://www.gnu.org/licenses/>. */ 17 18 #include <config.h> 19 20 /* Currently no specification header. */ 21 22 #include <fcntl.h> 23 #include <unistd.h> 24 #include <sys/ioctl.h> 25 26 int 27 login_tty (int slave_fd) /* */ 28 { 29 int i; 30 31 /* Create a new session. */ 32 setsid (); 33 34 /* Make fd the controlling terminal for the current process. 35 On BSD and OSF/1: There is ioctl TIOCSCTTY for this purpose. 36 On Solaris: 37 A terminal becomes the controlling terminal of a session 38 if it is being open()ed, at a moment when 39 1. it is not already the controlling terminal of some session, and 40 2. the process that open()s it is a session leader that does not have 41 a controlling terminal. 42 We assume condition 1, try to ensure condition 2, and then open() it. 43 */ 44 for (i = 0; i < 3; i++) 45 if (i != slave_fd) 46 close (i); 47 #ifdef TIOCSCTTY 48 if (ioctl (slave_fd, TIOCSCTTY, NULL) < 0) 49 return -1; 50 #else 51 { 52 char *slave_name; 53 int dummy_fd; 54 55 slave_name = ttyname (slave_fd); 56 if (slave_name == NULL) 57 return -1; 58 dummy_fd = open (slave_name, O_RDWR | O_CLOEXEC); 59 if (dummy_fd < 0) 60 return -1; 61 close (dummy_fd); 62 } 63 #endif 64 65 /* Assign fd to the standard input, standard output, and standard error of 66 the current process. */ 67 for (i = 0; i < 3; i++) 68 if (slave_fd != i) 69 if (dup2 (slave_fd, i) < 0) 70 return -1; 71 if (slave_fd >= 3) 72 close (slave_fd); 73 74 return 0; 75 }