From 4c4e778810435da3c913368430f0d25c110381b2 Mon Sep 17 00:00:00 2001 From: "John Ankarstr\\xf6m" Date: Mon, 31 May 2021 19:34:03 +0200 Subject: Change name from termsettitle to safetitle --- Makefile | 4 +- safetitle.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ termsettitle.c | 127 --------------------------------------------------------- 3 files changed, 126 insertions(+), 129 deletions(-) create mode 100644 safetitle.c delete mode 100644 termsettitle.c diff --git a/Makefile b/Makefile index 31132bb..3f6f76b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CFLAGS += -O2 -pedantic -Wall -Wextra -termsettitle: termsettitle.c +safetitle: safetitle.c install: - install termsettitle /usr/local/bin + install safetitle /usr/local/bin diff --git a/safetitle.c b/safetitle.c new file mode 100644 index 0000000..ee37d3b --- /dev/null +++ b/safetitle.c @@ -0,0 +1,124 @@ +/* + * safetitle sets the title of the terminal window to the given string, + * if and only if the terminal is recognized via its device attributes. + * + * If multiple terminals are attached to the same GNU screen session, + * the title is not set. It is theoretically possible to check every + * terminal too see if it is recognized and, if so, set the title -- + * but that would make the code more complex. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define XTERM_DA (char[]){27,91,62,52,49,59,51,51,48,59,48,99,0} +#define SCREEN_DA (char[]){27,91,62,56,51,59,52,48,56,48,48,59,48,99,0} + +int +da(int fd, char *buf, int real) +{ + char c; + fd_set fds; + int i, r, responses; + struct timeval timeout; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + timeout.tv_sec = 0; + timeout.tv_usec = 0; + responses = 0; + + i = 0; + if(real) write(fd, "\033P\033[>c\033\\", 8); + else write(fd, "\033[>c", 4); + +read: + while(r = read(fd, &c, 1)){ + if(!r){ + fprintf(stderr, "bad terminal\n"); + return -1; + } + buf[i++] = c; + if(c==99) break; + } + buf[i] = '\0'; + responses++; + + /* ensure there is only one real terminal */ + if(real && select(fd+1, &fds, NULL, NULL, &timeout)>0) + goto read; + if(responses>1) + buf[0] = '\0'; + + return i; +} + +int +main(int argc, char *argv[]) +{ + char *ap, *buf; + int debug, r, screen, ttyfd; + struct termios term, restore; + + r = 1; + + /* parse arguments */ + debug = 0; + if(argc==2) + ap = argv[1]; + else if(argc==3){ + ap = argv[2]; + if(strcmp(argv[1], "-d")==0) debug = 1; + else goto usage; + } + else goto usage; + + if((ttyfd = open("/dev/tty", O_RDWR))==-1){ + fprintf(stderr, "could not open /dev/tty\n"); + goto end; + } + if((buf = malloc(200*sizeof(char)))==NULL){ + fprintf(stderr, "could not allocate memory\n"); + goto end; + } + + /* enter "raw" terminal mode */ + tcgetattr(ttyfd, &restore); + tcgetattr(ttyfd, &term); + term.c_lflag &= ~(ICANON|ECHO); + tcsetattr(ttyfd, TCSANOW, &term); + + /* get device attributes for real terminal */ + if(da(ttyfd, buf, 0)==-1) goto end; + if(strcmp(buf, SCREEN_DA)==0) + screen = 1; + else + screen = 0; + if(da(ttyfd, buf, screen)==-1) goto end; + + /* set title */ + if(strcmp(buf, XTERM_DA)==0){ + if(screen) dprintf(ttyfd, "\033P\033]2;%s\007\033\\", ap); + else dprintf(ttyfd, "\033]2;%s\007", ap); + } + else{ + if(debug) fprintf(stderr, "wrong type of terminal\n"); + r = 2; + goto end; + } + + r = 0; +end: + tcsetattr(ttyfd, TCSANOW, &restore); + exit(r); +usage: + fprintf(stderr, "usage: %s [-d] title\n", argv[0]); + exit(1); +} diff --git a/termsettitle.c b/termsettitle.c deleted file mode 100644 index 2ff9883..0000000 --- a/termsettitle.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * termsettitle sets the title of the terminal window to the given string, - * if and only if the terminal is recognized via its device attributes. - * - * Note that this does NOT (yet) work inside GNU screen if several terminals - * are attached to the same session. In other words, you need to use -dr - * instead of -x when attaching with screen. - * - * (Maybe we could try to read again, but with a timeout? If there is more - * to read, we read it and then abort.) - * (Or maybe there IS a way to check if there is something to read.) - * (This would solve the problem completely!) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define XTERM_DA (char[]){27,91,62,52,49,59,51,51,48,59,48,99,0} -#define SCREEN_DA (char[]){27,91,62,56,51,59,52,48,56,48,48,59,48,99,0} - -int -da(int fd, char *buf, int real) -{ - char c; - fd_set fds; - int i, r, responses; - struct timeval timeout; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - timeout.tv_sec = 0; - timeout.tv_usec = 0; - responses = 0; - - i = 0; - if(real) write(fd, "\033P\033[>c\033\\", 8); - else write(fd, "\033[>c", 4); - -read: - while(r = read(fd, &c, 1)){ - if(!r){ - fprintf(stderr, "bad terminal\n"); - return -1; - } - buf[i++] = c; - if(c==99) break; - } - buf[i] = '\0'; - responses++; - - /* ensure there is only one real terminal */ - if(real && select(fd+1, &fds, NULL, NULL, &timeout)>0) - goto read; - if(responses>1) - buf[0] = '\0'; - - return i; -} - -int -main(int argc, char *argv[]) -{ - char *ap, *buf; - int debug, r, screen, ttyfd; - struct termios term, restore; - - r = 1; - - /* parse arguments */ - debug = 0; - if(argc==2) - ap = argv[1]; - else if(argc==3){ - ap = argv[2]; - if(strcmp(argv[1], "-d")==0) debug = 1; - else goto usage; - } - else goto usage; - - if((ttyfd = open("/dev/tty", O_RDWR))==-1){ - fprintf(stderr, "could not open /dev/tty\n"); - goto end; - } - if((buf = malloc(200*sizeof(char)))==NULL){ - fprintf(stderr, "could not allocate memory\n"); - goto end; - } - - /* enter "raw" terminal mode */ - tcgetattr(ttyfd, &restore); - tcgetattr(ttyfd, &term); - term.c_lflag &= ~(ICANON|ECHO); - tcsetattr(ttyfd, TCSANOW, &term); - - /* get device attributes for real terminal */ - if(da(ttyfd, buf, 0)==-1) goto end; - if(strcmp(buf, SCREEN_DA)==0) - screen = 1; - else - screen = 0; - if(da(ttyfd, buf, screen)==-1) goto end; - - /* set title */ - if(strcmp(buf, XTERM_DA)==0){ - if(screen) dprintf(ttyfd, "\033P\033]2;%s\007\033\\", ap); - else dprintf(ttyfd, "\033]2;%s\007", ap); - } - else{ - if(debug) fprintf(stderr, "wrong type of terminal\n"); - r = 2; - goto end; - } - - r = 0; -end: - tcsetattr(ttyfd, TCSANOW, &restore); - exit(r); -usage: - fprintf(stderr, "usage: %s [-d] title\n", argv[0]); - exit(1); -} -- cgit v1.2.3