terminal-util: refactor vt_disallocate()

Numerous fixes:

1. use vtnr_from_tty() to parse out VT number from tty path
2. open tty for write only when we want to output just ansi sequences
3. open tty in asynchronous mode, and apply a timeout, just to be safe
4. propagate error from writing (most callers ignore it anyway, might as
   well pass it along correctly)
This commit is contained in:
Lennart Poettering
2024-07-19 11:44:04 +02:00
parent 7147e10c9e
commit 45d785dfc0
+19 -40
View File
@@ -433,60 +433,39 @@ int terminal_vhangup_fd(int fd) {
return RET_NERRNO(ioctl(fd, TIOCVHANGUP));
}
int vt_disallocate(const char *name) {
const char *e;
int r;
int vt_disallocate(const char *tty_path) {
assert(tty_path);
/* 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). */
/* 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). */
e = path_startswith(name, "/dev/");
if (!e)
return -EINVAL;
if (tty_is_vc(name)) {
_cleanup_close_ int fd = -EBADF;
unsigned u;
const char *n;
n = startswith(e, "tty");
if (!n)
return -EINVAL;
r = safe_atou(n, &u);
if (r < 0)
return r;
if (u <= 0)
return -EINVAL;
/* Try to deallocate */
fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
int ttynr = vtnr_from_tty(tty_path);
if (ttynr > 0) {
_cleanup_close_ int fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return fd;
r = ioctl(fd, VT_DISALLOCATE, u);
if (r >= 0)
/* Try to deallocate */
if (ioctl(fd, VT_DISALLOCATE, ttynr) >= 0)
return 0;
if (errno != EBUSY)
return -errno;
}
/* So this is not a VT (in which case we cannot deallocate it),
* or we failed to deallocate. Let's at least clear the screen. */
/* So this is not a VT (in which case we cannot deallocate it), or we failed to deallocate. Let's at
* least clear the screen. */
_cleanup_close_ int fd2 = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
_cleanup_close_ int fd2 = open_terminal(tty_path, O_WRONLY|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd2 < 0)
return fd2;
(void) loop_write(fd2,
"\033[r" /* clear scrolling region */
"\033[H" /* move home */
"\033[3J" /* clear screen including scrollback, requires Linux 2.6.40 */
"\033c", /* reset to initial state */
SIZE_MAX);
return 0;
return loop_write_full(fd2,
"\033[r" /* clear scrolling region */
"\033[H" /* move home */
"\033[3J" /* clear screen including scrollback, requires Linux 2.6.40 */
"\033c", /* reset to initial state */
SIZE_MAX,
100 * USEC_PER_MSEC);
}
static int vt_default_utf8(void) {