/* * safetitle sets the title of the terminal window to the given string, * unless the terminal type is blacklisted. */ #include #include #include #include #include #include #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 blacklisted(int); int debug = 0; int screen = 0; int main(int argc, char *argv[]) { char *ap; int ttyfd; struct termios term, restore; 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{ usage: fprintf(stderr, "usage: %s [-d] title\n", argv[0]); return 1; } if((ttyfd = open("/dev/tty", O_RDWR))==-1) err(1, "open"); tcgetattr(ttyfd, &restore); tcgetattr(ttyfd, &term); term.c_lflag &= ~(ICANON|ECHO); tcsetattr(ttyfd, TCSANOW, &term); if(blacklisted(ttyfd)) goto end; /* set title */ 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; end: tcsetattr(ttyfd, TCSANOW, &restore); return 1; } int blacklisted(int fd) { char *buf, c; fd_set fds; int i, r; struct timeval timeout; 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; /* ignore strange trailing nul before reading response */ FD_ZERO(&fds); FD_SET(fd, &fds); timeout.tv_sec = 0; timeout.tv_usec = 0; while(select(fd+1, &fds, NULL, NULL, &timeout)>0) read(fd, &c, 1); /* 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; } buf[i++] = c; if(c==99) break; } buf[i] = '\0'; 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: FD_ZERO(&fds); FD_SET(fd, &fds); timeout.tv_sec = 0; timeout.tv_usec = 1; /* it takes a millisecond sometimes */ if(screen && select(fd+1, &fds, NULL, NULL, &timeout)>0){ /* ignore strange trailing nul before reading response */ if(read(fd, &c, 1)==-1){ warn("read"); return 1; } i = 0; if(c==0) goto check; else goto loop; } return 0; }