Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / librols / raisecond.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)raisecond.c      1.18 04/05/09 Copyright 1985, 1989, 1995-2004 J. Schilling */
14 /*
15  *      raise a condition (software signal)
16  */
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License version 2
20  * as published by the Free Software Foundation.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License along with
28  * this program; see the file COPYING.  If not, write to the Free Software
29  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31 /*
32  *      Check for installed condition handlers.
33  *      If a handler is found, the function is called with the appropriate args.
34  *      If no handler is found or no handler signals success,
35  *      the program will be aborted.
36  *
37  *      Copyright (c) 1985, 1989, 1995-2004 J. Schilling
38  */
39 #include <mconfig.h>
40 #include <stdio.h>
41 #include <standard.h>
42 #include <sigblk.h>
43 #include <unixstd.h>
44 #include <stdxlib.h>
45 #include <strdefs.h>
46 #include <avoffset.h>
47 #include <schily.h>
48
49 #if     !defined(AV_OFFSET) || !defined(FP_INDIR)
50 #       ifdef   HAVE_SCANSTACK
51 #       undef   HAVE_SCANSTACK
52 #       endif
53 #endif
54
55 /*
56  * Macros to print to stderr without stdio, to avoid screwing up.
57  */
58 #ifndef STDERR_FILENO
59 #define STDERR_FILENO   2
60 #endif
61 #define eprints(a)      do { int ret; ret = write(STDERR_FILENO, (a), sizeof (a)-1); } while (0)
62 #define eprintl(a)      do { int ret; ret = write(STDERR_FILENO, (a), strlen(a)); } while (0)
63
64 #define is_even(p)      ((((long)(p)) & 1) == 0)
65 #define even(p)         (((long)(p)) & ~1L)
66 #ifdef  __future__
67 #define even(p)         (((long)(p)) - 1) /* will this work with 64 bit ?? */
68 #endif
69
70
71 LOCAL   void raiseabort  __PR((const char *));
72
73 #ifdef  HAVE_SCANSTACK
74 #include <stkframe.h>
75 #define next_frame(vp)  do {                                                \
76                                 if (((struct frame *)(vp))->fr_savfp == 0) { \
77                                         vp = (void *)0;                     \
78                                         break;                              \
79                                 }                                           \
80                                 if (((struct frame *)(vp))->fr_savpc == 0) { \
81                                         vp = (void *)0;                     \
82                                         break;                              \
83                                 }                                           \
84                                 vp =                                        \
85                                     (void *)((struct frame *)(vp))->fr_savfp; \
86                         } while (vp != NULL && is_even(vp));                \
87                         vp = (struct frame *)even(vp);
88 #else
89 EXPORT  SIGBLK  *__roothandle;
90
91 #define next_frame(vp)  vp = (((SIGBLK *)(vp))->sb_savfp);
92 #endif
93
94 LOCAL   BOOL framehandle __PR((SIGBLK *, const char *, const char *, long));
95
96 /*
97  *      Loop through the chain of procedure frames on the stack.
98  *
99  *      Frame pointers normally have even values.
100  *      Frame pointers of procedures with an installed handler are marked odd.
101  *      The even base value, in this case actually points to a SIGBLK which
102  *      holds the saved "real" frame pointer.
103  *      The SIGBLK mentioned above may me the start of a chain of SIGBLK's,
104  *      containing different handlers.
105  */
106 EXPORT void
107 raisecond(signame, arg2)
108         const char      *signame;
109         long            arg2;
110 {
111         register void   *vp = NULL;
112
113 #ifdef  HAVE_SCANSTACK
114         /*
115          * As the SCO OpenServer C-Compiler has a bug that may cause
116          * the first function call to getfp() been done before the
117          * new stack frame is created, we call getfp() twice.
118          */
119         (void) getfp();
120         vp = getfp();
121         next_frame(vp);
122 #else
123         vp = __roothandle;
124 #endif
125
126         while (vp) {
127                 if (framehandle((SIGBLK *)vp, signame, signame, arg2))
128                         return;
129                 else if (framehandle((SIGBLK *)vp, "any_other", signame, arg2))
130                         return;
131 #ifdef  HAVE_SCANSTACK
132                 vp = (struct frame *)((SIGBLK *)vp)->sb_savfp;
133 #endif
134                 next_frame(vp);
135         }
136         /*
137          * No matching handler that signals success found.
138          * Print error message and abort.
139          */
140         raiseabort(signame);
141         /* NOTREACHED */
142 }
143
144 /*
145  *      Loop through the handler chain for a procedure frame.
146  *
147  *      If no handler with matching name is found, return FALSE,
148  *      otherwise the first handler with matching name is called.
149  *      The return value in the latter case depends on the called function.
150  */
151 LOCAL BOOL
152 framehandle(sp, handlename, signame, arg2)
153         register SIGBLK *sp;
154         const char      *handlename;
155         const char      *signame;
156         long            arg2;
157 {
158         for (; sp; sp = sp->sb_signext) {
159                 if (sp->sb_signame != NULL &&
160                     streql(sp->sb_signame, handlename)) {
161                         if (sp->sb_sigfun == NULL) {    /* deactivated */
162                                 return (FALSE);
163                         } else {
164                                 return (*sp->sb_sigfun)(signame,
165                                                         sp->sb_sigarg, arg2);
166                         }
167                 }
168         }
169         return (FALSE);
170 }
171
172 LOCAL void
173 raiseabort(signame)
174         const   char    *signame;
175 {
176         eprints("Condition not caught: "); eprintl(signame); eprints(".\n");
177         abort();
178         /* NOTREACHED */
179 }