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

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

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