diff -r e08745605692 sys/include/thread.h --- a/sys/include/thread.h Mon Nov 14 00:00:00 2011 +0100 +++ b/sys/include/thread.h Sun Nov 20 00:00:00 2011 +0100 @@ -98,6 +98,8 @@ void threadkillgrp(int); /* kill threads in group */ void threadmain(int argc, char *argv[]); void threadnonotes(void); +int threadspawn(int[3], char*, char*[]); +int threadspawnl(int[3], char*, ...); int threadnotify(int (*f)(void*, char*), int in); int threadid(void); int threadpid(int); diff -r e08745605692 sys/man/2/thread --- a/sys/man/2/thread Mon Nov 14 00:00:00 2011 +0100 +++ b/sys/man/2/thread Sun Nov 20 00:00:00 2011 +0100 @@ -41,6 +41,8 @@ threadpid, threadsetgrp, threadsetname, +threadspawn, +threadspawnl, threadwaitchan, yield \- thread and proc management .SH SYNOPSIS @@ -128,6 +130,8 @@ int chanclose(Channel *c); int chanclosing(Channel *c); .XX +int threadspawnl(int fd[3], char *file, ...) +int threadspawn(int fd[3], char *file, char *args[]) void procexecl(Channel *cpid, char *file, ...) void procexec(Channel *cpid, char *file, char *args[]) Channel* threadwaitchan(void) @@ -237,6 +241,7 @@ .IR procexec , .IR procexecl , .IR threadexits , +.IR threadspawn , .IR alt , .IR send , and @@ -362,6 +367,17 @@ .I procexec(l) mount pipes there. .PP +.I Threadspawnl +and +.I threadspawn +are like +.I threadexecl +and +.I threadexec +but do not replace the current thread. +They return the pid of the invoked program on success, or +\-1 on error. +.PP .I Threadwaitchan returns a channel of pointers to .B Waitmsg diff -r e08745605692 sys/src/libthread/exec.c --- a/sys/src/libthread/exec.c Mon Nov 14 00:00:00 2011 +0100 +++ b/sys/src/libthread/exec.c Sun Nov 20 00:00:00 2011 +0100 @@ -78,3 +78,63 @@ procexec(pidc, f, &f+1); } +static void +execproc(void *v) +{ + Execjob *e; + + e = v; + rfork(RFFDG); + dup(e->fd[0], 0); + dup(e->fd[1], 1); + dup(e->fd[2], 2); + procexec(e->c, e->cmd, e->argv); + threadexits(nil); +} + +int +threadspawn(int fd[3], char *cmd, char *argv[]) +{ + int pid; + Execjob e; + + e.fd = fd; + e.cmd = cmd; + e.argv = argv; + e.c = chancreate(sizeof(void*), 0); + proccreate(execproc, &e, 65536); + close(fd[0]); + close(fd[1]); + close(fd[2]); + pid = recvul(e.c); + chanfree(e.c); + return pid; +} + +int +threadspawnl(int fd[3], char *cmd, ...) +{ + char **argv, *s; + int n, pid; + va_list arg; + + va_start(arg, cmd); + for(n=0; va_arg(arg, char*) != nil; n++) + ; + n++; + va_end(arg); + + argv = malloc(n*sizeof(argv[0])); + if(argv == nil) + return -1; + + va_start(arg, cmd); + for(n=0; (s=va_arg(arg, char*)) != nil; n++) + argv[n] = s; + argv[n] = 0; + va_end(arg); + + pid = threadspawn(fd, cmd, argv); + free(argv); + return pid; +} diff -r e08745605692 sys/src/libthread/threadimpl.h --- a/sys/src/libthread/threadimpl.h Mon Nov 14 00:00:00 2011 +0100 +++ b/sys/src/libthread/threadimpl.h Sun Nov 20 00:00:00 2011 +0100 @@ -24,6 +24,7 @@ typedef struct Tqueue Tqueue; typedef struct Thread Thread; typedef struct Execargs Execargs; +typedef struct Execjob Execjob; typedef struct Proc Proc; /* must match list in sched.c */ @@ -101,6 +102,14 @@ int fd[2]; }; +struct Execjob +{ + int *fd; + char *cmd; + char **argv; + Channel *c; +}; + struct Proc { Lock lock;