Annotation of freem/src/sighnd.c, revision 1.9

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>