#include <u.h>
#include <libc.h>
/*
* create a remote inferno window to run a local plan 9 command.
* -r option creates a graphical window.
* interacts with newwinsrv (as in /n/rwin)
*/
void rmtnoteproc(int);
void execp(char **);
char *shcmd[] = {"/bin/rc", "-i", nil};
char *riocmd[] = {"/bin/rio", nil};
char **cmd = shcmd;
void
main(int argc, char **argv)
{
int ctlfd, fd, n, fd0, fd1, fd2, rio;
char buf[20], dir[50], path[70], *kind;
rio = 0;
ARGBEGIN{
case 'r':
rio = 1;
cmd = riocmd;
break;
default:
fprint(2, "usage: iwin [-r] [cmd [arg...]]\n");
exits("usage");
}ARGEND
if(argc > 0)
cmd = argv;
fd = open("/mnt/term/n/rwin/new", ORDWR);
if(fd == -1){
fprint(2, "iwin: no window creation service available\n");
exits("error");
}
if(fprint(fd, "%s", rio?"rio":"sh") == -1){
fprint(2, "iwin: cannot create window: %r\n");
exits("error");
}
n = pread(fd, buf, sizeof buf - 1, 0);
if(n <= 0){
fprint(2, "iwin: bad window directory\n");
exits("error");
}
buf[n] = 0;
snprint(dir, sizeof dir, "/mnt/term/n/rwin/%s", buf);
fprint(2, "win directory %s\n", dir);
if(fork())
exits(nil);
rfork(RFNAMEG|RFFDG);
if(!rio){
snprint(path, sizeof path, "%s/shctl", dir);
ctlfd = open(path, ORDWR);
if(ctlfd == -1)
fprint(2, "cannot open %s: %r\n", path);
fprint(ctlfd, "action Interrupt interrupt");
rmtnoteproc(ctlfd);
}
bind(dir, "/dev", MBEFORE);
close(0);
close(1);
close(2);
fd0 = open("/dev/cons", OREAD|ORCLOSE);
fd1 = open("/dev/cons", OWRITE);
fd2 = open("/dev/cons", OWRITE);
execp(cmd);
fprint(2, "failed to exec %s: %r\n", cmd[0]);
}
void
execp(char **argv)
{
char *p;
char *path;
p = argv[0];
if(p[0] == '.' && p[1] == '/' || p[0] == '/')
exec(p, argv);
else{
path = malloc(strlen(p)+6);
sprint(path, "/bin/%s", p);
exec(path, argv);
exec(p, argv);
}
}
/*
* loop reading /mnt/term/dev/note looking for notes.
* The child returns to start the shell.
*
* taken verbatim from /sys/src/cmd/cpu.c
*/
void
rmtnoteproc(int fd)
{
int n, pid, notepid;
char buf[256];
/* new proc returns to start shell */
pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM);
switch(pid){
case -1:
syslog(0, "cpu", "cpu -R: can't start noteproc: %r");
return;
case 0:
return;
}
/* new proc reads notes from other side and posts them to shell */
switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){
case -1:
syslog(0, "cpu", "cpu -R: can't start wait proc: %r");
_exits(0);
case 0:
for(;;){
n = read(fd, buf, sizeof(buf)-1);
if(n <= 0){
postnote(PNGROUP, pid, "hangup");
_exits(0);
}
buf[n] = 0;
postnote(PNGROUP, pid, buf);
}
break;
}
/* original proc waits for shell proc to die and kills note proc */
for(;;){
n = waitpid();
if(n < 0 || n == pid)
break;
}
postnote(PNPROC, notepid, "kill");
_exits(0);
}
|