1 /* error.c -- Error reporting routines for Khepera
2  * Created: Wed Dec 21 12:55:00 1994 by faith@dict.org
3  * Copyright 1994-1997, 2002 Rickard E. Faith (faith@dict.org)
4  * Copyright 2002-2008 Aleksey Cheusov (vle@gmx.net)
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * \section{Error Reporting Routines}
26  *
27  * \intro Several error reporting routines are provided.  These routines
28  * are always used to print errors generated within the \khepera library,
29  * and are available for the programmer as well.
30  *
31  */
32 
33 #include "maaP.h"
34 #include <errno.h>
35 
36 const char *_err_programName;
37 
38 /* \doc |err_set_program_name| records the value of |argv[0]| for the
39    calling program.  If this value is not "NULL", then it will be used when
40    printing errors and warnings. */
41 
err_set_program_name(const char * programName)42 void err_set_program_name(const char *programName)
43 {
44 	if (!programName){
45 		_err_programName = programName;
46 		return;
47 	}
48 
49 	const char *pt =strrchr(programName, '/');
50 
51 	if (pt)
52 		_err_programName = pt + 1;
53 	else
54 		_err_programName = programName;
55 }
56 
57 /* \doc |err_program_name| returns the value of |programName| that was
58    previously set with |err_set_program_name|.  This value may be
59    "NULL". */
60 
err_program_name(void)61 const char *err_program_name(void)
62 {
63 	return _err_programName;
64 }
65 
66 
67 /* \doc |err_fatal| flushes "stdout", prints a fatal error report on
68    "stderr", flushes "stderr" and "stdout", and calls |exit|.  |routine| is
69    the name of the routine in which the error took place. */
70 
err_fatal(const char * routine,const char * format,...)71 void err_fatal(const char *routine, const char *format, ...)
72 {
73 	va_list ap;
74 	va_list ap_copy;
75 
76 	fflush(stdout);
77 	if (_err_programName) {
78 		if (routine)
79 			fprintf(stderr, "%s (%s): ", _err_programName, routine);
80 		else
81 			fprintf(stderr, "%s: ", _err_programName);
82 	} else {
83 		if (routine) fprintf(stderr, "%s: ", routine);
84 	}
85 
86 	va_start(ap, format);
87 	va_copy(ap_copy, ap);
88 
89 	vfprintf(stderr, format, ap);
90 	fprintf(stderr, "\n");
91 	log_error_va(routine, format, ap_copy);
92 
93 	va_end(ap);
94 
95 	fflush(stderr);
96 	fflush(stdout);
97 	exit (1);
98 }
99 
100 /* \doc |err_fatal_errno| flushes "stdout", prints a fatal error report on
101    "stderr", prints the system error corresponding to |errno|, flushes
102    "stderr" and "stdout", and calls |exit|.  |routine| is the name of the
103    routine in which the error took place. */
104 
err_fatal_errno(const char * routine,const char * format,...)105 void err_fatal_errno(const char *routine, const char *format, ...)
106 {
107 	va_list ap;
108 	va_list ap_copy;
109 	int     errorno = errno;
110 
111 	fflush(stdout);
112 	if (_err_programName) {
113 		if (routine)
114 			fprintf(stderr, "%s (%s): ", _err_programName, routine);
115 		else
116 			fprintf(stderr, "%s: ", _err_programName);
117 	} else {
118 		if (routine) fprintf(stderr, "%s: ", routine);
119 	}
120 
121 	va_start(ap, format);
122 	va_copy(ap_copy, ap);
123 
124 	vfprintf(stderr, format, ap);
125 	log_error_va(routine, format, ap_copy);
126 
127 	va_end(ap);
128 
129 	fprintf(stderr, " %s: %s\n", routine, strerror(errorno));
130 	log_error(routine, "%s: %s", routine, strerror(errorno));
131 
132 	fflush(stderr);
133 	fflush(stdout);
134 	exit(1);
135 }
136 
137 /* \doc |err_warning| flushes "stdout", prints a non-fatal warning on
138    "stderr", and returns to the caller.  |routine| is the name of the
139    calling routine. */
140 
err_warning(const char * routine,const char * format,...)141 void err_warning(const char *routine, const char *format, ...)
142 {
143 	va_list ap;
144 	va_list ap_copy;
145 
146 	fflush(stdout);
147 	fflush(stderr);
148 	if (_err_programName) {
149 		if (routine)
150 			fprintf(stderr, "%s (%s): ", _err_programName, routine);
151 		else
152 			fprintf(stderr, "%s: ", _err_programName);
153 	} else {
154 		if (routine) fprintf(stderr, "%s: ", routine);
155 	}
156 
157 	va_start(ap, format);
158 	va_copy(ap_copy, ap);
159 
160 	vfprintf(stderr, format, ap);
161 	fprintf(stderr, "\n");
162 	log_error_va(routine, format, ap_copy);
163 
164 	va_end(ap);
165 }
166 
167 /* \doc |err_internal| flushes "stdout", prints the fatal error message,
168    flushes "stderr" and "stdout", and calls |abort| so that a core dump is
169    generated. */
170 
err_internal(const char * routine,const char * format,...)171 void err_internal(const char *routine, const char *format, ...)
172 {
173 	va_list ap;
174 	va_list ap_copy;
175 
176 	va_start(ap, format);
177 	va_copy(ap_copy, ap);
178 
179 	fflush(stdout);
180 	if (_err_programName) {
181 		if (routine)
182 			fprintf(stderr, "%s (%s): Internal error\n     ",
183 					_err_programName, routine);
184 		else
185 			fprintf(stderr, "%s: Internal error\n     ", _err_programName);
186 	} else {
187 		if (routine) fprintf(stderr, "%s: Internal error\n     ", routine);
188 		else         fprintf(stderr, "Internal error\n     ");
189 	}
190 
191 	vfprintf(stderr, format, ap);
192 	fprintf(stderr, "\n");
193 	log_error_va(routine, format, ap_copy);
194 
195 	va_end(ap);
196 
197 	if (_err_programName)
198 		fprintf(stderr, "Aborting %s...\n", _err_programName);
199 	else
200 		fprintf(stderr, "Aborting...\n");
201 	fflush(stderr);
202 	fflush(stdout);
203 	abort();
204 }
205