Add $ and ` for escaping and reorder it according to the ascii values
[midnight-commander.git] / slang / slsignal.c
blob276d6bbd6eb51f1b20e77de2c0e4de22fac8de31
1 /*
2 Copyright (C) 2004, 2005, 2006 John E. Davis
4 This file is part of the S-Lang Library.
6 The S-Lang Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The S-Lang Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 USA.
22 #include "slinclud.h"
24 #include <signal.h>
26 #ifdef HAVE_SYS_TYPES_H
27 # include <sys/types.h>
28 #endif
29 #ifdef HAVE_SYS_WAIT_H
30 # include <sys/wait.h>
31 #endif
33 #include <errno.h>
35 #include "slang.h"
36 #include "_slang.h"
38 /* Do not trust these environments */
39 #if defined(__MINGW32__) || defined(AMIGA)
40 # ifdef SLANG_POSIX_SIGNALS
41 # undef SLANG_POSIX_SIGNALS
42 # endif
43 #endif
45 /* This function will cause system calls to be restarted after signal if possible */
46 SLSig_Fun_Type *SLsignal (int sig, SLSig_Fun_Type *f)
48 #if defined(SLANG_POSIX_SIGNALS)
49 struct sigaction old_sa, new_sa;
51 # ifdef SIGALRM
52 /* We want system calls to be interrupted by SIGALRM. */
53 if (sig == SIGALRM) return SLsignal_intr (sig, f);
54 # endif
56 sigemptyset (&new_sa.sa_mask);
57 new_sa.sa_handler = f;
59 new_sa.sa_flags = 0;
60 # ifdef SA_RESTART
61 new_sa.sa_flags |= SA_RESTART;
62 # endif
64 if (-1 == sigaction (sig, &new_sa, &old_sa))
65 return (SLSig_Fun_Type *) SIG_ERR;
67 return old_sa.sa_handler;
68 #else
69 /* Not POSIX. */
70 return signal (sig, f);
71 #endif
74 /* This function will NOT cause system calls to be restarted after
75 * signal if possible
77 SLSig_Fun_Type *SLsignal_intr (int sig, SLSig_Fun_Type *f)
79 #ifdef SLANG_POSIX_SIGNALS
80 struct sigaction old_sa, new_sa;
82 sigemptyset (&new_sa.sa_mask);
83 new_sa.sa_handler = f;
85 new_sa.sa_flags = 0;
86 # ifdef SA_INTERRUPT
87 new_sa.sa_flags |= SA_INTERRUPT;
88 # endif
90 if (-1 == sigaction (sig, &new_sa, &old_sa))
91 return (SLSig_Fun_Type *) SIG_ERR;
93 return old_sa.sa_handler;
94 #else
95 /* Not POSIX. */
96 return signal (sig, f);
97 #endif
100 /* We are primarily interested in blocking signals that would cause the
101 * application to reset the tty. These include suspend signals and
102 * possibly interrupt signals.
104 #ifdef SLANG_POSIX_SIGNALS
105 static sigset_t Old_Signal_Mask;
106 #endif
108 static volatile unsigned int Blocked_Depth;
110 int SLsig_block_signals (void)
112 #ifdef SLANG_POSIX_SIGNALS
113 sigset_t new_mask;
114 #endif
116 Blocked_Depth++;
117 if (Blocked_Depth != 1)
119 return 0;
122 #ifdef SLANG_POSIX_SIGNALS
123 sigemptyset (&new_mask);
124 # ifdef SIGQUIT
125 sigaddset (&new_mask, SIGQUIT);
126 # endif
127 # ifdef SIGTSTP
128 sigaddset (&new_mask, SIGTSTP);
129 # endif
130 # ifdef SIGINT
131 sigaddset (&new_mask, SIGINT);
132 # endif
133 # ifdef SIGTTIN
134 sigaddset (&new_mask, SIGTTIN);
135 # endif
136 # ifdef SIGTTOU
137 sigaddset (&new_mask, SIGTTOU);
138 # endif
139 # ifdef SIGWINCH
140 sigaddset (&new_mask, SIGWINCH);
141 # endif
143 (void) sigprocmask (SIG_BLOCK, &new_mask, &Old_Signal_Mask);
144 return 0;
145 #else
146 /* Not implemented. */
147 return -1;
148 #endif
151 int SLsig_unblock_signals (void)
153 if (Blocked_Depth == 0)
154 return -1;
156 Blocked_Depth--;
158 if (Blocked_Depth != 0)
159 return 0;
161 #ifdef SLANG_POSIX_SIGNALS
162 (void) sigprocmask (SIG_SETMASK, &Old_Signal_Mask, NULL);
163 return 0;
164 #else
165 return -1;
166 #endif
169 #ifdef MSWINDOWS
170 int SLsystem (char *cmd)
172 SLang_verror (SL_NOT_IMPLEMENTED, "system not implemented");
173 return -1;
176 #else
177 int SLsystem (char *cmd)
179 #ifdef SLANG_POSIX_SIGNALS
180 pid_t pid;
181 int status;
182 struct sigaction ignore;
183 # ifdef SIGINT
184 struct sigaction save_intr;
185 # endif
186 # ifdef SIGQUIT
187 struct sigaction save_quit;
188 # endif
189 # ifdef SIGCHLD
190 sigset_t child_mask, save_mask;
191 # endif
193 if (cmd == NULL) return 1;
195 ignore.sa_handler = SIG_IGN;
196 sigemptyset (&ignore.sa_mask);
197 ignore.sa_flags = 0;
199 # ifdef SIGINT
200 if (-1 == sigaction (SIGINT, &ignore, &save_intr))
201 return -1;
202 # endif
204 # ifdef SIGQUIT
205 if (-1 == sigaction (SIGQUIT, &ignore, &save_quit))
207 (void) sigaction (SIGINT, &save_intr, NULL);
208 return -1;
210 # endif
212 # ifdef SIGCHLD
213 sigemptyset (&child_mask);
214 sigaddset (&child_mask, SIGCHLD);
215 if (-1 == sigprocmask (SIG_BLOCK, &child_mask, &save_mask))
217 # ifdef SIGINT
218 (void) sigaction (SIGINT, &save_intr, NULL);
219 # endif
220 # ifdef SIGQUIT
221 (void) sigaction (SIGQUIT, &save_quit, NULL);
222 # endif
223 return -1;
225 # endif
227 pid = fork();
229 if (pid == -1)
230 status = -1;
231 else if (pid == 0)
233 /* Child */
234 # ifdef SIGINT
235 (void) sigaction (SIGINT, &save_intr, NULL);
236 # endif
237 # ifdef SIGQUIT
238 (void) sigaction (SIGQUIT, &save_quit, NULL);
239 # endif
240 # ifdef SIGCHLD
241 (void) sigprocmask (SIG_SETMASK, &save_mask, NULL);
242 # endif
244 execl ("/bin/sh", "sh", "-c", cmd, NULL);
245 _exit (127);
247 else
249 /* parent */
250 while (-1 == waitpid (pid, &status, 0))
252 # ifdef EINTR
253 if (errno == EINTR)
254 continue;
255 # endif
256 # ifdef ERESTARTSYS
257 if (errno == ERESTARTSYS)
258 continue;
259 # endif
260 status = -1;
261 break;
264 # ifdef SIGINT
265 if (-1 == sigaction (SIGINT, &save_intr, NULL))
266 status = -1;
267 # endif
268 # ifdef SIGQUIT
269 if (-1 == sigaction (SIGQUIT, &save_quit, NULL))
270 status = -1;
271 # endif
272 # ifdef SIGCHLD
273 if (-1 == sigprocmask (SIG_SETMASK, &save_mask, NULL))
274 status = -1;
275 # endif
277 return status;
279 #else /* No POSIX Signals */
280 # ifdef SIGINT
281 void (*sint)(int);
282 # endif
283 # ifdef SIGQUIT
284 void (*squit)(int);
285 # endif
286 int status;
288 # ifdef SIGQUIT
289 squit = SLsignal (SIGQUIT, SIG_IGN);
290 # endif
291 # ifdef SIGINT
292 sint = SLsignal (SIGINT, SIG_IGN);
293 # endif
294 status = system (cmd);
295 # ifdef SIGINT
296 SLsignal (SIGINT, sint);
297 # endif
298 # ifdef SIGQUIT
299 SLsignal (SIGQUIT, squit);
300 # endif
301 return status;
302 #endif /* POSIX_SIGNALS */
304 #endif
306 #if 0
307 #include <windows.h>
308 static int msw_system (char *cmd)
310 STARTUPINFO startup_info;
311 PROCESS_INFORMATION process_info;
312 int status;
314 if (cmd == NULL) return -1;
316 memset ((char *) &startup_info, 0, sizeof (STARTUPINFO));
317 startup_info.cb = sizeof(STARTUPINFO);
318 startup_info.dwFlags = STARTF_USESHOWWINDOW;
319 startup_info.wShowWindow = SW_SHOWDEFAULT;
321 if (FALSE == CreateProcess (NULL,
322 cmd,
323 NULL,
324 NULL,
325 FALSE,
326 NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE,
327 NULL,
328 NULL,
329 &startup_info,
330 &process_info))
332 SLang_verror (0, "%s: CreateProcess failed.", cmd);
333 return -1;
336 status = -1;
338 if (0xFFFFFFFFUL != WaitForSingleObject (process_info.hProcess, INFINITE))
340 DWORD exit_code;
342 if (TRUE == GetExitCodeProcess (process_info.hProcess, &exit_code))
343 status = (int) exit_code;
346 CloseHandle (process_info.hThread);
347 CloseHandle (process_info.hProcess);
349 return status;
351 #endif