chiark / gitweb /
debian: Add libcdb-dev to Build-Depends.
[misc] / xtitle.c
1 #include <errno.h>
2 #include <unistd.h>
3 #include <termios.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <fcntl.h>
8
9 int main(int argc, char *argv[])
10 {
11   int query = 0;
12   int fd;
13   int openned = 0;
14   int i;
15
16   for (;;) {
17     i = getopt(argc, argv, "q");
18     if (i < 0)
19       break;
20     switch (i) {
21       case 'q':
22         query = 1;
23         break;
24       default:
25         fprintf(stderr, "usage: xtitle [-q] [STRING]\n");
26         return (1);
27     }
28   }
29
30   if (!query && optind == argc) {
31     fprintf(stderr, "xtitle: no string to set\n");
32     return (1);
33   }
34
35   {
36     char *t = getenv("TERM");
37     if (!t || strncmp(t, "xterm", 5))
38       return (0);
39   }
40
41   if (isatty(0))
42     fd = 0;
43   else {
44     fd = open("/dev/tty", O_RDWR);
45     if (fd < 0) {
46       fprintf(stderr, "xtitle: couldn't open terminal: %s", strerror(errno));
47       return (1);
48     }
49     openned = 1;
50   }
51
52   if (!query) {
53     char sp = ' ';
54     write(fd, "\33]0;", 4);
55     for (i = optind; i < argc; i++) {
56       write(fd, argv[i], strlen(argv[i]));
57       if (i < argc - 1)
58         write(fd, &sp, 1);
59     }
60     write(fd, "\7", 2);
61   } else {
62     struct termios o, n;
63     char hack;
64     int state = 0;
65
66     tcgetattr(fd, &o);
67     n = o;
68     n.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
69                    |INLCR|IGNCR|ICRNL|IXON);
70     n.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
71     n.c_cflag &= ~(CSIZE|PARENB);
72     n.c_cflag |= CS8;
73     tcsetattr(fd, TCSAFLUSH, &n);
74     write(fd, "\33[21t", 5);
75
76     while (state != -1) {
77       if (read(fd, &hack, 1) < 1)
78         break;
79       switch (state) {
80         case 0:
81           if (hack == '\33') state = 1;
82           break;
83         case 1:
84           if (hack == ']') state = 2; else state = 0;
85           break;
86         case 2:
87           if (hack == 'l') state = 3; else state = 0;
88           break;
89         case 3:
90           if (hack == '\33') state = 4; else putchar(hack);
91           break;
92         case 4:
93           if (hack == '\\') { state = -1; putchar('\n'); }
94           else { putchar('\33'); putchar(hack); state = 3; }
95           break;
96       }
97     }
98
99     tcsetattr(fd, TCSAFLUSH, &o);
100   }
101
102   if (openned)
103     close(fd);
104
105   return (0);
106 }