File:  [Coherent Logic Development] / freem / src / sighnd.c
Revision 1.6: download - view: text, annotated - select for diffs
Mon Mar 24 04:15:25 2025 UTC (8 days, 19 hours ago) by snw
Branches: MAIN
CVS tags: v0-62-3, HEAD
Create dummy onwinch signal handler for OS/2

/*
 *   $Id: sighnd.c,v 1.6 2025/03/24 04:15:25 snw Exp $
 *    FreeM signal handlers 
 *
 *  
 *   Author: Serena Willis <snw@coherent-logic.com>
 *    Copyright (C) 1998 MUG Deutschland
 *    Copyright (C) 2020, 2025 Coherent Logic Development LLC
 *
 *
 *   This file is part of FreeM.
 *
 *   FreeM is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   FreeM is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Affero Public License for more details.
 *
 *   You should have received a copy of the GNU Affero Public License
 *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
 *
 *   $Log: sighnd.c,v $
 *   Revision 1.6  2025/03/24 04:15:25  snw
 *   Create dummy onwinch signal handler for OS/2
 *
 *   Revision 1.5  2025/03/24 00:38:40  snw
 *   Fix termios junk in sighnd.c
 *
 *   Revision 1.4  2025/03/24 00:34:30  snw
 *   Fix termios junk in sighnd.c
 *
 *   Revision 1.3  2025/03/09 19:50:47  snw
 *   Second phase of REUSE compliance and header reformat
 *
 *
 * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
 * SPDX-License-Identifier: AGPL-3.0-or-later
 **/

#include <stddef.h>
#include <stdlib.h>
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>

#include <sys/types.h>
#include <sys/wait.h>

#if !defined(__APPLE__) && !defined(__gnu_hurd__) && !defined(EMSCRIPTEN)
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__AMIGA)
#  include <termios.h>
#  if !defined(__AMIGA)
#   define TCGETA TIOCGETA
#   define TCSETA TIOCSETA
#  endif
#  define termio termios
# else
#  if !defined(MSDOS)
#    include <termio.h>
#  endif
# endif
#else
# include <termios.h>
#endif

#include <sys/ioctl.h>

#include "mpsdef.h"
#include "transact.h"
#include "init.h"
#include "events.h"
#include "jobtab.h"
#include "shmmgr.h"



void m_log (int, const char *);
int pending_signal_type = -1;

void sig_attach(int sig, void *handler)
{
    struct sigaction act;

    act.sa_handler = handler;
#if !defined(__AMIGA)    
    sigaction (sig, &act, NULL);
#else
    //TODO: fill in for m68k-amigaos
#endif
}


void sig_init(void)
{
    /* signals stuff */
    sig_attach (SIGINT, &onintr);    /* set_up INTERRUPT  */
    sig_attach (SIGQUIT, &onquit);   /* set_up ZBREAK     */
    sig_attach (SIGTERM, &onkill);   /* catch kill signal */

#if !defined(__CYGWIN__) && !defined(MSDOS)
    sig_attach (SIGIOT, &onbus);     /* catch IOT error   */
#endif/*__CYGWIN__*/

#ifndef LINUX
    sig_attach (SIGEMT, &onbus);     /* catch EMT error   */
#endif/*LINUX*/

#if !defined(MSDOS)
    sig_attach (SIGWINCH, &onwinch);
#endif
    
    sig_attach (SIGUSR1, &oncld);    /* catch son dies signal */
    sig_attach (SIGHUP, &onhup);    /* catch hangup      */
    
    sig_attach (SIGUSR2, &onipc);    /* catch IPC signal */
    sig_attach (SIGFPE, &onfpe);     /* catch floating pt except */
}


#if !defined(MSDOS) && !defined(__OS2__)
void onwinch (void)
{
    struct winsize ws;

    /* restore handler */
    sig_attach (SIGWINCH, &onwinch);

    ioctl (STDIN_FILENO, TIOCGWINSZ, &ws);

    n_lines = ws.ws_row;
    n_columns = ws.ws_col;

    if (evt_async_enabled) {
        pending_signal_type = SIGWINCH;
        merr_raise (ASYNC);
    }

    return;
}
#else
void onwinch (void)
{
    sig_attach (SIGWINCH, &onwinch);

    return;
}
#endif

