xref: /plan9/sys/src/cmd/aux/conswdir.c (revision 208510e168b9c00c3c6969f56b807dc03575167d)
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