URI: 
       tlibthread: add threadspawnd - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 9e4b56e7645e08311590355824863ecf9f334f0c
   DIR parent 81c2c5e775d83896f25981cf4c4e486c5cc91180
  HTML Author: Russ Cox <rsc@swtch.com>
       Date:   Mon, 22 Oct 2012 12:32:09 -0400
       
       libthread: add threadspawnd
       
       R=rsc
       http://codereview.appspot.com/6742064
       
       Diffstat:
         M include/thread.h                    |       1 +
         M man/man3/thread.3                   |      11 +++++++++++
         M src/libthread/exec.c                |      17 +++++++++++++----
         M src/libthread/threadimpl.h          |       5 +++--
       
       4 files changed, 28 insertions(+), 6 deletions(-)
       ---
   DIR diff --git a/include/thread.h b/include/thread.h
       t@@ -175,6 +175,7 @@ long                iowrite(Ioproc *io, int fd, void *a, long n);
        void                threadexec(Channel*, int[3], char*, char *[]);
        void                threadexecl(Channel*, int[3], char*, ...);
        int                threadspawn(int[3], char*, char*[]);
       +int                threadspawnd(int[3], char*, char*[], char*);
        int                threadspawnl(int[3], char*, ...);
        Channel*        threadwaitchan(void);
        
   DIR diff --git a/man/man3/thread.3 b/man/man3/thread.3
       t@@ -42,6 +42,7 @@ threadsetgrp,
        threadsetname,
        threadsetstate,
        threadspawn,
       +threadspawnd,
        threadspawnl,
        threadwaitchan,
        yield \- thread and proc management
       t@@ -124,6 +125,7 @@ int        chanprint(Channel *c, char *fmt, ...)
        .XX
        int        threadspawnl(int fd[3], char *file, ...)
        int        threadspawn(int fd[3], char *file, char *args[])
       +int        threadspawnd(int fd[3], char *file, char *args[], char *dir)
        int        threadexecl(Channel *cpid, int fd[3], char *file, ...)
        int        threadexec(Channel *cpid, int fd[3], char *file, char *args[])
        Channel*        threadwaitchan(void)
       t@@ -240,6 +242,8 @@ Calls that do this are
        .IR threadexecl ,
        .IR threadexits ,
        .IR threadspawn ,
       +.IR threadspawnd ,
       +.IR threadspawnl ,
        .IR alt ,
        .IR send ,
        and
       t@@ -419,6 +423,13 @@ and
        but do not replace the current thread.
        They return the pid of the invoked program on success, or
        \-1 on error.
       +.I Threadspawnd
       +is like
       +.I threadspawn
       +but takes as its final argument the directory in which to run the invoked program.
       +The child will attempt to change into that directory before running the program,
       +but it is only best effort: failure to change into the directory does not
       +stop the running of the program.
        .PP
        .I Threadwaitchan
        returns a channel of pointers to
   DIR diff --git a/src/libthread/exec.c b/src/libthread/exec.c
       t@@ -12,7 +12,7 @@ execproc(void *v)
                Waitmsg *w;
        
                e = v;
       -        pid = _threadspawn(e->fd, e->cmd, e->argv);
       +        pid = _threadspawn(e->fd, e->cmd, e->argv, e->dir);
                sendul(e->c, pid);
                if(pid > 0){
                        w = waitfor(pid);
       t@@ -25,7 +25,7 @@ execproc(void *v)
        }
        
        int
       -_runthreadspawn(int *fd, char *cmd, char **argv)
       +_runthreadspawn(int *fd, char *cmd, char **argv, char *dir)
        {
                int pid;
                Execjob e;
       t@@ -33,6 +33,7 @@ _runthreadspawn(int *fd, char *cmd, char **argv)
                e.fd = fd;
                e.cmd = cmd;
                e.argv = argv;
       +        e.dir = dir;
                e.c = chancreate(sizeof(void*), 0);
                proccreate(execproc, &e, 65536);
                pid = recvul(e.c);
       t@@ -57,7 +58,7 @@ threadwaitchan(void)
        }
        
        int
       -_threadspawn(int fd[3], char *cmd, char *argv[])
       +_threadspawn(int fd[3], char *cmd, char *argv[], char *dir)
        {
                int i, n, p[2], pid;
                char exitstr[100];
       t@@ -77,6 +78,8 @@ _threadspawn(int fd[3], char *cmd, char *argv[])
                        return -1;
                case 0:
                        /* can't RFNOTEG - will lose tty */
       +                if(dir != nil )
       +                        chdir(dir); /* best effort */
                        dup2(fd[0], 0);
                        dup2(fd[1], 1);
                        dup2(fd[2], 2);
       t@@ -112,7 +115,13 @@ _threadspawn(int fd[3], char *cmd, char *argv[])
        int
        threadspawn(int fd[3], char *cmd, char *argv[])
        {
       -        return _runthreadspawn(fd, cmd, argv);
       +        return _runthreadspawn(fd, cmd, argv, nil);
       +}
       +
       +int
       +threadspawnd(int fd[3], char *cmd, char *argv[], char *dir)
       +{
       +        return _runthreadspawn(fd, cmd, argv, dir);
        }
        
        int
   DIR diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
       t@@ -121,6 +121,7 @@ struct Execjob
                int *fd;
                char *cmd;
                char **argv;
       +        char *dir;
                Channel *c;
        };
        
       t@@ -203,8 +204,8 @@ extern void _threadsetproc(Proc*);
        extern int _threadlock(Lock*, int, ulong);
        extern void _threadunlock(Lock*, ulong);
        extern void _pthreadinit(void);
       -extern int _threadspawn(int*, char*, char**);
       -extern int _runthreadspawn(int*, char*, char**);
       +extern int _threadspawn(int*, char*, char**, char*);
       +extern int _runthreadspawn(int*, char*, char**, char*);
        extern void _threadsetupdaemonize(void);
        extern void _threaddodaemonize(char*);
        extern void _threadpexit(void);