#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/ns.h>
#include <9pm/thread.h>
#include <9pm/threadimpl.h>
Channel *_threadwaitchan;
void
procexec(Channel *pidc, char *f, char *args[])
{
char *q;
int l, n, pid, s;
Dir *d;
Execproc *ep;
Tproc *p;
_threaddebug(DBGPROC, "procexec %s", f);
/* make sure exec is likely to succeed before tossing thread state */
d = dirstat(f);
if(d == nil || (d->mode & DMDIR)/* || access(f, AEXEC) < 0*/) {
_threaddebug(DBGPROC, "cannot find program %s", f);
free(d);
bad: if (pidc) sendul(pidc, ~0);
return;
}
free(d);
p = _threadgetproc();
if(p->threads.head != p->curthread || p->threads.head->nextt != nil)
goto bad;
/* committed to exec-ing */
_threadfdcoherence();
n = 0;
while (args[n++])
;
ep = &p->execproc;
q = ep->data;
s = sizeof(ep->data);
if ((l = n*sizeof(char *)) < s) {
_threaddebug(DBGPROC, "args on stack, %d pointers", n);
ep->arg = (char **)q;
q += l;
s -= l;
} else
ep->arg = _threadmalloc(l, 0); /* will be leaked */
if ((l = strlen(f) + 1) < s) {
ep->file = q;
strcpy(q, f);
_threaddebug(DBGPROC, "file on stack, %s", q);
q += l;
s -= l;
} else
ep->file = strdup(f); /* will be leaked */
ep->arg[--n] = nil;
while (--n >= 0)
if ((l = strlen(args[n]) + 1) < s) {
ep->arg[n] = q;
strcpy(q, args[n]);
_threaddebug(DBGPROC, "arg on stack, %s", q);
q += l;
s -= l;
} else
ep->arg[n] = strdup(args[n]); /* will be leaked */
p->arg = ep;
pid = _threadswtch(p->curthread->env, p->oldenv, DOEXEC);
close(0);
close(1);
/* 3 and up are already closed from fdcoherence */
if(pidc != nil)
sendul(pidc, pid);
_procexecwait(pid);
_threaddebug(DBGPROC, "Exiting (exec)");
_threadgetproc()->nowait = 1;
threadexits("libthread procexec");
}
void
procexecl(Channel *pidc, char *f, ...)
{
procexec(pidc, f, &f+1);
}
Channel*
threadwaitchan(void)
{
_threadwaitchan = chancreate(sizeof(Waitmsg*), 0);
return _threadwaitchan;
}
syntax highlighted by Code2HTML, v. 0.9.1