File: exception.c

package info (click to toggle)
reiser4progs 1.0.6-1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 5,348 kB
  • ctags: 3,714
  • sloc: ansic: 33,468; sh: 8,489; makefile: 1,012
file content (212 lines) | stat: -rw-r--r-- 5,514 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/* Copyright (C) 2001-2005 by Hans Reiser, licensing governed by
   reiser4progs/COPYING.
   
   exception.c -- common for all progs exception handler and related
   functions. */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <ctype.h>
#include <stdio.h>
#include <unistd.h>

#include <aal/libaal.h>
#include <misc/misc.h>

/* Strings for all exception types */
static char *type_names[] = {
	"",
        "Info ",
        "",
        "Warn ",
        "Error",
        "Fatal",
        "Bug  "
};

#define TYPES_COUNT (sizeof(type_names) / sizeof(void *))

/* This function returns number of specified turned on options */
static int misc_exception_option_count(
	aal_exception_option_t options,	    /* options to be inspected */
	int start)			    /* options will be inspected started
					       from */
{
	int i, count = 0;
    
	for (i = start; i < aal_log2(EXCEPTION_OPT_LAST); i++)
		count += ((1 << i) & options) ? 1 : 0;

	return count;
}

/* This function makes search for option by its name in passed available option
   set. */
static aal_exception_option_t misc_exception_oneof(
	char *name,			    /* option name to be checked */
	aal_exception_option_t options)     /* aavilable options */
{
	int i;
    
	if (!name || aal_strlen(name) == 0)
		return EXCEPTION_OPT_UNHANDLED;
    
	for (i = 0; i < aal_log2(EXCEPTION_OPT_LAST); i++) {
		if ((1 << i) & options) {
			char str1[256], str2[256];
			char *opt = aal_exception_option_name(1 << i);

			aal_memset(str1, 0, sizeof(str1));
			aal_memset(str2, 0, sizeof(str2));
	    
			misc_upper_case(str1, opt);
			misc_upper_case(str2, name);
	    
			if (aal_strncmp(str1, str2, aal_strlen(str2)) == 0 || 
			    (aal_strlen(str2) == 1 && str1[0] == name[0]))
			{
				return 1 << i;
			}
		}
	}
    
	return EXCEPTION_OPT_UNHANDLED;
}

/* Constructs exception message. */
static void misc_exception_print_wrap(aal_exception_t *exception,
				       void *stream)
{
	char buff[4096];

	aal_memset(buff, 0, sizeof(buff));
    
	if (exception->type != EXCEPTION_TYPE_MESSAGE &&
	    exception->type < TYPES_COUNT)
	{
		aal_snprintf(buff, sizeof(buff), "%s: ", 
			     type_names[exception->type]);
	}
    
	aal_strncat(buff, exception->message, 
		    aal_strlen(exception->message));

	misc_print_wrap(stream, buff);
}

/* This function prints exception options awailable to be choosen, takes user
   enter and converts it into aal_exception_option_t type. */
static aal_exception_option_t misc_exception_prompt(
	aal_exception_option_t options,  /* exception options can be selected */
	void *stream)
{
	int i;
	char *option;
	char prompt[256];

	if (misc_exception_option_count(options, 0) == 0)
		return EXCEPTION_OPT_UNHANDLED;
    
	aal_memset(prompt, 0, sizeof(prompt));
    
	aal_strncat(prompt, "(", 1);
	for (i = 1; i < aal_log2(EXCEPTION_OPT_LAST); i++) {
		if ((1 << i) & options) {
			char *opt = aal_exception_option_name(1 << i);
			int count = misc_exception_option_count(options, i + 1);
	    
			aal_strncat(prompt, opt, aal_strlen(opt));
	    
			if (i < aal_log2(EXCEPTION_OPT_LAST) - 1 && count  > 0)
				aal_strncat(prompt, "/", 1);
			else
				aal_strncat(prompt, "): ", 3);
		}
	}
    
	if (!(option = misc_readline(prompt, stream)) || aal_strlen(option) == 0)
		return EXCEPTION_OPT_UNHANDLED;
    
	return misc_exception_oneof(option, options);
}

/* Streams assigned with exception type are stored here */
static void *streams[10];

/* Current misc gauge. Used for correct pausing when exception */
extern aal_gauge_t *current_gauge;

/* Common exception handler for all reiser4progs. It implements exception
   handling in "question-answer" maner and used for all communications with
   user. */
aal_exception_option_t misc_exception_handler(
	aal_exception_t *exception)		/* exception to be processed */
{
#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_READLINE_H)
	int i;
	aal_list_t *variant = NULL;
#endif
	int tty;
	void *stream = stderr;
	aal_exception_option_t opt = EXCEPTION_OPT_UNHANDLED;
    
	if (misc_exception_option_count(exception->options, 0) == 1) {
		if (!(stream = streams[exception->type]))
			return exception->options;
	}
	
	if ((tty = fileno(stream)) == -1)
		return EXCEPTION_OPT_UNHANDLED;

	if (current_gauge && stream == stderr)
		aal_gauge_pause(current_gauge);
	else {
		if (isatty(tty))
			misc_wipe_line(stream);
	}

	misc_exception_print_wrap(exception, stream);
    
	if (misc_exception_option_count(exception->options, 0) == 1)
		return exception->options;

#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_READLINE_H)
	for (i = 1; i < aal_log2(EXCEPTION_OPT_LAST); i++) {
		if ((1 << i) & exception->options) {
			char *name = aal_exception_option_name(1 << i);
			variant = aal_list_append(variant, name);
		}
	}
	
	variant = aal_list_first(variant);
	misc_set_variant(variant);
#endif

	do {
		opt = misc_exception_prompt(exception->options, stream);
	} while (opt == EXCEPTION_OPT_UNHANDLED);
	
#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_READLINE_H)
	aal_list_free(variant, NULL, NULL);
	misc_set_variant(NULL);
#endif

	return opt;
}

/* This function sets up exception streams */
void misc_exception_set_stream(
	aal_exception_type_t type,	/* type to be assigned with stream */
	void *stream)	                /* stream to be assigned */
{
	streams[type] = stream;
}

/* This function gets exception streams */
void *misc_exception_get_stream(
	aal_exception_type_t type)	/* type exception stream will be obtained for */
{
	return streams[type];
}