#include #include /* * 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); }