root/games/warp/sig.c
/* Header: /usr/src/games/warp/RCS/sig.c,v 1.1 87/07/03 01:47:11 games Exp */

/* Log: sig.c,v
 * Revision 7.0.1.1a  87/07/03  01:47:11  games
 * Changed sigsetmask to use sigmask instead of calculating it (incorrectly)
 * by hand.
 *
 * Revision 7.0.1.1  86/12/12  17:02:44  lwall
 * Baseline for net release.
 *
 * Revision 7.0  86/10/08  15:13:24  lwall
 * Split into separate files.  Added amoebas and pirates.
 *
 */

#include "EXTERN.h"
#include "warp.h"
#include "play.h"
#include "score.h"
#include "term.h"
#include "util.h"
#include "INTERN.h"
#include "sig.h"

void
sig_init(void)
{
    sigignore(SIGINT);  /* for inquiry of existence via kill call */
#ifdef SIGTTOU
    sigignore(SIGTTOU);
#endif

    sigset(SIGHUP, sig_catcher);
    if (!debugging) {
        sigset(SIGQUIT, sig_catcher);
        sigset(SIGILL, sig_catcher);
        sigset(SIGFPE, sig_catcher);
#if 0
        sigset(SIGBUS, sig_catcher);
        sigset(SIGSEGV, sig_catcher);
#endif
        sigset(SIGSYS, sig_catcher);
        sigset(SIGTERM, sig_catcher);
    }
#ifdef SIGXCPU
    sigset(SIGXCPU, sig_catcher);
#endif
#ifdef SIGCONT
    sigset(SIGCONT, cont_catcher);
#endif
#ifdef SIGTSTP
    sigset(SIGTSTP, stop_catcher);
    sigset(SIGSTOP, stop_catcher);
#endif
}

#ifdef SIGTSTP
void
cont_catcher(int x)
{
#ifndef lint
    sigset(SIGCONT,cont_catcher);
#endif
    savetty();
    crmode();
    raw();
    noecho();
    nonl();
}
#endif

void
mytstp(void)
{
    resetty();
#ifdef SIGTSTP
    kill(0,SIGTSTP);
#else
    if (fork())
        wait(0);
    else {
        char *shell = getenv("SHELL");

        setuid(getuid());
        if (!*shell)
            shell = "/bin/sh";
        execl(shell,shell,0);
        exit(1);
    }
#endif
    rewrite();
}

void                                    /* very much void */
finalize(int status)
{
    if (bizarre)
        resetty();
    if (status < 0) {
        chdir("/usr/tmp");
        sigset(SIGILL,SIG_DFL);
        abort();
    }
    exit(status);
}

/* come here on signal other than interrupt, stop, or cont */

void
sig_catcher(int signo)
{
#ifdef VERBOSE
    static const char *signame[] = {
        "",
        "HUP",
        "INT",
        "QUIT",
        "ILL",
        "TRAP",
        "IOT",
        "EMT",
        "FPE",
        "KILL",
        "BUS",
        "SEGV",
        "SYS",
        "PIPE",
        "ALRM",
        "TERM",
        "???"
#ifdef SIGTSTP
        ,"STOP",
        "TSTP",
        "CONT",
        "CHLD",
        "TTIN",
        "TTOU",
        "TINT",
        "XCPU",
        "XFSZ"
#ifdef SIGPROF
        ,"VTALARM",
        "PROF"
#endif
#endif
        };
#endif

#ifdef SIGTTOU
#ifndef lint
    sigignore(SIGTTOU);
#endif /* lint */
#endif
#ifdef DEBUGGING
    if (debug) {
        printf("\r\nSIG%s--game not saved in debug\r\n",signame[signo]);
        finalize(-1);
    }
#endif
    panic++;
    if (panic >= 2) {
        if (panic >= 3)
            abort();
        chdir(SAVEDIR);
        kill(0,SIGIOT);
    }
    (void) sigset(SIGILL,SIG_DFL);
    if (signo == SIGHUP && (timer < 10 || didkill))
        signo = SIGQUIT;
    if (signo == SIGQUIT) {     /* can't let them bomb out without penalty */
        if (smarts < 20)
            smarts += 4;
        else if (smarts < 35)
            smarts += 2;
        else
            smarts++;
        totalscore -= possiblescore / 2;
    }
    save_game();
    if (signo != SIGHUP && signo != SIGQUIT) {
#ifdef VERBOSE
        IF(verbose)
            printf("\r\nCaught %s%s--%s\r\n",
                signo ? "a SIG" : "an internal error", signame[signo],
                experimenting ? "game saved" : "bye bye");
        ELSE
#endif
#ifdef TERSE
            printf("\r\nsignal %d--bye bye\r\n",signo);
#endif
    }
    switch (signo) {
    case SIGBUS:
    case SIGILL:
    case SIGSEGV:
        finalize(-signo);
    }
    finalize(1);                                /* and blow up */
}

#ifdef SIGTSTP
/* come here on stop signal */

void
stop_catcher(int sig)
{
    if (!waiting) {
        resetty();                      /* this is the point of all this */
#ifdef DEBUGGING
        if (debug)
            write(2,"stop_catcher\r\n",13);
#endif
        sigset(SIGTSTP,SIG_DFL);        /* enable stop */
#ifdef BSD42
        sigsetmask(sigblock(0L) & ~sigmask(SIGTSTP));
#endif
        kill(0,SIGTSTP);                /* and do the stop */
    }
#ifndef lint
    sigset(SIGTSTP,stop_catcher);       /* unenable the stop */
#endif
}
#endif