#include <9pm/u.h> #include <9pm/libc.h> #include <9pm/ns.h> #include <9pm/thread.h> #include <9pm/threadimpl.h> /* * Make sure that file descriptors 0, 1, and 2 have valid c->sysfd * equivalents, so that we can use them if we exec. We use system * pipes and extra copying processes; it's not exact but it's as close * as you're going to get. It means that this is not appropriate when * we depend on knowing when the exec'ed process is actually reading * (for example, a rio window behaves differently when the /dev/cons * it provides is being read from or not; thus we can't easily provide rio). * * On Windows, we can only specify three file descriptors: * stdin, stdout, and stderr. For consistency, we silently * close all but the first three file descriptors, on all platforms. */ static void copyproc(void *a) { int from, to; struct {int from; int to; Channel *c;} *s; char buf[8192]; int i, n; _threadgetproc()->nowait = 1; s = a; from = s->from; to = s->to; rfork(RFFDG); sendul(s->c, 0); for(i=0; i<3+6; i++) if(i!=from && i!=to) close(i); while((n = read(from, buf, sizeof buf)) > 0) write(to, buf, n); } static void bugger(Fgrp *f) { int i; /* make sure first three fds are not viewed as available by pipe() */ for(i=0; i<3; i++) if(f->fd[i] == nil) f->fd[i] = (Chan*)~0; } static void unbugger(Fgrp *f) { int i; for(i=0; i<3; i++) if(f->fd[i] == (Chan*)~0) f->fd[i] = nil; } int _threadfdcoherence(void) { int i, closefd, copyfd, fd[2], m, ret; Chan *c; struct {int from; int to; Channel *c;} s; Proc *p; Fgrp *f; rfork(RFFDG); /* * We now have our own file descriptor table, so holding * locks should be unnecessary: no one will modify it under us. * (Holding locks is counterproductive, since close et al. will * try to acquire them.) */ p = getproc(); f = p->fgrp; m = f->maxfd; if(m==0) return 0; assert(m>=3); /* mchan grows by chunks of DELTAFD >= 3 (currently 20) */ for(i=3; ifd[i]; if(c == nil) continue; if(issysfd(c)) continue; bugger(f); if(pipe(fd) < 0){ ret = -1; unbugger(f); continue; } unbugger(f); if(i==0){ s.from = i; s.to = fd[1]; closefd = fd[1]; copyfd = fd[0]; }else{ s.from = fd[0]; s.to = i; closefd = fd[0]; copyfd = fd[1]; } proccreate(copyproc, &s, 10240); recvul(s.c); close(closefd); dup(copyfd, i); close(copyfd); } chanfree(s.c); return ret; }