void onintr (void)
{
    sig_attach (SIGINT, &onintr); /* restore handler */

    //printf ("\r\nSIGINT codptr = '%s'\r\n", codptr);
    
    if (first_process) {
        job_request_stop (pid);
    }
    else {
        if (shm_config->hdr->maintenance_mode == 1) {

            job_slot_t *s = job_get (pid);


            if ((s->flags & JFLG_FMADM) != JFLG_FMADM) {
            
                fprintf (stderr, "\r\n***ENVIRONMENT IN MAINTENANCE MODE***\r\n");

                while (shm_config->hdr->maintenance_mode == 1) {
                    sleep (1);
                }

                return;

            }

        }
    }

    
    if (breakon) {
        merr_raise (INRPT);
        inrpt_after_async = TRUE;
        if (forsw) sigint_in_for = TRUE;
    }
    else {
        zcc = TRUE;
    }
    
    if (evt_async_enabled) {
        pending_signal_type = SIGINT;
    }    
    
    return;
}                   /* end of onintr */

void onfpe (void)
{
    sig_attach (SIGFPE, &onfpe); /* restore handler */

    if (evt_async_enabled) {
        pending_signal_type = SIGFPE;
    }

    merr_raise (MXNUM);
    return;
}                   /* end of onfpe */

void onquit (void)
{

    if (run_daemon == TRUE) {
        job_request_stop (pid);        
    }
    
    sig_attach (SIGQUIT, &onquit); /* restore handler */
    
    if (zbreakon && (merr () == OK)) ierr = OK - CTRLB;

    if (evt_async_enabled) {
        pending_signal_type = SIGQUIT;
    }

    return;
}                   /* end of onquit */

void onkill (void)
{
    int n = 0;

    if (run_daemon == TRUE) {
        job_request_stop (pid);        
    }

#if !defined(AMIGA68K)
    if (direct_mode == TRUE) {
        set_io (UNIX);
        fprintf (stderr, "\n\nFreeM process %d caught SIGTERM\n", pid);
        set_io (MUMPS);
    }
#endif


    sig_attach (SIGTERM, &onkill); /* restore handler */

    if (killerflag == FALSE) return;                /* ignore that signal */

    /* if there exists an error trap, process as an error */
    /* otherwise terminate the job                        */

    if (DSM2err) {          /* DSM V.2 error trapping */
        

            
            if (ztrap[NESTLEVLS + 1][0] != EOL) {
                merr_raise (KILLER);
                return;
            }


    } 
    else {

        
            while (n >= 0) {
                if (ztrap[n--][0] != EOL) {
                    merr_raise (KILLER);
                    return;
                }
            }
     

    }

    cleanup ();
    if (father) kill (father, SIGUSR1);     /* advertise death to parent */

    exit (1);               /* terminate mumps */
}                   /* end of onkill() */

void onhup (void)
{

    int n = nstx;


    if (run_daemon == TRUE) {
        fprintf (stderr, "freem:  daemon received SIGHUP\r\n");
        m_log (1, "freem:  daemon received SIGHUP");

        sig_attach (SIGHUP, &onhup);       /* restore handler */
        
        return;
    }
    
    sig_attach (SIGHUP, &onhup);       /* restore handler */

    if (huperflag == FALSE) return;             /* ignore that signal */

    /* if there exists an error trap, process as an error */
    /* otherwise terminate the job                        */

    if (DSM2err) {          /* DSM V.2 error trapping */

        if (ztrap[NESTLEVLS + 1][0] != EOL) {
            merr_raise (HUPER);
            return;
        }
        

    } 
    else {
            
        while (n >= 0) {
            if (ztrap[n--][0] != EOL) {
                merr_raise (HUPER);
                return;
            }
        }
        
    }

    cleanup ();

    if (father) kill (father, SIGUSR1);     /* advertise death to parent */

    exit (1);               /* terminate mumps */
    
} /* end of onhup() */

void onbus (void)
{
    cleanup ();
    
    printf ("\012\015BUS ERROR, SEGMENTATION VIOLATION\012\015");

    if (father) kill (father, SIGUSR1);     /* advertise death to parent */

    exit (1);               /* terminate mumps */
}                   /* end of onbus() */

/* under XENIX processes started with JOB hang around as zombies     */
/* if they HALT before the parent process, unless the parent process */
/* waits for his child to terminate. to solve the problem, the child */
/* sends a signal to his parent to avoid an unattended funeral which */
/* inevitably would result in a living dead sucking up cpu time      */
void oncld (void)
{
    int     status;

    /* ignore signal while as we're here */
    sig_attach (SIGUSR1, SIG_IGN);

    wait (&status);         /* wait for report from child */

    sig_attach (SIGUSR1, &oncld);/* restore handler */

    return;
}                   /* end of oncld() */

void onipc (void)
{
    /* restore handler */
    sig_attach (SIGUSR2, &onipc);

    ipc_pending = 1;

    return;
}

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