1 /*** 2 This file is part of systemd. 3 4 Copyright 2010 Lennart Poettering 5 6 systemd is free software; you can redistribute it and/or modify it 7 under the terms of the GNU Lesser General Public License as published by 8 the Free Software Foundation; either version 2.1 of the License, or 9 (at your option) any later version. 10 11 systemd is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with systemd; If not, see <http://www.gnu.org/licenses/>. 18 ***/ 19 20 #include <sys/ioctl.h> 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <termios.h> 24 #include <unistd.h> 25 #include <fcntl.h> 26 #include <signal.h> 27 #include <time.h> 28 #include <assert.h> 29 #include <poll.h> 30 #include <linux/vt.h> 31 #include <linux/tiocl.h> 32 #include <linux/kd.h> 33 34 #include "terminal-util.h" 35 #include "time-util.h" 36 #include "process-util.h" 37 #include "util.h" 38 #include "fileio.h" 39 #include "path-util.h" 40 41 static volatile unsigned cached_columns = 0; 42 static volatile unsigned cached_lines = 0; 43 open_terminal(const char *name, int mode)44int open_terminal(const char *name, int mode) { 45 int fd, r; 46 unsigned c = 0; 47 48 /* 49 * If a TTY is in the process of being closed opening it might 50 * cause EIO. This is horribly awful, but unlikely to be 51 * changed in the kernel. Hence we work around this problem by 52 * retrying a couple of times. 53 * 54 * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245 55 */ 56 57 assert(!(mode & O_CREAT)); 58 59 for (;;) { 60 fd = open(name, mode, 0); 61 if (fd >= 0) 62 break; 63 64 if (errno != EIO) 65 return -errno; 66 67 /* Max 1s in total */ 68 if (c >= 20) 69 return -errno; 70 71 usleep(50 * USEC_PER_MSEC); 72 c++; 73 } 74 75 r = isatty(fd); 76 if (r < 0) { 77 safe_close(fd); 78 return -errno; 79 } 80 81 if (!r) { 82 safe_close(fd); 83 return -ENOTTY; 84 } 85 86 return fd; 87 } 88