slsignal.c 7.0 KB

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