(add_name_to_object): Don't translate strings.
[kopensolaris-gnu/glibc.git] / hurd / hurdexec.c
1 /* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
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.
8
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.
13
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.  */
18
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>
30
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[])
37 {
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;
50
51   /* XXX needs to be hurdmalloc XXX */
52   if (err = __argz_create (argv, &args, &argslen))
53     return err;
54   if (err = __argz_create (envp, &env, &envlen))
55     goto outargs;
56
57   /* Load up the ports to give to the new program.  */
58   for (i = 0; i < _hurd_nports; ++i)
59     if (i == INIT_PORT_PROC && task != __mach_task_self ())
60       {
61         /* This is another task, so we need to ask the proc server
62            for the right proc server port for it.  */
63         if (err = __USEPORT (PROC, __proc_task2proc (port, task, &ports[i])))
64           {
65             while (--i > 0)
66               _hurd_port_free (&_hurd_ports[i], &ulink_ports[i], ports[i]);
67             goto outenv;
68           }
69       }
70     else
71       ports[i] = _hurd_port_get (&_hurd_ports[i], &ulink_ports[i]);
72
73
74   /* Load up the ints to give the new program.  */
75   for (i = 0; i < INIT_INT_MAX; ++i)
76     switch (i)
77       {
78       case INIT_UMASK:
79         ints[i] = _hurd_umask;
80         break;
81
82       case INIT_SIGMASK:
83       case INIT_SIGIGN:
84       case INIT_SIGPENDING:
85         /* We will set these all below.  */
86         break;
87
88       case INIT_TRACEMASK:
89         ints[i] = _hurdsig_traced;
90         break;
91
92       default:
93         ints[i] = 0;
94       }
95
96   ss = _hurd_self_sigstate ();
97
98   assert (! __spin_lock_locked (&ss->critical_section_lock));
99   __spin_lock (&ss->critical_section_lock);
100
101   __spin_lock (&ss->lock);
102   ints[INIT_SIGMASK] = ss->blocked;
103   ints[INIT_SIGPENDING] = ss->pending;
104   ints[INIT_SIGIGN] = 0;
105   for (i = 1; i < NSIG; ++i)
106     if (ss->actions[i].sa_handler == SIG_IGN)
107       ints[INIT_SIGIGN] |= __sigmask (i);
108
109   /* We hold the sigstate lock until the exec has failed so that no signal
110      can arrive between when we pack the blocked and ignored signals, and
111      when the exec actually happens.  A signal handler could change what
112      signals are blocked and ignored.  Either the change will be reflected
113      in the exec, or the signal will never be delivered.  Setting the
114      critical section flag avoids anything we call trying to acquire the
115      sigstate lock.  */
116
117   __spin_unlock (&ss->lock);
118
119   /* Pack up the descriptor table to give the new program.  */
120   __mutex_lock (&_hurd_dtable_lock);
121
122   dtablesize = _hurd_dtable ? _hurd_dtablesize : _hurd_init_dtablesize;
123
124   if (task == __mach_task_self ())
125     /* Request the exec server to deallocate some ports from us if the exec
126        succeeds.  The init ports and descriptor ports will arrive in the
127        new program's exec_startup message.  If we failed to deallocate
128        them, the new program would have duplicate user references for them.
129        But we cannot deallocate them ourselves, because we must still have
130        them after a failed exec call.  */
131     please_dealloc = __alloca ((_hurd_nports + (2 * dtablesize))
132                                 * sizeof (mach_port_t));
133   else
134     please_dealloc = NULL;
135   pdp = please_dealloc;
136
137   if (_hurd_dtable != NULL)
138     {
139       dtable = __alloca (dtablesize * sizeof (dtable[0]));
140       ulink_dtable = __alloca (dtablesize * sizeof (ulink_dtable[0]));
141       dtable_cells = __alloca (dtablesize * sizeof (dtable_cells[0]));
142       for (i = 0; i < dtablesize; ++i)
143         {
144           struct hurd_fd *const d = _hurd_dtable[i];
145           if (d == NULL)
146             {
147               dtable[i] = MACH_PORT_NULL;
148               continue;
149             }
150           __spin_lock (&d->port.lock);
151           if (d->flags & FD_CLOEXEC)
152             {
153               /* This descriptor is marked to be closed on exec.
154                  So don't pass it to the new program.  */
155               dtable[i] = MACH_PORT_NULL;
156               if (pdp && d->port.port != MACH_PORT_NULL)
157                 {
158                   /* We still need to deallocate the ports.  */
159                   *pdp++ = d->port.port;
160                   if (d->ctty.port != MACH_PORT_NULL)
161                     *pdp++ = d->ctty.port;
162                 }
163               __spin_unlock (&d->port.lock);
164             }
165           else
166             {
167               if (pdp && d->ctty.port != MACH_PORT_NULL)
168                 /* All the elements of DTABLE are added to PLEASE_DEALLOC
169                    below, so we needn't add the port itself.
170                    But we must deallocate the ctty port as well as
171                    the normal port that got installed in DTABLE[I].  */
172                 *pdp++ = d->ctty.port;
173               dtable[i] = _hurd_port_locked_get (&d->port, &ulink_dtable[i]);
174               dtable_cells[i] = &d->port;
175             }
176         }
177     }
178   else
179     {
180       dtable = _hurd_init_dtable;
181       ulink_dtable = NULL;
182       dtable_cells = NULL;
183     }
184
185   /* The information is all set up now.  Try to exec the file.  */
186
187   {
188     if (pdp)
189       {
190         /* Request the exec server to deallocate some ports from us if the exec
191            succeeds.  The init ports and descriptor ports will arrive in the
192            new program's exec_startup message.  If we failed to deallocate
193            them, the new program would have duplicate user references for them.
194            But we cannot deallocate them ourselves, because we must still have
195            them after a failed exec call.  */
196
197         for (i = 0; i < _hurd_nports; ++i)
198           *pdp++ = ports[i];
199         for (i = 0; i < dtablesize; ++i)
200           *pdp++ = dtable[i];
201       }
202
203     err = __file_exec (file, task, 0,
204                        args, argslen, env, envlen,
205                        dtable, MACH_MSG_TYPE_COPY_SEND, dtablesize,
206                        ports, MACH_MSG_TYPE_COPY_SEND, _hurd_nports,
207                        ints, INIT_INT_MAX,
208                        please_dealloc, pdp - please_dealloc,
209                        &_hurd_msgport, task == __mach_task_self () ? 1 : 0);
210   }
211
212   /* Release references to the standard ports.  */
213   for (i = 0; i < _hurd_nports; ++i)
214     if (i == INIT_PORT_PROC && task != __mach_task_self ())
215       __mach_port_deallocate (__mach_task_self (), ports[i]);
216     else
217       _hurd_port_free (&_hurd_ports[i], &ulink_ports[i], ports[i]);
218
219   if (ulink_dtable != NULL)
220     /* Release references to the file descriptor ports.  */
221     for (i = 0; i < dtablesize; ++i)
222       if (dtable[i] != MACH_PORT_NULL)
223         _hurd_port_free (dtable_cells[i], &ulink_dtable[i], dtable[i]);
224
225   /* Release lock on the file descriptor table. */
226   __mutex_unlock (&_hurd_dtable_lock);
227
228   /* Safe to let signals happen now.  */
229   _hurd_critical_section_unlock (ss);
230
231  outargs:
232   free (args);
233  outenv:
234   free (env);
235   return err;
236 }