diff options
-rw-r--r-- | src/util.c | 95 |
1 files changed, 30 insertions, 65 deletions
diff --git a/src/util.c b/src/util.c index 021be62547..a271708ba2 100644 --- a/src/util.c +++ b/src/util.c @@ -4449,16 +4449,27 @@ int terminal_vhangup(const char *name) { int vt_disallocate(const char *name) { int fd, r; unsigned u; - int temporary_vt, temporary_fd; - char tpath[64]; - struct vt_stat vt_stat; /* Deallocate the VT if possible. If not possible * (i.e. because it is the active one), at least clear it * entirely (including the scrollback buffer) */ - if (!tty_is_vc(name)) - return -EIO; + if (!startswith(name, "/dev/")) + return -EINVAL; + + if (!tty_is_vc(name)) { + /* So this is not a VT. I guess we cannot deallocate + * it then. But let's at least clear the screen */ + + fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return fd; + + loop_write(fd, "\033[H\033[2J", 7, false); /* clear screen */ + close_nointr_nofail(fd); + + return 0; + } if (!startswith(name, "/dev/tty")) return -EINVAL; @@ -4468,79 +4479,33 @@ int vt_disallocate(const char *name) { return r; if (u <= 0) - return -EIO; + return -EINVAL; + /* Try to deallocate */ fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) return fd; r = ioctl(fd, VT_DISALLOCATE, u); - if (r >= 0) { - close_nointr_nofail(fd); - return 0; - } - - if (errno != EBUSY) { - close_nointr_nofail(fd); - return -errno; - } - - if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0) { - close_nointr_nofail(fd); - return -errno; - } + close_nointr_nofail(fd); - if (u != vt_stat.v_active) { - close_nointr_nofail(fd); - return -EBUSY; - } + if (r >= 0) + return 0; - if (ioctl(fd, VT_OPENQRY, &temporary_vt) < 0) { - close_nointr_nofail(fd); + if (errno != EBUSY) return -errno; - } - - if (temporary_vt <= 0) { - close_nointr_nofail(fd); - return -EIO; - } - /* Switch to temporary VT */ - snprintf(tpath, sizeof(tpath), "/dev/tty%i", temporary_vt); - char_array_0(tpath); - temporary_fd = open_terminal(tpath, O_RDWR|O_NOCTTY|O_CLOEXEC); - ioctl(fd, VT_ACTIVATE, temporary_vt); - if (temporary_fd >= 0) - close_nointr_nofail(temporary_fd); - - /* Reopen /dev/tty0 */ - close_nointr_nofail(fd); - fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC); + /* Couldn't deallocate, so let's clear it fully with + * scrollback */ + fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); if (fd < 0) - r = -errno; - else { - /* Disallocate the real VT */ - if (ioctl(fd, VT_DISALLOCATE, u) < 0) - r = -errno; - else - r = 0; - } - - /* Recreate original VT */ - temporary_fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); - - if (temporary_fd >= 0) { - loop_write(temporary_fd, "\033[H\033[2J", 7, false); /* clear screen explicitly */ - close_nointr_nofail(temporary_fd); - } + return fd; - /* Switch back to original VT */ - if (fd >= 0) { - ioctl(fd, VT_ACTIVATE, vt_stat.v_active); - close_nointr_nofail(fd); - } + /* Requires Linux 2.6.40 */ + loop_write(fd, "\033[H\033[3J", 7, false); /* clear screen including scrollback */ + close_nointr_nofail(fd); - return r; + return 0; } static const char *const ioprio_class_table[] = { |