Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
**********/
* The signal routines for spice 3 and nutmeg.
*/
#include "ngspice/ngspice.h"
#include "ngspice/ifsim.h"
#include "ngspice/iferrmsg.h"
#include "ngspice/cpdefs.h"
#include "ngspice/ftedefs.h"
#include "ngspice/ftedev.h"
#include <setjmp.h>
#include <signal.h>
#include "signal_handler.h"
#include "plotting/graf.h"
#ifdef SIGTTIN
#include <unistd.h>
#endif
#ifdef HAS_WINGUI
void winmessage(char* new_msg);
#endif
#ifdef HAVE_GNUREADLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
#ifdef HAVE_BSDEDITLINE
#include <editline/readline.h>
#endif
JMP_BUF jbuf;
* cshpar) so it is global. They are ifdef BSD because of the sigmask
* stuff in sigstop. We set the interrupt flag and return if ft_setflag
* is TRUE.
*/
* signals which require user process context. Some kernel services are not
* allowed to be called from asynchronous signal handlers. (e.g. mutexes)
*/
void
ft_sigintr_cleanup(void)
{
gr_clean();
The following are not supported in editline */
#if defined(HAVE_GNUREADLINE)
(void) rl_free_line_state();
(void) rl_cleanup_after_signal();
(void) rl_reset_after_signal();
#endif
cp_interactive = TRUE;
cp_resetcontrol(TRUE);
}
void
ft_sigintr(void)
{
static int interrupt_counter = 0;
(void) signal(SIGINT, (SIGNAL_FUNCTION) ft_sigintr);
if (ft_intrpt) {
fprintf(cp_err, "\nInterrupted again (ouch)\n");
interrupt_counter++;
} else {
fprintf(cp_err, "\nInterrupted once . . .\n");
ft_intrpt = TRUE;
interrupt_counter = 1;
}
if (interrupt_counter >= 3) {
fprintf(cp_err, "\nKilling, since %d interrupts have been requested\n\n", interrupt_counter);
controlled_exit(1);
}
if (ft_setflag) {
return;
}
cp_background = FALSE;
LONGJMP(jbuf, 1);
}
void
sigfloat(int code)
{
fperror("Error", code);
rewind(cp_out);
(void) signal(SIGFPE, (SIGNAL_FUNCTION) sigfloat);
LONGJMP(jbuf, 1);
}
* attempting terminal IO as a background process.
*/
bool cp_background = FALSE;
#ifdef SIGTTIN
void
sigttio(void)
{
if (cp_cwait) {
* Set background flag and restart event loop.
*/
cp_background = TRUE;
LONGJMP(jbuf, 1);
} else {
* Stop.
*/
(void) signal(SIGTSTP, SIG_DFL);
(void) kill(getpid(), SIGTSTP);
}
}
void test_background(void)
{
pid_t terminal_group;
int tty;
tty = open("/dev/tty", O_RDONLY);
if (tty < 0) {
cp_background = TRUE;
return;
}
terminal_group = tcgetpgrp(tty);
close(tty);
cp_background = (terminal_group != getpgrp());
}
#endif
#ifdef SIGTSTP
void
sigstop(void)
{
gr_clean();
(void) signal(SIGTSTP, SIG_DFL);
(void) kill(getpid(), SIGTSTP);
}
void
sigcont(void)
{
(void) signal(SIGTSTP, (SIGNAL_FUNCTION) sigstop);
test_background();
if (cp_cwait)
LONGJMP(jbuf, 1);
}
#endif
void
sigill(void)
{
fprintf(cp_err, "\ninternal error -- illegal instruction\n");
fatal();
}
void
sigbus(void)
{
fprintf(cp_err, "\ninternal error -- bus error\n");
fatal();
}
void
sigsegv(void)
{
fprintf(cp_err, "\ninternal error -- segmentation violation\n");
#ifdef HAS_WINGUI
winmessage("Fatal error in NGSPICE");
#endif
fatal();
}
void
sigsegvsh(void)
{
fprintf(cp_err, "\ninternal error -- segmentation violation\n");
controlled_exit(EXIT_SEGV);
}
void
sig_sys(void)
{
fprintf(cp_err, "\ninternal error -- bad argument to system call\n");
fatal();
}