/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * Process in-band messages about window title changes. * The messages are of the form: * * \033];xxx\007 * * where xxx is the new directory. This format was chosen * because it changes the label on xterm windows. */ #include <u.h>#include <libc.h> struct { char *file; char name[512];} keep[] = { { "/dev/label" }, { "/dev/wdir" }}; char *prog = "/bin/rwd"; voidusage(void){ fprint(2, "usage: conswdir [/bin/rwd]\n"); exits("usage");} voidsave(void){ int i, fd; for(i = 0; i < nelem(keep); i++){ *keep[i].name = 0; if((fd = open(keep[i].file, OREAD)) != -1){ read(fd, keep[i].name, sizeof(keep[i].name)); close(fd); } }} voidrest(void){ int i, fd; for(i = 0; i < nelem(keep); i++) if((fd = open(keep[i].file, OWRITE)) != -1){ write(fd, keep[i].name, strlen(keep[i].name)); close(fd); } } voidsetpath(char *s){ switch(rfork(RFPROC|RFFDG|RFNOWAIT)){ case 0: execl(prog, prog, s, nil); _exits(nil); }} enum{ None, Esc, Brack, Semi, Bell,}; intprocess(char *buf, int n, int *pn){ char *p; char path[4096]; int start, state; start = 0; state = None; for(p=buf; p<buf+n; p++){ switch(state){ case None: if(*p == '\033'){ start = p-buf; state++; } break; case Esc: if(*p == ']') state++; else state = None; break; case Brack: if(*p == ';') state++; else state = None; break; case Semi: if(*p == '\007') state++; else if((uchar)*p < 040) state = None; break; } if(state == Bell){ memmove(path, buf+start+3, p - (buf+start+3)); path[p-(buf+start+3)] = 0; p++; memmove(buf+start, p, n-(p-buf)); n -= p-(buf+start); p = buf+start; p--; start = 0; state = None; setpath(path); } } /* give up if we go too long without seeing the close */ *pn = n; if(state == None || p-(buf+start) >= 2048) return (p - buf); else return start;} static voidcatchint(void*, char *msg){ if(strstr(msg, "interrupt")) noted(NCONT); else if(strstr(msg, "kill")) noted(NDFLT); else noted(NCONT);} voidmain(int argc, char **argv){ char buf[4096]; int n, m; notify(catchint); ARGBEGIN{ default: usage(); }ARGEND if(argc > 1) usage(); if(argc == 1) prog = argv[0]; save(); n = 0; for(;;){ m = read(0, buf+n, sizeof buf-n); if(m < 0){ rerrstr(buf, sizeof buf); if(strstr(buf, "interrupt")) continue; break; } n += m; m = process(buf, n, &n); if(m > 0){ write(1, buf, m); memmove(buf, buf+m, n-m); n -= m; } } rest(); exits(nil);}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
/*
* Process in-band messages about window title changes.
* The messages are of the form:
*
* \033];xxx\007
*
* where xxx is the new directory. This format was chosen
* because it changes the label on xterm windows.
*/
#include <u.h>
#include <libc.h>
struct {
char *file;
char name[512];
} keep[] = {
{ "/dev/label" },
{ "/dev/wdir" }
};
char *prog = "/bin/rwd";
void
usage(void)
{
fprint(2, "usage: conswdir [/bin/rwd]\n");
exits("usage");
}
void
save(void)
{
int i, fd;
for(i = 0; i < nelem(keep); i++){
*keep[i].name = 0;
if((fd = open(keep[i].file, OREAD)) != -1){
read(fd, keep[i].name, sizeof(keep[i].name));
close(fd);
}
}
}
void
rest(void)
{
int i, fd;
for(i = 0; i < nelem(keep); i++)
if((fd = open(keep[i].file, OWRITE)) != -1){
write(fd, keep[i].name, strlen(keep[i].name));
close(fd);
}
}
void
setpath(char *s)
{
switch(rfork(RFPROC|RFFDG|RFNOWAIT)){
case 0:
execl(prog, prog, s, nil);
_exits(nil);
}
}
enum
{
None,
Esc,
Brack,
Semi,
Bell,
};
int
process(char *buf, int n, int *pn)
{
char *p;
char path[4096];
int start, state;
start = 0;
state = None;
for(p=buf; p<buf+n; p++){
switch(state){
case None:
if(*p == '\033'){
start = p-buf;
state++;
}
break;
case Esc:
if(*p == ']')
state++;
else
state = None;
break;
case Brack:
if(*p == ';')
state++;
else
state = None;
break;
case Semi:
if(*p == '\007')
state++;
else if((uchar)*p < 040)
state = None;
break;
}
if(state == Bell){
memmove(path, buf+start+3, p - (buf+start+3));
path[p-(buf+start+3)] = 0;
p++;
memmove(buf+start, p, n-(p-buf));
n -= p-(buf+start);
p = buf+start;
p--;
start = 0;
state = None;
setpath(path);
}
}
/* give up if we go too long without seeing the close */
*pn = n;
if(state == None || p-(buf+start) >= 2048)
return (p - buf);
else
return start;
}
static void
catchint(void*, char *msg)
{
if(strstr(msg, "interrupt"))
noted(NCONT);
else if(strstr(msg, "kill"))
noted(NDFLT);
else
noted(NCONT);
}
void
main(int argc, char **argv)
{
char buf[4096];
int n, m;
notify(catchint);
ARGBEGIN{
default:
usage();
}ARGEND
if(argc > 1)
usage();
if(argc == 1)
prog = argv[0];
save();
n = 0;
for(;;){
m = read(0, buf+n, sizeof buf-n);
if(m < 0){
rerrstr(buf, sizeof buf);
if(strstr(buf, "interrupt"))
continue;
break;
}
n += m;
m = process(buf, n, &n);
if(m > 0){
write(1, buf, m);
memmove(buf, buf+m, n-m);
n -= m;
}
}
rest();
exits(nil);
}