Annotation of freem/src/sighnd.c, revision 1.11
1.1 snw 1: /*
1.11 ! snw 2: * $Id: sighnd.c,v 1.10 2025/04/30 20:03:09 snw Exp $
1.1 snw 3: * FreeM signal handlers
4: *
5: *
1.2 snw 6: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 7: * Copyright (C) 1998 MUG Deutschland
1.3 snw 8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
1.1 snw 9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
1.4 snw 26: * $Log: sighnd.c,v $
1.11 ! snw 27: * Revision 1.10 2025/04/30 20:03:09 snw
! 28: * Work on entryref parser
! 29: *
1.10 snw 30: * Revision 1.9 2025/04/15 18:39:20 snw
31: * Remove extraneous CRLFs in logprintf calls
32: *
1.9 snw 33: * Revision 1.8 2025/04/15 16:49:36 snw
34: * Make use of logprintf throughout codebase
35: *
1.8 snw 36: * Revision 1.7 2025/04/10 01:24:38 snw
37: * Remove C++ style comments
38: *
1.7 snw 39: * Revision 1.6 2025/03/24 04:15:25 snw
40: * Create dummy onwinch signal handler for OS/2
41: *
1.6 snw 42: * Revision 1.5 2025/03/24 00:38:40 snw
43: * Fix termios junk in sighnd.c
44: *
1.5 snw 45: * Revision 1.4 2025/03/24 00:34:30 snw
46: * Fix termios junk in sighnd.c
47: *
1.4 snw 48: * Revision 1.3 2025/03/09 19:50:47 snw
49: * Second phase of REUSE compliance and header reformat
50: *
1.3 snw 51: *
52: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
53: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 54: **/
55:
56: #include <stddef.h>
57: #include <stdlib.h>
58: #include <setjmp.h>
59: #include <signal.h>
60: #include <unistd.h>
61: #include <stdio.h>
62:
63: #include <sys/types.h>
64: #include <sys/wait.h>
65:
1.4 snw 66: #if !defined(__APPLE__) && !defined(__gnu_hurd__) && !defined(EMSCRIPTEN)
67: # if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__AMIGA)
68: # include <termios.h>
69: # if !defined(__AMIGA)
70: # define TCGETA TIOCGETA
71: # define TCSETA TIOCSETA
72: # endif
73: # define termio termios
74: # else
75: # if !defined(MSDOS)
76: # include <termio.h>
77: # endif
78: # endif
79: #else
80: # include <termios.h>
81: #endif
82:
1.1 snw 83: #include <sys/ioctl.h>
84:
85: #include "mpsdef.h"
86: #include "transact.h"
87: #include "init.h"
88: #include "events.h"
89: #include "jobtab.h"
90: #include "shmmgr.h"
1.8 snw 91: #include "log.h"
1.1 snw 92:
1.4 snw 93:
1.1 snw 94: int pending_signal_type = -1;
95:
96: void sig_attach(int sig, void *handler)
97: {
98: struct sigaction act;
99:
100: act.sa_handler = handler;
101: #if !defined(__AMIGA)
102: sigaction (sig, &act, NULL);
103: #else
1.7 snw 104: /* TODO: fill in for m68k-amigaos */
1.1 snw 105: #endif
106: }
107:
108:
109: void sig_init(void)
110: {
111: /* signals stuff */
112: sig_attach (SIGINT, &onintr); /* set_up INTERRUPT */
113: sig_attach (SIGQUIT, &onquit); /* set_up ZBREAK */
114: sig_attach (SIGTERM, &onkill); /* catch kill signal */
115:
116: #if !defined(__CYGWIN__) && !defined(MSDOS)
117: sig_attach (SIGIOT, &onbus); /* catch IOT error */
118: #endif/*__CYGWIN__*/
119:
120: #ifndef LINUX
121: sig_attach (SIGEMT, &onbus); /* catch EMT error */
122: #endif/*LINUX*/
123:
124: #if !defined(MSDOS)
125: sig_attach (SIGWINCH, &onwinch);
126: #endif
127:
128: sig_attach (SIGUSR1, &oncld); /* catch son dies signal */
129: sig_attach (SIGHUP, &onhup); /* catch hangup */
130:
131: sig_attach (SIGUSR2, &onipc); /* catch IPC signal */
132: sig_attach (SIGFPE, &onfpe); /* catch floating pt except */
133: }
134:
135:
1.5 snw 136: #if !defined(MSDOS) && !defined(__OS2__)
1.1 snw 137: void onwinch (void)
138: {
139: struct winsize ws;
140:
141: /* restore handler */
142: sig_attach (SIGWINCH, &onwinch);
143:
144: ioctl (STDIN_FILENO, TIOCGWINSZ, &ws);
145:
146: n_lines = ws.ws_row;
147: n_columns = ws.ws_col;
148:
149: if (evt_async_enabled) {
150: pending_signal_type = SIGWINCH;
151: merr_raise (ASYNC);
152: }
153:
154: return;
155: }
1.6 snw 156: #else
157: void onwinch (void)
158: {
159: sig_attach (SIGWINCH, &onwinch);
160:
161: return;
162: }
1.1 snw 163: #endif
164:
165: void onintr (void)
166: {
167: sig_attach (SIGINT, &onintr); /* restore handler */
168:
1.10 snw 169: /* printf ("\r\nSIGINT codptr = '%s'\r\n", codptr); */
1.1 snw 170:
171: if (first_process) {
172: job_request_stop (pid);
173: }
174: else {
175: if (shm_config->hdr->maintenance_mode == 1) {
176:
177: job_slot_t *s = job_get (pid);
178:
179:
180: if ((s->flags & JFLG_FMADM) != JFLG_FMADM) {
181:
182: fprintf (stderr, "\r\n***ENVIRONMENT IN MAINTENANCE MODE***\r\n");
183:
184: while (shm_config->hdr->maintenance_mode == 1) {
185: sleep (1);
186: }
187:
188: return;
189:
190: }
191:
192: }
193: }
194:
1.10 snw 195: if (breakon) {
1.1 snw 196: merr_raise (INRPT);
197: inrpt_after_async = TRUE;
198: if (forsw) sigint_in_for = TRUE;
1.10 snw 199:
200: if (usermode == 1) {
201: debug_mode = TRUE;
202: }
1.1 snw 203: }
204: else {
205: zcc = TRUE;
206: }
207:
208: if (evt_async_enabled) {
209: pending_signal_type = SIGINT;
210: }
211:
212: return;
213: } /* end of onintr */
214:
215: void onfpe (void)
216: {
217: sig_attach (SIGFPE, &onfpe); /* restore handler */
218:
219: if (evt_async_enabled) {
220: pending_signal_type = SIGFPE;
221: }
222:
223: merr_raise (MXNUM);
224: return;
225: } /* end of onfpe */
226:
227: void onquit (void)
228: {
229:
230: if (run_daemon == TRUE) {
231: job_request_stop (pid);
232: }
233:
234: sig_attach (SIGQUIT, &onquit); /* restore handler */
235:
236: if (zbreakon && (merr () == OK)) ierr = OK - CTRLB;
237:
238: if (evt_async_enabled) {
239: pending_signal_type = SIGQUIT;
240: }
241:
242: return;
243: } /* end of onquit */
244:
245: void onkill (void)
246: {
247: int n = 0;
248:
249: if (run_daemon == TRUE) {
250: job_request_stop (pid);
251: }
252:
253: #if !defined(AMIGA68K)
254: if (direct_mode == TRUE) {
255: set_io (UNIX);
256: fprintf (stderr, "\n\nFreeM process %d caught SIGTERM\n", pid);
257: set_io (MUMPS);
258: }
259: #endif
260:
261:
262: sig_attach (SIGTERM, &onkill); /* restore handler */
263:
264: if (killerflag == FALSE) return; /* ignore that signal */
265:
266: /* if there exists an error trap, process as an error */
267: /* otherwise terminate the job */
268:
269: if (DSM2err) { /* DSM V.2 error trapping */
270:
271:
272:
273: if (ztrap[NESTLEVLS + 1][0] != EOL) {
274: merr_raise (KILLER);
275: return;
276: }
277:
278:
279: }
280: else {
281:
282:
283: while (n >= 0) {
284: if (ztrap[n--][0] != EOL) {
285: merr_raise (KILLER);
286: return;
287: }
288: }
289:
290:
291: }
292:
293: cleanup ();
294: if (father) kill (father, SIGUSR1); /* advertise death to parent */
295:
296: exit (1); /* terminate mumps */
297: } /* end of onkill() */
298:
299: void onhup (void)
300: {
301:
302: int n = nstx;
303:
304:
305: if (run_daemon == TRUE) {
1.9 snw 306: logprintf (FM_LOG_INFO, "environment: daemon received SIGHUP");
1.1 snw 307:
308: sig_attach (SIGHUP, &onhup); /* restore handler */
309:
310: return;
311: }
312:
313: sig_attach (SIGHUP, &onhup); /* restore handler */
314:
315: if (huperflag == FALSE) return; /* ignore that signal */
316:
317: /* if there exists an error trap, process as an error */
318: /* otherwise terminate the job */
319:
320: if (DSM2err) { /* DSM V.2 error trapping */
321:
322: if (ztrap[NESTLEVLS + 1][0] != EOL) {
323: merr_raise (HUPER);
324: return;
325: }
326:
327:
328: }
329: else {
330:
331: while (n >= 0) {
332: if (ztrap[n--][0] != EOL) {
333: merr_raise (HUPER);
334: return;
335: }
336: }
337:
338: }
339:
340: cleanup ();
341:
342: if (father) kill (father, SIGUSR1); /* advertise death to parent */
343:
344: exit (1); /* terminate mumps */
345:
346: } /* end of onhup() */
347:
348: void onbus (void)
349: {
350: cleanup ();
351:
352: printf ("\012\015BUS ERROR, SEGMENTATION VIOLATION\012\015");
353:
354: if (father) kill (father, SIGUSR1); /* advertise death to parent */
355:
356: exit (1); /* terminate mumps */
357: } /* end of onbus() */
358:
359: /* under XENIX processes started with JOB hang around as zombies */
360: /* if they HALT before the parent process, unless the parent process */
361: /* waits for his child to terminate. to solve the problem, the child */
362: /* sends a signal to his parent to avoid an unattended funeral which */
363: /* inevitably would result in a living dead sucking up cpu time */
364: void oncld (void)
365: {
366: int status;
367:
368: /* ignore signal while as we're here */
369: sig_attach (SIGUSR1, SIG_IGN);
370:
371: wait (&status); /* wait for report from child */
372:
373: sig_attach (SIGUSR1, &oncld);/* restore handler */
374:
375: return;
376: } /* end of oncld() */
377:
378: void onipc (void)
379: {
380: /* restore handler */
381: sig_attach (SIGUSR2, &onipc);
382:
383: ipc_pending = 1;
384:
385: return;
386: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>