Skip to content

Instantly share code, notes, and snippets.

@pikhq
Last active May 2, 2021 17:52
Show Gist options
  • Save pikhq/5dda4f4052db04a261d4 to your computer and use it in GitHub Desktop.
Save pikhq/5dda4f4052db04a261d4 to your computer and use it in GitHub Desktop.
Small util to detect if a terminal does or does not support terminal titles.
/* Copyright © 2015 Ada Worcester <oss@ada.pihq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define _XOPEN_SOURCE 700
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
static int fd_getc(int f)
{
char buf;
ssize_t len;
int old_errno;
old_errno = errno;
len = read(f, &buf, 1);
if(len == 0) errno = old_errno;
if(len <= 0) return EOF;
return buf;
}
static int read_pos(int fd, int *x, int *y)
{
int c;
*x = 0; *y = 0;
if(dprintf(fd, "\033[6n") < 0) return -1;
errno = 0;
if(fd_getc(fd) != '\033') {
if(errno == 0) errno = EINVAL;
return -1;
}
if(fd_getc(fd) != '[') {
if(errno == 0) errno = EINVAL;
return -1;
}
while((c = fd_getc(fd)) != ';') {
if(!(c >= '0' && c <= '9')) {
if(errno == 0) errno = EINVAL;
return -1;
}
*x *= 10;
*x += c - '0';
}
while((c = fd_getc(fd)) != 'R') {
if(!(c >= '0' && c <= '9')) {
if(errno == 0) errno = EINVAL;
return -1;
}
*y *= 10;
*y += c - '0';
}
return 0;
}
static void die()
{
perror("detect-title");
exit(1);
}
static struct termios orig_termios;
static int term_fd;
static void atexit_handler(void)
{
tcsetattr(term_fd, TCSANOW, &orig_termios);
}
int main()
{
struct termios termios;
sigset_t set, oldset;
int x1, y1, x2, y2;
int orig_err;
sigfillset(&set);
term_fd = open("/dev/tty", O_RDWR);
if(term_fd < 0) die();
if(tcgetattr(term_fd, &orig_termios) < 0) die();
termios = orig_termios;
termios.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | CREAD);
termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | IXON);
termios.c_cflag &= ~(CSIZE | PARENB);
termios.c_cflag |= CS8;
termios.c_oflag &= ~(OPOST);
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 0;
sigprocmask(SIG_BLOCK, &set, &oldset);
atexit(atexit_handler);
if(tcsetattr(term_fd, TCSAFLUSH, &termios) < 0) die();
if(read_pos(term_fd, &x1, &y1)) die();
if(dprintf(term_fd, "\033]0;testing\033\\") < 0) die();
if(read_pos(term_fd, &x2, &y2)) die();
if(dprintf(term_fd, "\033[%d;%dH\033[J", x1, y1) < 0) die();
if(tcsetattr(term_fd, TCSANOW, &orig_termios) < 0) die();
sigprocmask(SIG_SETMASK, &oldset, 0);
if(x1 == x2 && y1 == y2) {
if(dprintf(1, "yes\n") < 0) die();
} else {
if(dprintf(1, "no\n") < 0) die();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment