File:  [Coherent Logic Development] / freem / src / sighnd.c
Revision 1.12: download - view: text, annotated - select for diffs
Wed Jan 7 19:51:33 2026 UTC (2 months, 3 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Fix segfault in reverse $QUERY

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

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