Update.
[glibc.git] / hurd / hurdexec.c
blob2a283563b8ee373e2f298bad9200a81658262b02
1 /* Copyright (C) 1991,92,93,94,95,96,97,99 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #include <errno.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <limits.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <hurd.h>
26 #include <hurd/fd.h>
27 #include <hurd/signal.h>
28 #include <assert.h>
29 #include <argz.h>
31 /* Overlay TASK, executing FILE with arguments ARGV and environment ENVP.
32 If TASK == mach_task_self (), some ports are dealloc'd by the exec server.
33 ARGV and ENVP are terminated by NULL pointers. */
34 error_t
35 _hurd_exec (task_t task, file_t file,
36 char *const argv[], char *const envp[])
38 error_t err;
39 char *args, *env;
40 size_t argslen, envlen;
41 int ints[INIT_INT_MAX];
42 mach_port_t ports[_hurd_nports];
43 struct hurd_userlink ulink_ports[_hurd_nports];
44 file_t *dtable;
45 unsigned int dtablesize, i;
46 struct hurd_port **dtable_cells;
47 struct hurd_userlink *ulink_dtable;
48 struct hurd_sigstate *ss;
49 mach_port_t *please_dealloc, *pdp;
51 /* XXX needs to be hurdmalloc XXX */
52 if (argv == NULL)
53 args = NULL, argslen = 0;
54 else if (err = __argz_create (argv, &args, &argslen))
55 return err;
56 if (envp == NULL)
57 env = NULL, envlen = 0;
58 else if (err = __argz_create (envp, &env, &envlen))
59 goto outargs;
61 /* Load up the ports to give to the new program. */
62 for (i = 0; i < _hurd_nports; ++i)
63 if (i == INIT_PORT_PROC && task != __mach_task_self ())
65 /* This is another task, so we need to ask the proc server
66 for the right proc server port for it. */
67 if (err = __USEPORT (PROC, __proc_task2proc (port, task, &ports[i])))
69 while (--i > 0)
70 _hurd_port_free (&_hurd_ports[i], &ulink_ports[i], ports[i]);
71 goto outenv;
74 else
75 ports[i] = _hurd_port_get (&_hurd_ports[i], &ulink_ports[i]);
78 /* Load up the ints to give the new program. */
79 for (i = 0; i < INIT_INT_MAX; ++i)
80 switch (i)
82 case INIT_UMASK:
83 ints[i] = _hurd_umask;
84 break;
86 case INIT_SIGMASK:
87 case INIT_SIGIGN:
88 case INIT_SIGPENDING:
89 /* We will set these all below. */
90 break;
92 case INIT_TRACEMASK:
93 ints[i] = _hurdsig_traced;
94 break;
96 default:
97 ints[i] = 0;
100 ss = _hurd_self_sigstate ();
102 assert (! __spin_lock_locked (&ss->critical_section_lock));
103 __spin_lock (&ss->critical_section_lock);
105 __spin_lock (&ss->lock);
106 ints[INIT_SIGMASK] = ss->blocked;
107 ints[INIT_SIGPENDING] = ss->pending;
108 ints[INIT_SIGIGN] = 0;
109 for (i = 1; i < NSIG; ++i)
110 if (ss->actions[i].sa_handler == SIG_IGN)
111 ints[INIT_SIGIGN] |= __sigmask (i);
113 /* We hold the sigstate lock until the exec has failed so that no signal
114 can arrive between when we pack the blocked and ignored signals, and
115 when the exec actually happens. A signal handler could change what
116 signals are blocked and ignored. Either the change will be reflected
117 in the exec, or the signal will never be delivered. Setting the
118 critical section flag avoids anything we call trying to acquire the
119 sigstate lock. */
121 __spin_unlock (&ss->lock);
123 /* Pack up the descriptor table to give the new program. */
124 __mutex_lock (&_hurd_dtable_lock);
126 dtablesize = _hurd_dtable ? _hurd_dtablesize : _hurd_init_dtablesize;
128 if (task == __mach_task_self ())
129 /* Request the exec server to deallocate some ports from us if the exec
130 succeeds. The init ports and descriptor ports will arrive in the
131 new program's exec_startup message. If we failed to deallocate
132 them, the new program would have duplicate user references for them.
133 But we cannot deallocate them ourselves, because we must still have
134 them after a failed exec call. */
135 please_dealloc = __alloca ((_hurd_nports + (2 * dtablesize))
136 * sizeof (mach_port_t));
137 else
138 please_dealloc = NULL;
139 pdp = please_dealloc;
141 if (_hurd_dtable != NULL)
143 dtable = __alloca (dtablesize * sizeof (dtable[0]));
144 ulink_dtable = __alloca (dtablesize * sizeof (ulink_dtable[0]));
145 dtable_cells = __alloca (dtablesize * sizeof (dtable_cells[0]));
146 for (i = 0; i < dtablesize; ++i)
148 struct hurd_fd *const d = _hurd_dtable[i];
149 if (d == NULL)
151 dtable[i] = MACH_PORT_NULL;
152 continue;
154 __spin_lock (&d->port.lock);
155 if (d->flags & FD_CLOEXEC)
157 /* This descriptor is marked to be closed on exec.
158 So don't pass it to the new program. */
159 dtable[i] = MACH_PORT_NULL;
160 if (pdp && d->port.port != MACH_PORT_NULL)
162 /* We still need to deallocate the ports. */
163 *pdp++ = d->port.port;
164 if (d->ctty.port != MACH_PORT_NULL)
165 *pdp++ = d->ctty.port;
167 __spin_unlock (&d->port.lock);
169 else
171 if (pdp && d->ctty.port != MACH_PORT_NULL)
172 /* All the elements of DTABLE are added to PLEASE_DEALLOC
173 below, so we needn't add the port itself.
174 But we must deallocate the ctty port as well as
175 the normal port that got installed in DTABLE[I]. */
176 *pdp++ = d->ctty.port;
177 dtable[i] = _hurd_port_locked_get (&d->port, &ulink_dtable[i]);
178 dtable_cells[i] = &d->port;
182 else
184 dtable = _hurd_init_dtable;
185 ulink_dtable = NULL;
186 dtable_cells = NULL;
189 /* The information is all set up now. Try to exec the file. */
192 if (pdp)
194 /* Request the exec server to deallocate some ports from us if the exec
195 succeeds. The init ports and descriptor ports will arrive in the
196 new program's exec_startup message. If we failed to deallocate
197 them, the new program would have duplicate user references for them.
198 But we cannot deallocate them ourselves, because we must still have
199 them after a failed exec call. */
201 for (i = 0; i < _hurd_nports; ++i)
202 *pdp++ = ports[i];
203 for (i = 0; i < dtablesize; ++i)
204 *pdp++ = dtable[i];
207 err = __file_exec (file, task, 0,
208 args, argslen, env, envlen,
209 dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
210 ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
211 ints, INIT_INT_MAX,
212 please_dealloc, pdp - please_dealloc,
213 &_hurd_msgport, task == __mach_task_self () ? 1 : 0);
216 /* Release references to the standard ports. */
217 for (i = 0; i < _hurd_nports; ++i)
218 if (i == INIT_PORT_PROC && task != __mach_task_self ())
219 __mach_port_deallocate (__mach_task_self (), ports[i]);
220 else
221 _hurd_port_free (&_hurd_ports[i], &ulink_ports[i], ports[i]);
223 if (ulink_dtable != NULL)
224 /* Release references to the file descriptor ports. */
225 for (i = 0; i < dtablesize; ++i)
226 if (dtable[i] != MACH_PORT_NULL)
227 _hurd_port_free (dtable_cells[i], &ulink_dtable[i], dtable[i]);
229 /* Release lock on the file descriptor table. */
230 __mutex_unlock (&_hurd_dtable_lock);
232 /* Safe to let signals happen now. */
233 _hurd_critical_section_unlock (ss);
235 outargs:
236 free (args);
237 outenv:
238 free (env);
239 return err;