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