2001-07-24 Igor Khavkine <i_khavki@alcor.concordia.ca>
[platform/upstream/glibc.git] / hurd / hurdsig.c
1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000,01
2         Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <cthreads.h>           /* For `struct mutex'.  */
25 #include <mach.h>
26 #include <mach/thread_switch.h>
27
28 #include <hurd.h>
29 #include <hurd/id.h>
30 #include <hurd/signal.h>
31
32 #include "hurdfault.h"
33 #include "hurdmalloc.h"         /* XXX */
34
35 const char *_hurdsig_getenv (const char *);
36
37 struct mutex _hurd_siglock;
38 int _hurd_stopped;
39
40 /* Port that receives signals and other miscellaneous messages.  */
41 mach_port_t _hurd_msgport;
42
43 /* Thread listening on it.  */
44 thread_t _hurd_msgport_thread;
45
46 /* Thread which receives task-global signals.  */
47 thread_t _hurd_sigthread;
48
49 /* These are set up by _hurdsig_init.  */
50 unsigned long int __hurd_sigthread_stack_base;
51 unsigned long int __hurd_sigthread_stack_end;
52 unsigned long int *__hurd_sigthread_variables;
53
54 /* Linked-list of per-thread signal state.  */
55 struct hurd_sigstate *_hurd_sigstates;
56
57 /* Timeout for RPC's after interrupt_operation. */
58 mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 3000;
59 \f
60 static void
61 default_sigaction (struct sigaction actions[NSIG])
62 {
63   int signo;
64
65   __sigemptyset (&actions[0].sa_mask);
66   actions[0].sa_flags = SA_RESTART;
67   actions[0].sa_handler = SIG_DFL;
68
69   for (signo = 1; signo < NSIG; ++signo)
70     actions[signo] = actions[0];
71 }
72
73 struct hurd_sigstate *
74 _hurd_thread_sigstate (thread_t thread)
75 {
76   struct hurd_sigstate *ss;
77   __mutex_lock (&_hurd_siglock);
78   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
79     if (ss->thread == thread)
80        break;
81   if (ss == NULL)
82     {
83       ss = malloc (sizeof (*ss));
84       if (ss == NULL)
85         __libc_fatal ("hurd: Can't allocate thread sigstate\n");
86       ss->thread = thread;
87       __spin_lock_init (&ss->lock);
88
89       /* Initialize default state.  */
90       __sigemptyset (&ss->blocked);
91       __sigemptyset (&ss->pending);
92       memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
93       ss->preemptors = NULL;
94       ss->suspended = MACH_PORT_NULL;
95       ss->intr_port = MACH_PORT_NULL;
96       ss->context = NULL;
97
98       /* Initialize the sigaction vector from the default signal receiving
99          thread's state, and its from the system defaults.  */
100       if (thread == _hurd_sigthread)
101         default_sigaction (ss->actions);
102       else
103         {
104           struct hurd_sigstate *s;
105           for (s = _hurd_sigstates; s != NULL; s = s->next)
106             if (s->thread == _hurd_sigthread)
107               break;
108           if (s)
109             {
110               __spin_lock (&s->lock);
111               memcpy (ss->actions, s->actions, sizeof (s->actions));
112               __spin_unlock (&s->lock);
113             }
114           else
115             default_sigaction (ss->actions);
116         }
117
118       ss->next = _hurd_sigstates;
119       _hurd_sigstates = ss;
120     }
121   __mutex_unlock (&_hurd_siglock);
122   return ss;
123 }
124 \f
125 /* Signal delivery itself is on this page.  */
126
127 #include <hurd/fd.h>
128 #include <hurd/crash.h>
129 #include <hurd/resource.h>
130 #include <hurd/paths.h>
131 #include <setjmp.h>
132 #include <fcntl.h>
133 #include <sys/wait.h>
134 #include "thread_state.h"
135 #include <hurd/msg_server.h>
136 #include <hurd/msg_reply.h>     /* For __msg_sig_post_reply.  */
137 #include <hurd/interrupt.h>
138 #include <assert.h>
139 #include <unistd.h>
140
141
142 /* Call the crash dump server to mummify us before we die.
143    Returns nonzero if a core file was written.  */
144 static int
145 write_corefile (int signo, const struct hurd_signal_detail *detail)
146 {
147   error_t err;
148   mach_port_t coreserver;
149   file_t file, coredir;
150   const char *name;
151
152   /* Don't bother locking since we just read the one word.  */
153   rlim_t corelimit = _hurd_rlimits[RLIMIT_CORE].rlim_cur;
154
155   if (corelimit == 0)
156     /* No core dumping, thank you very much.  Note that this makes
157        `ulimit -c 0' prevent crash-suspension too, which is probably
158        what the user wanted.  */
159     return 0;
160
161   /* XXX RLIMIT_CORE:
162      When we have a protocol to make the server return an error
163      for RLIMIT_FSIZE, then tell the corefile fs server the RLIMIT_CORE
164      value in place of the RLIMIT_FSIZE value.  */
165
166   /* First get a port to the core dumping server.  */
167   coreserver = MACH_PORT_NULL;
168   name = _hurdsig_getenv ("CRASHSERVER");
169   if (name != NULL)
170     coreserver = __file_name_lookup (name, 0, 0);
171   if (coreserver == MACH_PORT_NULL)
172     coreserver = __file_name_lookup (_SERVERS_CRASH, 0, 0);
173   if (coreserver == MACH_PORT_NULL)
174     return 0;
175
176   /* Get a port to the directory where the new core file will reside.  */
177   file = MACH_PORT_NULL;
178   name = _hurdsig_getenv ("COREFILE");
179   if (name == NULL)
180     name = "core";
181   coredir = __file_name_split (name, (char **) &name);
182   if (coredir != MACH_PORT_NULL)
183     /* Create the new file, but don't link it into the directory yet.  */
184     __dir_mkfile (coredir, O_WRONLY|O_CREAT,
185                   0600 & ~_hurd_umask, /* XXX ? */
186                   &file);
187
188   /* Call the core dumping server to write the core file.  */
189   err = __crash_dump_task (coreserver,
190                            __mach_task_self (),
191                            file,
192                            signo, detail->code, detail->error,
193                            detail->exc, detail->exc_code, detail->exc_subcode,
194                            _hurd_ports[INIT_PORT_CTTYID].port,
195                            MACH_MSG_TYPE_COPY_SEND);
196   __mach_port_deallocate (__mach_task_self (), coreserver);
197
198   if (! err && file != MACH_PORT_NULL)
199     /* The core dump into FILE succeeded, so now link it into the
200        directory.  */
201     err = __dir_link (file, coredir, name, 1);
202   __mach_port_deallocate (__mach_task_self (), file);
203   __mach_port_deallocate (__mach_task_self (), coredir);
204   return !err && file != MACH_PORT_NULL;
205 }
206
207
208 /* The lowest-numbered thread state flavor value is 1,
209    so we use bit 0 in machine_thread_all_state.set to
210    record whether we have done thread_abort.  */
211 #define THREAD_ABORTED 1
212
213 /* SS->thread is suspended.  Abort the thread and get its basic state.  */
214 static void
215 abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
216               void (*reply) (void))
217 {
218   if (!(state->set & THREAD_ABORTED))
219     {
220       error_t err = __thread_abort (ss->thread);
221       assert_perror (err);
222       /* Clear all thread state flavor set bits, because thread_abort may
223          have changed the state.  */
224       state->set = THREAD_ABORTED;
225     }
226
227   if (reply)
228     (*reply) ();
229
230   machine_get_basic_state (ss->thread, state);
231 }
232
233 /* Find the location of the MiG reply port cell in use by the thread whose
234    state is described by THREAD_STATE.  If SIGTHREAD is nonzero, make sure
235    that this location can be set without faulting, or else return NULL.  */
236
237 static mach_port_t *
238 interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
239                                  int sigthread)
240 {
241   mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
242     (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
243
244   if (sigthread && _hurdsig_catch_memory_fault (portloc))
245     /* Faulted trying to read the stack.  */
246     return NULL;
247
248   /* Fault now if this pointer is bogus.  */
249   *(volatile mach_port_t *) portloc = *portloc;
250
251   if (sigthread)
252     _hurdsig_end_catch_fault ();
253
254   return portloc;
255 }
256 \f
257 #include <hurd/sigpreempt.h>
258 #include "intr-msg.h"
259
260 /* Timeout on interrupt_operation calls.  */
261 mach_msg_timeout_t _hurdsig_interrupt_timeout = 1000;
262
263 /* SS->thread is suspended.
264
265    Abort any interruptible RPC operation the thread is doing.
266
267    This uses only the constant member SS->thread and the unlocked, atomically
268    set member SS->intr_port, so no locking is needed.
269
270    If successfully sent an interrupt_operation and therefore the thread should
271    wait for its pending RPC to return (possibly EINTR) before taking the
272    incoming signal, returns the reply port to be received on.  Otherwise
273    returns MACH_PORT_NULL.
274
275    SIGNO is used to find the applicable SA_RESTART bit.  If SIGNO is zero,
276    the RPC fails with EINTR instead of restarting (thread_cancel).
277
278    *STATE_CHANGE is set nonzero if STATE->basic was modified and should
279    be applied back to the thread if it might ever run again, else zero.  */
280
281 mach_port_t
282 _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
283                      struct machine_thread_all_state *state, int *state_change,
284                      void (*reply) (void))
285 {
286   extern const void _hurd_intr_rpc_msg_in_trap;
287   mach_port_t rcv_port = MACH_PORT_NULL;
288   mach_port_t intr_port;
289
290   *state_change = 0;
291
292   intr_port = ss->intr_port;
293   if (intr_port == MACH_PORT_NULL)
294     /* No interruption needs done.  */
295     return MACH_PORT_NULL;
296
297   /* Abort the thread's kernel context, so any pending message send or
298      receive completes immediately or aborts.  */
299   abort_thread (ss, state, reply);
300
301   if (state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap)
302     {
303       /* The thread is about to do the RPC, but hasn't yet entered
304          mach_msg.  Mutate the thread's state so it knows not to try
305          the RPC.  */
306       INTR_MSG_BACK_OUT (&state->basic);
307       MACHINE_THREAD_STATE_SET_PC (&state->basic,
308                                    &_hurd_intr_rpc_msg_in_trap);
309       state->basic.SYSRETURN = MACH_SEND_INTERRUPTED;
310       *state_change = 1;
311     }
312   else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap &&
313            /* The thread was blocked in the system call.  After thread_abort,
314               the return value register indicates what state the RPC was in
315               when interrupted.  */
316            state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
317       {
318         /* The RPC request message was sent and the thread was waiting for
319            the reply message; now the message receive has been aborted, so
320            the mach_msg call will return MACH_RCV_INTERRUPTED.  We must tell
321            the server to interrupt the pending operation.  The thread must
322            wait for the reply message before running the signal handler (to
323            guarantee that the operation has finished being interrupted), so
324            our nonzero return tells the trampoline code to finish the message
325            receive operation before running the handler.  */
326
327         mach_port_t *reply = interrupted_reply_port_location (state,
328                                                               sigthread);
329         error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout);
330
331         if (err)
332           {
333             if (reply)
334               {
335                 /* The interrupt didn't work.
336                    Destroy the receive right the thread is blocked on.  */
337                 __mach_port_destroy (__mach_task_self (), *reply);
338                 *reply = MACH_PORT_NULL;
339               }
340
341             /* The system call return value register now contains
342                MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
343                call.  Since we have just destroyed the receive right, the
344                retry will fail with MACH_RCV_INVALID_NAME.  Instead, just
345                change the return value here to EINTR so mach_msg will not
346                retry and the EINTR error code will propagate up.  */
347             state->basic.SYSRETURN = EINTR;
348             *state_change = 1;
349           }
350         else if (reply)
351           rcv_port = *reply;
352
353         /* All threads whose RPCs were interrupted by the interrupt_operation
354            call above will retry their RPCs unless we clear SS->intr_port.
355            So we clear it for the thread taking a signal when SA_RESTART is
356            clear, so that its call returns EINTR.  */
357         if (! signo || !(ss->actions[signo].sa_flags & SA_RESTART))
358           ss->intr_port = MACH_PORT_NULL;
359       }
360
361   return rcv_port;
362 }
363
364
365 /* Abort the RPCs being run by all threads but this one;
366    all other threads should be suspended.  If LIVE is nonzero, those
367    threads may run again, so they should be adjusted as necessary to be
368    happy when resumed.  STATE is clobbered as a scratch area; its initial
369    contents are ignored, and its contents on return are not useful.  */
370
371 static void
372 abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
373 {
374   /* We can just loop over the sigstates.  Any thread doing something
375      interruptible must have one.  We needn't bother locking because all
376      other threads are stopped.  */
377
378   struct hurd_sigstate *ss;
379   size_t nthreads;
380   mach_port_t *reply_ports;
381
382   /* First loop over the sigstates to count them.
383      We need to know how big a vector we will need for REPLY_PORTS.  */
384   nthreads = 0;
385   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
386     ++nthreads;
387
388   reply_ports = alloca (nthreads * sizeof *reply_ports);
389
390   nthreads = 0;
391   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next, ++nthreads)
392     if (ss->thread == _hurd_msgport_thread)
393       reply_ports[nthreads] = MACH_PORT_NULL;
394     else
395       {
396         int state_changed;
397         state->set = 0;         /* Reset scratch area.  */
398
399         /* Abort any operation in progress with interrupt_operation.
400            Record the reply port the thread is waiting on.
401            We will wait for all the replies below.  */
402         reply_ports[nthreads] = _hurdsig_abort_rpcs (ss, signo, 1,
403                                                      state, &state_changed,
404                                                      NULL);
405         if (live)
406           {
407             if (reply_ports[nthreads] != MACH_PORT_NULL)
408               {
409                 /* We will wait for the reply to this RPC below, so the
410                    thread must issue a new RPC rather than waiting for the
411                    reply to the one it sent.  */
412                 state->basic.SYSRETURN = EINTR;
413                 state_changed = 1;
414               }
415             if (state_changed)
416               /* Aborting the RPC needed to change this thread's state,
417                  and it might ever run again.  So write back its state.  */
418               __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
419                                   (natural_t *) &state->basic,
420                                   MACHINE_THREAD_STATE_COUNT);
421           }
422       }
423
424   /* Wait for replies from all the successfully interrupted RPCs.  */
425   while (nthreads-- > 0)
426     if (reply_ports[nthreads] != MACH_PORT_NULL)
427       {
428         error_t err;
429         mach_msg_header_t head;
430         err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head,
431                           reply_ports[nthreads],
432                           _hurd_interrupted_rpc_timeout, MACH_PORT_NULL);
433         switch (err)
434           {
435           case MACH_RCV_TIMED_OUT:
436           case MACH_RCV_TOO_LARGE:
437             break;
438
439           default:
440             assert_perror (err);
441           }
442       }
443 }
444
445 struct hurd_signal_preemptor *_hurdsig_preemptors = 0;
446 sigset_t _hurdsig_preempted_set;
447
448 /* XXX temporary to deal with spelling fix */
449 weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
450
451 /* Mask of stop signals.  */
452 #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
453                   sigmask (SIGSTOP) | sigmask (SIGTSTP))
454
455 /* Deliver a signal.  SS is not locked.  */
456 void
457 _hurd_internal_post_signal (struct hurd_sigstate *ss,
458                             int signo, struct hurd_signal_detail *detail,
459                             mach_port_t reply_port,
460                             mach_msg_type_name_t reply_port_type,
461                             int untraced)
462 {
463   error_t err;
464   struct machine_thread_all_state thread_state;
465   enum { stop, ignore, core, term, handle } act;
466   sighandler_t handler;
467   sigset_t pending;
468   int ss_suspended;
469
470   /* Reply to this sig_post message.  */
471   __typeof (__msg_sig_post_reply) *reply_rpc
472     = (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply);
473   void reply (void)
474     {
475       error_t err;
476       if (reply_port == MACH_PORT_NULL)
477         return;
478       err = (*reply_rpc) (reply_port, reply_port_type, 0);
479       reply_port = MACH_PORT_NULL;
480       if (err != MACH_SEND_INVALID_DEST) /* Ignore dead reply port.  */
481         assert_perror (err);
482     }
483
484   /* Mark the signal as pending.  */
485   void mark_pending (void)
486     {
487       __sigaddset (&ss->pending, signo);
488       /* Save the details to be given to the handler when SIGNO is
489          unblocked.  */
490       ss->pending_data[signo] = *detail;
491     }
492
493   /* Suspend the process with SIGNO.  */
494   void suspend (void)
495     {
496       /* Stop all other threads and mark ourselves stopped.  */
497       __USEPORT (PROC,
498                  ({
499                    /* Hold the siglock while stopping other threads to be
500                       sure it is not held by another thread afterwards.  */
501                    __mutex_lock (&_hurd_siglock);
502                    __proc_dostop (port, _hurd_msgport_thread);
503                    __mutex_unlock (&_hurd_siglock);
504                    abort_all_rpcs (signo, &thread_state, 1);
505                    reply ();
506                    __proc_mark_stop (port, signo, detail->code);
507                  }));
508       _hurd_stopped = 1;
509     }
510   /* Resume the process after a suspension.  */
511   void resume (void)
512     {
513       /* Resume the process from being stopped.  */
514       thread_t *threads;
515       mach_msg_type_number_t nthreads, i;
516       error_t err;
517
518       if (! _hurd_stopped)
519         return;
520
521       /* Tell the proc server we are continuing.  */
522       __USEPORT (PROC, __proc_mark_cont (port));
523       /* Fetch ports to all our threads and resume them.  */
524       err = __task_threads (__mach_task_self (), &threads, &nthreads);
525       assert_perror (err);
526       for (i = 0; i < nthreads; ++i)
527         {
528           if (threads[i] != _hurd_msgport_thread &&
529               (act != handle || threads[i] != ss->thread))
530             {
531               err = __thread_resume (threads[i]);
532               assert_perror (err);
533             }
534           err = __mach_port_deallocate (__mach_task_self (),
535                                         threads[i]);
536           assert_perror (err);
537         }
538       __vm_deallocate (__mach_task_self (),
539                        (vm_address_t) threads,
540                        nthreads * sizeof *threads);
541       _hurd_stopped = 0;
542       if (act == handle)
543         /* The thread that will run the handler is already suspended.  */
544         ss_suspended = 1;
545     }
546
547   if (signo == 0)
548     {
549       if (untraced)
550         /* This is PTRACE_CONTINUE.  */
551         resume ();
552
553       /* This call is just to check for pending signals.  */
554       __spin_lock (&ss->lock);
555       goto check_pending_signals;
556     }
557
558  post_signal:
559
560   thread_state.set = 0;         /* We know nothing.  */
561
562   __spin_lock (&ss->lock);
563
564   /* Check for a preempted signal.  Preempted signals can arrive during
565      critical sections.  */
566   {
567     inline sighandler_t try_preemptor (struct hurd_signal_preemptor *pe)
568       {                         /* PE cannot be null.  */
569         do
570           {
571             if (HURD_PREEMPT_SIGNAL_P (pe, signo, detail->code))
572               {
573                 if (pe->preemptor)
574                   {
575                     sighandler_t handler = (*pe->preemptor) (pe, ss,
576                                                              &signo, detail);
577                     if (handler != SIG_ERR)
578                       return handler;
579                   }
580                 else
581                   return pe->handler;
582               }
583             pe = pe->next;
584           } while (pe != 0);
585         return SIG_ERR;
586       }
587
588     handler = ss->preemptors ? try_preemptor (ss->preemptors) : SIG_ERR;
589
590     /* If no thread-specific preemptor, check for a global one.  */
591     if (handler == SIG_ERR && (__sigmask (signo) & _hurdsig_preempted_set))
592       {
593         __mutex_lock (&_hurd_siglock);
594         handler = try_preemptor (_hurdsig_preemptors);
595         __mutex_unlock (&_hurd_siglock);
596       }
597   }
598
599   ss_suspended = 0;
600
601   if (handler == SIG_IGN)
602     /* Ignore the signal altogether.  */
603     act = ignore;
604   else if (handler != SIG_ERR)
605     /* Run the preemption-provided handler.  */
606     act = handle;
607   else
608     {
609       /* No preemption.  Do normal handling.  */
610
611       if (!untraced && __sigismember (&_hurdsig_traced, signo))
612         {
613           /* We are being traced.  Stop to tell the debugger of the signal.  */
614           if (_hurd_stopped)
615             /* Already stopped.  Mark the signal as pending;
616                when resumed, we will notice it and stop again.  */
617             mark_pending ();
618           else
619             suspend ();
620           __spin_unlock (&ss->lock);
621           reply ();
622           return;
623         }
624
625       handler = ss->actions[signo].sa_handler;
626
627       if (handler == SIG_DFL)
628         /* Figure out the default action for this signal.  */
629         switch (signo)
630           {
631           case 0:
632             /* A sig_post msg with SIGNO==0 is sent to
633                tell us to check for pending signals.  */
634             act = ignore;
635             break;
636
637           case SIGTTIN:
638           case SIGTTOU:
639           case SIGSTOP:
640           case SIGTSTP:
641             act = stop;
642             break;
643
644           case SIGCONT:
645           case SIGIO:
646           case SIGURG:
647           case SIGCHLD:
648           case SIGWINCH:
649             act = ignore;
650             break;
651
652           case SIGQUIT:
653           case SIGILL:
654           case SIGTRAP:
655           case SIGIOT:
656           case SIGEMT:
657           case SIGFPE:
658           case SIGBUS:
659           case SIGSEGV:
660           case SIGSYS:
661             act = core;
662             break;
663
664           case SIGINFO:
665             if (_hurd_pgrp == _hurd_pid)
666               {
667                 /* We are the process group leader.  Since there is no
668                    user-specified handler for SIGINFO, we use a default one
669                    which prints something interesting.  We use the normal
670                    handler mechanism instead of just doing it here to avoid
671                    the signal thread faulting or blocking in this
672                    potentially hairy operation.  */
673                 act = handle;
674                 handler = _hurd_siginfo_handler;
675               }
676             else
677               act = ignore;
678             break;
679
680           default:
681             act = term;
682             break;
683           }
684       else if (handler == SIG_IGN)
685         act = ignore;
686       else
687         act = handle;
688
689       if (__sigmask (signo) & STOPSIGS)
690         /* Stop signals clear a pending SIGCONT even if they
691            are handled or ignored (but not if preempted).  */
692         ss->pending &= ~sigmask (SIGCONT);
693       else
694         {
695           if (signo == SIGCONT)
696             /* Even if handled or ignored (but not preempted), SIGCONT clears
697                stop signals and resumes the process.  */
698             ss->pending &= ~STOPSIGS;
699
700           if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT))
701             resume ();
702         }
703     }
704
705   if (_hurd_orphaned && act == stop &&
706       (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) |
707                             __sigmask (SIGTSTP))))
708     {
709       /* If we would ordinarily stop for a job control signal, but we are
710          orphaned so noone would ever notice and continue us again, we just
711          quietly die, alone and in the dark.  */
712       detail->code = signo;
713       signo = SIGKILL;
714       act = term;
715     }
716
717   /* Handle receipt of a blocked signal, or any signal while stopped.  */
718   if (act != ignore &&          /* Signals ignored now are forgotten now.  */
719       __sigismember (&ss->blocked, signo) ||
720       (signo != SIGKILL && _hurd_stopped))
721     {
722       mark_pending ();
723       act = ignore;
724     }
725
726   /* Perform the chosen action for the signal.  */
727   switch (act)
728     {
729     case stop:
730       if (_hurd_stopped)
731         {
732           /* We are already stopped, but receiving an untraced stop
733              signal.  Instead of resuming and suspending again, just
734              notify the proc server of the new stop signal.  */
735           error_t err = __USEPORT (PROC, __proc_mark_stop
736                                    (port, signo, detail->code));
737           assert_perror (err);
738         }
739       else
740         /* Suspend the process.  */
741         suspend ();
742       break;
743
744     case ignore:
745       /* Nobody cares about this signal.  If there was a call to resume
746          above in SIGCONT processing and we've left a thread suspended,
747          now's the time to set it going. */
748       if (ss_suspended)
749         {
750           err = __thread_resume (ss->thread);
751           assert_perror (err);
752           ss_suspended = 0;
753         }
754       break;
755
756     sigbomb:
757       /* We got a fault setting up the stack frame for the handler.
758          Nothing to do but die; BSD gets SIGILL in this case.  */
759       detail->code = signo;     /* XXX ? */
760       signo = SIGILL;
761       act = core;
762       /* FALLTHROUGH */
763
764     case term:                  /* Time to die.  */
765     case core:                  /* And leave a rotting corpse.  */
766       /* Have the proc server stop all other threads in our task.  */
767       err = __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
768       assert_perror (err);
769       /* No more user instructions will be executed.
770          The signal can now be considered delivered.  */
771       reply ();
772       /* Abort all server operations now in progress.  */
773       abort_all_rpcs (signo, &thread_state, 0);
774
775       {
776         int status = W_EXITCODE (0, signo);
777         /* Do a core dump if desired.  Only set the wait status bit saying we
778            in fact dumped core if the operation was actually successful.  */
779         if (act == core && write_corefile (signo, detail))
780           status |= WCOREFLAG;
781         /* Tell proc how we died and then stick the saber in the gut.  */
782         _hurd_exit (status);
783         /* NOTREACHED */
784       }
785
786     case handle:
787       /* Call a handler for this signal.  */
788       {
789         struct sigcontext *scp, ocontext;
790         int wait_for_reply, state_changed;
791
792         /* Stop the thread and abort its pending RPC operations.  */
793         if (! ss_suspended)
794           {
795             err = __thread_suspend (ss->thread);
796             assert_perror (err);
797           }
798
799         /* Abort the thread's kernel context, so any pending message send
800            or receive completes immediately or aborts.  If an interruptible
801            RPC is in progress, abort_rpcs will do this.  But we must always
802            do it before fetching the thread's state, because
803            thread_get_state is never kosher before thread_abort.  */
804         abort_thread (ss, &thread_state, NULL);
805
806         if (ss->context)
807           {
808             /* We have a previous sigcontext that sigreturn was about
809                to restore when another signal arrived.  */
810
811             mach_port_t *loc;
812
813             if (_hurdsig_catch_memory_fault (ss->context))
814               {
815                 /* We faulted reading the thread's stack.  Forget that
816                    context and pretend it wasn't there.  It almost
817                    certainly crash if this handler returns, but that's it's
818                    problem.  */
819                 ss->context = NULL;
820               }
821             else
822               {
823                 /* Copy the context from the thread's stack before
824                    we start diddling the stack to set up the handler.  */
825                 ocontext = *ss->context;
826                 ss->context = &ocontext;
827               }
828             _hurdsig_end_catch_fault ();
829
830             if (! machine_get_basic_state (ss->thread, &thread_state))
831               goto sigbomb;
832             loc = interrupted_reply_port_location (&thread_state, 1);
833             if (loc && *loc != MACH_PORT_NULL)
834               /* This is the reply port for the context which called
835                  sigreturn.  Since we are abandoning that context entirely
836                  and restoring SS->context instead, destroy this port.  */
837               __mach_port_destroy (__mach_task_self (), *loc);
838
839             /* The thread was in sigreturn, not in any interruptible RPC.  */
840             wait_for_reply = 0;
841
842             assert (! __spin_lock_locked (&ss->critical_section_lock));
843           }
844         else
845           {
846             int crit = __spin_lock_locked (&ss->critical_section_lock);
847
848             wait_for_reply
849               = (_hurdsig_abort_rpcs (ss,
850                                       /* In a critical section, any RPC
851                                          should be cancelled instead of
852                                          restarted, regardless of
853                                          SA_RESTART, so the entire
854                                          "atomic" operation can be aborted
855                                          as a unit.  */
856                                       crit ? 0 : signo, 1,
857                                       &thread_state, &state_changed,
858                                       &reply)
859                  != MACH_PORT_NULL);
860
861             if (crit)
862               {
863                 /* The thread is in a critical section.  Mark the signal as
864                    pending.  When it finishes the critical section, it will
865                    check for pending signals.  */
866                 mark_pending ();
867                 if (state_changed)
868                   /* Some cases of interrupting an RPC must change the
869                      thread state to back out the call.  Normally this
870                      change is rolled into the warping to the handler and
871                      sigreturn, but we are not running the handler now
872                      because the thread is in a critical section.  Instead,
873                      mutate the thread right away for the RPC interruption
874                      and resume it; the RPC will return early so the
875                      critical section can end soon.  */
876                   __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
877                                       (natural_t *) &thread_state.basic,
878                                       MACHINE_THREAD_STATE_COUNT);
879                 /* */
880                 ss->intr_port = MACH_PORT_NULL;
881                 __thread_resume (ss->thread);
882                 break;
883               }
884           }
885
886         /* Call the machine-dependent function to set the thread up
887            to run the signal handler, and preserve its old context.  */
888         scp = _hurd_setup_sighandler (ss, handler, signo, detail,
889                                       wait_for_reply, &thread_state);
890         if (scp == NULL)
891           goto sigbomb;
892
893         /* Set the machine-independent parts of the signal context.  */
894
895         {
896           /* Fetch the thread variable for the MiG reply port,
897              and set it to MACH_PORT_NULL.  */
898           mach_port_t *loc = interrupted_reply_port_location (&thread_state,
899                                                               1);
900           if (loc)
901             {
902               scp->sc_reply_port = *loc;
903               *loc = MACH_PORT_NULL;
904             }
905           else
906             scp->sc_reply_port = MACH_PORT_NULL;
907
908           /* Save the intr_port in use by the interrupted code,
909              and clear the cell before running the trampoline.  */
910           scp->sc_intr_port = ss->intr_port;
911           ss->intr_port = MACH_PORT_NULL;
912
913           if (ss->context)
914             {
915               /* After the handler runs we will restore to the state in
916                  SS->context, not the state of the thread now.  So restore
917                  that context's reply port and intr port.  */
918
919               scp->sc_reply_port = ss->context->sc_reply_port;
920               scp->sc_intr_port = ss->context->sc_intr_port;
921
922               ss->context = NULL;
923             }
924         }
925
926         /* Backdoor extra argument to signal handler.  */
927         scp->sc_error = detail->error;
928
929         scp->sc_mask = ss->blocked;
930
931         if ((ss->actions[signo].sa_flags & SA_NODEFER) == 0)
932           /* Block SIGNO and requested signals while running the handler.  */
933           ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
934
935         if (ss->actions[signo].sa_flags & SA_RESETHAND)
936           /* Silly SysV/Linux compatibility option.  */
937           ss->actions[signo].sa_handler = SIG_DFL;
938
939         /* Start the thread running the handler (or possibly waiting for an
940            RPC reply before running the handler).  */
941         err = __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
942                                   (natural_t *) &thread_state.basic,
943                                   MACHINE_THREAD_STATE_COUNT);
944         assert_perror (err);
945         err = __thread_resume (ss->thread);
946         assert_perror (err);
947         thread_state.set = 0;   /* Everything we know is now wrong.  */
948         break;
949       }
950     }
951
952   /* The signal has either been ignored or is now being handled.  We can
953      consider it delivered and reply to the killer.  */
954   reply ();
955
956   /* We get here unless the signal was fatal.  We still hold SS->lock.
957      Check for pending signals, and loop to post them.  */
958   {
959     /* Return nonzero if SS has any signals pending we should worry about.
960        We don't worry about any pending signals if we are stopped, nor if
961        SS is in a critical section.  We are guaranteed to get a sig_post
962        message before any of them become deliverable: either the SIGCONT
963        signal, or a sig_post with SIGNO==0 as an explicit poll when the
964        thread finishes its critical section.  */
965     inline int signals_pending (void)
966       {
967         if (_hurd_stopped || __spin_lock_locked (&ss->critical_section_lock))
968           return 0;
969         return pending = ss->pending & ~ss->blocked;
970       }
971
972   check_pending_signals:
973     untraced = 0;
974
975     if (signals_pending ())
976       {
977         for (signo = 1; signo < NSIG; ++signo)
978           if (__sigismember (&pending, signo))
979             {
980             deliver_pending:
981               __sigdelset (&ss->pending, signo);
982               *detail = ss->pending_data[signo];
983               __spin_unlock (&ss->lock);
984               goto post_signal;
985             }
986       }
987
988     /* No pending signals left undelivered for this thread.
989        If we were sent signal 0, we need to check for pending
990        signals for all threads.  */
991     if (signo == 0)
992       {
993         __spin_unlock (&ss->lock);
994         __mutex_lock (&_hurd_siglock);
995         for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
996           {
997             __spin_lock (&ss->lock);
998             for (signo = 1; signo < NSIG; ++signo)
999               if (__sigismember (&ss->pending, signo)
1000                   && (!__sigismember (&ss->blocked, signo)
1001                       /* We "deliver" immediately pending blocked signals whose
1002                          action might be to ignore, so that if ignored they are
1003                          dropped right away.  */
1004                       || ss->actions[signo].sa_handler == SIG_IGN
1005                       || ss->actions[signo].sa_handler == SIG_DFL))
1006                 {
1007                   mutex_unlock (&_hurd_siglock);
1008                   goto deliver_pending;
1009                 }
1010             __spin_unlock (&ss->lock);
1011           }
1012         __mutex_unlock (&_hurd_siglock);
1013       }
1014     else
1015       {
1016         /* No more signals pending; SS->lock is still locked.
1017            Wake up any sigsuspend call that is blocking SS->thread.  */
1018         if (ss->suspended != MACH_PORT_NULL)
1019           {
1020             /* There is a sigsuspend waiting.  Tell it to wake up.  */
1021             error_t err;
1022             mach_msg_header_t msg;
1023             msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
1024             msg.msgh_remote_port = ss->suspended;
1025             msg.msgh_local_port = MACH_PORT_NULL;
1026             /* These values do not matter.  */
1027             msg.msgh_id = 8675309; /* Jenny, Jenny.  */
1028             msg.msgh_seqno = 17; /* Random.  */
1029             ss->suspended = MACH_PORT_NULL;
1030             err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
1031                               MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
1032                               MACH_PORT_NULL);
1033             assert_perror (err);
1034           }
1035         __spin_unlock (&ss->lock);
1036       }
1037   }
1038
1039   /* All pending signals delivered to all threads.
1040      Now we can send the reply message even for signal 0.  */
1041   reply ();
1042 }
1043 \f
1044 /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
1045    Returns zero if so, otherwise the error code to return to the sender.  */
1046
1047 static error_t
1048 signal_allowed (int signo, mach_port_t refport)
1049 {
1050   if (signo < 0 || signo >= NSIG)
1051     return EINVAL;
1052
1053   if (refport == __mach_task_self ())
1054     /* Can send any signal.  */
1055     goto win;
1056
1057   /* Avoid needing to check for this below.  */
1058   if (refport == MACH_PORT_NULL)
1059     return EPERM;
1060
1061   switch (signo)
1062     {
1063     case SIGINT:
1064     case SIGQUIT:
1065     case SIGTSTP:
1066     case SIGHUP:
1067     case SIGINFO:
1068     case SIGTTIN:
1069     case SIGTTOU:
1070     case SIGWINCH:
1071       /* Job control signals can be sent by the controlling terminal.  */
1072       if (__USEPORT (CTTYID, port == refport))
1073         goto win;
1074       break;
1075
1076     case SIGCONT:
1077       {
1078         /* A continue signal can be sent by anyone in the session.  */
1079         mach_port_t sessport;
1080         if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
1081           {
1082             __mach_port_deallocate (__mach_task_self (), sessport);
1083             if (refport == sessport)
1084               goto win;
1085           }
1086       }
1087       break;
1088
1089     case SIGIO:
1090     case SIGURG:
1091       {
1092         /* Any io object a file descriptor refers to might send us
1093            one of these signals using its async ID port for REFPORT.
1094
1095            This is pretty wide open; it is not unlikely that some random
1096            process can at least open for reading something we have open,
1097            get its async ID port, and send us a spurious SIGIO or SIGURG
1098            signal.  But BSD is actually wider open than that!--you can set
1099            the owner of an io object to any process or process group
1100            whatsoever and send them gratuitous signals.
1101
1102            Someday we could implement some reasonable scheme for
1103            authorizing SIGIO and SIGURG signals properly.  */
1104
1105         int d;
1106         int lucky = 0;          /* True if we find a match for REFPORT.  */
1107         __mutex_lock (&_hurd_dtable_lock);
1108         for (d = 0; !lucky && (unsigned) d < (unsigned) _hurd_dtablesize; ++d)
1109           {
1110             struct hurd_userlink ulink;
1111             io_t port;
1112             mach_port_t asyncid;
1113             if (_hurd_dtable[d] == NULL)
1114               continue;
1115             port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
1116             if (! __io_get_icky_async_id (port, &asyncid))
1117               {
1118                 if (refport == asyncid)
1119                   /* Break out of the loop on the next iteration.  */
1120                   lucky = 1;
1121                 __mach_port_deallocate (__mach_task_self (), asyncid);
1122               }
1123             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
1124           }
1125         /* If we found a lucky winner, we've set D to -1 in the loop.  */
1126         if (lucky)
1127           goto win;
1128       }
1129     }
1130
1131   /* If this signal is legit, we have done `goto win' by now.
1132      When we return the error, mig deallocates REFPORT.  */
1133   return EPERM;
1134
1135  win:
1136   /* Deallocate the REFPORT send right; we are done with it.  */
1137   __mach_port_deallocate (__mach_task_self (), refport);
1138
1139   return 0;
1140 }
1141
1142 /* Implement the sig_post RPC from <hurd/msg.defs>;
1143    sent when someone wants us to get a signal.  */
1144 kern_return_t
1145 _S_msg_sig_post (mach_port_t me,
1146                  mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
1147                  int signo, natural_t sigcode,
1148                  mach_port_t refport)
1149 {
1150   error_t err;
1151   struct hurd_signal_detail d;
1152
1153   if (err = signal_allowed (signo, refport))
1154     return err;
1155
1156   d.code = sigcode;
1157   d.exc = 0;
1158
1159   /* Post the signal to the designated signal-receiving thread.  This will
1160      reply when the signal can be considered delivered.  */
1161   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1162                               signo, &d, reply_port, reply_port_type,
1163                               0); /* Stop if traced.  */
1164
1165   return MIG_NO_REPLY;          /* Already replied.  */
1166 }
1167
1168 /* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
1169    sent when the debugger wants us to really get a signal
1170    even if we are traced.  */
1171 kern_return_t
1172 _S_msg_sig_post_untraced (mach_port_t me,
1173                           mach_port_t reply_port,
1174                           mach_msg_type_name_t reply_port_type,
1175                           int signo, natural_t sigcode,
1176                           mach_port_t refport)
1177 {
1178   error_t err;
1179   struct hurd_signal_detail d;
1180
1181   if (err = signal_allowed (signo, refport))
1182     return err;
1183
1184   d.code = sigcode;
1185   d.exc = 0;
1186
1187   /* Post the signal to the designated signal-receiving thread.  This will
1188      reply when the signal can be considered delivered.  */
1189   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1190                               signo, &d, reply_port, reply_port_type,
1191                               1); /* Untraced flag. */
1192
1193   return MIG_NO_REPLY;          /* Already replied.  */
1194 }
1195 \f
1196 extern void __mig_init (void *);
1197
1198 #include <mach/task_special_ports.h>
1199
1200 /* Initialize the message port and _hurd_sigthread and start the signal
1201    thread.  */
1202
1203 void
1204 _hurdsig_init (const int *intarray, size_t intarraysize)
1205 {
1206   error_t err;
1207   vm_size_t stacksize;
1208   struct hurd_sigstate *ss;
1209
1210   __mutex_init (&_hurd_siglock);
1211
1212   err = __mach_port_allocate (__mach_task_self (),
1213                               MACH_PORT_RIGHT_RECEIVE,
1214                               &_hurd_msgport);
1215   assert_perror (err);
1216
1217   /* Make a send right to the signal port.  */
1218   err = __mach_port_insert_right (__mach_task_self (),
1219                                   _hurd_msgport,
1220                                   _hurd_msgport,
1221                                   MACH_MSG_TYPE_MAKE_SEND);
1222   assert_perror (err);
1223
1224   /* Initialize the main thread's signal state.  */
1225   ss = _hurd_self_sigstate ();
1226
1227   /* Copy inherited values from our parent (or pre-exec process state)
1228      into the signal settings of the main thread.  */
1229   if (intarraysize > INIT_SIGMASK)
1230     ss->blocked = intarray[INIT_SIGMASK];
1231   if (intarraysize > INIT_SIGPENDING)
1232     ss->pending = intarray[INIT_SIGPENDING];
1233   if (intarraysize > INIT_SIGIGN && intarray[INIT_SIGIGN] != 0)
1234     {
1235       int signo;
1236       for (signo = 1; signo < NSIG; ++signo)
1237         if (intarray[INIT_SIGIGN] & __sigmask(signo))
1238           ss->actions[signo].sa_handler = SIG_IGN;
1239     }
1240
1241   /* Set the default thread to receive task-global signals
1242      to this one, the main (first) user thread.  */
1243   _hurd_sigthread = ss->thread;
1244
1245   /* Start the signal thread listening on the message port.  */
1246
1247   if (__hurd_threadvar_stack_mask == 0)
1248     {
1249       err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
1250       assert_perror (err);
1251
1252       stacksize = __vm_page_size * 8; /* Small stack for signal thread.  */
1253       err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
1254                                  _hurd_msgport_receive,
1255                                  (vm_address_t *) &__hurd_sigthread_stack_base,
1256                                  &stacksize);
1257       assert_perror (err);
1258
1259       __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
1260       __hurd_sigthread_variables =
1261         malloc (__hurd_threadvar_max * sizeof (unsigned long int));
1262       if (__hurd_sigthread_variables == NULL)
1263         __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n");
1264
1265       /* Reinitialize the MiG support routines so they will use a per-thread
1266          variable for the cached reply port.  */
1267       __mig_init ((void *) __hurd_sigthread_stack_base);
1268
1269       err = __thread_resume (_hurd_msgport_thread);
1270       assert_perror (err);
1271     }
1272   else
1273     {
1274       /* When cthreads is being used, we need to make the signal thread a
1275          proper cthread.  Otherwise it cannot use mutex_lock et al, which
1276          will be the cthreads versions.  Various of the message port RPC
1277          handlers need to take locks, so we need to be able to call into
1278          cthreads code and meet its assumptions about how our thread and
1279          its stack are arranged.  Since cthreads puts it there anyway,
1280          we'll let the signal thread's per-thread variables be found as for
1281          any normal cthread, and just leave the magic __hurd_sigthread_*
1282          values all zero so they'll be ignored.  */
1283 #pragma weak cthread_fork
1284 #pragma weak cthread_detach
1285       cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0));
1286
1287       /* XXX We need the thread port for the signal thread further on
1288          in this thread (see hurdfault.c:_hurdsigfault_init).
1289          Therefore we block until _hurd_msgport_thread is initialized
1290          by the newly created thread.  This really shouldn't be
1291          necessary; we should be able to fetch the thread port for a
1292          cthread from here.  */
1293       while (_hurd_msgport_thread == 0)
1294         __swtch_pri (0);
1295     }
1296
1297   /* Receive exceptions on the signal port.  */
1298   __task_set_special_port (__mach_task_self (),
1299                            TASK_EXCEPTION_PORT, _hurd_msgport);
1300
1301   /* Sanity check.  Any pending, unblocked signals should have been
1302      taken by our predecessor incarnation (i.e. parent or pre-exec state)
1303      before packing up our init ints.  This assert is last (not above)
1304      so that signal handling is all set up to handle the abort.  */
1305   assert ((ss->pending &~ ss->blocked) == 0);
1306 }
1307 \f                               /* XXXX */
1308 /* Reauthenticate with the proc server.  */
1309
1310 static void
1311 reauth_proc (mach_port_t new)
1312 {
1313   mach_port_t ref, ignore;
1314
1315   ref = __mach_reply_port ();
1316   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1317                        __proc_reauthenticate (port, ref,
1318                                               MACH_MSG_TYPE_MAKE_SEND) ||
1319                        __auth_user_authenticate (new, ref,
1320                                                  MACH_MSG_TYPE_MAKE_SEND,
1321                                                  &ignore))
1322       && ignore != MACH_PORT_NULL)
1323     __mach_port_deallocate (__mach_task_self (), ignore);
1324   __mach_port_destroy (__mach_task_self (), ref);
1325
1326   /* Set the owner of the process here too. */
1327   mutex_lock (&_hurd_id.lock);
1328   if (!_hurd_check_ids ())
1329     HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1330                    __proc_setowner (port,
1331                                     (_hurd_id.gen.nuids
1332                                      ? _hurd_id.gen.uids[0] : 0),
1333                                     !_hurd_id.gen.nuids));
1334   mutex_unlock (&_hurd_id.lock);
1335
1336   (void) &reauth_proc;          /* Silence compiler warning.  */
1337 }
1338 text_set_element (_hurd_reauth_hook, reauth_proc);
1339 \f
1340 /* Like `getenv', but safe for the signal thread to run.
1341    If the environment is trashed, this will just return NULL.  */
1342
1343 const char *
1344 _hurdsig_getenv (const char *variable)
1345 {
1346   if (_hurdsig_catch_memory_fault (__environ))
1347     /* We bombed in getenv.  */
1348     return NULL;
1349   else
1350     {
1351       const size_t len = strlen (variable);
1352       char *value = NULL;
1353       char *volatile *ep = __environ;
1354       while (*ep)
1355         {
1356           const char *p = *ep;
1357           _hurdsig_fault_preemptor.first = (long int) p;
1358           _hurdsig_fault_preemptor.last = VM_MAX_ADDRESS;
1359           if (! strncmp (p, variable, len) && p[len] == '=')
1360             {
1361               size_t valuelen;
1362               p += len + 1;
1363               valuelen = strlen (p);
1364               _hurdsig_fault_preemptor.last = (long int) (p + valuelen);
1365               value = malloc (++valuelen);
1366               if (value)
1367                 memcpy (value, p, valuelen);
1368               break;
1369             }
1370           _hurdsig_fault_preemptor.first = (long int) ++ep;
1371           _hurdsig_fault_preemptor.last = (long int) (ep + 1);
1372         }
1373       _hurdsig_end_catch_fault ();
1374       return value;
1375     }
1376 }