1 | /*****
2 | ** ** Module Header ******************************************************* **
3 | ** **
4 | ** Modules Revision 3.0 **
5 | ** Providing a flexible user environment **
6 | ** **
7 | ** File: error.c **
8 | ** First Edition: 1991/10/23 **
9 | ** **
10 | ** Authors: Jens Hamisch, jens@Strawberry.COM **
11 | ** **
12 | ** Description: The modules error logger **
13 | ** **
14 | ** Exports: Module_Error **
15 | ** GetFacilityPtr **
16 | ** CheckFacility **
17 | ** Enable_Error **
18 | ** Disable_Error **
19 | ** Restore_Error **
20 | ** **
21 | ** Notes: **
22 | ** **
23 | ** ************************************************************************ **
24 | ****/
25 |
26 | /** ** Copyright *********************************************************** **
27 | ** **
28 | ** Copyright 1991-1994 by John L. Furlan. **
29 | ** see LICENSE.GPL, which must be provided, for details **
30 | ** **
31 | ** ************************************************************************ **/
32 |
33 | static char Id[] = "@(#)$Id: error.c.src.html,v 1.6 2006/01/18 05:35:11 rkowen Exp $";
34 | static void *UseId[] = { &UseId, Id };
35 |
36 | /** ************************************************************************ **/
37 | /** HEADERS **/
38 | /** ************************************************************************ **/
39 |
40 | #include "modules_def.h"
41 | #if HAVE_STDARG_H
42 | # include <stdarg.h>
43 | #else
44 | # error "You need an ANSI C compiler"
45 | #endif
46 |
47 | #if defined(HAVE_SYSLOG) && defined(WITH_LOGGING)
48 | # include <syslog.h>
49 | #endif
50 |
51 | #include <pwd.h>
52 | #include <grp.h>
53 |
54 | /** ************************************************************************ **/
55 | /** LOCAL DATATYPES **/
56 | /** ************************************************************************ **/
57 |
58 | /**
59 | ** Error weights
60 | **/
61 |
62 | typedef enum _err_weights {
63 | WGHT_NONE=0, /** Dummy value: No error **/
64 | WGHT_VERBOSE, /** Verbose messages **/
65 | WGHT_INFO=3, /** Informal message **/
66 | WGHT_DEBUG=5, /** Debugger output **/
67 | WGHT_TRACE, /** Tracing output **/
68 | WGHT_WARN=10, /** Warning: Prog. flow not affected **/
69 | WGHT_PROB=20, /** Problem: Prog. flow cond. aff. **/
70 | WGHT_ERROR=25, /** Error and Fatal: Prog. flow aff. **/
71 | WGHT_FATAL=27, /** Return to the caller **/
72 | WGHT_PANIC=29 /** Panic: Exit program immediatelly **/
73 | } ErrWeights;
74 |
75 | /**
76 | ** Log facilities
77 | **/
78 |
79 | typedef struct _err_facility {
80 | ErrWeights Weight; /** Error weight **/
81 | char *facility; /** Log facility **/
82 | char *def_facility; /** Default facility (facility undef)**/
83 | } ErrFacilities;
84 |
85 | typedef struct _facil_names {
86 | char *name; /** Name of a facility **/
87 | int token; /** Assigned token **/
88 | } FacilityNames;
89 |
90 | /**
91 | ** Error measurement table
92 | **/
93 |
94 | typedef struct {
95 | ErrWeights error_weight; /** The weight itsself **/
96 | char *message; /** Message to be printed **/
97 | ErrCode ret_nov, /** Return code **/
98 | ret_adv,
99 | ret_exp;
100 | } ErrMeasr;
101 |
102 | /**
103 | ** Error code translation table
104 | **/
105 |
106 | typedef struct {
107 | ErrType error_type; /** The error type as specified by **/
108 | /** the caller **/
109 | ErrWeights error_weight; /** The weight of this error **/
110 | char *messages; /** List of messages to be printed **/
111 | } ErrTransTab;
112 |
113 | /** ************************************************************************ **/
114 | /** CONSTANTS **/
115 | /** ************************************************************************ **/
116 |
117 | #define ARGLIST_SIZE 10
118 | #define ERR_LINELEN 80 /** internal buffer size **/
119 | #define ERR_BUFSIZE 4096 /** buffer for the whole error msg. **/
120 |
121 | /** ************************************************************************ **/
122 | /** MACROS **/
123 | /** ************************************************************************ **/
124 |
125 | /** not applicable **/
126 |
127 | /** ************************************************************************ **/
128 | /** LOCAL DATA **/
129 | /** ************************************************************************ **/
130 |
131 | static char module_name[] = "error.c"; /** File name of this module **/
132 |
133 | /**
134 | ** Local flags
135 | **/
136 | static int quiet_on_error = 0;
137 |
138 | /**
139 | ** Local strings
140 | **/
141 |
142 | static char unknown[] = "unknown"; /** If something's unknown **/
143 |
144 | static char buffer[ ERR_LINELEN]; /** Internal string buffer **/
145 | char *error_line = NULL;
146 | static int strsize = 0;
147 |
148 | /**
149 | ** Log facility table
150 | **/
151 |
152 | static char _stderr[] = "stderr";
153 | static char _stdout[] = "stdout";
154 | static char _null[] = "null";
155 | static char _none[] = "none";
156 | static char _unknown[] = "unknown";
157 |
158 | static ErrFacilities Facilities[] = {
159 | { WGHT_NONE, NULL, NULL },
160 | { WGHT_VERBOSE, NULL, DEF_FACILITY_VERBOSE },
161 | { WGHT_INFO, NULL, DEF_FACILITY_INFO },
162 | { WGHT_DEBUG, NULL, DEF_FACILITY_DEBUG },
163 | { WGHT_TRACE, NULL, DEF_FACILITY_TRACE },
164 | { WGHT_WARN, NULL, DEF_FACILITY_WARN },
165 | { WGHT_PROB, NULL, DEF_FACILITY_PROB },
166 | { WGHT_ERROR, NULL, DEF_FACILITY_ERROR },
167 | { WGHT_FATAL, NULL, DEF_FACILITY_FATAL },
168 | { WGHT_PANIC, NULL, DEF_FACILITY_PANIC }
169 | };
170 |
171 | /**
172 | ** Syslog facility names
173 | **/
174 |
175 | static FacilityNames facility_names[] = {
176 | #if defined(HAVE_SYSLOG) && defined(WITH_LOGGING)
177 | { "auth", LOG_AUTH },
178 | { "cron", LOG_CRON },
179 | { "daemon", LOG_DAEMON },
180 | { "kern", LOG_KERN },
181 | { "local0", LOG_LOCAL0 },
182 | { "local1", LOG_LOCAL1 },
183 | { "local2", LOG_LOCAL2 },
184 | { "local3", LOG_LOCAL3 },
185 | { "local4", LOG_LOCAL4 },
186 | { "local5", LOG_LOCAL5 },
187 | { "local6", LOG_LOCAL6 },
188 | { "local7", LOG_LOCAL7 },
189 | { "lpr", LOG_LPR },
190 | { "mail", LOG_MAIL },
191 | { "news", LOG_NEWS },
192 | { "user", LOG_USER },
193 | { "uucp", LOG_UUCP }
194 | #else
195 | { "none", 0 }
196 | #endif
197 | };
198 |
199 | /**
200 | ** Syslog level names
201 | **/
202 |
203 | static FacilityNames level_names[] = {
204 | #if defined(HAVE_SYSLOG) && defined(WITH_LOGGING)
205 | { "alert", LOG_ALERT },
206 | { "crit", LOG_CRIT },
207 | { "debug", LOG_DEBUG },
208 | { "emerg", LOG_EMERG },
209 | { "err", LOG_ERR },
210 | { "info", LOG_INFO },
211 | { "notice", LOG_NOTICE },
212 | { "warning", LOG_WARNING }
213 | #else
214 | { "none", 0 }
215 | #endif
216 | };
217 |
218 | /**
219 | ** Error measurement table
220 | ** Take care that this list is sorted in ascending order concerning the error
221 | ** weights
222 | **/
223 |
224 | #define MEAS_VERB_NDX 1 /** Index of the 'VERBOSE' entry **/
225 |
226 | static ErrMeasr Measurements[] = {
227 | { WGHT_NONE, "" , OK, OK, OK },
228 | { WGHT_VERBOSE,"VERB" , OK, OK, OK },
229 | { WGHT_INFO, "INFO" , OK, OK, OK },
230 | { WGHT_DEBUG, "DEBUG", OK, OK, OK },
231 | { WGHT_TRACE, "TRACE", OK, OK, OK },
232 | { WGHT_WARN, "WARN" , PROBLEM, WARN, OK },
233 | { WGHT_PROB, "PROB" , ERROR, PROBLEM, OK },
234 | { WGHT_ERROR, "ERROR", ERROR, ERROR, ERROR },
235 | { WGHT_FATAL, "FATAL", FATAL, FATAL, FATAL },
236 | { WGHT_PANIC, "PANIC", PANIC, PANIC, PANIC },
237 | };
238 |
239 | /**
240 | ** Error code translation table
241 | ** Take care that this list is sorted in ascending order concerning the error
242 | ** types
243 | **/
244 |
245 | static ErrTransTab TransTab[] = {
246 | { NO_ERR, WGHT_NONE, NULL },
247 | { NO_ERR_DEBUG, WGHT_DEBUG, "$*" },
248 | { NO_ERR_START, WGHT_DEBUG, "Starting $*" },
249 | { NO_ERR_END, WGHT_DEBUG, "Exit $*" },
250 | { NO_ERR_VERBOSE, WGHT_VERBOSE, NULL },
251 | { ERR_PARAM, WGHT_ERROR, "Paramter error concerning '$1'" },
252 | { ERR_USAGE, WGHT_ERROR, "Usage is '$*'" },
253 | { ERR_ARGSTOLONG, WGHT_ERROR, "'$1': Arguments to long. Max. is '$2'" },
254 | { ERR_OPT_AMBIG, WGHT_ERROR, "Option '$1' is ambiguous" },
255 | { ERR_OPT_NOARG, WGHT_ERROR, "Option '$1' allows no argument" },
256 | { ERR_OPT_REQARG, WGHT_ERROR, "Option '$1' requires an argument" },
257 | { ERR_OPT_UNKNOWN, WGHT_ERROR, "Unrecognized option '$1'" },
258 | { ERR_OPT_ILL, WGHT_ERROR, "Illegal option '$1'" },
259 | { ERR_OPT_INV, WGHT_ERROR, "Invalid option '$1'" },
260 | { ERR_USERLVL, WGHT_ERROR, "Undefined userlevel '$1'" },
261 | { ERR_GETOPT, WGHT_FATAL, "getopt() failed" },
262 | { ERR_OPEN, WGHT_ERROR, "Cannot open file '$1' for '$2'" },
263 | { ERR_POPEN, WGHT_ERROR, "Cannot open pipe '$1' for '$2'" },
264 | { ERR_OPENDIR, WGHT_ERROR, "Cannot open directory '$1' for reading" },
265 | { ERR_CLOSE, WGHT_WARN, "Cannot close file '$1'" },
266 | { ERR_PCLOSE, WGHT_WARN, "Cannot close pipe '$1'" },
267 | { ERR_CLOSEDIR, WGHT_WARN, "Cannot close directory '$1'" },
268 | { ERR_READ, WGHT_ERROR, "Error while reading file '$1'" },
269 | { ERR_READDIR, WGHT_ERROR, "Error while reading directory '$1'" },
270 | { ERR_WRITE, WGHT_ERROR, "Error while writing file '$1'" },
271 | { ERR_SEEK, WGHT_ERROR, "Seek error on file '$1'" },
272 | { ERR_FLUSH, WGHT_WARN, "Flush error on file '$1'" },
273 | { ERR_DUP, WGHT_WARN, "Cannot duplicate handle of file '$1'" },
274 | { ERR_DIRNAME, WGHT_ERROR, "Cannot build directory name" },
275 | { ERR_NAMETOLONG, WGHT_ERROR, "Requested directory name to long: "
276 | "dir='$1',file='$2'" },
277 | { ERR_DIRNOTFOUND, WGHT_ERROR, "Directory '$1' not found" },
278 | { ERR_FILEINDIR, WGHT_ERROR, "File '$1' not found in directory '$2'" },
279 | { ERR_NODIR, WGHT_ERROR, "'$1' is not a directory" },
280 | { ERR_UNLINK, WGHT_WARN, "Cannot unlink '$1'" },
281 | { ERR_RENAME, WGHT_PROB, "Cannot rename '$1' to '$2'" },
282 | { ERR_ALLOC, WGHT_FATAL, "Out of memory." },
283 | { ERR_SOURCE, WGHT_WARN, "Error sourcing file '$1'" },
284 | { ERR_UNAME, WGHT_FATAL, "'uname (2)' failed." },
285 | { ERR_GETHOSTNAME, WGHT_FATAL, "'gethostname (2)' failed." },
286 | { ERR_GETDOMAINNAME,WGHT_FATAL, "'getdomainname (2)' failed." },
287 | { ERR_STRING, WGHT_FATAL, "string error" },
288 | { ERR_DISPLAY, WGHT_ERROR, "Cannot open display" },
289 | { ERR_PARSE, WGHT_ERROR, "Parse error" },
290 | { ERR_EXEC, WGHT_ERROR, "Tcl command execution failed: $1" },
291 | { ERR_EXTRACT, WGHT_ERROR, "Cannot extract X11 resources" },
292 | { ERR_COMMAND, WGHT_ERROR, "'$1' is an unrecognized subcommand" },
293 | { ERR_LOCATE, WGHT_ERROR, "Unable to locate a modulefile for '$1'" },
294 | { ERR_MAGIC, WGHT_ERROR, "Magic cookie '#%Module' missing in '$1'" },
295 | { ERR_MODULE_PATH, WGHT_ERROR, "'MODULEPATH' not set" },
296 | { ERR_HOME, WGHT_ERROR, "'HOME' not set" },
297 | { ERR_SHELL, WGHT_ERROR, "Unknown shell type '$1'" },
298 | { ERR_DERELICT, WGHT_ERROR, "Unknown shell derelict '$1'" },
299 | { ERR_CONFLICT, WGHT_ERROR, "Module '$1' conflicts with the currently "
300 | "loaded module(s) '$2*'" },
301 | { ERR_PREREQ, WGHT_ERROR, "Module '$1' depends on one of the "
302 | "module(s) '$2*'" },
303 | { ERR_NOTLOADED, WGHT_ERROR, "Module '$1' is currently not loaded" },
304 | { ERR_DUP_SYMVERS, WGHT_PROB, "Duplicate version symbol '$1' found" },
305 | { ERR_SYMLOOP, WGHT_ERROR, "Version symbol '$1' loops" },
306 | { ERR_BADMODNAM, WGHT_PROB, "Invalid modulename '$1' found" },
307 | { ERR_DUP_ALIAS, WGHT_WARN, "Duplicate alias '$1' found" },
308 | { ERR_CACHE_INVAL, WGHT_ERROR, "Invalid cache version '$1' found" },
309 | { ERR_CACHE_LOAD, WGHT_WARN, "Couldn't load the cache properly" },
310 | { ERR_BEGINENV, WGHT_WARN, "Invalid update subcommand - "
311 | #ifdef BEGINENV
312 | # if BEGINENV == 99
313 | "No _MODULESBEGINENV_ file"
314 | # else
315 | "No .modulesbeginenv file"
316 | # endif
317 | #else
318 | ".modulesbeginenv not supported"
319 | #endif
320 | },
321 | { ERR_BEGINENVX, WGHT_WARN,
322 | "Invalid update subcommand - No MODULESBEGINENV - hence not supported"},
323 | { ERR_INIT_TCL, WGHT_ERROR, "Cannot initialize TCL" },
324 | { ERR_INIT_TCLX, WGHT_WARN, "Cannot initialize TCLX modules using "
325 | "extended commands might fail" },
326 | { ERR_INIT_ALPATH, WGHT_WARN, "Could not extend auto_path variable. "
327 | "Module using autoloadable functions might "
328 | "fail" },
329 | { ERR_INIT_STUP, WGHT_WARN, "Cannot find a 'module load' command in "
330 | "any of the '$1' startup files" },
331 | { ERR_SET_VAR, WGHT_WARN, "Cannot set TCL variable '$1'" },
332 | { ERR_INFO_DESCR, WGHT_ERROR, "Unrecognized module info descriptor '$1'" },
333 | { ERR_INVWGHT_WARN, WGHT_WARN, "Invalid error weight '$1' found" },
334 | { ERR_INVFAC_WARN, WGHT_WARN, "Invalid log facility '$1'" },
335 | { ERR_COLON, WGHT_WARN, "Spurious colon in pattern '$1'" },
336 | { ERR_INTERAL, WGHT_PANIC, "Internal error in the alias handler" },
337 | { ERR_INTERRL, WGHT_PANIC, "Internal error in the error logger" },
338 | { ERR_INVAL, WGHT_PANIC, "Invalid error type '$1' found" },
339 | { ERR_INVWGHT, WGHT_PANIC, "Invalid error weight '$1' found" },
340 | { ERR_INVFAC, WGHT_PANIC, "Invalid log facility '$1'" },
341 | { ERR_ENVVAR, WGHT_FATAL, "The environment variables LOADMODULES and _LMFILES_ have inconsistent lengths." }
342 | };
343 |
344 | /** ************************************************************************ **/
345 | /** PROTOTYPES **/
346 | /** ************************************************************************ **/
347 |
348 | static ErrTransTab *ErrorLookup( ErrType error_type );
349 |
350 | static ErrMeasr *MeasLookup( ErrWeights weigth );
351 |
352 | static int FlushError( ErrType Type,
353 | char *module,
354 | int lineno,
355 | ErrWeights Weight,
356 | char *WeightMsg,
357 | char *ErrMsgs,
358 | int argc,
359 | char **argv);
360 |
361 | static int PrintError( char *buffer,
362 | ErrType Type,
363 | char *module,
364 | int lineno,
365 | ErrWeights Weight,
366 | char *WeightMsg,
367 | char *ErrMsgs,
368 | int argc,
369 | char **argv);
370 |
371 | static char *ErrorString( char *ErrMsgs,
372 | int argc,
373 | char **argv);
374 |
375 | static void add_param( char **Control,
376 | char **Target,
377 | int *Length,
378 | int argc,
379 | char **argv);
380 |
381 | static int scan_facility( char *s,
382 | FacilityNames *table,
383 | int size);
384 |
385 | static char *GetFacility( ErrWeights Weight);
386 | static ErrFacilities *GetFacility_sub( ErrWeights Weight);
387 |
388 | static void Print_Tracing( char *buffer,
389 | int result,
390 | int argc,
391 | char **argv);
392 |
393 | /*++++
394 | ** ** Function-Header ***************************************************** **
395 | ** **
396 | ** Function: Module_Tracing **
397 | ** Print_Tracing **
398 | ** Module_Verbosity **
399 | ** **
400 | ** Description: Display a tracing or verbose message **
401 | ** **
402 | ** First Edition: 1995/12/27 **
403 | ** **
404 | ** Parameters: int result Result code of th module command **
405 | ** int argc Number od arguments to the module **
406 | ** command **
407 | ** char **argv Argument array **
408 | ** char *buffer Print buffer **
409 | ** **
410 | ** Result: - **
411 | ** **
412 | ** Attached Globals: g_current_module The module which is handled **
413 | ** by the current command **
414 | ** **
415 | ** ************************************************************************ **
416 | ++++*/
417 |
418 | void Module_Tracing( int result,
419 | int argc,
420 | char **argv)
421 | {
422 | if( !FlushError( NO_ERR, (char *) NULL, result, WGHT_TRACE, (char *) NULL,
423 | (char *) NULL, argc, argv)) {
424 | ErrorLogger( ERR_INTERRL, LOC, NULL);
425 | }
426 |
427 | } /** End of 'Module_Tracing' **/
428 |
429 | void Module_Verbosity( int argc,
430 | char **argv)
431 | {
432 | if( sw_verbose && argc && *argv)
433 | if( !FlushError( NO_ERR_VERBOSE, g_current_module,linenum,WGHT_VERBOSE,
434 | Measurements[ MEAS_VERB_NDX].message, *argv, argc, argv)) {
435 | ErrorLogger( ERR_INTERRL, LOC, NULL);
436 | }
437 |
438 | } /** End of 'Module_Verbosity' **/
439 |
440 | static void Print_Tracing( char *buffer,
441 | int result,
442 | int argc,
443 | char **argv)
444 | {
445 | char *s = buffer;
446 | struct passwd *pwent;
447 | struct group *grpent;
448 | uid_t uid;
449 | gid_t gid;
450 |
451 | /**
452 | ** Print the arguments
453 | **/
454 |
455 | while( argc--) {
456 | /* sprintf( s, "%s ", *argv++); */
457 | strcpy( s, *argv++);
458 | strcat( s, " ");
459 | s += strlen( s);
460 | }
461 |
462 | /**
463 | ** Add the real and effective user- and group-id
464 | **/
465 |
466 | pwent = getpwuid( uid = getuid());
467 | sprintf( s, " [%s(%d)", (pwent ? pwent->pw_name : _unknown), uid);
468 | s += strlen( s);
469 | grpent = getgrgid( gid = getgid());
470 | sprintf( s, ".%s(%d)]", (grpent ? grpent->gr_name : _unknown), gid);
471 | s += strlen( s);
472 |
473 | pwent = getpwuid( uid = geteuid());
474 | sprintf( s, " [%s(%d)", (pwent ? pwent->pw_name : _unknown), uid);
475 | s += strlen( s);
476 | grpent = getgrgid( gid = getegid());
477 | sprintf( s, ".%s(%d)] = ", (grpent ? grpent->gr_name : _unknown), gid);
478 | s += strlen( s);
479 |
480 | /**
481 | ** Add the commands result
482 | **/
483 |
484 | switch( result) {
485 | case TCL_OK:
486 | strcpy( s, "TCL_OK");
487 | break;
488 | case TCL_ERROR:
489 | strcpy( s, "TCL_ERROR");
490 | break;
491 | case TCL_RETURN:
492 | strcpy( s, "TCL_RETURN");
493 | break;
494 | case TCL_BREAK:
495 | strcpy( s, "TCL_BREAK");
496 | break;
497 | case TCL_CONTINUE:
498 | strcpy( s, "TCL_CONTINUE");
499 | break;
500 | default:
501 | strcpy( s, "UNKNOWN");
502 | break;
503 | }
504 |
505 | s += strlen( s);
506 | sprintf( s, "(%d)", result);
507 |
508 | } /** End of 'Module_Tracing' **/
509 |
510 | /*++++
511 | ** ** Function-Header ***************************************************** **
512 | ** **
513 | ** Function: Enable_Error, Disable_Error, Restore_Error **
514 | ** **
515 | ** Description: Enables, disables, or restores error logging **
516 | ** Sometimes an error isn't really an error **
517 | ** **
518 | ** First Edition: 1999/11/11 **
519 | ** **
520 | ** Parameters: none **
521 | ** **
522 | ** Result: none **
523 | ** **
524 | ** ************************************************************************ **
525 | ++++*/
526 |
527 | static void save_error_state(int reset) {
528 | static int in_effect = 0;
529 | static int saved_state = 0;
530 |
531 | if (reset && in_effect ) {
532 | quiet_on_error = saved_state;
533 | in_effect = 0;
534 | } else if (!reset && !in_effect ) {
535 | saved_state = quiet_on_error;
536 | in_effect = 1;
537 | }
538 | }
539 |
540 |
541 | void Enable_Error(void) {
542 | save_error_state(0);
543 | quiet_on_error = 0;
544 | }
545 |
546 | void Disable_Error(void) {
547 | save_error_state(0);
548 | quiet_on_error = 1;
549 | }
550 |
551 | void Restore_Error(void) {
552 | quiet_on_error = 0; /* the default is to output errors */
553 | save_error_state(1);
554 | }
555 |
556 | /*++++
557 | ** ** Function-Header ***************************************************** **
558 | ** **
559 | ** Function: Module_Error **
560 | ** **
561 | ** Description: Error handling for the modules package **
562 | ** **
563 | ** First Edition: 1995/08/06 **
564 | ** **
565 | ** Parameters: ErrType error_type Type of the error **
566 | ** char *module Affected module **
567 | ** int lineo Line number **
568 | ** ... Argument list **
569 | ** **
570 | ** Result: ErrCode OK No error **
571 | ** PROBLEM Problem. Program may **
572 | ** continue running **
573 | ** ERROR Caller should try to **
574 | ** exit gracefully **
575 | ** **
576 | ** Attached Globals: **
577 | ** **
578 | ** ************************************************************************ **
579 | ++++*/
580 |
581 | int Module_Error( ErrType error_type,
582 | char *module,
583 | int lineno,
584 | ... )
585 | {
586 | int listsize = ARGLIST_SIZE, /** Initial size of the argu-**/
587 | /** ment list **/
588 | argc = 0; /** Actual number of args **/
589 | char **argv, /** Argument array **/
590 | *arg; /** A single argument **/
591 | va_list parptr; /** Varargs scan pointer **/
592 | ErrTransTab *TransPtr; /** Error transtab entry **/
593 | ErrMeasr *MeasPtr; /** Measurement pointer **/
594 | ErrCode ret_code;
595 | int NoArgs = (error_type == ERR_ALLOC);
596 |
597 | if( quiet_on_error ) return OK; /* do nothing - just OK */
598 |
599 | /**
600 | ** Argument check
601 | **/
602 | if( NO_ERR_VERBOSE == error_type && !sw_verbose)
603 | return( OK);
604 |
605 | if( !module)
606 | module = unknown;
607 |
608 | /**
609 | ** Build the argument array at first
610 | **/
611 |
612 | if( NULL == (argv = (char **) malloc( listsize * sizeof( char *)))) {
613 | module = module_name;
614 | error_type = ERR_ALLOC;
615 | NoArgs = 1;
616 | }
617 |
618 | va_start( parptr, lineno);
619 | while( !NoArgs && (NULL != (arg = va_arg( parptr, char *)))) {
620 |
621 | /**
622 | ** Conditionally realloc
623 | **/
624 | while( argc >= listsize) {
625 | listsize += ARGLIST_SIZE;
626 | if( NULL == (argv = (char **) realloc( argv,
627 | listsize * sizeof(char *)))) {
628 | module = module_name;
629 | error_type = ERR_ALLOC;
630 | NoArgs = 1;
631 | break;
632 | }
633 | }
634 |
635 | argv[ argc++] = arg;
636 |
637 | } /** while **/
638 |
639 | if( NO_ERR_VERBOSE == error_type && !argc)
640 | return( OK);
641 |
642 | /**
643 | ** Locate the error translation table entry according to the
644 | ** passed error type
645 | **/
646 | if( NULL == (TransPtr = ErrorLookup( error_type))) {
647 | if( argv)
648 | null_free((void *) &argv);
649 | return( ErrorLogger( ERR_INVAL, LOC, (sprintf( buffer, "%d",
650 | error_type), buffer), NULL));
651 | }
652 |
653 | /**
654 | ** Now locate the assigned error weight ...
655 | **/
656 |
657 | if( NULL == (MeasPtr = MeasLookup( TransPtr->error_weight))) {
658 | if( argv)
659 | null_free((void *) &argv);
660 | argc = 0;
661 | return( ErrorLogger( ERR_INVWGHT, LOC, (sprintf( buffer, "%d",
662 | TransPtr->error_weight), buffer), NULL));
663 | }
664 |
665 | /**
666 | ** Use the return code as defined for the current user level
667 | **/
668 | switch( sw_userlvl) {
669 | case UL_NOVICE:
670 | ret_code = MeasPtr->ret_nov;
671 | break;
672 | case UL_ADVANCED:
673 | ret_code = MeasPtr->ret_adv;
674 | break;
675 | case UL_EXPERT:
676 | ret_code = MeasPtr->ret_exp;
677 | break;
678 | }
679 |
680 | /**
681 | ** Print the error message
682 | **/
683 | if( TransPtr->error_weight <= WGHT_TRACE || ret_code != OK)
684 | if( !FlushError( error_type, module, lineno, TransPtr->error_weight,
685 | MeasPtr->message, TransPtr->messages, argc, argv)) {
686 | if( argv)
687 | null_free((void *) &argv);
688 | argc = 0;
689 | return( ErrorLogger( ERR_INTERRL, LOC, NULL));
690 | }
691 |
692 | /**
693 | ** Return to the caller ... conditionally ...
694 | **/
695 | if( WARN == ret_code)
696 | ret_code = OK;
697 |
698 | if( argv)
699 | null_free((void *) &argv);
700 | argc = 0;
701 |
702 | if( ret_code > ERROR)
703 | exit( ret_code);
704 |
705 | return( ret_code);
706 | } /** End of 'Module_Error' **/
707 |
708 | /*++++
709 | ** ** Function-Header ***************************************************** **
710 | ** **
711 | ** Function: ErrorLookup **
712 | ** **
713 | ** Description: Look up the passed error type in the translation tab.**
714 | ** **
715 | ** First Edition: 1995/08/06 **
716 | ** **
717 | ** Parameters: ErrType error_type Type of the error **
718 | ** **
719 | ** Result: ErrTransTab* NULL Not found **
720 | ** else Pointer to the acc. entry **
721 | ** **
722 | ** Attached Globals: **
723 | ** **
724 | ** ************************************************************************ **
725 | ++++*/
726 |
727 | static ErrTransTab *ErrorLookup( ErrType error_type )
728 | {
729 | ErrTransTab *low, *mid, *high, *save; /** Search pointers **/
730 |
731 | /**
732 | ** Init serach pointers
733 | **/
734 |
735 | low = TransTab;
736 | high = TransTab + (sizeof( TransTab) / sizeof( TransTab[0]) -1);
737 | mid = (ErrTransTab *) NULL;
738 |
739 | /**
740 | ** Search loop
741 | **/
742 |
743 | while( low < high) {
744 |
745 | save = mid;
746 | mid = low + ((high - low) / 2);
747 | if( save == mid)
748 | low = mid = high; /** Just for safety ... **/
749 |
750 | if( mid->error_type < error_type ) {
751 | low = mid;
752 | } else if( mid->error_type > error_type ) {
753 | high = mid;
754 | } else
755 | return( mid); /** Yep! Got it! **/
756 |
757 | } /** while **/
758 |
759 | /**
760 | ** Maybe the loop has been finished before the comparison took place
761 | ** (low == high) and hit!
762 | **/
763 |
764 | if( mid->error_type == error_type )
765 | return( mid); /** Yep! Got it! **/
766 |
767 | /**
768 | ** If this point is reached, nothing has been found ...
769 | **/
770 |
771 | return( NULL);
772 |
773 | } /** End of 'ErrorLookup' **/
774 |
775 | /*++++
776 | ** ** Function-Header ***************************************************** **
777 | ** **
778 | ** Function: MeasLookup **
779 | ** **
780 | ** Description: Look up the passed error weight in the measurement **
781 | ** table **
782 | ** **
783 | ** First Edition: 1995/08/06 **
784 | ** **
785 | ** Parameters: ErrWeights weigth Weight of the error **
786 | ** **
787 | ** Result: ErrMeasr* NULL Not found **
788 | ** else Pointer to the acc. entry **
789 | ** **
790 | ** Attached Globals: **
791 | ** **
792 | ** ************************************************************************ **
793 | ++++*/
794 |
795 | static ErrMeasr *MeasLookup( ErrWeights weigth )
796 | {
797 | ErrMeasr *low, *mid, *high, *save; /** Search pointers **/
798 |
799 | /**
800 | ** Init serach pointers
801 | **/
802 |
803 | low = Measurements;
804 | high = Measurements + (sizeof( Measurements) / sizeof( Measurements[0]) -1);
805 | save = (ErrMeasr *) NULL;
806 | mid = (ErrMeasr *) NULL;
807 |
808 | /**
809 | ** Search loop
810 | **/
811 |
812 | while( low < high) {
813 |
814 | save = mid;
815 | mid = low + ((high - low) / 2);
816 | if( save == mid)
817 | low = mid = high; /** Just to be sure ... **/
818 |
819 | if( mid->error_weight < weigth ) {
820 | low = mid;
821 | } else if( mid->error_weight > weigth ) {
822 | high = mid;
823 | } else
824 | return( mid); /** Yep! Got it! **/
825 |
826 | } /** while **/
827 |
828 | /**
829 | ** Maybe the loop has been finished before the comparison took place
830 | ** (low == high) and hit!
831 | **/
832 |
833 | if( mid->error_weight == weigth )
834 | return( mid); /** Yep! Got it! **/
835 |
836 | /**
837 | ** If this point is reached, nothing has been found ...
838 | **/
839 |
840 | return( NULL);
841 |
842 | } /** End of 'MeasLookup' **/
843 |
844 | /*++++
845 | ** ** Function-Header ***************************************************** **
846 | ** **
847 | ** Function: FlushError **
848 | ** **
849 | ** Description: Print the error message. Decide which facility to **
850 | ** use and schedule the according logger routine **
851 | ** **
852 | ** First Edition: 1995/12/21 **
853 | ** **
854 | ** Parameters: ErrType Type Error type as passed **
855 | ** char *module Module name **
856 | ** int lineno Line number **
857 | ** ErrWeights Weight Error Weight **
858 | ** char *WeightMsg Printable Weight **
859 | ** char *ErrMsgs Error message **
860 | ** int argc Number of arguments **
861 | ** char **argv Argument array **
862 | ** **
863 | ** Result: int 1 Everything OK **
864 | ** 0 Error occured while printing **
865 | ** **
866 | ** ************************************************************************ **
867 | ++++*/
868 |
869 | static int FlushError( ErrType Type,
870 | char *module,
871 | int lineno,
872 | ErrWeights Weight,
873 | char *WeightMsg,
874 | char *ErrMsgs,
875 | int argc,
876 | char **argv)
877 | {
878 | char *facilities, *buffer;
879 | char *fac;
880 | FILE *facfp;
881 | char *errmsg_buffer;
882 | int fac_alloc = 0;
883 |
884 | /**
885 | ** get the error facilities at first. If there isn't any, we may
886 | ** return on success immediatelly.
887 | **/
888 | if((char *) NULL == (facilities = GetFacility( Weight)))
889 | goto success0;
890 |
891 | /**
892 | ** PANIC and FATAL error messages ought to be on stderr at least!
893 | **/
894 | if( WGHT_FATAL == Weight || WGHT_PANIC == Weight)
895 | if( !strstr( facilities, _stderr)) {
896 |
897 | if((char *) NULL == (buffer = stringer(NULL,0,
898 | _stderr,":", facilities, NULL))) {
899 | ErrorLogger( ERR_STRING, LOC, NULL);
900 | goto unwind0;
901 | }
902 |
903 | facilities = buffer;
904 | fac_alloc = 1;
905 | }
906 |
907 | /**
908 | ** Print the error message into the buffer
909 | **/
910 | if((char *) NULL == (errmsg_buffer = stringer(NULL, ERR_BUFSIZE, NULL))) {
911 | ErrorLogger( ERR_ALLOC, LOC, NULL);
912 | goto unwind1;
913 | }
914 |
915 | /**
916 | ** In case of verbosity, the first argument is the ErrMsgs format string
917 | **/
918 | if( WGHT_VERBOSE == Weight) {
919 | ErrMsgs = *argv++;
920 | --argc;
921 | }
922 |
923 | if( WGHT_TRACE == Weight)
924 | Print_Tracing( errmsg_buffer, lineno, argc, argv);
925 | else if( !PrintError( errmsg_buffer, Type, module, lineno, Weight,
926 | WeightMsg, ErrMsgs, argc, argv))
927 | goto unwind2;
928 |
929 | /**
930 | ** Now tokenize the facilities string and schedule the error messge
931 | ** for every single facility
932 | **/
933 | for( fac = strtok( facilities, ":");
934 | fac;
935 | fac = strtok( (char *) NULL, ":") ) {
936 |
937 | /**
938 | ** Check for filenames. Two specials are defined: stderr and stdout
939 | ** Otherwise filenames are expected to begin on '.' or '/'.
940 | ** Everthing not recognized as a filename is assumed to be a
941 | ** syslog facility
942 | ** 'null' and 'none' are known as 'no logging'
943 | **/
944 | if( !strcmp( fac, _null) || !strcmp( fac, _none))
945 | continue;
946 |
947 | else if( !strcmp( fac, _stderr))
948 | fprintf( stderr, "%s", errmsg_buffer);
949 |
950 | else if( !strcmp( fac, _stdout))
951 | fprintf( stdout, "%s", errmsg_buffer);
952 |
953 | /**
954 | ** Syslog
955 | **/
956 | else if( '.' != *fac && '/' != *fac) {
957 | #if defined(HAVE_SYSLOG) && defined(WITH_LOGGING)
958 | int syslog_fac, syslog_lvl;
959 |
960 | if( CheckFacility( fac, &syslog_fac, &syslog_lvl)) {
961 | openlog( "modulecmd", LOG_PID, syslog_fac);
962 | setlogmask( LOG_UPTO( syslog_lvl));
963 | syslog( (syslog_fac | syslog_lvl), "%s", errmsg_buffer);
964 | closelog();
965 |
966 | /**
967 | ** Invalid facilities ... take care not to end up in
968 | ** infinite loops
969 | **/
970 | } else if( Type == ERR_INVFAC ||
971 | OK == ErrorLogger( ERR_INVFAC, LOC, fac, NULL))
972 | continue;
973 |
974 | #else
975 | # ifdef SYSLOG_DIR
976 | /* this is an intential memory leak */
977 | buffer = stringer(NULL,0, SYSLOG_DIR, "/", fac);
978 | fac = buffer;
979 | # endif
980 | #endif
981 | }
982 |
983 | /**
984 | ** Custom files ...
985 | ** This may result from the syslog part above
986 | **/
987 | if( '.' == *fac || '/' == *fac) {
988 | if((FILE *) NULL == (facfp = fopen( fac, "a"))) {
989 |
990 | if( WGHT_PANIC == Weight) /** Avoid endless loops! **/
991 | goto unwind2;
992 |
993 | /**
994 | ** Invalid facilities ... take care not to end up in
995 | ** infinite loops
996 | **/
997 | if( Type == ERR_INVFAC ||
998 | OK == ErrorLogger( ERR_INVFAC, LOC, fac, NULL))
999 | continue;
1000 | else
1001 | goto unwind2;
1002 | }
1003 |
1004 | fprintf( facfp, "%s", errmsg_buffer);
1005 |
1006 | if( EOF == fclose( facfp))
1007 | if( OK != ErrorLogger( ERR_CLOSE, LOC, fac, NULL))
1008 | goto unwind2;
1009 |
1010 | }
1011 | } /** for **/
1012 |
1013 | /**
1014 | ** Return on success
1015 | **/
1016 | null_free((void *) &errmsg_buffer);
1017 | if( fac_alloc)
1018 | null_free((void *) &facilities);
1019 | success0:
1020 | return( 1); /** -------- EXIT (SUCCESS) -------> **/
1021 |
1022 | unwind2:
1023 | null_free((void *) &errmsg_buffer);
1024 | unwind1:
1025 | if( fac_alloc)
1026 | null_free((void *) &facilities);
1027 | unwind0:
1028 | return( 0); /** -------- EXIT (FAILURE) -------> **/
1029 |
1030 | } /** End of 'FlushError' **/
1031 |
1032 | /*++++
1033 | ** ** Function-Header ***************************************************** **
1034 | ** **
1035 | ** Function: GetFacility **
1036 | ** **
1037 | ** Description: Get the log facility according to the passed error **
1038 | ** weight **
1039 | ** **
1040 | ** First Edition: 1995/12/21 **
1041 | ** **
1042 | ** Parameters: ErrWeights Weight Error Weight **
1043 | ** **
1044 | ** Result: char* NULL No facility found **
1045 | ** Otherwise Pointer to the colon separa- **
1046 | ** ted facility string **
1047 | ** **
1048 | ** ************************************************************************ **
1049 | ++++*/
1050 |
1051 | static char *GetFacility( ErrWeights Weight)
1052 | {
1053 | ErrFacilities *facility;
1054 |
1055 | /**
1056 | ** Get the facility table entry at first
1057 | **/
1058 | if( !(facility = GetFacility_sub( Weight)))
1059 | return((char *) NULL);
1060 |
1061 | /**
1062 | ** Now we've got two possibilities:
1063 | ** First of all there may be a custom facilitiy defined
1064 | ** Otherwise the default facility is to be returned now
1065 | **/
1066 | return( facility->facility ? facility->facility : facility->def_facility);
1067 |
1068 | } /** End of 'GetFacility' **/
1069 |
1070 | static ErrFacilities *GetFacility_sub( ErrWeights Weight)
1071 | {
1072 | ErrFacilities *low, *mid, *high, *save;
1073 | char buffer[ 20];
1074 |
1075 | /**
1076 | ** Binary search for the passed facility in the Facilities table.
1077 | ** This requires the table to be sorted on ascending error weight
1078 | **/
1079 | low = Facilities;
1080 | high = Facilities + (sizeof( Facilities) / sizeof( Facilities[0]));
1081 | save = (ErrFacilities *) NULL;
1082 | mid = (ErrFacilities *) NULL;
1083 |
1084 | while( low < high) {
1085 | save = mid;
1086 | mid = low + ((high - low) / 2);
1087 | if( save == mid)
1088 | low = mid = high; /** Just to be sure ... **/
1089 |
1090 | if( mid->Weight > Weight)
1091 | high = mid;
1092 | else if( mid->Weight < Weight)
1093 | low = mid;
1094 | else
1095 | break; /** found! **/
1096 | }
1097 |
1098 | /**
1099 | ** We have to check, if we've found something or if there's an internal
1100 | ** error (wrong weight)
1101 | **/
1102 | if( mid->Weight != Weight) {
1103 | if( OK == ErrorLogger( ERR_INVWGHT, LOC, (sprintf( buffer, "%d",
1104 | Weight), buffer), NULL))
1105 | return( NULL);
1106 | }
1107 |
1108 | return( mid);
1109 |
1110 | } /** End of 'GetFacility_sub' **/
1111 |
1112 | /*++++
1113 | ** ** Function-Header ***************************************************** **
1114 | ** **
1115 | ** Function: CheckFacility **
1116 | ** **
1117 | ** Description: Check the passwd string to be a valid combination **
1118 | ** of <syslog_facility>.<syslog_level> **
1119 | ** **
1120 | ** First Edition: 1995/12/21 **
1121 | ** **
1122 | ** Parameters: char *string Input facility string **
1123 | ** int *facility Buffer for the real facility **
1124 | ** int *level Buffer for the real level **
1125 | ** **
1126 | ** Result: int 1 Success **
1127 | ** 0 Failure. String not valid **
1128 | ** **
1129 | ** ************************************************************************ **
1130 | ++++*/
1131 |
1132 | int CheckFacility( char *string, int *facility, int *level)
1133 | {
1134 | char *s, *buf;
1135 | int x;
1136 |
1137 | /**
1138 | ** We do not want to change the strings ... so allocate a buffer here
1139 | **/
1140 | if((char *) NULL == (buf = stringer(NULL,0, string,NULL)))
1141 | if( OK == ErrorLogger( ERR_STRING, LOC, NULL))
1142 | goto unwind0;
1143 |
1144 | /**
1145 | ** We cannot use strtok here, because there's one initialized in an
1146 | ** outter loop!
1147 | **/
1148 | for( s=buf; s && *s && *s != '.'; s++);
1149 | if( !s || !*s)
1150 | goto unwind1;
1151 | *s = '\0';
1152 |
1153 | /**
1154 | ** This should be the facility
1155 | **/
1156 | if( -1 == (x = scan_facility( buf, facility_names,
1157 | (sizeof( facility_names) / sizeof( facility_names[0])) )))
1158 | goto unwind1;
1159 | *facility = x;
1160 |
1161 | /**
1162 | ** This should be the level
1163 | **/
1164 | if( -1 == (x = scan_facility( ++s, level_names,
1165 | (sizeof( level_names) / sizeof( level_names[0])) )))
1166 | goto unwind1;
1167 | *level = x;
1168 |
1169 | /**
1170 | ** Success
1171 | **/
1172 | null_free((void *) &buf);
1173 | return( 1); /** -------- EXIT (SUCCESS) -------> **/
1174 |
1175 | unwind1:
1176 | null_free((void *) &buf);
1177 | unwind0:
1178 | return( 0); /** -------- EXIT (FAILURE) -------> **/
1179 |
1180 | } /** End of 'CheckFacility' **/
1181 |
1182 | /*++++
1183 | ** ** Function-Header ***************************************************** **
1184 | ** **
1185 | ** Function: scan_facility **
1186 | ** **
1187 | ** Description: Scan the passed facility names table for the given **
1188 | ** string and pass back the assigned token **
1189 | ** **
1190 | ** First Edition: 1995/12/21 **
1191 | ** **
1192 | ** Parameters: char *s String to be checked **
1193 | ** FacilityNames *table Table of valid names and **
1194 | ** tokens **
1195 | ** int size Size of the table **
1196 | ** **
1197 | ** Result: int -1 name not found in the table **
1198 | ** Otherwise Assigned token **
1199 | ** **
1200 | ** ************************************************************************ **
1201 | ++++*/
1202 |
1203 | static int scan_facility( char *s, FacilityNames *table, int size)
1204 | {
1205 | FacilityNames *low, *mid, *high, *save;
1206 |
1207 | low = table;
1208 | high = table + size;
1209 | save = (FacilityNames *) NULL;
1210 |
1211 | while( low < high) {
1212 | int x; /** Have to use this, because strcmp will **/
1213 | /** not return -1 and 1 on Solaris 2.x **/
1214 | save = mid;
1215 | mid = low + ((high - low) / 2);
1216 | if( save == mid)
1217 | low = mid = high; /** To prevent endless loops **/
1218 |
1219 | if (mid == high)
1220 | return -1;
1221 | x = strcmp( mid->name, s);
1222 |
1223 | if( x < 0 )
1224 | low = mid;
1225 | else if( x > 0)
1226 | high = mid;
1227 | else
1228 | return( mid->token);
1229 |
1230 | } /** while **/
1231 |
1232 | return( !strcmp( mid->name, s) ? mid->token : -1 );
1233 |
1234 | } /** End of 'scan_facility' **/
1235 |
1236 | /*++++
1237 | ** ** Function-Header ***************************************************** **
1238 | ** **
1239 | ** Function: GetFacilityPtr **
1240 | ** **
1241 | ** Description: Scan the passed facility names table for the given **
1242 | ** string and pass back the assigned token **
1243 | ** **
1244 | ** First Edition: 1995/12/21 **
1245 | ** **
1246 | ** Parameters: char *facility Name of the facility **
1247 | ** **
1248 | ** Result: char** NULL Invalid facility name **
1249 | ** Otherwise Pointer to the facilty string**
1250 | ** reference **
1251 | ** **
1252 | ** ************************************************************************ **
1253 | ++++*/
1254 |
1255 | char **GetFacilityPtr( char *facility)
1256 | {
1257 | int i, len;
1258 | ErrMeasr *measptr;
1259 | char *buf, *s, *t;
1260 | ErrFacilities *facptr;
1261 |
1262 | /**
1263 | ** Try to figure out the error weight at first
1264 | ** Need the given weight in upper case for this
1265 | **/
1266 | len = strlen( facility);
1267 |
1268 | if((char *) NULL == (buf = stringer(NULL, 0, facility, NULL)))
1269 | if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
1270 | goto unwind0;
1271 |
1272 | for( t = buf; *t; ++t) *t = toupper(*t);
1273 |
1274 | /**
1275 | ** Now look up the measurements table for the uppercase weight
1276 | **/
1277 | i = sizeof( Measurements) / sizeof( Measurements[ 0]);
1278 | measptr = Measurements;
1279 |
1280 | while( i) {
1281 | if( !strncmp( measptr->message, buf, len))
1282 | break;
1283 | i--; measptr++;
1284 | }
1285 |
1286 | null_free((void *) &buf);
1287 |
1288 | if( !i) /** not found **/
1289 | goto unwind0;
1290 |
1291 | /**
1292 | ** Now get the facility table entry
1293 | **/
1294 |
1295 | if((ErrFacilities *) NULL == (facptr = GetFacility_sub(
1296 | measptr->error_weight))) {
1297 | ErrorLogger( ERR_INVWGHT_WARN, LOC, facility, NULL);
1298 | goto unwind0;
1299 | }
1300 |
1301 | /**
1302 | ** Got it ... return the desired pointer
1303 | **/
1304 | return( &facptr->facility); /** -------- EXIT (RESULT) -------> **/
1305 |
1306 | unwind0:
1307 | return((char **) NULL); /** -------- EXIT (FAILURE) -------> **/
1308 |
1309 | } /** End of 'GetFacilityPtr' **/
1310 |
1311 | /*++++
1312 | ** ** Function-Header ***************************************************** **
1313 | ** **
1314 | ** Function: PrintError **
1315 | ** **
1316 | ** Description: Print the error message **
1317 | ** **
1318 | ** First Edition: 1995/08/06 **
1319 | ** **
1320 | ** Parameters: char *errbuffer Buffer to hold the **
1321 | ** error messge **
1322 | ** ErrType Type Error type as passed **
1323 | ** char *module Module name **
1324 | ** int lineno Line number **
1325 | ** ErrWeights Weight Error Weight **
1326 | ** char *WeightMsg Printable Weight **
1327 | ** char *ErrMsgs Error message **
1328 | ** int argc Number of arguments **
1329 | ** char **argv Argument array **
1330 | ** **
1331 | ** Result: int 1 Everything OK **
1332 | ** 0 Error occured while printing **
1333 | ** **
1334 | ** Notes: According to the error type, the passed module and line num- **
1335 | ** ber will be handled as a module-file related one or depending**
1336 | ** on the packages source code: **
1337 | ** **
1338 | ** src -> ERR_IN_MODULEFILE -> modulefile -> ERR_INTERNAL -> src**
1339 | ** **
1340 | ** ************************************************************************ **
1341 | ++++*/
1342 |
1343 | static int PrintError( char *errbuffer,
1344 | ErrType Type,
1345 | char *module,
1346 | int lineno,
1347 | ErrWeights Weight,
1348 | char *WeightMsg,
1349 | char *ErrMsgs,
1350 | int argc,
1351 | char **argv)
1352 | {
1353 | char *error_string;
1354 |
1355 | /**
1356 | ** Build the error string at first. Note - we cannot alloc memory any
1357 | ** more!
1358 | **/
1359 | if( ERR_ALLOC == Type)
1360 | error_string = ErrMsgs;
1361 | else
1362 | if( NULL == (error_string = ErrorString( ErrMsgs, argc, argv)))
1363 | return( 0);
1364 |
1365 | /**
1366 | ** Print
1367 | **/
1368 |
1369 | if( ERR_INTERNAL > Type && ERR_IN_MODULEFILE < Type &&
1370 | linenum && g_current_module )
1371 |
1372 | sprintf( errbuffer, "%s(%s):%s:%d: %s\n", g_current_module,
1373 | (sprintf( buffer, "%d", linenum), buffer),
1374 | WeightMsg, Type, (error_string ? error_string : "") );
1375 | else
1376 |
1377 | sprintf( errbuffer, "%s(%s):%s:%d: %s\n", (module ? module : "??"),
1378 | ( lineno ? (sprintf( buffer, "%d", lineno), buffer) : "??" ),
1379 | WeightMsg, Type, (error_string ? error_string : "") );
1380 |
1381 | /**
1382 | ** Success
1383 | **/
1384 | return( 1);
1385 |
1386 | } /** End of 'PrintError' **/
1387 |
1388 | /*++++
1389 | ** ** Function-Header ***************************************************** **
1390 | ** **
1391 | ** Function: ErrorString **
1392 | ** **
1393 | ** Description: Print the error message **
1394 | ** **
1395 | ** First Edition: 1995/08/06 **
1396 | ** **
1397 | ** Parameters: char *ErrMsgs Error message **
1398 | ** int argc Number of arguments **
1399 | ** char **argv Argument array **
1400 | ** **
1401 | ** Result: char* NULL Parse or alloc error **
1402 | ** else Pointer to the error string **
1403 | ** **
1404 | ** Attached Globals: - **
1405 | ** **
1406 | ** ************************************************************************ **
1407 | ++++*/
1408 |
1409 | static char *ErrorString( char *ErrMsgs,
1410 | int argc,
1411 | char **argv)
1412 | {
1413 | char *s; /** Insertion pointer **/
1414 | int len = 0; /** Current length **/
1415 | int backslash = 0; /** backslash found ? **/
1416 |
1417 | if( !ErrMsgs)
1418 | return( NULL);
1419 |
1420 | /**
1421 | ** Allocate memory if neccessary
1422 | **/
1423 | if( !error_line)
1424 | if((char *) NULL ==(error_line = stringer(NULL,strsize = ERR_LINELEN,
1425 | NULL))){
1426 | ErrorLogger( ERR_STRING, LOC, NULL);
1427 | return( NULL);
1428 | }
1429 |
1430 | s = error_line;
1431 |
1432 | /**
1433 | ** Scan the error strings to be printed
1434 | **/
1435 | while( *ErrMsgs) {
1436 |
1437 | /**
1438 | ** Check for special characters
1439 | **/
1440 | switch( *ErrMsgs) {
1441 | case '\\': if( !backslash) {
1442 | backslash = 1;
1443 | ErrMsgs++;
1444 | continue; /** while( *ErrMsgs) **/
1445 | }
1446 | break; /** switch **/
1447 |
1448 | case '$': if( !backslash) {
1449 | ErrMsgs++;
1450 | add_param( &ErrMsgs, &s, &len, argc, argv);
1451 | error_line = s - len;
1452 | continue; /** while( *ErrMsgs) **/
1453 | }
1454 | break; /** switch **/
1455 | } /** switch **/
1456 |
1457 | /**
1458 | ** Add a single character to the error string
1459 | **/
1460 | if( ++len >= strsize - 5) { /** 5 Bytes for safety **/
1461 | if( NULL == (error_line = (char *) realloc( error_line,
1462 | strsize += ERR_LINELEN))) {
1463 | ErrorLogger( ERR_ALLOC, LOC, NULL);
1464 | return( NULL);
1465 | }
1466 | s = error_line + len - 1;
1467 | }
1468 |
1469 | *s++ = *ErrMsgs++;
1470 | backslash = 0;
1471 |
1472 | } /** while( *ErrMsgs) **/
1473 |
1474 | /**
1475 | ** Success. Return a pointer to the newly created string
1476 | **/
1477 | *s++ = '\0';
1478 | return( error_line);
1479 |
1480 | } /** End of 'ErrorString' **/
1481 |
1482 | /*++++
1483 | ** ** Function-Header ***************************************************** **
1484 | ** **
1485 | ** Function: add_param **
1486 | ** **
1487 | ** Description: Put an argument to the error string **
1488 | ** **
1489 | ** First Edition: 1995/08/06 **
1490 | ** **
1491 | ** Parameters: char **Control Parameter control **
1492 | ** char **Target Target to print to **
1493 | ** int *Length Current length of the**
1494 | ** output string **
1495 | ** int argc Number of arguments **
1496 | ** char **argv Argument array **
1497 | ** **
1498 | ** Result: - **
1499 | ** **
1500 | ** Attached Globals: - **
1501 | ** **
1502 | ** ************************************************************************ **
1503 | ++++*/
1504 |
1505 | static void add_param( char **Control,
1506 | char **Target,
1507 | int *Length,
1508 | int argc,
1509 | char **argv)
1510 | {
1511 | char *s; /** Scan pointer fot the ctrl field **/
1512 | int index, last = 0; /** parameter index **/
1513 | int len = 0; /** Parameter string length **/
1514 |
1515 | /**
1516 | ** Copy the current control field into the buffer
1517 | **/
1518 |
1519 | for( s = buffer; **Control; (*Control)++ ) {
1520 |
1521 | if( **Control == '*') {
1522 | last = argc;
1523 | continue;
1524 | } else if( **Control < '0' || **Control > '9')
1525 | break;
1526 |
1527 | *s++ = **Control;
1528 | }
1529 |
1530 | *s = '\0';
1531 |
1532 | /**
1533 | ** Has something been found ? If not, print a '$'
1534 | **/
1535 | if( s == buffer && !last) {
1536 |
1537 | if( ++(*Length) >= strsize) {
1538 | if( NULL == (error_line = (char*) realloc( error_line,
1539 | strsize += ERR_LINELEN))) {
1540 | ErrorLogger( ERR_ALLOC, LOC, NULL);
1541 | return;
1542 | }
1543 | *Target = error_line + *Length - 1;
1544 | }
1545 |
1546 | *(*Target++) = '$';
1547 |
1548 | } else {
1549 |
1550 | /**
1551 | ** Something has been found. Form the parameter index at first
1552 | **/
1553 | if( s == buffer)
1554 | index = 0;
1555 | else
1556 | index = atoi( buffer) - 1;
1557 |
1558 | if( !last)
1559 | last = index + 1;
1560 | if( last > argc)
1561 | last = argc;
1562 |
1563 | /**
1564 | ** Spool them all out
1565 | **/
1566 | while( index < last) {
1567 |
1568 | len = strlen( argv[ index]);
1569 |
1570 | while(( *Length + len + 1) >= strsize - 5) {
1571 | if( NULL == (error_line = (char*) realloc( error_line,
1572 | strsize += ERR_LINELEN))) {
1573 | ErrorLogger( ERR_ALLOC, LOC, NULL);
1574 | return;
1575 | }
1576 | *Target = error_line + *Length;
1577 | }
1578 |
1579 | strcpy( *Target, argv[ index]);
1580 | *Target += len;
1581 | *Length += len;
1582 |
1583 | index++;
1584 |
1585 | } /** while **/
1586 | } /** if **/
1587 |
1588 | } /** End of 'add_param' **/