2001-06-18 Roland McGrath <roland@frob.com>
[kopensolaris-gnu/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 Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    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    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 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 = 0;
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         /* Block SIGNO and requested signals while running the handler.  */
930         scp->sc_mask = ss->blocked;
931         ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
932
933         /* Start the thread running the handler (or possibly waiting for an
934            RPC reply before running the handler).  */
935         err = __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
936                                   (natural_t *) &thread_state.basic,
937                                   MACHINE_THREAD_STATE_COUNT);
938         assert_perror (err);
939         err = __thread_resume (ss->thread);
940         assert_perror (err);
941         thread_state.set = 0;   /* Everything we know is now wrong.  */
942         break;
943       }
944     }
945
946   /* The signal has either been ignored or is now being handled.  We can
947      consider it delivered and reply to the killer.  */
948   reply ();
949
950   /* We get here unless the signal was fatal.  We still hold SS->lock.
951      Check for pending signals, and loop to post them.  */
952   {
953     /* Return nonzero if SS has any signals pending we should worry about.
954        We don't worry about any pending signals if we are stopped, nor if
955        SS is in a critical section.  We are guaranteed to get a sig_post
956        message before any of them become deliverable: either the SIGCONT
957        signal, or a sig_post with SIGNO==0 as an explicit poll when the
958        thread finishes its critical section.  */
959     inline int signals_pending (void)
960       {
961         if (_hurd_stopped || __spin_lock_locked (&ss->critical_section_lock))
962           return 0;
963         return pending = ss->pending & ~ss->blocked;
964       }
965
966   check_pending_signals:
967     untraced = 0;
968
969     if (signals_pending ())
970       {
971         for (signo = 1; signo < NSIG; ++signo)
972           if (__sigismember (&pending, signo))
973             {
974             deliver_pending:
975               __sigdelset (&ss->pending, signo);
976               *detail = ss->pending_data[signo];
977               __spin_unlock (&ss->lock);
978               goto post_signal;
979             }
980       }
981
982     /* No pending signals left undelivered for this thread.
983        If we were sent signal 0, we need to check for pending
984        signals for all threads.  */
985     if (signo == 0)
986       {
987         __spin_unlock (&ss->lock);
988         __mutex_lock (&_hurd_siglock);
989         for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
990           {
991             __spin_lock (&ss->lock);
992             for (signo = 1; signo < NSIG; ++signo)
993               if (__sigismember (&ss->pending, signo)
994                   && (!__sigismember (&ss->blocked, signo)
995                       /* We "deliver" immediately pending blocked signals whose
996                          action might be to ignore, so that if ignored they are
997                          dropped right away.  */
998                       || ss->actions[signo].sa_handler == SIG_IGN
999                       || ss->actions[signo].sa_handler == SIG_DFL))
1000                 {
1001                   mutex_unlock (&_hurd_siglock);
1002                   goto deliver_pending;
1003                 }
1004             __spin_unlock (&ss->lock);
1005           }
1006         __mutex_unlock (&_hurd_siglock);
1007       }
1008     else
1009       {
1010         /* No more signals pending; SS->lock is still locked.
1011            Wake up any sigsuspend call that is blocking SS->thread.  */
1012         if (ss->suspended != MACH_PORT_NULL)
1013           {
1014             /* There is a sigsuspend waiting.  Tell it to wake up.  */
1015             error_t err;
1016             mach_msg_header_t msg;
1017             err = __mach_port_insert_right (__mach_task_self (),
1018                                             ss->suspended, ss->suspended,
1019                                             MACH_MSG_TYPE_MAKE_SEND);
1020             assert_perror (err);
1021             msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MOVE_SEND, 0);
1022             msg.msgh_remote_port = ss->suspended;
1023             msg.msgh_local_port = MACH_PORT_NULL;
1024             /* These values do not matter.  */
1025             msg.msgh_id = 8675309; /* Jenny, Jenny.  */
1026             msg.msgh_seqno = 17; /* Random.  */
1027             ss->suspended = MACH_PORT_NULL;
1028             err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
1029                               MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
1030                               MACH_PORT_NULL);
1031             assert_perror (err);
1032           }
1033         __spin_unlock (&ss->lock);
1034       }
1035   }
1036
1037   /* All pending signals delivered to all threads.
1038      Now we can send the reply message even for signal 0.  */
1039   reply ();
1040 }
1041 \f
1042 /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
1043    Returns zero if so, otherwise the error code to return to the sender.  */
1044
1045 static error_t
1046 signal_allowed (int signo, mach_port_t refport)
1047 {
1048   if (signo < 0 || signo >= NSIG)
1049     return EINVAL;
1050
1051   if (refport == __mach_task_self ())
1052     /* Can send any signal.  */
1053     goto win;
1054
1055   /* Avoid needing to check for this below.  */
1056   if (refport == MACH_PORT_NULL)
1057     return EPERM;
1058
1059   switch (signo)
1060     {
1061     case SIGINT:
1062     case SIGQUIT:
1063     case SIGTSTP:
1064     case SIGHUP:
1065     case SIGINFO:
1066     case SIGTTIN:
1067     case SIGTTOU:
1068     case SIGWINCH:
1069       /* Job control signals can be sent by the controlling terminal.  */
1070       if (__USEPORT (CTTYID, port == refport))
1071         goto win;
1072       break;
1073
1074     case SIGCONT:
1075       {
1076         /* A continue signal can be sent by anyone in the session.  */
1077         mach_port_t sessport;
1078         if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
1079           {
1080             __mach_port_deallocate (__mach_task_self (), sessport);
1081             if (refport == sessport)
1082               goto win;
1083           }
1084       }
1085       break;
1086
1087     case SIGIO:
1088     case SIGURG:
1089       {
1090         /* Any io object a file descriptor refers to might send us
1091            one of these signals using its async ID port for REFPORT.
1092
1093            This is pretty wide open; it is not unlikely that some random
1094            process can at least open for reading something we have open,
1095            get its async ID port, and send us a spurious SIGIO or SIGURG
1096            signal.  But BSD is actually wider open than that!--you can set
1097            the owner of an io object to any process or process group
1098            whatsoever and send them gratuitous signals.
1099
1100            Someday we could implement some reasonable scheme for
1101            authorizing SIGIO and SIGURG signals properly.  */
1102
1103         int d;
1104         int lucky = 0;          /* True if we find a match for REFPORT.  */
1105         __mutex_lock (&_hurd_dtable_lock);
1106         for (d = 0; !lucky && (unsigned) d < (unsigned) _hurd_dtablesize; ++d)
1107           {
1108             struct hurd_userlink ulink;
1109             io_t port;
1110             mach_port_t asyncid;
1111             if (_hurd_dtable[d] == NULL)
1112               continue;
1113             port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
1114             if (! __io_get_icky_async_id (port, &asyncid))
1115               {
1116                 if (refport == asyncid)
1117                   /* Break out of the loop on the next iteration.  */
1118                   lucky = 1;
1119                 __mach_port_deallocate (__mach_task_self (), asyncid);
1120               }
1121             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
1122           }
1123         /* If we found a lucky winner, we've set D to -1 in the loop.  */
1124         if (lucky)
1125           goto win;
1126       }
1127     }
1128
1129   /* If this signal is legit, we have done `goto win' by now.
1130      When we return the error, mig deallocates REFPORT.  */
1131   return EPERM;
1132
1133  win:
1134   /* Deallocate the REFPORT send right; we are done with it.  */
1135   __mach_port_deallocate (__mach_task_self (), refport);
1136
1137   return 0;
1138 }
1139
1140 /* Implement the sig_post RPC from <hurd/msg.defs>;
1141    sent when someone wants us to get a signal.  */
1142 kern_return_t
1143 _S_msg_sig_post (mach_port_t me,
1144                  mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
1145                  int signo, natural_t sigcode,
1146                  mach_port_t refport)
1147 {
1148   error_t err;
1149   struct hurd_signal_detail d;
1150
1151   if (err = signal_allowed (signo, refport))
1152     return err;
1153
1154   d.code = sigcode;
1155   d.exc = 0;
1156
1157   /* Post the signal to the designated signal-receiving thread.  This will
1158      reply when the signal can be considered delivered.  */
1159   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1160                               signo, &d, reply_port, reply_port_type,
1161                               0); /* Stop if traced.  */
1162
1163   return MIG_NO_REPLY;          /* Already replied.  */
1164 }
1165
1166 /* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
1167    sent when the debugger wants us to really get a signal
1168    even if we are traced.  */
1169 kern_return_t
1170 _S_msg_sig_post_untraced (mach_port_t me,
1171                           mach_port_t reply_port,
1172                           mach_msg_type_name_t reply_port_type,
1173                           int signo, natural_t sigcode,
1174                           mach_port_t refport)
1175 {
1176   error_t err;
1177   struct hurd_signal_detail d;
1178
1179   if (err = signal_allowed (signo, refport))
1180     return err;
1181
1182   d.code = sigcode;
1183   d.exc = 0;
1184
1185   /* Post the signal to the designated signal-receiving thread.  This will
1186      reply when the signal can be considered delivered.  */
1187   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1188                               signo, &d, reply_port, reply_port_type,
1189                               1); /* Untraced flag. */
1190
1191   return MIG_NO_REPLY;          /* Already replied.  */
1192 }
1193 \f
1194 extern void __mig_init (void *);
1195
1196 #include <mach/task_special_ports.h>
1197
1198 /* Initialize the message port and _hurd_sigthread and start the signal
1199    thread.  */
1200
1201 void
1202 _hurdsig_init (const int *intarray, size_t intarraysize)
1203 {
1204   error_t err;
1205   vm_size_t stacksize;
1206   struct hurd_sigstate *ss;
1207
1208   __mutex_init (&_hurd_siglock);
1209
1210   err = __mach_port_allocate (__mach_task_self (),
1211                               MACH_PORT_RIGHT_RECEIVE,
1212                               &_hurd_msgport);
1213   assert_perror (err);
1214
1215   /* Make a send right to the signal port.  */
1216   err = __mach_port_insert_right (__mach_task_self (),
1217                                   _hurd_msgport,
1218                                   _hurd_msgport,
1219                                   MACH_MSG_TYPE_MAKE_SEND);
1220   assert_perror (err);
1221
1222   /* Initialize the main thread's signal state.  */
1223   ss = _hurd_self_sigstate ();
1224
1225   /* Copy inherited values from our parent (or pre-exec process state)
1226      into the signal settings of the main thread.  */
1227   if (intarraysize > INIT_SIGMASK)
1228     ss->blocked = intarray[INIT_SIGMASK];
1229   if (intarraysize > INIT_SIGPENDING)
1230     ss->blocked = intarray[INIT_SIGPENDING];
1231   if (intarraysize > INIT_SIGIGN && intarray[INIT_SIGIGN] != 0)
1232     {
1233       int signo;
1234       for (signo = 1; signo < NSIG; ++signo)
1235         if (intarray[INIT_SIGIGN] & __sigmask(signo))
1236           ss->actions[signo].sa_handler = SIG_IGN;
1237     }
1238
1239   /* Set the default thread to receive task-global signals
1240      to this one, the main (first) user thread.  */
1241   _hurd_sigthread = ss->thread;
1242
1243   /* Start the signal thread listening on the message port.  */
1244
1245   if (__hurd_threadvar_stack_mask == 0)
1246     {
1247       err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
1248       assert_perror (err);
1249
1250       stacksize = ~__hurd_threadvar_stack_mask + 1;
1251       stacksize = __vm_page_size * 8; /* Small stack for signal thread.  */
1252       err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
1253                                  _hurd_msgport_receive,
1254                                  (vm_address_t *) &__hurd_sigthread_stack_base,
1255                                  &stacksize);
1256       assert_perror (err);
1257
1258       __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
1259       __hurd_sigthread_variables =
1260         malloc (__hurd_threadvar_max * sizeof (unsigned long int));
1261       if (__hurd_sigthread_variables == NULL)
1262         __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n");
1263
1264       /* Reinitialize the MiG support routines so they will use a per-thread
1265          variable for the cached reply port.  */
1266       __mig_init ((void *) __hurd_sigthread_stack_base);
1267
1268       err = __thread_resume (_hurd_msgport_thread);
1269       assert_perror (err);
1270     }
1271   else
1272     {
1273       /* When cthreads is being used, we need to make the signal thread a
1274          proper cthread.  Otherwise it cannot use mutex_lock et al, which
1275          will be the cthreads versions.  Various of the message port RPC
1276          handlers need to take locks, so we need to be able to call into
1277          cthreads code and meet its assumptions about how our thread and
1278          its stack are arranged.  Since cthreads puts it there anyway,
1279          we'll let the signal thread's per-thread variables be found as for
1280          any normal cthread, and just leave the magic __hurd_sigthread_*
1281          values all zero so they'll be ignored.  */
1282 #pragma weak cthread_fork
1283 #pragma weak cthread_detach
1284       cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0));
1285
1286       /* XXX We need the thread port for the signal thread further on
1287          in this thread (see hurdfault.c:_hurdsigfault_init).
1288          Therefore we block until _hurd_msgport_thread is initialized
1289          by the newly created thread.  This really shouldn't be
1290          necessary; we should be able to fetch the thread port for a
1291          cthread from here.  */
1292       while (_hurd_msgport_thread == 0)
1293         __swtch_pri (0);
1294     }
1295
1296   /* Receive exceptions on the signal port.  */
1297   __task_set_special_port (__mach_task_self (),
1298                            TASK_EXCEPTION_PORT, _hurd_msgport);
1299
1300   /* Sanity check.  Any pending, unblocked signals should have been
1301      taken by our predecessor incarnation (i.e. parent or pre-exec state)
1302      before packing up our init ints.  This assert is last (not above)
1303      so that signal handling is all set up to handle the abort.  */
1304   assert ((ss->pending &~ ss->blocked) == 0);
1305 }
1306 \f                               /* XXXX */
1307 /* Reauthenticate with the proc server.  */
1308
1309 static void
1310 reauth_proc (mach_port_t new)
1311 {
1312   mach_port_t ref, ignore;
1313
1314   ref = __mach_reply_port ();
1315   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1316                        __proc_reauthenticate (port, ref,
1317                                               MACH_MSG_TYPE_MAKE_SEND) ||
1318                        __auth_user_authenticate (new, ref,
1319                                                  MACH_MSG_TYPE_MAKE_SEND,
1320                                                  &ignore))
1321       && ignore != MACH_PORT_NULL)
1322     __mach_port_deallocate (__mach_task_self (), ignore);
1323   __mach_port_destroy (__mach_task_self (), ref);
1324
1325   /* Set the owner of the process here too. */
1326   mutex_lock (&_hurd_id.lock);
1327   if (!_hurd_check_ids ())
1328     HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1329                    __proc_setowner (port,
1330                                     (_hurd_id.gen.nuids
1331                                      ? _hurd_id.gen.uids[0] : 0),
1332                                     !_hurd_id.gen.nuids));
1333   mutex_unlock (&_hurd_id.lock);
1334
1335   (void) &reauth_proc;          /* Silence compiler warning.  */
1336 }
1337 text_set_element (_hurd_reauth_hook, reauth_proc);
1338 \f
1339 /* Like `getenv', but safe for the signal thread to run.
1340    If the environment is trashed, this will just return NULL.  */
1341
1342 const char *
1343 _hurdsig_getenv (const char *variable)
1344 {
1345   if (_hurdsig_catch_memory_fault (__environ))
1346     /* We bombed in getenv.  */
1347     return NULL;
1348   else
1349     {
1350       const size_t len = strlen (variable);
1351       char *value = NULL;
1352       char *volatile *ep = __environ;
1353       while (*ep)
1354         {
1355           const char *p = *ep;
1356           _hurdsig_fault_preemptor.first = (long int) p;
1357           _hurdsig_fault_preemptor.last = VM_MAX_ADDRESS;
1358           if (! strncmp (p, variable, len) && p[len] == '=')
1359             {
1360               size_t valuelen;
1361               p += len + 1;
1362               valuelen = strlen (p);
1363               _hurdsig_fault_preemptor.last = (long int) (p + valuelen);
1364               value = malloc (++valuelen);
1365               if (value)
1366                 memcpy (value, p, valuelen);
1367               break;
1368             }
1369           _hurdsig_fault_preemptor.first = (long int) ++ep;
1370           _hurdsig_fault_preemptor.last = (long int) (ep + 1);
1371         }
1372       _hurdsig_end_catch_fault ();
1373       return value;
1374     }
1375 }