#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; }