summaryrefslogtreecommitdiff
path: root/librols/raisecond.c
diff options
context:
space:
mode:
Diffstat (limited to 'librols/raisecond.c')
-rw-r--r--librols/raisecond.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/librols/raisecond.c b/librols/raisecond.c
new file mode 100644
index 0000000..01cef9c
--- /dev/null
+++ b/librols/raisecond.c
@@ -0,0 +1,179 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)raisecond.c 1.18 04/05/09 Copyright 1985, 1989, 1995-2004 J. Schilling */
+/*
+ * raise a condition (software signal)
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*
+ * Check for installed condition handlers.
+ * If a handler is found, the function is called with the appropriate args.
+ * If no handler is found or no handler signals success,
+ * the program will be aborted.
+ *
+ * Copyright (c) 1985, 1989, 1995-2004 J. Schilling
+ */
+#include <mconfig.h>
+#include <stdio.h>
+#include <standard.h>
+#include <sigblk.h>
+#include <unixstd.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <avoffset.h>
+#include <schily.h>
+
+#if !defined(AV_OFFSET) || !defined(FP_INDIR)
+# ifdef HAVE_SCANSTACK
+# undef HAVE_SCANSTACK
+# endif
+#endif
+
+/*
+ * Macros to print to stderr without stdio, to avoid screwing up.
+ */
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+#define eprints(a) do { int ret; ret = write(STDERR_FILENO, (a), sizeof (a)-1); } while (0)
+#define eprintl(a) do { int ret; ret = write(STDERR_FILENO, (a), strlen(a)); } while (0)
+
+#define is_even(p) ((((long)(p)) & 1) == 0)
+#define even(p) (((long)(p)) & ~1L)
+#ifdef __future__
+#define even(p) (((long)(p)) - 1) /* will this work with 64 bit ?? */
+#endif
+
+
+LOCAL void raiseabort __PR((const char *));
+
+#ifdef HAVE_SCANSTACK
+#include <stkframe.h>
+#define next_frame(vp) do { \
+ if (((struct frame *)(vp))->fr_savfp == 0) { \
+ vp = (void *)0; \
+ break; \
+ } \
+ if (((struct frame *)(vp))->fr_savpc == 0) { \
+ vp = (void *)0; \
+ break; \
+ } \
+ vp = \
+ (void *)((struct frame *)(vp))->fr_savfp; \
+ } while (vp != NULL && is_even(vp)); \
+ vp = (struct frame *)even(vp);
+#else
+EXPORT SIGBLK *__roothandle;
+
+#define next_frame(vp) vp = (((SIGBLK *)(vp))->sb_savfp);
+#endif
+
+LOCAL BOOL framehandle __PR((SIGBLK *, const char *, const char *, long));
+
+/*
+ * Loop through the chain of procedure frames on the stack.
+ *
+ * Frame pointers normally have even values.
+ * Frame pointers of procedures with an installed handler are marked odd.
+ * The even base value, in this case actually points to a SIGBLK which
+ * holds the saved "real" frame pointer.
+ * The SIGBLK mentioned above may me the start of a chain of SIGBLK's,
+ * containing different handlers.
+ */
+EXPORT void
+raisecond(signame, arg2)
+ const char *signame;
+ long arg2;
+{
+ register void *vp = NULL;
+
+#ifdef HAVE_SCANSTACK
+ /*
+ * As the SCO OpenServer C-Compiler has a bug that may cause
+ * the first function call to getfp() been done before the
+ * new stack frame is created, we call getfp() twice.
+ */
+ (void) getfp();
+ vp = getfp();
+ next_frame(vp);
+#else
+ vp = __roothandle;
+#endif
+
+ while (vp) {
+ if (framehandle((SIGBLK *)vp, signame, signame, arg2))
+ return;
+ else if (framehandle((SIGBLK *)vp, "any_other", signame, arg2))
+ return;
+#ifdef HAVE_SCANSTACK
+ vp = (struct frame *)((SIGBLK *)vp)->sb_savfp;
+#endif
+ next_frame(vp);
+ }
+ /*
+ * No matching handler that signals success found.
+ * Print error message and abort.
+ */
+ raiseabort(signame);
+ /* NOTREACHED */
+}
+
+/*
+ * Loop through the handler chain for a procedure frame.
+ *
+ * If no handler with matching name is found, return FALSE,
+ * otherwise the first handler with matching name is called.
+ * The return value in the latter case depends on the called function.
+ */
+LOCAL BOOL
+framehandle(sp, handlename, signame, arg2)
+ register SIGBLK *sp;
+ const char *handlename;
+ const char *signame;
+ long arg2;
+{
+ for (; sp; sp = sp->sb_signext) {
+ if (sp->sb_signame != NULL &&
+ streql(sp->sb_signame, handlename)) {
+ if (sp->sb_sigfun == NULL) { /* deactivated */
+ return (FALSE);
+ } else {
+ return (*sp->sb_sigfun)(signame,
+ sp->sb_sigarg, arg2);
+ }
+ }
+ }
+ return (FALSE);
+}
+
+LOCAL void
+raiseabort(signame)
+ const char *signame;
+{
+ eprints("Condition not caught: "); eprintl(signame); eprints(".\n");
+ abort();
+ /* NOTREACHED */
+}