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