Commit Diff


commit - 81c2c5e775d83896f25981cf4c4e486c5cc91180
commit + 9e4b56e7645e08311590355824863ecf9f334f0c
blob - 43c35bf3e9e6e89e76632ae44268564e26653798
blob + c01cd5166a40360c20712ac806afa4a5e69bedf5
--- include/thread.h
+++ include/thread.h
@@ -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);
 
blob - 7f5cd69c50fbde91172a2cb4646359fe20595ec4
blob + 0ebbddd0a421a959ff09aa141da9bf9195d19154
--- man/man3/thread.3
+++ man/man3/thread.3
@@ -42,6 +42,7 @@ threadsetgrp,
 threadsetname,
 threadsetstate,
 threadspawn,
+threadspawnd,
 threadspawnl,
 threadwaitchan,
 yield \- thread and proc management
@@ -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)
@@ -240,6 +242,8 @@ Calls that do this are
 .IR threadexecl ,
 .IR threadexits ,
 .IR threadspawn ,
+.IR threadspawnd ,
+.IR threadspawnl ,
 .IR alt ,
 .IR send ,
 and
@@ -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
blob - 1875eb98a5ae1ea839405bce0674562db630b7ca
blob + 62805ba282d15a825403cb516e379f6fd3a3602b
--- src/libthread/exec.c
+++ src/libthread/exec.c
@@ -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);
@@ -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;
@@ -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);
@@ -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];
@@ -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);
@@ -112,10 +115,16 @@ _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
 threadspawnl(int fd[3], char *cmd, ...)
 {
 	char **argv, *s;
blob - 9518f785e5abb9b8c09e6b50c1d1ae4f9a0d5b38
blob + 144a2136b1687b2501ec3dbb3ca9af1109c1b168
--- src/libthread/threadimpl.h
+++ src/libthread/threadimpl.h
@@ -121,6 +121,7 @@ struct Execjob
 	int *fd;
 	char *cmd;
 	char **argv;
+	char *dir;
 	Channel *c;
 };
 
@@ -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);