1 /* interpreter signal handling functions */
2 /*
3 Copyright (C) 2004-2017,2018 John E. Davis
4 
5 This file is part of the S-Lang Library.
6 
7 The S-Lang Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11 
12 The S-Lang Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 USA.
21 */
22 
23 #include "slinclud.h"
24 
25 #include <signal.h>
26 #include <errno.h>
27 
28 #ifdef HAVE_SYS_TYPES_H
29 # include <sys/types.h>
30 #endif
31 #ifdef HAVE_SYS_WAIT_H
32 # include <sys/wait.h>
33 #endif
34 
35 #ifdef HAVE_SYS_TIME_H
36 # include <sys/time.h>
37 #endif
38 
39 #include "slang.h"
40 #include "_slang.h"
41 
42 #if SLANG_HAS_SIGNALS		       /* until end of file */
43 
44 /* Do not trust these environments */
45 #if defined(__MINGW32__) || defined(AMIGA)
46 # ifdef SLANG_POSIX_SIGNALS
47 #  undef SLANG_POSIX_SIGNALS
48 # endif
49 #endif
50 
51 typedef struct
52 {
53    int sig;
54    SLFUTURE_CONST char *name;
55    SLang_Name_Type *handler;
56    void (*c_handler)(int);
57    int pending;			       /* if set, the signal needs to be delivered */
58    int forbidden;		       /* If set, this signal is off-limits */
59 }
60 Signal_Type;
61 
62 #define SIG_DFL_CONSTANT	0
63 #define SIG_IGN_CONSTANT	1
64 #define SIG_APP_CONSTANT	2
65 
66 /* SIG_APP represents the application's handler */
67 #ifdef SLANG_POSIX_SIGNALS
68 typedef sigset_t Signal_Set_Type;
69 #else
70 typedef int Signal_Set_Type;
71 #endif
72 
73 #define MAKE_SIGNAL(sig,name) {sig,name,NULL,NULL,0,0}
74 static Signal_Type Signal_Table [] =
75 {
76 #ifdef SIGHUP
77      MAKE_SIGNAL(SIGHUP,"SIGHUP"),
78 #endif
79 #ifdef SIGINT
80      MAKE_SIGNAL(SIGINT,"SIGINT"),
81 #endif
82 #ifdef SIGQUIT
83      MAKE_SIGNAL(SIGQUIT,"SIGQUIT"),
84 #endif
85 #ifdef SIGILL
86      MAKE_SIGNAL(SIGILL,"SIGILL"),
87 #endif
88 #ifdef SIGTRAP
89      MAKE_SIGNAL(SIGTRAP,"SIGTRAP"),
90 #endif
91 #ifdef SIGABRT
92      MAKE_SIGNAL(SIGABRT,"SIGABRT"),
93 #endif
94 #ifdef SIGIOT
95      MAKE_SIGNAL(SIGIOT,"SIGIOT"),
96 #endif
97 #ifdef SIGBUS
98      MAKE_SIGNAL(SIGBUS,"SIGBUS"),
99 #endif
100 #ifdef SIGFPE
101      MAKE_SIGNAL(SIGFPE,"SIGFPE"),
102 #endif
103 #ifdef SIGKILL
104      MAKE_SIGNAL(SIGKILL,"SIGKILL"),
105 #endif
106 #ifdef SIGUSR1
107      MAKE_SIGNAL(SIGUSR1,"SIGUSR1"),
108 #endif
109 #ifdef SIGSEGV
110      MAKE_SIGNAL(SIGSEGV,"SIGSEGV"),
111 #endif
112 #ifdef SIGUSR2
113      MAKE_SIGNAL(SIGUSR2,"SIGUSR2"),
114 #endif
115 #ifdef SIGPIPE
116      MAKE_SIGNAL(SIGPIPE,"SIGPIPE"),
117 #endif
118 #ifdef SIGALRM
119      MAKE_SIGNAL(SIGALRM,"SIGALRM"),
120 #endif
121 #ifdef SIGTERM
122      MAKE_SIGNAL(SIGTERM,"SIGTERM"),
123 #endif
124 #ifdef SIGSTKFLT
125      MAKE_SIGNAL(SIGSTKFLT,"SIGSTKFLT"),
126 #endif
127 #ifdef SIGCHLD
128      MAKE_SIGNAL(SIGCHLD,"SIGCHLD"),
129 #endif
130 #ifdef SIGCONT
131      MAKE_SIGNAL(SIGCONT,"SIGCONT"),
132 #endif
133 #ifdef SIGSTOP
134      MAKE_SIGNAL(SIGSTOP,"SIGSTOP"),
135 #endif
136 #ifdef SIGTSTP
137      MAKE_SIGNAL(SIGTSTP,"SIGTSTP"),
138 #endif
139 #ifdef SIGTTIN
140      MAKE_SIGNAL(SIGTTIN,"SIGTTIN"),
141 #endif
142 #ifdef SIGTTOU
143      MAKE_SIGNAL(SIGTTOU,"SIGTTOU"),
144 #endif
145 #ifdef SIGURG
146      MAKE_SIGNAL(SIGURG,"SIGURG"),
147 #endif
148 #ifdef SIGXCPU
149      MAKE_SIGNAL(SIGXCPU,"SIGXCPU"),
150 #endif
151 #ifdef SIGXFSZ
152      MAKE_SIGNAL(SIGXFSZ,"SIGXFSZ"),
153 #endif
154 #ifdef SIGVTALRM
155      MAKE_SIGNAL(SIGVTALRM,"SIGVTALRM"),
156 #endif
157 #ifdef SIGPROF
158      MAKE_SIGNAL(SIGPROF,"SIGPROF"),
159 #endif
160 #ifdef SIGWINCH
161      MAKE_SIGNAL(SIGWINCH,"SIGWINCH"),
162 #endif
163 #ifdef SIGIO
164      MAKE_SIGNAL(SIGIO,"SIGIO"),
165 #endif
166 #ifdef SIGPOLL
167      MAKE_SIGNAL(SIGPOLL,"SIGPOLL"),
168 #endif
169 #ifdef SIGPWR
170      MAKE_SIGNAL(SIGPWR,"SIGPWR"),
171 #endif
172 #ifdef SIGSYS
173      MAKE_SIGNAL(SIGSYS,"SIGSYS"),
174 #endif
175      MAKE_SIGNAL(-1, NULL),
176 };
177 
find_signal(int sig)178 static Signal_Type *find_signal (int sig)
179 {
180    Signal_Type *s = Signal_Table;
181 
182    while (s->name != NULL)
183      {
184 	if (s->sig == sig)
185 	  return s;
186 	s++;
187      }
188    return NULL;
189 }
190 
191 #ifdef SLANG_POSIX_SIGNALS
do_sigprocmask(int how,sigset_t * new_mask,sigset_t * old_mask)192 static int do_sigprocmask (int how, sigset_t *new_mask, sigset_t *old_mask)
193 {
194    while (-1 == sigprocmask (how, new_mask, old_mask))
195      {
196 #ifdef EINTR
197 	if (errno == EINTR)
198 	  continue;
199 #endif
200 	return -1;
201      }
202    return 0;
203 }
204 #endif
205 
block_signal(int sig,int * was_blocked)206 static int block_signal (int sig, int *was_blocked)
207 {
208 #ifdef SLANG_POSIX_SIGNALS
209    sigset_t new_mask;
210    sigset_t old_mask;
211    sigemptyset (&new_mask);
212    sigaddset (&new_mask, sig);
213    (void) do_sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
214    *was_blocked = sigismember (&old_mask, sig);
215    return 0;
216 #else
217    *was_blocked = 0;
218    return 0;
219 #endif
220 }
221 
unblock_signal(int sig)222 static int unblock_signal (int sig)
223 {
224 #ifdef SLANG_POSIX_SIGNALS
225    sigset_t new_mask;
226    sigemptyset (&new_mask);
227    sigaddset (&new_mask, sig);
228    (void) do_sigprocmask (SIG_UNBLOCK, &new_mask, NULL);
229 #endif
230    return 0;
231 }
232 
signal_handler(int sig)233 static void signal_handler (int sig)
234 {
235    Signal_Type *s;
236    int e = errno;
237 
238    /* Until the signal has been delivered, block it. */
239    /* Hmmm... it appears that the system unblocks the signal as soon
240     * as this function exits.  Fortunately, this is not an issue.
241     */
242    /* (void) block_signal (sig); */
243    (void) SLsignal_intr (sig, &signal_handler);
244 
245    s = find_signal (sig);	       /* cannot fail here */
246 
247    s->pending = 1;
248    if (sig == SIGINT)
249      SLKeyBoard_Quit = 1;
250    _pSLang_signal_interrupt ();
251    errno = e;
252 }
253 
_pSLsig_block_and_call(int (* func)(VOID_STAR),VOID_STAR cd)254 int _pSLsig_block_and_call (int (*func)(VOID_STAR), VOID_STAR cd)
255 {
256    Signal_Type *s;
257    int status;
258 
259 #ifdef SLANG_POSIX_SIGNALS
260    sigset_t new_mask, old_mask;
261    sigemptyset (&new_mask);
262 #endif
263 
264    s = Signal_Table;
265    while (s->name != NULL)
266      {
267 	if (s->handler == NULL)
268 	  {
269 	     s++;
270 	     continue;
271 	  }
272 #ifdef SLANG_POSIX_SIGNALS
273 	sigaddset (&new_mask, s->sig);
274 #endif
275 	s++;
276      }
277 
278 #ifdef SLANG_POSIX_SIGNALS
279    (void) do_sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
280 #endif
281 
282    status = (*func) (cd);
283 
284 #ifdef SLANG_POSIX_SIGNALS
285    (void) do_sigprocmask (SIG_SETMASK, &old_mask, NULL);
286 #endif
287 
288    return status;
289 }
290 
291 /* This function is reentrant */
handle_signal(Signal_Type * s)292 static int handle_signal (Signal_Type *s)
293 {
294    int status = 0;
295    int was_blocked;
296 
297    (void) block_signal (s->sig, &was_blocked);
298 
299    /* At this point, sig is blocked and the handler is about to be called.
300     * The pending flag can be safely set to 0 here.
301     */
302    s->pending = 0;
303 
304    if (s->handler != NULL)
305      {
306 	int depth = SLstack_depth ();
307 
308 	if ((-1 == SLang_start_arg_list ())
309 	    || (-1 == SLang_push_integer (s->sig))
310 	    || (-1 == SLang_end_arg_list ())
311 	    || (-1 == SLexecute_function (s->handler)))
312 	  status = -1;
313 
314 	if ((status == 0)
315 	    && (depth != SLstack_depth ()))
316 	  {
317 	     SLang_verror (SL_Application_Error, "The signal handler %s corrupted the stack", s->handler->name);
318 	     status = -1;
319 	  }
320      }
321 
322    if (was_blocked == 0)
323      (void) unblock_signal (s->sig);
324 
325    return status;
326 }
327 
328 /* This routine gets called by the interpreter when a signal needs to be
329  * handled.
330  */
_pSLsig_handle_signals(void)331 int _pSLsig_handle_signals (void)
332 {
333    Signal_Type *s = Signal_Table;
334    int status = 0;
335 
336    while (s->name != NULL)
337      {
338 	if ((s->pending != 0)
339 	    && (-1 == handle_signal (s)))
340 	  status = -1;
341 
342 	s++;
343      }
344    return status;
345 }
346 
pop_signal(Signal_Type ** sp)347 static int pop_signal (Signal_Type **sp)
348 {
349    int sig;
350    Signal_Type *s;
351 
352    if (-1 == SLang_pop_int (&sig))
353      return -1;
354 
355    s = Signal_Table;
356    while (s->name != NULL)
357      {
358 	if (s->sig == sig)
359 	  {
360 	     if (s->forbidden)
361 	       {
362 		  SLang_set_error (SL_Forbidden_Error);
363 		  return -1;
364 	       }
365 
366 	     *sp = s;
367 	     return 0;
368 	  }
369 	s++;
370      }
371 
372    _pSLang_verror (SL_INVALID_PARM, "Signal %d invalid or unknown", sig);
373    return -1;
374 }
375 
set_old_handler(Signal_Type * s,SLang_Ref_Type * ref,void (* old_handler)(int))376 static int set_old_handler (Signal_Type *s, SLang_Ref_Type *ref, void (*old_handler)(int))
377 {
378    if (old_handler == (void (*)(int))SIG_ERR)
379      {
380 	_pSLang_verror (0, "signal system call failed");
381 	return -1;
382      }
383 
384    if (ref != NULL)
385      {
386 	int ret;
387 
388 	if (old_handler == signal_handler)
389 	  ret = SLang_assign_nametype_to_ref (ref, s->handler);
390 	else
391 	  {
392 	     int h;
393 
394 	     if (old_handler == SIG_IGN)
395 	       h = SIG_IGN_CONSTANT;
396 	     else if (old_handler == SIG_DFL)
397 	       h = SIG_DFL_CONSTANT;
398 	     else
399 	       h = SIG_APP_CONSTANT;
400 
401 	     ret = SLang_assign_to_ref (ref, SLANG_INT_TYPE, &h);
402 	  }
403 	if (ret == -1)
404 	  {
405 	     (void) SLsignal_intr (s->sig, old_handler);
406 	     return -1;
407 	  }
408      }
409 
410    if (old_handler != signal_handler)
411      s->c_handler = old_handler;
412 
413    return 0;
414 }
415 
signal_intrinsic(void)416 static void signal_intrinsic (void)
417 {
418    SLang_Name_Type *f;
419    Signal_Type *s;
420    void (*old_handler) (int);
421    SLang_Ref_Type *old_ref;
422 
423    if (SLang_Num_Function_Args == 3)
424      {
425 	if (-1 == SLang_pop_ref (&old_ref))
426 	  return;
427      }
428    else old_ref = NULL;
429 
430    if (SLang_Num_Function_Args == 0)
431      {
432 	SLang_verror (SL_Internal_Error, "signal called with 0 args");
433 	return;
434      }
435 
436    if (SLANG_INT_TYPE == SLang_peek_at_stack ())
437      {
438 	int h;
439 
440 	if ((-1 == SLang_pop_int (&h))
441 	    || (-1 == pop_signal (&s)))
442 	  {
443 	     SLang_free_ref (old_ref);
444 	     return;
445 	  }
446 
447 	/* If this signal has already been caught, deliver it now to the old handler */
448 	if (s->pending)
449 	  handle_signal (s);
450 	/* Note that the signal has the potential of being lost if the user has
451 	 * blocked its delivery.  For this reason, the unblock_signal intrinsic
452 	 * will have to deliver the signal via an explicit kill if it is pending.
453 	 */
454 
455 	if (h == SIG_IGN_CONSTANT)
456 	  old_handler = SLsignal_intr (s->sig, SIG_IGN);
457 	else if (h == SIG_DFL_CONSTANT)
458 	  old_handler = SLsignal_intr (s->sig, SIG_DFL);
459 	else if (h == SIG_APP_CONSTANT)
460 	  old_handler = SLsignal_intr (s->sig, s->c_handler);
461 	else
462 	  {
463 	     SLang_free_ref (old_ref);
464 	     _pSLang_verror (SL_INVALID_PARM, "Signal handler '%d' is invalid", h);
465 	     return;
466 	  }
467 
468 	if (-1 == set_old_handler (s, old_ref, old_handler))
469 	  {
470 	     SLang_free_ref (old_ref);
471 	     return;
472 	  }
473 
474 	if (s->handler != NULL)
475 	  {
476 	     SLang_free_function (s->handler);
477 	     s->handler = NULL;
478 	  }
479 
480 	SLang_free_ref (old_ref);
481 	return;
482      }
483 
484    if (NULL == (f = SLang_pop_function ()))
485      {
486 	SLang_free_ref (old_ref);
487 	return;
488      }
489 
490    if (-1 == pop_signal (&s))
491      {
492 	SLang_free_ref (old_ref);
493 	SLang_free_function (f);
494 	return;
495      }
496 
497    old_handler = SLsignal_intr (s->sig, signal_handler);
498    if (-1 == set_old_handler (s, old_ref, old_handler))
499      {
500 	SLang_free_ref (old_ref);
501 	SLang_free_function (f);
502 	return;
503      }
504 
505    if (s->handler != NULL)
506      SLang_free_function (s->handler);
507    s->handler = f;
508    SLang_free_ref (old_ref);
509 }
510 
alarm_intrinsic(void)511 static void alarm_intrinsic (void)
512 {
513 #ifndef HAVE_ALARM
514    SLang_set_error (SL_NotImplemented_Error);
515 #else
516    SLang_Ref_Type *ref = NULL;
517    unsigned int secs;
518    Signal_Type *s;
519 
520    if (SLang_Num_Function_Args == 2)
521      {
522 	if (-1 == SLang_pop_ref (&ref))
523 	  return;
524      }
525 
526    if (-1 == SLang_pop_uint (&secs))
527      {
528 	SLang_free_ref (ref);	       /* NULL ok */
529 	return;
530      }
531 #ifdef SIGALRM
532    if ((NULL != (s = find_signal (SIGALRM)))
533        && s->forbidden)
534      {
535 	SLang_set_error (SL_Forbidden_Error);
536 	return;
537      }
538 #endif
539    secs = alarm (secs);
540    if (ref != NULL)
541      (void) SLang_assign_to_ref (ref, SLANG_UINT_TYPE, &secs);
542 #endif
543 }
544 
545 #ifdef SLANG_POSIX_SIGNALS
pop_signal_mask(sigset_t * maskp)546 static int pop_signal_mask (sigset_t *maskp)
547 {
548    SLang_Array_Type *at;
549    unsigned int i, num, num_set;
550    int *sigs;
551 
552    if (-1 == SLang_pop_array_of_type (&at, SLANG_INT_TYPE))
553      return -1;
554 
555    sigemptyset (maskp);
556    num = at->num_elements;
557    sigs = (int *) at->data;
558    num_set = 0;
559 
560    for (i = 0; i < num; i++)
561      {
562 	int sig = sigs[i];
563 	if (NULL == find_signal (sig))
564 	  continue;
565 
566 	sigaddset (maskp, sig);
567 	num_set++;
568      }
569    SLang_free_array (at);
570 
571    return 0;
572 }
573 #endif 				       /* SLANG_POSIX_SIGNALS */
574 
sigsuspend_intrinsic(void)575 static void sigsuspend_intrinsic (void)
576 {
577 #ifdef SLANG_POSIX_SIGNALS
578    sigset_t mask;
579 #endif
580 
581    if (SLang_Num_Function_Args == 0)
582      {
583 #ifdef HAVE_PAUSE
584 	(void) pause ();
585 #else
586 	SLang_set_error (SL_NotImplemented_Error);
587 #endif
588 	return;
589      }
590 
591 #ifndef SLANG_POSIX_SIGNALS
592    SLang_set_error (SL_NotImplemented_Error);
593 #else
594    if (-1 == pop_signal_mask (&mask))
595      return;
596 
597    (void) sigsuspend (&mask);
598 #endif
599 }
600 
601 #ifdef SLANG_POSIX_SIGNALS
mask_to_array(sigset_t * mask)602 static SLang_Array_Type *mask_to_array (sigset_t *mask)
603 {
604    SLang_Array_Type *at;
605    SLindex_Type num;
606    Signal_Type *s;
607    int *data;
608 
609    num = 0;
610    s = Signal_Table;
611    while (s->name != NULL)
612      {
613 	if (sigismember (mask, s->sig))
614 	  num++;
615 	s++;
616      }
617    at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, &num, 1);
618    if (at == NULL)
619      return NULL;
620 
621    s = Signal_Table;
622    data = (int *)at->data;
623    while (s->name != NULL)
624      {
625 	if (sigismember (mask, s->sig))
626 	  *data++ = s->sig;
627 	s++;
628      }
629 
630    return at;
631 }
632 
assign_mask_to_ref(sigset_t * mask,SLang_Ref_Type * ref)633 static int assign_mask_to_ref (sigset_t *mask, SLang_Ref_Type *ref)
634 {
635    SLang_Array_Type *at = mask_to_array (mask);
636 
637    if (at == NULL)
638      return -1;
639 
640    if (-1 == SLang_assign_to_ref (ref, SLANG_ARRAY_TYPE, (VOID_STAR)&at))
641      {
642 	SLang_free_array (at);
643 	return -1;
644      }
645    SLang_free_array (at);
646    return 0;
647 }
648 
sigprocmask_intrinsic(void)649 static void sigprocmask_intrinsic (void)
650 {
651    sigset_t mask, oldmask;
652    SLang_Ref_Type *ref = NULL;
653    int how;
654 
655    if (SLang_Num_Function_Args == 3)
656      {
657        if (-1 == SLang_pop_ref (&ref))
658 	  return;
659      }
660 
661    if (-1 == pop_signal_mask (&mask))
662      {
663 	SLang_free_ref (ref);
664 	return;
665      }
666 
667    if (-1 == SLang_pop_int (&how))
668      {
669 	SLang_free_ref (ref);
670 	return;
671      }
672 
673    if ((how != SIG_BLOCK) && (how != SIG_UNBLOCK) && (how != SIG_SETMASK))
674      {
675 	_pSLang_verror (SL_InvalidParm_Error, "sigprocmask: invalid operation");
676 	SLang_free_ref (ref);
677 	return;
678      }
679 
680    do_sigprocmask (how, &mask, &oldmask);
681 
682    if (ref == NULL)
683      return;
684 
685    if (-1 == assign_mask_to_ref (&oldmask, ref))
686      do_sigprocmask (SIG_SETMASK, &oldmask, NULL);
687 
688    SLang_free_ref (ref);
689 }
690 
691 #endif
692 
693 #if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
timeval_to_double(struct timeval * tv)694 static double timeval_to_double (struct timeval *tv)
695 {
696    return tv->tv_sec + (double) tv->tv_usec * 1e-6;
697 }
698 
double_to_timeval(double t,struct timeval * tv)699 static void double_to_timeval (double t, struct timeval *tv)
700 {
701    if (t < 0.0)
702      t = 0.0;
703    tv->tv_sec = (long) t;
704    tv->tv_usec = (long) ((t - (long)t) * 1e6);
705 }
706 
707 # ifdef HAVE_GETITIMER
getitimer_intrinsic(int * wp)708 static void getitimer_intrinsic (int *wp)
709 {
710    struct itimerval it;
711 
712    if (-1 == getitimer (*wp, &it))
713      {
714 	SLerrno_set_errno (errno);
715 	SLang_verror (SL_OS_Error, "getitimer failed: %s", SLerrno_strerror (errno));
716 	return;
717      }
718    (void) SLang_push_double (timeval_to_double (&it.it_value));
719    (void) SLang_push_double (timeval_to_double (&it.it_interval));
720 }
721 # endif
722 # ifdef HAVE_SETITIMER
setitimer_intrinsic(void)723 static void setitimer_intrinsic (void)
724 {
725    SLang_Ref_Type *interval_ref = NULL, *value_ref = NULL;
726    int w;
727    struct itimerval new_value, old_value;
728    double interval = 0.0, value;
729    int argc = SLang_Num_Function_Args;
730 
731    if (SLang_peek_at_stack () == SLANG_REF_TYPE)
732      {
733 	if (-1 == SLang_pop_ref (&value_ref))
734 	  return;
735 	argc--;
736 	if (SLang_peek_at_stack() == SLANG_REF_TYPE)
737 	  {
738 	     interval_ref = value_ref;
739 	     if (-1 == SLang_pop_ref (&value_ref))
740 	       goto free_and_return;
741 	     argc--;
742 	  }
743      }
744 
745    switch (argc)
746      {
747       case 3:
748 	if (-1 == SLang_pop_double (&interval))
749 	  goto free_and_return;
750 	/* drop */
751       case 2:
752       default:
753 	if ((-1 == SLang_pop_double (&value))
754 	    || (-1 == SLang_pop_int (&w)))
755 	  goto free_and_return;
756      }
757 
758    double_to_timeval (interval, &new_value.it_interval);
759    double_to_timeval (value, &new_value.it_value);
760 
761    if (-1 == setitimer (w, &new_value, &old_value))
762      {
763 	SLerrno_set_errno (errno);
764 	SLang_verror (SL_OS_Error, "setitimer failed: %s", SLerrno_strerror (errno));
765 	goto free_and_return;
766      }
767 
768    if (value_ref != NULL)
769      {
770 	value = timeval_to_double (&old_value.it_value);
771 	if (-1 == SLang_assign_to_ref (value_ref, SLANG_DOUBLE_TYPE, &value))
772 	  goto free_and_return;
773      }
774    if (interval_ref != NULL)
775      {
776 	interval = timeval_to_double (&old_value.it_interval);
777 	if (-1 == SLang_assign_to_ref (interval_ref, SLANG_DOUBLE_TYPE, &interval))
778 	  goto free_and_return;
779      }
780 
781 free_and_return:
782    if (value_ref != NULL)
783      SLang_free_ref (value_ref);
784    if (interval_ref != NULL)
785      SLang_free_ref (interval_ref);
786 }
787 # endif
788 #endif
789 
790 static SLang_IConstant_Type IConsts [] =
791 {
792 #ifdef SLANG_POSIX_SIGNALS
793    MAKE_ICONSTANT("SIG_BLOCK", SIG_BLOCK),
794    MAKE_ICONSTANT("SIG_UNBLOCK", SIG_UNBLOCK),
795    MAKE_ICONSTANT("SIG_SETMASK", SIG_SETMASK),
796 #endif
797    MAKE_ICONSTANT("SIG_IGN", SIG_IGN_CONSTANT),
798    MAKE_ICONSTANT("SIG_DFL", SIG_DFL_CONSTANT),
799    MAKE_ICONSTANT("SIG_APP", SIG_APP_CONSTANT),
800 #ifdef ITIMER_REAL
801    MAKE_ICONSTANT("ITIMER_REAL", ITIMER_REAL),
802 #endif
803 #ifdef ITIMER_VIRTUAL
804    MAKE_ICONSTANT("ITIMER_VIRTUAL", ITIMER_VIRTUAL),
805 #endif
806 #ifdef ITIMER_PROF
807    MAKE_ICONSTANT("ITIMER_PROF", ITIMER_PROF),
808 #endif
809    SLANG_END_ICONST_TABLE
810 };
811 
812 static SLang_Intrin_Fun_Type Intrin_Table [] =
813 {
814    MAKE_INTRINSIC_0("signal", signal_intrinsic, SLANG_VOID_TYPE),
815    MAKE_INTRINSIC_0("alarm", alarm_intrinsic, SLANG_VOID_TYPE),
816 #ifdef HAVE_SETITIMER
817    MAKE_INTRINSIC_0("setitimer", setitimer_intrinsic, SLANG_VOID_TYPE),
818 #endif
819 #ifdef HAVE_GETITIMER
820    MAKE_INTRINSIC_1("getitimer", getitimer_intrinsic, SLANG_VOID_TYPE, SLANG_INT_TYPE),
821 #endif
822    MAKE_INTRINSIC_0("sigsuspend", sigsuspend_intrinsic, SLANG_VOID_TYPE),
823 #ifdef SLANG_POSIX_SIGNALS
824    MAKE_INTRINSIC_0("sigprocmask", sigprocmask_intrinsic, SLANG_VOID_TYPE),
825 #endif
826    SLANG_END_INTRIN_FUN_TABLE
827 };
828 
SLang_init_signal(void)829 int SLang_init_signal (void)
830 {
831    Signal_Type *s;
832 
833    if ((-1 == SLadd_intrin_fun_table(Intrin_Table, NULL))
834        || (-1 == SLadd_iconstant_table (IConsts, NULL)))
835      return -1;
836 
837    s = Signal_Table;
838    while (s->name != NULL)
839      {
840 	if (-1 == SLns_add_iconstant (NULL, s->name, SLANG_INT_TYPE, s->sig))
841 	  return -1;
842 
843 	s++;
844      }
845 
846    return 0;
847 }
848 #endif				       /* SLANG_HAS_SIGNALS */
849 
SLsig_forbid_signal(int sig)850 int SLsig_forbid_signal (int sig)
851 {
852 #if SLANG_HAS_SIGNALS
853    Signal_Type *s = find_signal (sig);
854    if (s != NULL)
855      s->forbidden = 1;
856    return 0;
857 #else
858    (void) sig;
859    return 0;
860 #endif
861 }
862 
863