1 /*
2 * Process in-band messages about window title changes.
3 * The messages are of the form:
4 *
5 * \033];xxx\007
6 *
7 * where xxx is the new directory. This format was chosen
8 * because it changes the label on xterm windows.
9 */
10
11 #include <u.h>
12 #include <libc.h>
13
14 struct {
15 char *file;
16 char name[512];
17 } keep[] = {
18 { "/dev/label" },
19 { "/dev/wdir" }
20 };
21
22 char *prog = "/bin/rwd";
23
24 void
usage(void)25 usage(void)
26 {
27 fprint(2, "usage: conswdir [/bin/rwd]\n");
28 exits("usage");
29 }
30
31 void
save(void)32 save(void)
33 {
34 int i, fd;
35 for(i = 0; i < nelem(keep); i++){
36 *keep[i].name = 0;
37 if((fd = open(keep[i].file, OREAD)) != -1){
38 read(fd, keep[i].name, sizeof(keep[i].name));
39 close(fd);
40 }
41 }
42 }
43
44 void
rest(void)45 rest(void)
46 {
47 int i, fd;
48 for(i = 0; i < nelem(keep); i++)
49 if((fd = open(keep[i].file, OWRITE)) != -1){
50 write(fd, keep[i].name, strlen(keep[i].name));
51 close(fd);
52 }
53
54 }
55
56 void
setpath(char * s)57 setpath(char *s)
58 {
59 switch(rfork(RFPROC|RFFDG|RFNOWAIT)){
60 case 0:
61 execl(prog, prog, s, nil);
62 _exits(nil);
63 }
64 }
65
66 enum
67 {
68 None,
69 Esc,
70 Brack,
71 Semi,
72 Bell,
73 };
74
75 int
process(char * buf,int n,int * pn)76 process(char *buf, int n, int *pn)
77 {
78 char *p;
79 char path[4096];
80 int start, state;
81
82 start = 0;
83 state = None;
84 for(p=buf; p<buf+n; p++){
85 switch(state){
86 case None:
87 if(*p == '\033'){
88 start = p-buf;
89 state++;
90 }
91 break;
92 case Esc:
93 if(*p == ']')
94 state++;
95 else
96 state = None;
97 break;
98 case Brack:
99 if(*p == ';')
100 state++;
101 else
102 state = None;
103 break;
104 case Semi:
105 if(*p == '\007')
106 state++;
107 else if((uchar)*p < 040)
108 state = None;
109 break;
110 }
111 if(state == Bell){
112 memmove(path, buf+start+3, p - (buf+start+3));
113 path[p-(buf+start+3)] = 0;
114 p++;
115 memmove(buf+start, p, n-(p-buf));
116 n -= p-(buf+start);
117 p = buf+start;
118 p--;
119 start = 0;
120 state = None;
121 setpath(path);
122 }
123 }
124 /* give up if we go too long without seeing the close */
125 *pn = n;
126 if(state == None || p-(buf+start) >= 2048)
127 return (p - buf);
128 else
129 return start;
130 }
131
132 static void
catchint(void *,char * msg)133 catchint(void*, char *msg)
134 {
135 if(strstr(msg, "interrupt"))
136 noted(NCONT);
137 else if(strstr(msg, "kill"))
138 noted(NDFLT);
139 else
140 noted(NCONT);
141 }
142
143 void
main(int argc,char ** argv)144 main(int argc, char **argv)
145 {
146 char buf[4096];
147 int n, m;
148
149 notify(catchint);
150
151 ARGBEGIN{
152 default:
153 usage();
154 }ARGEND
155
156 if(argc > 1)
157 usage();
158 if(argc == 1)
159 prog = argv[0];
160
161 save();
162 n = 0;
163 for(;;){
164 m = read(0, buf+n, sizeof buf-n);
165 if(m < 0){
166 rerrstr(buf, sizeof buf);
167 if(strstr(buf, "interrupt"))
168 continue;
169 break;
170 }
171 n += m;
172 m = process(buf, n, &n);
173 if(m > 0){
174 write(1, buf, m);
175 memmove(buf, buf+m, n-m);
176 n -= m;
177 }
178 }
179 rest();
180 exits(nil);
181 }
182