1 /* @(#)raisecond.c 1.22 09/07/10 Copyright 1985, 1989, 1995-2004 J. Schilling */ 2 /* 3 * raise a condition (software signal) 4 */ 5 /* 6 * The contents of this file are subject to the terms of the 7 * Common Development and Distribution License, Version 1.0 only 8 * (the "License"). You may not use this file except in compliance 9 * with the License. 10 * 11 * See the file CDDL.Schily.txt in this distribution for details. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file CDDL.Schily.txt from this distribution. 15 */ 16 /* 17 * Check for installed condition handlers. 18 * If a handler is found, the function is called with the appropriate args. 19 * If no handler is found or no handler signals success, 20 * the program will be aborted. 21 * 22 * Copyright (c) 1985, 1989, 1995-2004 J. Schilling 23 */ 24 #include <schily/mconfig.h> 25 #include <schily/stdio.h> 26 #include <schily/standard.h> 27 #include <schily/sigblk.h> 28 #include <schily/unistd.h> 29 #include <schily/stdlib.h> 30 #include <schily/string.h> 31 #include <schily/avoffset.h> 32 #include <schily/schily.h> 33 34 #if !defined(AV_OFFSET) || !defined(FP_INDIR) 35 # ifdef HAVE_SCANSTACK 36 # undef HAVE_SCANSTACK 37 # endif 38 #endif 39 40 /* 41 * Macros to print to stderr without stdio, to avoid screwing up. 42 */ 43 #ifndef STDERR_FILENO 44 #define STDERR_FILENO 2 45 #endif 46 #define eprints(a) (void)write(STDERR_FILENO, (a), sizeof (a)-1) 47 #define eprintl(a) (void)write(STDERR_FILENO, (a), strlen(a)) 48 49 #define is_even(p) ((((long)(p)) & 1) == 0) 50 #define even(p) (((long)(p)) & ~1L) 51 #ifdef __future__ 52 #define even(p) (((long)(p)) - 1) /* will this work with 64 bit ?? */ 53 #endif 54 55 56 LOCAL void raiseabort __PR((const char *)); 57 58 #ifdef HAVE_SCANSTACK 59 #include <schily/stkframe.h> 60 #define next_frame(vp) do { \ 61 if (((struct frame *)(vp))->fr_savfp == 0) { \ 62 vp = (void *)0; \ 63 break; \ 64 } \ 65 if (((struct frame *)(vp))->fr_savpc == 0) { \ 66 vp = (void *)0; \ 67 break; \ 68 } \ 69 vp = \ 70 (void *)((struct frame *)(vp))->fr_savfp; \ 71 } while (vp != NULL && is_even(vp)); \ 72 vp = (struct frame *)even(vp); 73 #else 74 #if defined(IS_MACOS_X) 75 /* 76 * The MAC OS X linker does not grok "common" varaibles. 77 * Make __roothandle a "data" variable. 78 */ 79 EXPORT SIGBLK *__roothandle = 0; 80 #else 81 EXPORT SIGBLK *__roothandle; 82 #endif 83 84 #define next_frame(vp) vp = (((SIGBLK *)(vp))->sb_savfp); 85 #endif 86 87 LOCAL BOOL framehandle __PR((SIGBLK *, const char *, const char *, long)); 88 89 /* 90 * Loop through the chain of procedure frames on the stack. 91 * 92 * Frame pointers normally have even values. 93 * Frame pointers of procedures with an installed handler are marked odd. 94 * The even base value, in this case actually points to a SIGBLK which 95 * holds the saved "real" frame pointer. 96 * The SIGBLK mentioned above may me the start of a chain of SIGBLK's, 97 * containing different handlers. 98 */ 99 EXPORT void 100 raisecond(signame, arg2) 101 const char *signame; 102 long arg2; 103 { 104 register void *vp = NULL; 105 106 #ifdef HAVE_SCANSTACK 107 /* 108 * As the SCO OpenServer C-Compiler has a bug that may cause 109 * the first function call to getfp() been done before the 110 * new stack frame is created, we call getfp() twice. 111 */ 112 (void) getfp(); 113 vp = getfp(); 114 next_frame(vp); 115 #else 116 vp = __roothandle; 117 #endif 118 119 while (vp) { 120 if (framehandle((SIGBLK *)vp, signame, signame, arg2)) 121 return; 122 else if (framehandle((SIGBLK *)vp, "any_other", signame, arg2)) 123 return; 124 #ifdef HAVE_SCANSTACK 125 vp = (struct frame *)((SIGBLK *)vp)->sb_savfp; 126 #endif 127 next_frame(vp); 128 } 129 /* 130 * No matching handler that signals success found. 131 * Print error message and abort. 132 */ 133 raiseabort(signame); 134 /* NOTREACHED */ 135 } 136 137 /* 138 * Loop through the handler chain for a procedure frame. 139 * 140 * If no handler with matching name is found, return FALSE, 141 * otherwise the first handler with matching name is called. 142 * The return value in the latter case depends on the called function. 143 */ 144 LOCAL BOOL 145 framehandle(sp, handlename, signame, arg2) 146 register SIGBLK *sp; 147 const char *handlename; 148 const char *signame; 149 long arg2; 150 { 151 for (; sp; sp = sp->sb_signext) { 152 if (sp->sb_signame != NULL && 153 streql(sp->sb_signame, handlename)) { 154 if (sp->sb_sigfun == NULL) { /* deactivated */ 155 return (FALSE); 156 } else { 157 return (*sp->sb_sigfun)(signame, 158 sp->sb_sigarg, arg2); 159 } 160 } 161 } 162 return (FALSE); 163 } 164 165 LOCAL void 166 raiseabort(signame) 167 const char *signame; 168 { 169 eprints("Condition not caught: "); eprintl(signame); eprints(".\n"); 170 abort(); 171 /* NOTREACHED */ 172 } 173