slsignal.c 6.5 KB

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