/* * Copyright (c) 1995, 1996 Gunther Schadow. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "pg_config.h" IDENT("@(#) trap.c (Gunther Schadow) 12/19/96"); #include "trap.h" #include #include #include volatile bool israised[NSIG]; jmp_buf __signal_jmp[NSIG]; void __jsignal(int sig) { israised[sig] = TRUE; DBG(syslog(LOG_DEBUG, "signal handler: %s", sys_siglist[sig])); longjmp(__signal_jmp[sig], TRUE); } void stimeout(int sec, __sighandler_t hdl, int flags) { ualarm(sec * 1000000, 0); ssignal(SIGALRM, hdl, flags); } void svsignal(int sig, struct sigsave *ss) { sigset_t set, old_set; sigfillset(&set); sigprocmask(SIG_SETMASK, &set, &old_set); sigaction(sig, NULL, &ss->ss_sa); memcpy(&ss->ss_jmp, &__signal_jmp[sig], sizeof(jmp_buf)); ss->ss_blk = sigismember(&old_set, sig); sigprocmask(SIG_SETMASK, &old_set, NULL); return; } void rssignal(int sig, struct sigsave *ss) { sigset_t set, old_set; sigfillset(&set); sigprocmask(SIG_SETMASK, &set, &old_set); memcpy(&__signal_jmp[sig], &ss->ss_jmp, sizeof(jmp_buf)); sigaction(sig, &ss->ss_sa, NULL); if(ss->ss_blk) sigaddset(&old_set, sig); else sigdelset(&old_set, sig); sigprocmask(SIG_SETMASK, &old_set, NULL); return; } void ssignal(int sig, __sighandler_t hdl, int flags) { struct sigaction sigacts; sigset_t set; sigemptyset(&set); sigaddset(&set, sig); /* Block signal */ sigprocmask(SIG_BLOCK, &set, NULL); sigaction(sig, NULL, &sigacts); /* Discard pending signal */ if(flags & T_DISCARD) { sigacts.sa_handler = SIG_IGN; sigaction(sig, &sigacts, NULL); israised[sig] = FALSE; } /* Install new handler */ if(hdl != SIG_NULL) sigacts.sa_handler = hdl; /* Set the flags * always reset the flags to prevent surprize * currently only SA_RESTART is supported */ if(flags & T_SINTR) sigacts.sa_flags = 0; else sigacts.sa_flags = SA_RESTART; sigaction(sig, &sigacts, NULL); /* Release blocking */ if(!(flags & T_BLOCK)) sigprocmask(SIG_UNBLOCK, &set, NULL); }