fix
[midnight-commander.git] / slang / slsignal.c
blobf6fa21c849801af2e0b7ecad8ef815bba7b3f199
1 /* Copyright (c) 1998, 1999, 2001, 2002 John E. Davis
2 * This file is part of the S-Lang library.
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Perl Artistic License.
6 */
7 #include "slinclud.h"
9 #include <signal.h>
11 #ifdef HAVE_SYS_TYPES_H
12 # include <sys/types.h>
13 #endif
14 #ifdef HAVE_SYS_WAIT_H
15 # include <sys/wait.h>
16 #endif
18 #include <errno.h>
20 #include "slang.h"
21 #include "_slang.h"
23 /* Do not trust these environments */
24 #if defined(__CYGWIN32__) || defined(__MINGW32__) || defined(AMIGA)
25 # ifdef SLANG_POSIX_SIGNALS
26 # undef SLANG_POSIX_SIGNALS
27 # endif
28 #endif
30 /* This function will cause system calls to be restarted after signal if possible */
31 SLSig_Fun_Type *SLsignal (int sig, SLSig_Fun_Type *f)
33 #if defined(SLANG_POSIX_SIGNALS)
34 struct sigaction old_sa, new_sa;
36 # ifdef SIGALRM
37 /* We want system calls to be interrupted by SIGALRM. */
38 if (sig == SIGALRM) return SLsignal_intr (sig, f);
39 # endif
41 sigemptyset (&new_sa.sa_mask);
42 new_sa.sa_handler = f;
44 new_sa.sa_flags = 0;
45 # ifdef SA_RESTART
46 new_sa.sa_flags |= SA_RESTART;
47 # endif
49 if (-1 == sigaction (sig, &new_sa, &old_sa))
50 return (SLSig_Fun_Type *) SIG_ERR;
52 return old_sa.sa_handler;
53 #else
54 /* Not POSIX. */
55 return signal (sig, f);
56 #endif
59 /* This function will NOT cause system calls to be restarted after
60 * signal if possible
62 SLSig_Fun_Type *SLsignal_intr (int sig, SLSig_Fun_Type *f)
64 #ifdef SLANG_POSIX_SIGNALS
65 struct sigaction old_sa, new_sa;
67 sigemptyset (&new_sa.sa_mask);
68 new_sa.sa_handler = f;
70 new_sa.sa_flags = 0;
71 # ifdef SA_INTERRUPT
72 new_sa.sa_flags |= SA_INTERRUPT;
73 # endif
75 if (-1 == sigaction (sig, &new_sa, &old_sa))
76 return (SLSig_Fun_Type *) SIG_ERR;
78 return old_sa.sa_handler;
79 #else
80 /* Not POSIX. */
81 return signal (sig, f);
82 #endif
85 /* We are primarily interested in blocking signals that would cause the
86 * application to reset the tty. These include suspend signals and
87 * possibly interrupt signals.
89 #ifdef SLANG_POSIX_SIGNALS
90 static sigset_t Old_Signal_Mask;
91 #endif
93 static volatile unsigned int Blocked_Depth;
95 int SLsig_block_signals (void)
97 #ifdef SLANG_POSIX_SIGNALS
98 sigset_t new_mask;
99 #endif
101 Blocked_Depth++;
102 if (Blocked_Depth != 1)
104 return 0;
107 #ifdef SLANG_POSIX_SIGNALS
108 sigemptyset (&new_mask);
109 # ifdef SIGQUIT
110 sigaddset (&new_mask, SIGQUIT);
111 # endif
112 # ifdef SIGTSTP
113 sigaddset (&new_mask, SIGTSTP);
114 # endif
115 # ifdef SIGINT
116 sigaddset (&new_mask, SIGINT);
117 # endif
118 # ifdef SIGTTIN
119 sigaddset (&new_mask, SIGTTIN);
120 # endif
121 # ifdef SIGTTOU
122 sigaddset (&new_mask, SIGTTOU);
123 # endif
124 # ifdef SIGWINCH
125 sigaddset (&new_mask, SIGWINCH);
126 # endif
128 (void) sigprocmask (SIG_BLOCK, &new_mask, &Old_Signal_Mask);
129 return 0;
130 #else
131 /* Not implemented. */
132 return -1;
133 #endif
136 int SLsig_unblock_signals (void)
138 if (Blocked_Depth == 0)
139 return -1;
141 Blocked_Depth--;
143 if (Blocked_Depth != 0)
144 return 0;
146 #ifdef SLANG_POSIX_SIGNALS
147 (void) sigprocmask (SIG_SETMASK, &Old_Signal_Mask, NULL);
148 return 0;
149 #else
150 return -1;
151 #endif
154 #ifdef MSWINDOWS
155 int SLsystem (char *cmd)
157 SLang_verror (SL_NOT_IMPLEMENTED, "system not implemented");
158 return -1;
161 #else
162 int SLsystem (char *cmd)
164 #ifdef SLANG_POSIX_SIGNALS
165 pid_t pid;
166 int status;
167 struct sigaction ignore;
168 # ifdef SIGINT
169 struct sigaction save_intr;
170 # endif
171 # ifdef SIGQUIT
172 struct sigaction save_quit;
173 # endif
174 # ifdef SIGCHLD
175 sigset_t child_mask, save_mask;
176 # endif
178 if (cmd == NULL) return 1;
180 ignore.sa_handler = SIG_IGN;
181 sigemptyset (&ignore.sa_mask);
182 ignore.sa_flags = 0;
184 # ifdef SIGINT
185 if (-1 == sigaction (SIGINT, &ignore, &save_intr))
186 return -1;
187 # endif
189 # ifdef SIGQUIT
190 if (-1 == sigaction (SIGQUIT, &ignore, &save_quit))
192 (void) sigaction (SIGINT, &save_intr, NULL);
193 return -1;
195 # endif
197 # ifdef SIGCHLD
198 sigemptyset (&child_mask);
199 sigaddset (&child_mask, SIGCHLD);
200 if (-1 == sigprocmask (SIG_BLOCK, &child_mask, &save_mask))
202 # ifdef SIGINT
203 (void) sigaction (SIGINT, &save_intr, NULL);
204 # endif
205 # ifdef SIGQUIT
206 (void) sigaction (SIGQUIT, &save_quit, NULL);
207 # endif
208 return -1;
210 # endif
212 pid = fork();
214 if (pid == -1)
215 status = -1;
216 else if (pid == 0)
218 /* Child */
219 # ifdef SIGINT
220 (void) sigaction (SIGINT, &save_intr, NULL);
221 # endif
222 # ifdef SIGQUIT
223 (void) sigaction (SIGQUIT, &save_quit, NULL);
224 # endif
225 # ifdef SIGCHLD
226 (void) sigprocmask (SIG_SETMASK, &save_mask, NULL);
227 # endif
229 execl ("/bin/sh", "sh", "-c", cmd, NULL);
230 _exit (127);
232 else
234 /* parent */
235 while (-1 == waitpid (pid, &status, 0))
237 # ifdef EINTR
238 if (errno == EINTR)
239 continue;
240 # endif
241 # ifdef ERESTARTSYS
242 if (errno == ERESTARTSYS)
243 continue;
244 # endif
245 status = -1;
246 break;
249 # ifdef SIGINT
250 if (-1 == sigaction (SIGINT, &save_intr, NULL))
251 status = -1;
252 # endif
253 # ifdef SIGQUIT
254 if (-1 == sigaction (SIGQUIT, &save_quit, NULL))
255 status = -1;
256 # endif
257 # ifdef SIGCHLD
258 if (-1 == sigprocmask (SIG_SETMASK, &save_mask, NULL))
259 status = -1;
260 # endif
262 return status;
264 #else /* No POSIX Signals */
265 # ifdef SIGINT
266 void (*sint)(int);
267 # endif
268 # ifdef SIGQUIT
269 void (*squit)(int);
270 # endif
271 int status;
273 # ifdef SIGQUIT
274 squit = SLsignal (SIGQUIT, SIG_IGN);
275 # endif
276 # ifdef SIGINT
277 sint = SLsignal (SIGINT, SIG_IGN);
278 # endif
279 status = system (cmd);
280 # ifdef SIGINT
281 SLsignal (SIGINT, sint);
282 # endif
283 # ifdef SIGQUIT
284 SLsignal (SIGQUIT, squit);
285 # endif
286 return status;
287 #endif /* POSIX_SIGNALS */
289 #endif
291 #if 0
292 #include <windows.h>
293 static int msw_system (char *cmd)
295 STARTUPINFO startup_info;
296 PROCESS_INFORMATION process_info;
297 int status;
299 if (cmd == NULL) return -1;
301 memset ((char *) &startup_info, 0, sizeof (STARTUPINFO));
302 startup_info.cb = sizeof(STARTUPINFO);
303 startup_info.dwFlags = STARTF_USESHOWWINDOW;
304 startup_info.wShowWindow = SW_SHOWDEFAULT;
306 if (FALSE == CreateProcess (NULL,
307 cmd,
308 NULL,
309 NULL,
310 FALSE,
311 NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE,
312 NULL,
313 NULL,
314 &startup_info,
315 &process_info))
317 SLang_verror (0, "%s: CreateProcess failed.", cmd);
318 return -1;
321 status = -1;
323 if (0xFFFFFFFFUL != WaitForSingleObject (process_info.hProcess, INFINITE))
325 DWORD exit_code;
327 if (TRUE == GetExitCodeProcess (process_info.hProcess, &exit_code))
328 status = (int) exit_code;
331 CloseHandle (process_info.hThread);
332 CloseHandle (process_info.hProcess);
334 return status;
336 #endif