#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; i<m; i++)
close(i);
ret = 0;
s.c = chancreate(sizeof(ulong), 0);
for(i=0; i<3; i++){
c = f->fd[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;
}
syntax highlighted by Code2HTML, v. 0.9.1