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