Added code to manage Ascii and WideChar class names, and to return the
[wine] / loader / signal.c
1 /*
2  * Wine signal handling
3  *
4  */
5
6 #include "config.h"
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <signal.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <time.h>
14 #include <setjmp.h>
15
16 #include <sys/time.h>
17 #include <sys/timeb.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20
21 #ifdef HAVE_SYS_PARAM_H
22 # include <sys/param.h>
23 #endif
24 #ifdef HAVE_SYSCALL_H
25 # include <syscall.h>
26 #else
27 # ifdef HAVE_SYS_SYSCALL_H
28 #  include <sys/syscall.h>
29 # endif
30 #endif
31
32 #include "miscemu.h"
33 #include "selectors.h"
34 #include "sig_context.h"
35 #include "winsock.h"
36
37 /* Linux sigaction function */
38
39 #if defined(linux) && defined(__i386__)
40 /* This is the sigaction structure from the Linux 2.1.20 kernel.  */
41 #undef sa_handler
42 struct kernel_sigaction
43 {
44     void (*sa_handler)();
45     unsigned long sa_mask;
46     unsigned long sa_flags;
47     void (*sa_restorer)();
48 };
49
50 /* Similar to the sigaction function in libc, except it leaves alone the
51    restorer field, which is used to specify the signal stack address */
52 static __inline__ int wine_sigaction( int sig, struct kernel_sigaction *new,
53                                       struct kernel_sigaction *old )
54 {
55 #ifdef __PIC__
56     __asm__ __volatile__( "pushl %%ebx\n\t"
57                           "movl %2,%%ebx\n\t"
58                           "int $0x80\n\t"
59                           "popl %%ebx"
60                           : "=a" (sig)
61                           : "0" (SYS_sigaction),
62                             "g" (sig),
63                             "c" (new),
64                             "d" (old) );
65 #else
66     __asm__ __volatile__( "int $0x80"
67                           : "=a" (sig)
68                           : "0" (SYS_sigaction),
69                             "b" (sig),
70                             "c" (new),
71                             "d" (old) );
72 #endif  /* __PIC__ */
73     if (sig>=0)
74         return 0;
75     errno = -sig;
76     return -1;
77 }
78 #endif /* linux && __i386__ */
79
80 /* Signal stack */
81
82 static char SIGNAL_Stack[16384];
83 static sigset_t async_signal_set;
84
85 /**********************************************************************
86  *              SIGNAL_child
87  * 
88  * wait4 terminated child processes
89  */
90 static HANDLER_DEF(SIGNAL_child)
91 {
92     HANDLER_INIT();
93 #ifdef HAVE_WAIT4
94     wait4( 0, NULL, WNOHANG, NULL);
95 #elif defined (HAVE_WAITPID)
96     /* I am sort-of guessing that this is the same as the wait4 call.  */
97     waitpid (0, NULL, WNOHANG);
98 #else
99     wait(NULL);
100 #endif
101 }
102
103
104 /**********************************************************************
105  *              SIGNAL_SetHandler
106  */
107 void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
108 {
109     int ret;
110
111 #if defined(linux) && defined(__i386__)
112
113     struct kernel_sigaction sig_act;
114     sig_act.sa_handler = func;
115     sig_act.sa_flags   = SA_RESTART | (flags) ? SA_NOMASK : 0;
116     sig_act.sa_mask    = 0;
117     /* Point to the top of the stack, minus 4 just in case, and make
118        it aligned  */
119     sig_act.sa_restorer = 
120         (void (*)())((int)(SIGNAL_Stack + sizeof(SIGNAL_Stack) - 4) & ~3);
121     ret = wine_sigaction( sig, &sig_act, NULL );
122
123 #else  /* linux && __i386__ */
124
125     struct sigaction sig_act;
126     sig_act.sa_handler = func;
127     sigemptyset( &sig_act.sa_mask );
128
129 # if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
130     sig_act.sa_flags = SA_ONSTACK;
131 # elif defined (__svr4__) || defined(_SCO_DS)
132     sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
133 # elif defined(__EMX__)
134     sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */
135 # else
136     sig_act.sa_flags = 0;
137 # endif
138     ret = sigaction( sig, &sig_act, NULL );
139
140 #endif  /* linux && __i386__ */
141
142     if (ret < 0)
143     {
144         perror( "sigaction" );
145         exit(1);
146     }
147 }
148
149 extern void stop_wait(int a);
150 extern void WINSOCK_sigio(int a);
151
152
153 /**********************************************************************
154  *              SIGNAL_Init
155  */
156 BOOL32 SIGNAL_Init(void)
157 {
158     extern void SYNC_SetupSignals(void);
159
160 #ifdef HAVE_WORKING_SIGALTSTACK
161     struct sigaltstack ss;
162     ss.ss_sp    = SIGNAL_Stack;
163     ss.ss_size  = sizeof(SIGNAL_Stack);
164     ss.ss_flags = 0;
165     if (sigaltstack(&ss, NULL) < 0)
166     {
167         perror("sigstack");
168         return FALSE;
169     }
170 #endif  /* HAVE_SIGALTSTACK */
171     
172     sigemptyset(&async_signal_set);
173
174     SIGNAL_SetHandler( SIGCHLD, (void (*)())SIGNAL_child, 1);
175 #ifdef CONFIG_IPC
176     sigaddset(&async_signal_set, SIGUSR2);
177     SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1);      /* For IPC */
178 #endif
179 #ifdef SIGIO
180     sigaddset(&async_signal_set, SIGIO);
181     SIGNAL_SetHandler( SIGIO,   (void (*)())WINSOCK_sigio, 0); 
182 #endif
183
184     sigaddset(&async_signal_set, SIGALRM);
185
186     /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead  */
187     signal (SIGPIPE, SIG_IGN);
188
189     SYNC_SetupSignals();
190     return TRUE;
191 }
192
193
194 /**********************************************************************
195  *              SIGNAL_MaskAsyncEvents
196  */
197 void SIGNAL_MaskAsyncEvents( BOOL32 flag )
198 {
199   sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &async_signal_set, NULL);
200 }
201