Build Lunapaint from Contrib.
[AROS-Contrib.git] / regina / signals.c
blobf16b93ff985f1b3d5ddcfc273d448c2160704928
1 /*
2 * The Regina Rexx Interpreter
3 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "rexx.h"
21 #include <string.h>
22 #include <stdio.h>
23 #include <signal.h>
25 #ifdef VMS
26 # ifndef SIG_ERR
27 # define SIG_ERR BADSIG
28 # endif
29 #endif
31 /* at least dolphin does not have a properly ANSI C set of include files */
32 #ifndef SIG_ERR
33 # define SIG_ERR ((void(*)())(-1))
34 #endif
36 const char *signalnames[] = {
37 "ERROR",
38 "FAILURE",
39 "HALT",
40 "NOVALUE",
41 "NOTREADY",
42 "SYNTAX",
43 "LOSTDIGITS"
44 } ;
46 #ifdef TRACEMEM
47 void mark_signals( const tsd_t *TSD )
49 if (TSD->nextsig)
51 markmemory( TSD->nextsig, TRC_MATH ) ;
52 if (TSD->nextsig->descr)
53 markmemory( TSD->nextsig->descr, TRC_MATH ) ;
56 #endif
59 static trap *dupltraps( const tsd_t *TSD, const trap *traps )
61 trap *ptr=NULL ;
62 int i=0 ;
64 ptr = (trap *)MallocTSD( sizeof(trap) * SIGNALS ) ;
65 /* Stupid SunOS acc gives incorrect warning for the next line */
66 memcpy( ptr, traps, sizeof(trap) * SIGNALS ) ;
67 for ( i = 0; i < SIGNALS; i++ )
68 if (traps[i].name)
69 ptr[i].name = Str_dupTSD( traps[i].name ) ;
72 return ptr ;
76 sigtype *getsigs( proclevel level )
78 for (; level && (!level->sig); level=level->prev ) ;
79 return ((level) ? (level->sig) : (NULL)) ;
82 trap *gettraps( const tsd_t *TSD, proclevel level )
84 proclevel ptr=level ;
86 if (!ptr->traps)
88 for (ptr=level; ptr && ptr->traps==NULL; ptr=ptr->prev ) ;
89 if (ptr==NULL || ptr->traps==NULL)
90 exiterror( ERR_INTERPRETER_FAILURE, 1, __FILE__, __LINE__, "" ) ;
92 level->traps = dupltraps( TSD, ptr->traps ) ;
93 ptr = level ;
96 return ptr->traps ;
100 int condition_hook( tsd_t *TSD, int type, int errorno, int suberrorno, int lineno, streng *description, streng *condition_description )
102 trap *traps;
103 sigtype *sigptr=NULL ;
105 traps = gettraps( TSD, TSD->currlevel ) ;
106 /* if we dont know what to do, ... or */
107 /* if we don't *really* want to try to recover from these ... */
108 if (traps==NULL || type == SIGNAL_FATAL)
110 if (description)
111 Free_stringTSD( description ) ;
112 return 0 ;
115 if (lineno==(-1))
117 if (TSD->currentnode)
118 lineno = TSD->currentnode->lineno ;
119 else
120 #ifdef NDEBUG
121 lineno = 0 ;
122 #else
123 exiterror( ERR_INTERPRETER_FAILURE, 1, __FILE__, __LINE__, "" ) ;
124 #endif
126 if ( traps[type].on_off) /* condition is being trapped */
128 if ((traps[type].delayed) && (traps[type].ignored))
130 if (description)
131 Free_stringTSD( description ) ;
132 return 0 ;
135 sigptr = (sigtype *)MallocTSD( sizeof( sigtype )) ;
137 sigptr->type = type ;
138 sigptr->info = NULL ; /* BUG: I don't really think this is used */
139 #if 0
140 sigptr->descr = description ;
141 #else
142 if (condition_description)
143 sigptr->descr = condition_description ;
144 else
145 sigptr->descr = description ;
146 #endif
147 sigptr->invoke = traps[type].invoked ;
148 sigptr->rc = errorno ;
149 sigptr->subrc = suberrorno ;
150 sigptr->lineno = lineno ;
152 if ( traps[type].invoked ) /* if SIGNAL ON */
154 /* traps[type].on_off = 0 ; */ /* turn trap off */
155 /* traps[type].trapped = 0 ; */ /* unecessary, just to be sure */
156 traps[type].delayed = 0 ; /* ... ditto ... */
157 set_reserved_value( TSD, POOL0_SIGL, NULL, lineno, VFLAG_NUM );
158 if (type == SIGNAL_SYNTAX) /* special condition */
159 set_reserved_value( TSD, POOL0_RC, NULL, errorno, VFLAG_NUM );
161 TSD->nextsig = sigptr ;
163 jump_rexx_signal( TSD );
165 else
167 TSD->nextsig = sigptr ;
168 return 1 ;
172 if (description)
173 Free_stringTSD(description) ;
175 /* signal is not to be trapped */
176 return (traps[type].def_act) ;
180 int identify_trap( int type )
182 switch (type)
184 case X_S_HALT: return SIGNAL_HALT ;
185 case X_S_SYNTAX: return SIGNAL_SYNTAX ;
186 case X_S_NOVALUE: return SIGNAL_NOVALUE ;
187 case X_S_NOTREADY: return SIGNAL_NOTREADY ;
188 case X_S_ERROR: return SIGNAL_ERROR ;
189 case X_S_FAILURE: return SIGNAL_FAILURE ;
190 case X_S_LOSTDIGITS: return SIGNAL_LOSTDIGITS;
192 exiterror( ERR_INTERPRETER_FAILURE, 1, __FILE__, __LINE__, "" ) ;
193 return SIGNAL_FATAL ;
197 /* the rest should probably also be defined */
198 static const char *signals_names[] = {
199 "", "SIGHUP", "SIGINT", "", "", "", "", "", "", "",
200 "", "", "", "", "", "SIGTERM", "", "", "", "", "",
201 "SIGBREAK", "", "", "", "", "", "", "", "", "",
202 "", ""
205 #if defined (HAVE_SIGACTION) && defined(SA_RESTART) && defined(HAVE__SIGHANDLER_T)
206 /* Most things only works if a signal doesn't break the current system call.
207 * sigaction has such a flag and should always been preferred. It has an
208 * exactlier defined standard.
209 * Defining a "signal()" here also overwrites signal calls in the whole
210 * program. FGC
212 signal_handler regina_signal(int signum,__sighandler_t action)
214 struct sigaction nsig,osig;
216 nsig.sa_handler = action;
217 sigemptyset(&nsig.sa_mask);
218 nsig.sa_flags = SA_RESTART;
219 if (sigaction(signum,&nsig,&osig) != 0)
220 return(SIG_ERR);
221 return(osig.sa_handler);
223 #elif defined(__AROS__)
224 signal_handler regina_signal(int signum,signal_handler action)
226 return SIG_ERR;
228 #else
229 signal_handler regina_signal(int signum,signal_handler action)
231 # if defined(__WINS__) || defined(__EPOC32__)
232 return 0;
233 # else
234 return( signal ( signum, action ) ) ;
235 # endif
237 #endif
240 * halt_raised is invoked by the interpreter's main loop after detecting a
241 * halt condition.
242 * This routine raises the HALT condition and probably terminates the current
243 * thread.
245 void halt_raised( tsd_t *TSD )
247 int sig = TSD->HaltRaised;
249 TSD->HaltRaised = 0;
251 if ( condition_hook( TSD,
252 SIGNAL_HALT,
253 ERR_PROG_INTERRUPT,
255 lineno_of( TSD->currentnode ),
256 Str_creTSD( signals_names[sig] ),
257 NULL ) )
258 return;
259 #ifdef VMS
261 * FIXME: Why do we use vms_killproc instead of using exiterror() ?
263 vms_killproc( TSD );
264 #endif
265 exiterror( ERR_PROG_INTERRUPT, 0 );
268 #if !defined(__WINS__) && !defined(__EPOC32__) && !defined(__AROS__)
269 /* Yuk! Some of these should *really* have been volatilized */
270 static void halt_handler( int num )
272 #ifdef WIN32
274 * Braindamaged Win32 systems raise ^C in a different thread. We need a
275 * synchroneous alert. We just set a global flag in the halt handler and
276 * reset it here doing the proper functionality for the signal. One
277 * thread has to pick the signal during execution in the main loop.
278 * fixes bug 553022
280 regina_signal( num, halt_handler );
281 __regina_Win32CtrlCRaised = SIGINT;
282 #else
283 tsd_t *TSD = __regina_get_tsd(); /* The TSD must be fetched directly. */
286 if (regina_signal( num, halt_handler ) == SIG_ERR)
287 exiterror( ERR_SYSTEM_FAILURE, 0 );
288 TSD->HaltRaised = num;
289 #endif
292 # if defined(SIGHUP)
293 static void hup_handler( int dummy )
296 * FGC: FIXME: Doing an exit is too heavy and too early. Maybe, we
297 * should ignore it completely. Every IO request will return EPIPE or
298 * similar, and we can do a graceful shutdown then.
300 exiterror( ERR_PROG_INTERRUPT, 0 );
302 # endif
303 #endif
306 void signal_setup( const tsd_t *TSD )
308 TSD = TSD; /* keep compiler happy */
311 * EPOC32 does not have signal()!!
312 * AROS at the moment also lacks signal
314 #if !defined(__WINS__) && !defined(__EPOC32__) && !defined(__AROS__)
315 # if defined(SIGTERM)
316 if (regina_signal( SIGTERM, halt_handler ) == SIG_ERR)
317 exiterror( ERR_SYSTEM_FAILURE, 0 ) ;
318 # endif
319 # if defined(SIGINT)
320 if (regina_signal( SIGINT, halt_handler) == SIG_ERR)
321 exiterror( ERR_SYSTEM_FAILURE, 0 ) ;
322 # endif
323 # if defined(SIGBREAK)
324 if (regina_signal( SIGBREAK, halt_handler) == SIG_ERR)
325 exiterror( ERR_SYSTEM_FAILURE, 0 ) ;
326 # endif
327 # if defined(SIGHUP)
328 if (regina_signal( SIGHUP, (TSD->isclient)?(hup_handler):(halt_handler)) == SIG_ERR)
329 exiterror( ERR_SYSTEM_FAILURE, 0 ) ;
330 # endif
331 #endif
334 void set_rexx_halt( tsd_t *TSD )
336 TSD->HaltRaised = SIGINT;