1 /*
2     This code (with some modifications) is from GNU Parted
3     Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
4 */
5 
6 #ifdef HAVE_CONFIG_H
7 #  include <config.h>
8 #endif
9 
10 #include <reiserfs/reiserfs.h>
11 #include <reiserfs/debug.h>
12 
13 #define N_(String) (String)
14 #if ENABLE_NLS
15 #  include <libintl.h>
16 #  define _(String) dgettext (PACKAGE, String)
17 #else
18 #  define _(String) (String)
19 #endif
20 
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 
25 static reiserfs_exception_option_t default_handler(reiserfs_exception_t *ex);
26 static reiserfs_exception_handler_t exception_handler = default_handler;
27 static reiserfs_exception_t *exception = NULL;
28 
29 static int fetch_count = 0;
30 static int libreiserfs_exception = 0;
31 
32 static char *type_strings[] = {
33     N_("Information"),
34     N_("Warning"),
35     N_("Error"),
36     N_("Fatal"),
37     N_("Bug")
38 };
39 
40 static char *option_strings[] = {
41     N_("Yes"),
42     N_("No"),
43     N_("OK"),
44     N_("Retry"),
45     N_("Ignore"),
46     N_("Cancel")
47 };
48 
libreiserfs_exception_type_string(reiserfs_exception_type_t type)49 char *libreiserfs_exception_type_string(reiserfs_exception_type_t type) {
50     return type_strings[type - 1];
51 }
52 
libreiserfs_exception_type(reiserfs_exception_t * ex)53 reiserfs_exception_type_t libreiserfs_exception_type(reiserfs_exception_t *ex) {
54     return ex->type;
55 }
56 
libreiserfs_exception_option_string(reiserfs_exception_option_t opt)57 char *libreiserfs_exception_option_string(reiserfs_exception_option_t opt) {
58     return option_strings[reiserfs_tools_log2(opt)];
59 }
60 
libreiserfs_exception_option(reiserfs_exception_t * ex)61 reiserfs_exception_option_t libreiserfs_exception_option(reiserfs_exception_t *ex) {
62     return ex->options;
63 }
64 
libreiserfs_exception_message(reiserfs_exception_t * ex)65 char *libreiserfs_exception_message(reiserfs_exception_t *ex) {
66     return ex->message;
67 }
68 
default_handler(reiserfs_exception_t * ex)69 static reiserfs_exception_option_t default_handler(reiserfs_exception_t *ex) {
70     if (ex->type == EXCEPTION_BUG)
71 	fprintf (stderr, _("A bug has been detected in libreiserfs. "
72 	    "Please email a bug report to torque@ukrpost.net containing the version (%s) "
73 	    "and the following message: "), VERSION);
74     else
75         fprintf (stderr, "%s: ", libreiserfs_exception_type_string(ex->type));
76 
77     fprintf (stderr, "%s\n", ex->message);
78 
79     switch (ex->options) {
80         case EXCEPTION_OK:
81         case EXCEPTION_CANCEL:
82         case EXCEPTION_IGNORE:
83             return ex->options;
84 
85         default:
86             return EXCEPTION_UNHANDLED;
87     }
88 }
89 
libreiserfs_exception_set_handler(reiserfs_exception_handler_t handler)90 void libreiserfs_exception_set_handler(reiserfs_exception_handler_t handler) {
91     if (handler)
92 	exception_handler = handler;
93     else
94 	exception_handler = default_handler;
95 }
96 
libreiserfs_exception_catch(void)97 void libreiserfs_exception_catch(void) {
98     if (libreiserfs_exception) {
99 	libreiserfs_exception = 0;
100 	libreiserfs_free(exception->message);
101 	libreiserfs_free(exception);
102 	exception = NULL;
103     }
104 }
105 
do_throw(void)106 static reiserfs_exception_option_t do_throw(void) {
107     reiserfs_exception_option_t opt;
108 
109     libreiserfs_exception = 1;
110 
111     if (fetch_count)
112 	return EXCEPTION_UNHANDLED;
113     else {
114 	opt = exception_handler(exception);
115 	libreiserfs_exception_catch();
116 	return opt;
117     }
118 }
119 
libreiserfs_exception_throw(reiserfs_exception_type_t type,reiserfs_exception_option_t opts,const char * message,...)120 reiserfs_exception_option_t libreiserfs_exception_throw(reiserfs_exception_type_t type,
121     reiserfs_exception_option_t opts, const char* message, ...)
122 {
123     va_list arg_list;
124     reiserfs_gauge_t *libreiserfs_gauge;
125 
126     if (exception)
127 	libreiserfs_exception_catch();
128 
129     if (!(exception = (reiserfs_exception_t *)libreiserfs_calloc(sizeof(reiserfs_exception_t), 0)))
130 	goto no_memory;
131 
132     if (!(exception->message = (char *)libreiserfs_calloc(4096, 0)))
133 	goto no_memory;
134 
135     exception->type = type;
136     exception->options = opts;
137 
138     va_start(arg_list, message);
139 
140 #ifdef DJGPP
141     vsprintf(exception->message, message, arg_list);
142 #else
143     vsnprintf(exception->message, 4096, message, arg_list);
144 #endif
145 
146     va_end(arg_list);
147 
148     if ((libreiserfs_gauge = libreiserfs_get_gauge())) {
149 
150 	if (libreiserfs_gauge->state != REISERFS_GAUGE_DONE &&
151 		libreiserfs_gauge->state != REISERFS_GAUGE_FAILED)
152 	    libreiserfs_gauge_finish(libreiserfs_gauge, 0);
153     }
154 
155     return do_throw();
156 
157 no_memory:
158     fprintf(stderr, "Out of memory in exception handler!\n");
159 
160     va_start(arg_list, message);
161     vprintf(message, arg_list);
162     va_end(arg_list);
163 
164     return EXCEPTION_UNHANDLED;
165 }
166 
libreiserfs_exception_rethrow(void)167 reiserfs_exception_option_t libreiserfs_exception_rethrow(void) {
168     return do_throw();
169 }
170 
libreiserfs_exception_fetch_all(void)171 void libreiserfs_exception_fetch_all(void) {
172     fetch_count++;
173 }
174 
libreiserfs_exception_leave_all(void)175 void libreiserfs_exception_leave_all(void) {
176     ASSERT(fetch_count > 0, return);
177     fetch_count--;
178 }
179 
180