From 0ca238cdf10d2d6d1bf3c167ff818481a41ef886 Mon Sep 17 00:00:00 2001 From: "John Ankarstr\\xf6m" Date: Tue, 1 Jun 2021 00:52:33 +0200 Subject: Support multiple attached terminals --- safetitle.1 | 25 +++++++--------- safetitle.c | 97 ++++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 68 insertions(+), 54 deletions(-) diff --git a/safetitle.1 b/safetitle.1 index 2d85c57..d8fa0e4 100644 --- a/safetitle.1 +++ b/safetitle.1 @@ -12,7 +12,8 @@ .Pp .Nm sets the title of the current terminal window, -unless the current terminal is recognized as +unless the current terminal type is blacklisted. +By default, the single blacklisted terminal is NetBSD's .Xr wscons 4 . .Pp If run within @@ -21,14 +22,20 @@ If run within will correctly identify the terminal in which .Xr screen 1 is run. +If there are multiple terminals attached to the same +.Xr screen 1 +session, +.Nm +will ensure that none of them are blacklisted. .Pp +The reason why .Nm -is superstitious about the type of the terminal -because some terminals do not support the control sequences +is superstitious about the type of the terminal is +that some terminals do not support the control sequences that modify the title. Specifically, NetBSD's .Xr wscons 4 -is rendered (almost) unusable when it is sent such control sequences. +is rendered (nearly) unusable when it is sent such control sequences. .Nm provides a simple interface to setting the title in terminals that support it, while leaving terminals that do not support it alone. @@ -44,13 +51,3 @@ will warn you if the current terminal type is blacklisted. .Nm is written by John Ankarström .Aq Mt john (at) ankarstrom.se . -.Sh BUGS -.Pp -.Nm -supports -.Xr screen 1 , -except if there are more than one terminal attached to the current session. -In that case, -.Nm -will err on the side of caution and regard the terminals as blacklisted. -Thus, the title will not be set. diff --git a/safetitle.c b/safetitle.c index bf73e2c..9004b03 100644 --- a/safetitle.c +++ b/safetitle.c @@ -1,11 +1,6 @@ /* * 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 @@ -17,60 +12,95 @@ #include #include +#define WSCONS 0 +#define SCREEN 1 + #define WSCONS_DA (char[]){27,91,62,50,52,59,50,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 debug = 0; +int screen = 0; int -da(int fd, char *buf, int real) +blacklisted(int fd) { - char c; + char *buf, c; fd_set fds; - int i, r, responses; + int i, r; struct timeval timeout; + /* setup */ + if((buf = malloc(200*sizeof(char)))==NULL) + err(1, "malloc"); + + /* check if GNU screen */ + write(fd, "\033[>c", 4); + i = 0; + while(r = read(fd, &c, 1)){ + if(r==-1){ + warn("read"); + return 1; + } + buf[i++] = c; + if(c=='c') break; + } + buf[i] = '\0'; + screen = strcmp(buf, SCREEN_DA)==0; + FD_ZERO(&fds); FD_SET(fd, &fds); timeout.tv_sec = 0; - timeout.tv_usec = 1; - responses = 0; - i = 0; + timeout.tv_usec = 0; + + /* ignore strange trailing nul */ + while(select(fd+1, &fds, NULL, NULL, &timeout)>0) + read(fd, &c, 1); - if(real) write(fd, "\033P\033[>c\033\\", 8); + /* check (real) terminal type(s) */ + if(screen) write(fd, "\033P\033[>c\033\\", 8); else write(fd, "\033[>c", 4); + i = 0; while(r = read(fd, &c, 1)){ loop: if(r==-1){ warn("read"); - return -1; + return 1; } buf[i++] = c; if(c==99) break; } buf[i] = '\0'; - responses++; - /* ensure there is only one real terminal */ + if(strcmp(buf, WSCONS_DA)==0){ + if(debug) fprintf(stderr, "blacklisted terminal type\n"); + return 1; + } + + /* go back and check remaining responses (if any) */ check: - if(real && select(fd+1, &fds, NULL, NULL, &timeout)>0){ - if ((r = read(fd, &c, 1)) && c==0) goto check; /* extra nul */ + FD_ZERO(&fds); + FD_SET(fd, &fds); + timeout.tv_sec = 0; + timeout.tv_usec = 1; + if(screen && select(fd+1, &fds, NULL, NULL, &timeout)>0){ + i = 0; + if(read(fd, &c, 1)==-1){ + warn("read"); + return 1; + } + if(c==0) goto check; /* ignore strange trailing nul */ else goto loop; } - if(responses>1){ - if(debug) fprintf(stderr, "more than one attached terminal\n"); - return -1; - } - return i; + return 0; } int main(int argc, char *argv[]) { - char *ap, *buf; - int screen, ttyfd; + char *ap; + int ttyfd; struct termios term, restore; /* parse arguments */ @@ -85,8 +115,6 @@ main(int argc, char *argv[]) if((ttyfd = open("/dev/tty", O_RDWR))==-1) err(1, "open"); - if((buf = malloc(200*sizeof(char)))==NULL) - err(1, "malloc"); /* enter "raw" terminal mode */ tcgetattr(ttyfd, &restore); @@ -95,23 +123,12 @@ main(int argc, char *argv[]) tcsetattr(ttyfd, TCSANOW, &term); /* get device attributes for real terminal */ - if(da(ttyfd, buf, 0)==-1){ + if(blacklisted(ttyfd)) goto end; - } - screen = strcmp(buf, SCREEN_DA)==0; - if(screen && da(ttyfd, buf, screen)==-1){ - goto end; - } /* set title */ - if(strcmp(buf, WSCONS_DA)==0){ - if(debug) fprintf(stderr, "wrong type of terminal\n"); - goto end; - } - else{ - if(screen) dprintf(ttyfd, "\033P\033]2;%s\007\033\\", ap); - else dprintf(ttyfd, "\033]2;%s\007", ap); - } + if(screen) dprintf(ttyfd, "\033P\033]2;%s\007\033\\", ap); + else dprintf(ttyfd, "\033]2;%s\007", ap); tcsetattr(ttyfd, TCSANOW, &restore); return 0; -- cgit v1.2.3