Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <thread.h>
4
#include "threadimpl.h"
5
 
6
#define PIPEMNT	"/mnt/temp"
7
 
8
void
9
procexec(Channel *pidc, char *prog, char *args[])
10
{
11
	int n;
12
	Proc *p;
13
	Thread *t;
14
 
15
	_threaddebug(DBGEXEC, "procexec %s", prog);
16
	/* must be only thread in proc */
17
	p = _threadgetproc();
18
	t = p->thread;
19
	if(p->threads.head != t || p->threads.head->nextt != nil){
20
		werrstr("not only thread in proc");
21
	Bad:
22
		if(pidc)
23
			sendul(pidc, ~0);
24
		return;
25
	}
26
 
27
	/*
28
	 * We want procexec to behave like exec; if exec succeeds,
29
	 * never return, and if it fails, return with errstr set.
30
	 * Unfortunately, the exec happens in another proc since
31
	 * we have to wait for the exec'ed process to finish.
32
	 * To provide the semantics, we open a pipe with the 
33
	 * write end close-on-exec and hand it to the proc that
34
	 * is doing the exec.  If the exec succeeds, the pipe will
35
	 * close so that our read below fails.  If the exec fails,
36
	 * then the proc doing the exec sends the errstr down the
37
	 * pipe to us.
38
	 */
39
	if(bind("#|", PIPEMNT, MREPL) < 0)
40
		goto Bad;
41
	if((p->exec.fd[0] = open(PIPEMNT "/data", OREAD)) < 0){
42
		unmount(nil, PIPEMNT);
43
		goto Bad;
44
	}
45
	if((p->exec.fd[1] = open(PIPEMNT "/data1", OWRITE|OCEXEC)) < 0){
46
		close(p->exec.fd[0]);
47
		unmount(nil, PIPEMNT);
48
		goto Bad;
49
	}
50
	unmount(nil, PIPEMNT);
51
 
52
	/* exec in parallel via the scheduler */
53
	assert(p->needexec==0);
54
	p->exec.prog = prog;
55
	p->exec.args = args;
56
	p->needexec = 1;
57
	_sched();
58
 
59
	close(p->exec.fd[1]);
60
	if((n = read(p->exec.fd[0], p->exitstr, ERRMAX-1)) > 0){	/* exec failed */
61
		p->exitstr[n] = '\0';
62
		errstr(p->exitstr, ERRMAX);
63
		close(p->exec.fd[0]);
64
		goto Bad;
65
	}
66
	close(p->exec.fd[0]);
67
 
68
	if(pidc)
69
		sendul(pidc, t->ret);
70
 
71
	/* wait for exec'ed program, then exit */
72
	_schedexecwait();
73
}
74
 
75
void
76
procexecl(Channel *pidc, char *f, ...)
77
{
78
	procexec(pidc, f, &f+1);
79
}
80