File:  [Coherent Logic Development] / freem / src / sighnd.c
Revision 1.11: download - view: text, annotated - select for diffs
Thu May 1 21:02:31 2025 UTC (3 months ago) by snw
Branches: MAIN
CVS tags: HEAD
Documentation updates

    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>