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