aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--safetitle.125
-rw-r--r--safetitle.c97
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 <err.h>
@@ -17,60 +12,95 @@
#include <termios.h>
#include <unistd.h>
+#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;