2001-07-11 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         /* 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             msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
1018             msg.msgh_remote_port = ss->suspended;
1019             msg.msgh_local_port = MACH_PORT_NULL;
1020             /* These values do not matter.  */
1021             msg.msgh_id = 8675309; /* Jenny, Jenny.  */
1022             msg.msgh_seqno = 17; /* Random.  */
1023             ss->suspended = MACH_PORT_NULL;
1024             err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
1025                               MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
1026                               MACH_PORT_NULL);
1027             assert_perror (err);
1028           }
1029         __spin_unlock (&ss->lock);
1030       }
1031   }
1032
1033   /* All pending signals delivered to all threads.
1034      Now we can send the reply message even for signal 0.  */
1035   reply ();
1036 }
1037 \f
1038 /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
1039    Returns zero if so, otherwise the error code to return to the sender.  */
1040
1041 static error_t
1042 signal_allowed (int signo, mach_port_t refport)
1043 {
1044   if (signo < 0 || signo >= NSIG)
1045     return EINVAL;
1046
1047   if (refport == __mach_task_self ())
1048     /* Can send any signal.  */
1049     goto win;
1050
1051   /* Avoid needing to check for this below.  */
1052   if (refport == MACH_PORT_NULL)
1053     return EPERM;
1054
1055   switch (signo)
1056     {
1057     case SIGINT:
1058     case SIGQUIT:
1059     case SIGTSTP:
1060     case SIGHUP:
1061     case SIGINFO:
1062     case SIGTTIN:
1063     case SIGTTOU:
1064     case SIGWINCH:
1065       /* Job control signals can be sent by the controlling terminal.  */
1066       if (__USEPORT (CTTYID, port == refport))
1067         goto win;
1068       break;
1069
1070     case SIGCONT:
1071       {
1072         /* A continue signal can be sent by anyone in the session.  */
1073         mach_port_t sessport;
1074         if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
1075           {
1076             __mach_port_deallocate (__mach_task_self (), sessport);
1077             if (refport == sessport)
1078               goto win;
1079           }
1080       }
1081       break;
1082
1083     case SIGIO:
1084     case SIGURG:
1085       {
1086         /* Any io object a file descriptor refers to might send us
1087            one of these signals using its async ID port for REFPORT.
1088
1089            This is pretty wide open; it is not unlikely that some random
1090            process can at least open for reading something we have open,
1091            get its async ID port, and send us a spurious SIGIO or SIGURG
1092            signal.  But BSD is actually wider open than that!--you can set
1093            the owner of an io object to any process or process group
1094            whatsoever and send them gratuitous signals.
1095
1096            Someday we could implement some reasonable scheme for
1097            authorizing SIGIO and SIGURG signals properly.  */
1098
1099         int d;
1100         int lucky = 0;          /* True if we find a match for REFPORT.  */
1101         __mutex_lock (&_hurd_dtable_lock);
1102         for (d = 0; !lucky && (unsigned) d < (unsigned) _hurd_dtablesize; ++d)
1103           {
1104             struct hurd_userlink ulink;
1105             io_t port;
1106             mach_port_t asyncid;
1107             if (_hurd_dtable[d] == NULL)
1108               continue;
1109             port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
1110             if (! __io_get_icky_async_id (port, &asyncid))
1111               {
1112                 if (refport == asyncid)
1113                   /* Break out of the loop on the next iteration.  */
1114                   lucky = 1;
1115                 __mach_port_deallocate (__mach_task_self (), asyncid);
1116               }
1117             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
1118           }
1119         /* If we found a lucky winner, we've set D to -1 in the loop.  */
1120         if (lucky)
1121           goto win;
1122       }
1123     }
1124
1125   /* If this signal is legit, we have done `goto win' by now.
1126      When we return the error, mig deallocates REFPORT.  */
1127   return EPERM;
1128
1129  win:
1130   /* Deallocate the REFPORT send right; we are done with it.  */
1131   __mach_port_deallocate (__mach_task_self (), refport);
1132
1133   return 0;
1134 }
1135
1136 /* Implement the sig_post RPC from <hurd/msg.defs>;
1137    sent when someone wants us to get a signal.  */
1138 kern_return_t
1139 _S_msg_sig_post (mach_port_t me,
1140                  mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
1141                  int signo, natural_t sigcode,
1142                  mach_port_t refport)
1143 {
1144   error_t err;
1145   struct hurd_signal_detail d;
1146
1147   if (err = signal_allowed (signo, refport))
1148     return err;
1149
1150   d.code = sigcode;
1151   d.exc = 0;
1152
1153   /* Post the signal to the designated signal-receiving thread.  This will
1154      reply when the signal can be considered delivered.  */
1155   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1156                               signo, &d, reply_port, reply_port_type,
1157                               0); /* Stop if traced.  */
1158
1159   return MIG_NO_REPLY;          /* Already replied.  */
1160 }
1161
1162 /* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
1163    sent when the debugger wants us to really get a signal
1164    even if we are traced.  */
1165 kern_return_t
1166 _S_msg_sig_post_untraced (mach_port_t me,
1167                           mach_port_t reply_port,
1168                           mach_msg_type_name_t reply_port_type,
1169                           int signo, natural_t sigcode,
1170                           mach_port_t refport)
1171 {
1172   error_t err;
1173   struct hurd_signal_detail d;
1174
1175   if (err = signal_allowed (signo, refport))
1176     return err;
1177
1178   d.code = sigcode;
1179   d.exc = 0;
1180
1181   /* Post the signal to the designated signal-receiving thread.  This will
1182      reply when the signal can be considered delivered.  */
1183   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1184                               signo, &d, reply_port, reply_port_type,
1185                               1); /* Untraced flag. */
1186
1187   return MIG_NO_REPLY;          /* Already replied.  */
1188 }
1189 \f
1190 extern void __mig_init (void *);
1191
1192 #include <mach/task_special_ports.h>
1193
1194 /* Initialize the message port and _hurd_sigthread and start the signal
1195    thread.  */
1196
1197 void
1198 _hurdsig_init (const int *intarray, size_t intarraysize)
1199 {
1200   error_t err;
1201   vm_size_t stacksize;
1202   struct hurd_sigstate *ss;
1203
1204   __mutex_init (&_hurd_siglock);
1205
1206   err = __mach_port_allocate (__mach_task_self (),
1207                               MACH_PORT_RIGHT_RECEIVE,
1208                               &_hurd_msgport);
1209   assert_perror (err);
1210
1211   /* Make a send right to the signal port.  */
1212   err = __mach_port_insert_right (__mach_task_self (),
1213                                   _hurd_msgport,
1214                                   _hurd_msgport,
1215                                   MACH_MSG_TYPE_MAKE_SEND);
1216   assert_perror (err);
1217
1218   /* Initialize the main thread's signal state.  */
1219   ss = _hurd_self_sigstate ();
1220
1221   /* Copy inherited values from our parent (or pre-exec process state)
1222      into the signal settings of the main thread.  */
1223   if (intarraysize > INIT_SIGMASK)
1224     ss->blocked = intarray[INIT_SIGMASK];
1225   if (intarraysize > INIT_SIGPENDING)
1226     ss->blocked = intarray[INIT_SIGPENDING];
1227   if (intarraysize > INIT_SIGIGN && intarray[INIT_SIGIGN] != 0)
1228     {
1229       int signo;
1230       for (signo = 1; signo < NSIG; ++signo)
1231         if (intarray[INIT_SIGIGN] & __sigmask(signo))
1232           ss->actions[signo].sa_handler = SIG_IGN;
1233     }
1234
1235   /* Set the default thread to receive task-global signals
1236      to this one, the main (first) user thread.  */
1237   _hurd_sigthread = ss->thread;
1238
1239   /* Start the signal thread listening on the message port.  */
1240
1241   if (__hurd_threadvar_stack_mask == 0)
1242     {
1243       err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
1244       assert_perror (err);
1245
1246       stacksize = __vm_page_size * 8; /* Small stack for signal thread.  */
1247       err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
1248                                  _hurd_msgport_receive,
1249                                  (vm_address_t *) &__hurd_sigthread_stack_base,
1250                                  &stacksize);
1251       assert_perror (err);
1252
1253       __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
1254       __hurd_sigthread_variables =
1255         malloc (__hurd_threadvar_max * sizeof (unsigned long int));
1256       if (__hurd_sigthread_variables == NULL)
1257         __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n");
1258
1259       /* Reinitialize the MiG support routines so they will use a per-thread
1260          variable for the cached reply port.  */
1261       __mig_init ((void *) __hurd_sigthread_stack_base);
1262
1263       err = __thread_resume (_hurd_msgport_thread);
1264       assert_perror (err);
1265     }
1266   else
1267     {
1268       /* When cthreads is being used, we need to make the signal thread a
1269          proper cthread.  Otherwise it cannot use mutex_lock et al, which
1270          will be the cthreads versions.  Various of the message port RPC
1271          handlers need to take locks, so we need to be able to call into
1272          cthreads code and meet its assumptions about how our thread and
1273          its stack are arranged.  Since cthreads puts it there anyway,
1274          we'll let the signal thread's per-thread variables be found as for
1275          any normal cthread, and just leave the magic __hurd_sigthread_*
1276          values all zero so they'll be ignored.  */
1277 #pragma weak cthread_fork
1278 #pragma weak cthread_detach
1279       cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0));
1280
1281       /* XXX We need the thread port for the signal thread further on
1282          in this thread (see hurdfault.c:_hurdsigfault_init).
1283          Therefore we block until _hurd_msgport_thread is initialized
1284          by the newly created thread.  This really shouldn't be
1285          necessary; we should be able to fetch the thread port for a
1286          cthread from here.  */
1287       while (_hurd_msgport_thread == 0)
1288         __swtch_pri (0);
1289     }
1290
1291   /* Receive exceptions on the signal port.  */
1292   __task_set_special_port (__mach_task_self (),
1293                            TASK_EXCEPTION_PORT, _hurd_msgport);
1294
1295   /* Sanity check.  Any pending, unblocked signals should have been
1296      taken by our predecessor incarnation (i.e. parent or pre-exec state)
1297      before packing up our init ints.  This assert is last (not above)
1298      so that signal handling is all set up to handle the abort.  */
1299   assert ((ss->pending &~ ss->blocked) == 0);
1300 }
1301 \f                               /* XXXX */
1302 /* Reauthenticate with the proc server.  */
1303
1304 static void
1305 reauth_proc (mach_port_t new)
1306 {
1307   mach_port_t ref, ignore;
1308
1309   ref = __mach_reply_port ();
1310   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1311                        __proc_reauthenticate (port, ref,
1312                                               MACH_MSG_TYPE_MAKE_SEND) ||
1313                        __auth_user_authenticate (new, ref,
1314                                                  MACH_MSG_TYPE_MAKE_SEND,
1315                                                  &ignore))
1316       && ignore != MACH_PORT_NULL)
1317     __mach_port_deallocate (__mach_task_self (), ignore);
1318   __mach_port_destroy (__mach_task_self (), ref);
1319
1320   /* Set the owner of the process here too. */
1321   mutex_lock (&_hurd_id.lock);
1322   if (!_hurd_check_ids ())
1323     HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1324                    __proc_setowner (port,
1325                                     (_hurd_id.gen.nuids
1326                                      ? _hurd_id.gen.uids[0] : 0),
1327                                     !_hurd_id.gen.nuids));
1328   mutex_unlock (&_hurd_id.lock);
1329
1330   (void) &reauth_proc;          /* Silence compiler warning.  */
1331 }
1332 text_set_element (_hurd_reauth_hook, reauth_proc);
1333 \f
1334 /* Like `getenv', but safe for the signal thread to run.
1335    If the environment is trashed, this will just return NULL.  */
1336
1337 const char *
1338 _hurdsig_getenv (const char *variable)
1339 {
1340   if (_hurdsig_catch_memory_fault (__environ))
1341     /* We bombed in getenv.  */
1342     return NULL;
1343   else
1344     {
1345       const size_t len = strlen (variable);
1346       char *value = NULL;
1347       char *volatile *ep = __environ;
1348       while (*ep)
1349         {
1350           const char *p = *ep;
1351           _hurdsig_fault_preemptor.first = (long int) p;
1352           _hurdsig_fault_preemptor.last = VM_MAX_ADDRESS;
1353           if (! strncmp (p, variable, len) && p[len] == '=')
1354             {
1355               size_t valuelen;
1356               p += len + 1;
1357               valuelen = strlen (p);
1358               _hurdsig_fault_preemptor.last = (long int) (p + valuelen);
1359               value = malloc (++valuelen);
1360               if (value)
1361                 memcpy (value, p, valuelen);
1362               break;
1363             }
1364           _hurdsig_fault_preemptor.first = (long int) ++ep;
1365           _hurdsig_fault_preemptor.last = (long int) (ep + 1);
1366         }
1367       _hurdsig_end_catch_fault ();
1368       return value;
1369     }
1370 }