mirror of
https://github.com/envmodules/modules.git
synced 2026-06-10 00:56:30 +08:00
* default for cache is now "no" * Added version_test() to testsuite to make some of the tests conditional on the values generated by --version. - the configure options help is formatted with AC_HELP_STRING
1576 lines
44 KiB
C
1576 lines
44 KiB
C
/*****
|
||
** ** Module Header ******************************************************* **
|
||
** **
|
||
** Modules Revision 3.0 **
|
||
** Providing a flexible user environment **
|
||
** **
|
||
** File: error.c **
|
||
** First Edition: 91/10/23 **
|
||
** **
|
||
** Authors: Jens Hamisch, jens@Strawberry.COM **
|
||
** **
|
||
** Description: The modules error logger **
|
||
** **
|
||
** Exports: Module_Error **
|
||
** GetFacilityPtr **
|
||
** CheckFacility **
|
||
** Enable_Error **
|
||
** Disable_Error **
|
||
** Restore_Error **
|
||
** **
|
||
** Notes: **
|
||
** **
|
||
** ************************************************************************ **
|
||
****/
|
||
|
||
/** ** Copyright *********************************************************** **
|
||
** **
|
||
** Copyright 1991-1994 by John L. Furlan. **
|
||
** see LICENSE.GPL, which must be provided, for details **
|
||
** **
|
||
** ************************************************************************ **/
|
||
|
||
static char Id[] = "@(#)$Id: error.c,v 1.5 2002/06/17 05:58:43 rkowen Exp $";
|
||
static void *UseId[] = { &UseId, Id };
|
||
|
||
/** ************************************************************************ **/
|
||
/** HEADERS **/
|
||
/** ************************************************************************ **/
|
||
|
||
#include "modules_def.h"
|
||
#if HAVE_STDARG_H
|
||
# include <stdarg.h>
|
||
#else
|
||
# error "You need an ANSI C compiler"
|
||
#endif
|
||
|
||
#if defined(HAVE_SYSLOG) && defined(WITH_LOGGING)
|
||
# include <syslog.h>
|
||
#endif
|
||
|
||
#include <pwd.h>
|
||
#include <grp.h>
|
||
|
||
/** ************************************************************************ **/
|
||
/** LOCAL DATATYPES **/
|
||
/** ************************************************************************ **/
|
||
|
||
/**
|
||
** Error weights
|
||
**/
|
||
|
||
typedef enum _err_weights {
|
||
WGHT_NONE=0, /** Dummy value: No error **/
|
||
WGHT_VERBOSE, /** Verbose messages **/
|
||
WGHT_INFO=3, /** Informal message **/
|
||
WGHT_DEBUG=5, /** Debugger output **/
|
||
WGHT_TRACE, /** Tracing output **/
|
||
WGHT_WARN=10, /** Warning: Prog. flow not affected **/
|
||
WGHT_PROB=20, /** Problem: Prog. flow cond. aff. **/
|
||
WGHT_ERROR=25, /** Error and Fatal: Prog. flow aff. **/
|
||
WGHT_FATAL=27, /** Return to the caller **/
|
||
WGHT_PANIC=29 /** Panic: Exit program immediatelly **/
|
||
} ErrWeights;
|
||
|
||
/**
|
||
** Log facilities
|
||
**/
|
||
|
||
typedef struct _err_facility {
|
||
ErrWeights Weight; /** Error weight **/
|
||
char *facility; /** Log facility **/
|
||
char *def_facility; /** Default facility (facility undef)**/
|
||
} ErrFacilities;
|
||
|
||
typedef struct _facil_names {
|
||
char *name; /** Name of a facility **/
|
||
int token; /** Assigned token **/
|
||
} FacilityNames;
|
||
|
||
/**
|
||
** Error measurement table
|
||
**/
|
||
|
||
typedef struct {
|
||
ErrWeights error_weight; /** The weight itsself **/
|
||
char *message; /** Message to be printed **/
|
||
ErrCode ret_nov, /** Return code **/
|
||
ret_adv,
|
||
ret_exp;
|
||
} ErrMeasr;
|
||
|
||
/**
|
||
** Error code translation table
|
||
**/
|
||
|
||
typedef struct {
|
||
ErrType error_type; /** The error type as specified by **/
|
||
/** the caller **/
|
||
ErrWeights error_weight; /** The weight of this error **/
|
||
char *messages; /** List of messages to be printed **/
|
||
} ErrTransTab;
|
||
|
||
/** ************************************************************************ **/
|
||
/** CONSTANTS **/
|
||
/** ************************************************************************ **/
|
||
|
||
#define ARGLIST_SIZE 10
|
||
#define ERR_LINELEN 80 /** internal buffer size **/
|
||
#define ERR_BUFSIZE 4096 /** buffer for the whole error msg. **/
|
||
|
||
/** ************************************************************************ **/
|
||
/** MACROS **/
|
||
/** ************************************************************************ **/
|
||
|
||
/** not applicable **/
|
||
|
||
/** ************************************************************************ **/
|
||
/** LOCAL DATA **/
|
||
/** ************************************************************************ **/
|
||
|
||
static char module_name[] = "error.c"; /** File name of this module **/
|
||
|
||
/**
|
||
** Local flags
|
||
**/
|
||
static int quiet_on_error = 0;
|
||
|
||
/**
|
||
** Local strings
|
||
**/
|
||
|
||
static char unknown[] = "unknown"; /** If something's unknown **/
|
||
|
||
static char buffer[ ERR_LINELEN]; /** Internal string buffer **/
|
||
char *error_line = NULL;
|
||
static int strsize = 0;
|
||
|
||
/**
|
||
** Log facility table
|
||
**/
|
||
|
||
static char _stderr[] = "stderr";
|
||
static char _stdout[] = "stdout";
|
||
static char _null[] = "null";
|
||
static char _none[] = "none";
|
||
static char _unknown[] = "unknown";
|
||
|
||
static ErrFacilities Facilities[] = {
|
||
{ WGHT_NONE, NULL, NULL },
|
||
{ WGHT_VERBOSE, NULL, DEF_FACILITY_VERBOSE },
|
||
{ WGHT_INFO, NULL, DEF_FACILITY_INFO },
|
||
{ WGHT_DEBUG, NULL, DEF_FACILITY_DEBUG },
|
||
{ WGHT_TRACE, NULL, DEF_FACILITY_TRACE },
|
||
{ WGHT_WARN, NULL, DEF_FACILITY_WARN },
|
||
{ WGHT_PROB, NULL, DEF_FACILITY_PROB },
|
||
{ WGHT_ERROR, NULL, DEF_FACILITY_ERROR },
|
||
{ WGHT_FATAL, NULL, DEF_FACILITY_FATAL },
|
||
{ WGHT_PANIC, NULL, DEF_FACILITY_PANIC }
|
||
};
|
||
|
||
/**
|
||
** Syslog facility names
|
||
**/
|
||
|
||
static FacilityNames facility_names[] = {
|
||
#if defined(HAVE_SYSLOG) && defined(WITH_LOGGING)
|
||
{ "auth", LOG_AUTH },
|
||
{ "cron", LOG_CRON },
|
||
{ "daemon", LOG_DAEMON },
|
||
{ "kern", LOG_KERN },
|
||
{ "local0", LOG_LOCAL0 },
|
||
{ "local1", LOG_LOCAL1 },
|
||
{ "local2", LOG_LOCAL2 },
|
||
{ "local3", LOG_LOCAL3 },
|
||
{ "local4", LOG_LOCAL4 },
|
||
{ "local5", LOG_LOCAL5 },
|
||
{ "local6", LOG_LOCAL6 },
|
||
{ "local7", LOG_LOCAL7 },
|
||
{ "lpr", LOG_LPR },
|
||
{ "mail", LOG_MAIL },
|
||
{ "news", LOG_NEWS },
|
||
{ "user", LOG_USER },
|
||
{ "uucp", LOG_UUCP }
|
||
#else
|
||
{ "none", 0 }
|
||
#endif
|
||
};
|
||
|
||
/**
|
||
** Syslog level names
|
||
**/
|
||
|
||
static FacilityNames level_names[] = {
|
||
#if defined(HAVE_SYSLOG) && defined(WITH_LOGGING)
|
||
{ "alert", LOG_ALERT },
|
||
{ "crit", LOG_CRIT },
|
||
{ "debug", LOG_DEBUG },
|
||
{ "emerg", LOG_EMERG },
|
||
{ "err", LOG_ERR },
|
||
{ "info", LOG_INFO },
|
||
{ "notice", LOG_NOTICE },
|
||
{ "warning", LOG_WARNING }
|
||
#else
|
||
{ "none", 0 }
|
||
#endif
|
||
};
|
||
|
||
/**
|
||
** Error measurement table
|
||
** Take care that this list is sorted in ascending order concerning the error
|
||
** weights
|
||
**/
|
||
|
||
#define MEAS_VERB_NDX 1 /** Index of the 'VERBOSE' entry **/
|
||
|
||
static ErrMeasr Measurements[] = {
|
||
{ WGHT_NONE, "" , OK, OK, OK },
|
||
{ WGHT_VERBOSE,"VERB" , OK, OK, OK },
|
||
{ WGHT_INFO, "INFO" , OK, OK, OK },
|
||
{ WGHT_DEBUG, "DEBUG", OK, OK, OK },
|
||
{ WGHT_TRACE, "TRACE", OK, OK, OK },
|
||
{ WGHT_WARN, "WARN" , PROBLEM, WARN, OK },
|
||
{ WGHT_PROB, "PROB" , ERROR, PROBLEM, OK },
|
||
{ WGHT_ERROR, "ERROR", ERROR, ERROR, ERROR },
|
||
{ WGHT_FATAL, "FATAL", FATAL, FATAL, FATAL },
|
||
{ WGHT_PANIC, "PANIC", PANIC, PANIC, PANIC },
|
||
};
|
||
|
||
/**
|
||
** Error code translation table
|
||
** Take care that this list is sorted in ascending order concerning the error
|
||
** types
|
||
**/
|
||
|
||
static ErrTransTab TransTab[] = {
|
||
{ NO_ERR, WGHT_NONE, NULL },
|
||
{ NO_ERR_DEBUG, WGHT_DEBUG, "$*" },
|
||
{ NO_ERR_START, WGHT_DEBUG, "Starting $*" },
|
||
{ NO_ERR_END, WGHT_DEBUG, "Exit $*" },
|
||
{ NO_ERR_VERBOSE, WGHT_VERBOSE, NULL },
|
||
{ ERR_PARAM, WGHT_ERROR, "Paramter error concerning '$1'" },
|
||
{ ERR_USAGE, WGHT_ERROR, "Usage is '$*'" },
|
||
{ ERR_ARGSTOLONG, WGHT_ERROR, "'$1': Arguments to long. Max. is '$2'" },
|
||
{ ERR_OPT_AMBIG, WGHT_ERROR, "Option '$1' is ambiguous" },
|
||
{ ERR_OPT_NOARG, WGHT_ERROR, "Option '$1' allows no argument" },
|
||
{ ERR_OPT_REQARG, WGHT_ERROR, "Option '$1' requires an argument" },
|
||
{ ERR_OPT_UNKNOWN, WGHT_ERROR, "Unrecognized option '$1'" },
|
||
{ ERR_OPT_ILL, WGHT_ERROR, "Illegal option '$1'" },
|
||
{ ERR_OPT_INV, WGHT_ERROR, "Invalid option '$1'" },
|
||
{ ERR_USERLVL, WGHT_ERROR, "Undefined userlevel '$1'" },
|
||
{ ERR_GETOPT, WGHT_FATAL, "getopt() failed" },
|
||
{ ERR_OPEN, WGHT_ERROR, "Cannot open file '$1' for '$2'" },
|
||
{ ERR_POPEN, WGHT_ERROR, "Cannot open pipe '$1' for '$2'" },
|
||
{ ERR_OPENDIR, WGHT_ERROR, "Cannot open directory '$1' for reading" },
|
||
{ ERR_CLOSE, WGHT_WARN, "Cannot close file '$1'" },
|
||
{ ERR_PCLOSE, WGHT_WARN, "Cannot close pipe '$1'" },
|
||
{ ERR_CLOSEDIR, WGHT_WARN, "Cannot close directory '$1'" },
|
||
{ ERR_READ, WGHT_ERROR, "Error while reading file '$1'" },
|
||
{ ERR_READDIR, WGHT_ERROR, "Error while reading directory '$1'" },
|
||
{ ERR_WRITE, WGHT_ERROR, "Error while writing file '$1'" },
|
||
{ ERR_SEEK, WGHT_ERROR, "Seek error on file '$1'" },
|
||
{ ERR_FLUSH, WGHT_WARN, "Flush error on file '$1'" },
|
||
{ ERR_DUP, WGHT_WARN, "Cannot duplicate handle of file '$1'" },
|
||
{ ERR_DIRNAME, WGHT_ERROR, "Cannot build directory name" },
|
||
{ ERR_NAMETOLONG, WGHT_ERROR, "Requested directory name to long: "
|
||
"dir='$1',file='$2'" },
|
||
{ ERR_DIRNOTFOUND, WGHT_ERROR, "Directory '$1' not found" },
|
||
{ ERR_FILEINDIR, WGHT_ERROR, "File '$1' not found in directory '$2'" },
|
||
{ ERR_NODIR, WGHT_ERROR, "'$1' is not a directory" },
|
||
{ ERR_UNLINK, WGHT_WARN, "Cannot unlink '$1'" },
|
||
{ ERR_RENAME, WGHT_PROB, "Cannot rename '$1' to '$2'" },
|
||
{ ERR_ALLOC, WGHT_FATAL, "Out of memory." },
|
||
{ ERR_SOURCE, WGHT_WARN, "Error sourcing file '$1'" },
|
||
{ ERR_UNAME, WGHT_FATAL, "'uname (2)' failed." },
|
||
{ ERR_GETHOSTNAME, WGHT_FATAL, "'gethostname (2)' failed." },
|
||
{ ERR_GETDOMAINNAME,WGHT_FATAL, "'getdomainname (2)' failed." },
|
||
{ ERR_STRING, WGHT_FATAL, "string error" },
|
||
{ ERR_DISPLAY, WGHT_ERROR, "Cannot open display" },
|
||
{ ERR_PARSE, WGHT_ERROR, "Parse error" },
|
||
{ ERR_EXEC, WGHT_ERROR, "Tcl command execution failed: $1" },
|
||
{ ERR_EXTRACT, WGHT_ERROR, "Cannot extract X11 resources" },
|
||
{ ERR_COMMAND, WGHT_ERROR, "'$1' is an unrecognized subcommand" },
|
||
{ ERR_LOCATE, WGHT_ERROR, "Unable to locate a modulefile for '$1'" },
|
||
{ ERR_MAGIC, WGHT_ERROR, "Magic cookie '#%Module' missing in '$1'" },
|
||
{ ERR_MODULE_PATH, WGHT_ERROR, "'MODULEPATH' not set" },
|
||
{ ERR_HOME, WGHT_ERROR, "'HOME' not set" },
|
||
{ ERR_SHELL, WGHT_ERROR, "Unknown shell type '$1'" },
|
||
{ ERR_DERELICT, WGHT_ERROR, "Unknown shell derelict '$1'" },
|
||
{ ERR_CONFLICT, WGHT_ERROR, "Module '$1' conflicts with the currently "
|
||
"loaded module(s) '$2*'" },
|
||
{ ERR_PREREQ, WGHT_ERROR, "Module '$1' depends on one of the "
|
||
"module(s) '$2*'" },
|
||
{ ERR_NOTLOADED, WGHT_ERROR, "Module '$1' is currently not loaded" },
|
||
{ ERR_DUP_SYMVERS, WGHT_PROB, "Duplicate version symbol '$1' found" },
|
||
{ ERR_SYMLOOP, WGHT_ERROR, "Version symbol '$1' loops" },
|
||
{ ERR_BADMODNAM, WGHT_PROB, "Invalid modulename '$1' found" },
|
||
{ ERR_DUP_ALIAS, WGHT_WARN, "Duplicate alias '$1' found" },
|
||
{ ERR_CACHE_INVAL, WGHT_ERROR, "Invalid cache version '$1' found" },
|
||
{ ERR_CACHE_LOAD, WGHT_WARN, "Couldn't load the cache properly" },
|
||
{ ERR_BEGINENV, WGHT_WARN, "Invalid update subcommand "
|
||
"- no .modulesbeginenv" },
|
||
{ ERR_INIT_TCL, WGHT_ERROR, "Cannot initialize TCL" },
|
||
{ ERR_INIT_TCLX, WGHT_WARN, "Cannot initialize TCLX modules using "
|
||
"extended commands might fail" },
|
||
{ ERR_INIT_ALPATH, WGHT_WARN, "Could not extend auto_path variable. "
|
||
"Module using autoloadable functions might "
|
||
"fail" },
|
||
{ ERR_INIT_STUP, WGHT_WARN, "Cannot find a 'module load' command in "
|
||
"any of the '$1' startup files" },
|
||
{ ERR_SET_VAR, WGHT_WARN, "Cannot set TCL variable '$1'" },
|
||
{ ERR_INFO_DESCR, WGHT_ERROR, "Unrecognized module info descriptor '$1'" },
|
||
{ ERR_INVWGHT_WARN, WGHT_WARN, "Invalid error weight '$1' found" },
|
||
{ ERR_INVFAC_WARN, WGHT_WARN, "Invalid log facility '$1'" },
|
||
{ ERR_COLON, WGHT_WARN, "Spurious colon in pattern '$1'" },
|
||
{ ERR_INTERAL, WGHT_PANIC, "Internal error in the alias handler" },
|
||
{ ERR_INTERRL, WGHT_PANIC, "Internal error in the error logger" },
|
||
{ ERR_INVAL, WGHT_PANIC, "Invalid error type '$1' found" },
|
||
{ ERR_INVWGHT, WGHT_PANIC, "Invalid error weight '$1' found" },
|
||
{ ERR_INVFAC, WGHT_PANIC, "Invalid log facility '$1'" },
|
||
{ ERR_ENVVAR, WGHT_FATAL, "The environment variables LOADMODULES and _LMFILES_ have inconsistent lengths." }
|
||
};
|
||
|
||
/** ************************************************************************ **/
|
||
/** PROTOTYPES **/
|
||
/** ************************************************************************ **/
|
||
|
||
static ErrTransTab *ErrorLookup( ErrType error_type );
|
||
|
||
static ErrMeasr *MeasLookup( ErrWeights weigth );
|
||
|
||
static int FlushError( ErrType Type,
|
||
char *module,
|
||
int lineno,
|
||
ErrWeights Weight,
|
||
char *WeightMsg,
|
||
char *ErrMsgs,
|
||
int argc,
|
||
char **argv);
|
||
|
||
static int PrintError( char *buffer,
|
||
ErrType Type,
|
||
char *module,
|
||
int lineno,
|
||
ErrWeights Weight,
|
||
char *WeightMsg,
|
||
char *ErrMsgs,
|
||
int argc,
|
||
char **argv);
|
||
|
||
static char *ErrorString( char *ErrMsgs,
|
||
int argc,
|
||
char **argv);
|
||
|
||
static void add_param( char **Control,
|
||
char **Target,
|
||
int *Length,
|
||
int argc,
|
||
char **argv);
|
||
|
||
static int scan_facility( char *s,
|
||
FacilityNames *table,
|
||
int size);
|
||
|
||
static char *GetFacility( ErrWeights Weight);
|
||
static ErrFacilities *GetFacility_sub( ErrWeights Weight);
|
||
|
||
static void Print_Tracing( char *buffer,
|
||
int result,
|
||
int argc,
|
||
char **argv);
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: Module_Tracing **
|
||
** Print_Tracing **
|
||
** Module_Verbosity **
|
||
** **
|
||
** Description: Display a tracing or verbose message **
|
||
** **
|
||
** First Edition: 95/12/27 **
|
||
** **
|
||
** Parameters: int result Result code of th module command **
|
||
** int argc Number od arguments to the module **
|
||
** command **
|
||
** char **argv Argument array **
|
||
** char *buffer Print buffer **
|
||
** **
|
||
** Result: - **
|
||
** **
|
||
** Attached Globals: g_current_module The module which is handled **
|
||
** by the current command **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
void Module_Tracing( int result,
|
||
int argc,
|
||
char **argv)
|
||
{
|
||
if( !FlushError( NO_ERR, (char *) NULL, result, WGHT_TRACE, (char *) NULL,
|
||
(char *) NULL, argc, argv)) {
|
||
ErrorLogger( ERR_INTERRL, LOC, NULL);
|
||
}
|
||
|
||
} /** End of 'Module_Tracing' **/
|
||
|
||
void Module_Verbosity( int argc,
|
||
char **argv)
|
||
{
|
||
if( sw_verbose && argc && *argv)
|
||
if( !FlushError( NO_ERR_VERBOSE, g_current_module,linenum,WGHT_VERBOSE,
|
||
Measurements[ MEAS_VERB_NDX].message, *argv, argc, argv)) {
|
||
ErrorLogger( ERR_INTERRL, LOC, NULL);
|
||
}
|
||
|
||
} /** End of 'Module_Verbosity' **/
|
||
|
||
static void Print_Tracing( char *buffer,
|
||
int result,
|
||
int argc,
|
||
char **argv)
|
||
{
|
||
char *s = buffer;
|
||
struct passwd *pwent;
|
||
struct group *grpent;
|
||
uid_t uid;
|
||
gid_t gid;
|
||
|
||
/**
|
||
** Print the arguments
|
||
**/
|
||
|
||
while( argc--) {
|
||
/* sprintf( s, "%s ", *argv++); */
|
||
strcpy( s, *argv++);
|
||
strcat( s, " ");
|
||
s += strlen( s);
|
||
}
|
||
|
||
/**
|
||
** Add the real and effective user- and group-id
|
||
**/
|
||
|
||
pwent = getpwuid( uid = getuid());
|
||
sprintf( s, " [%s(%d)", (pwent ? pwent->pw_name : _unknown), uid);
|
||
s += strlen( s);
|
||
grpent = getgrgid( gid = getgid());
|
||
sprintf( s, ".%s(%d)]", (grpent ? grpent->gr_name : _unknown), gid);
|
||
s += strlen( s);
|
||
|
||
pwent = getpwuid( uid = geteuid());
|
||
sprintf( s, " [%s(%d)", (pwent ? pwent->pw_name : _unknown), uid);
|
||
s += strlen( s);
|
||
grpent = getgrgid( gid = getegid());
|
||
sprintf( s, ".%s(%d)] = ", (grpent ? grpent->gr_name : _unknown), gid);
|
||
s += strlen( s);
|
||
|
||
/**
|
||
** Add the commands result
|
||
**/
|
||
|
||
switch( result) {
|
||
case TCL_OK:
|
||
strcpy( s, "TCL_OK");
|
||
break;
|
||
case TCL_ERROR:
|
||
strcpy( s, "TCL_ERROR");
|
||
break;
|
||
case TCL_RETURN:
|
||
strcpy( s, "TCL_RETURN");
|
||
break;
|
||
case TCL_BREAK:
|
||
strcpy( s, "TCL_BREAK");
|
||
break;
|
||
case TCL_CONTINUE:
|
||
strcpy( s, "TCL_CONTINUE");
|
||
break;
|
||
default:
|
||
strcpy( s, "UNKNOWN");
|
||
break;
|
||
}
|
||
|
||
s += strlen( s);
|
||
sprintf( s, "(%d)", result);
|
||
|
||
} /** End of 'Module_Tracing' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: Enable_Error, Disable_Error, Restore_Error **
|
||
** **
|
||
** Description: Enables, disables, or restores error logging **
|
||
** Sometimes an error isn't really an error **
|
||
** **
|
||
** First Edition: 1999/11/11 **
|
||
** **
|
||
** Parameters: none **
|
||
** **
|
||
** Result: none **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static void save_error_state(int reset) {
|
||
static int in_effect = 0;
|
||
static int saved_state = 0;
|
||
|
||
if (reset && in_effect ) {
|
||
quiet_on_error = saved_state;
|
||
in_effect = 0;
|
||
} else if (!reset && !in_effect ) {
|
||
saved_state = quiet_on_error;
|
||
in_effect = 1;
|
||
}
|
||
}
|
||
|
||
|
||
void Enable_Error(void) {
|
||
save_error_state(0);
|
||
quiet_on_error = 0;
|
||
}
|
||
|
||
void Disable_Error(void) {
|
||
save_error_state(0);
|
||
quiet_on_error = 1;
|
||
}
|
||
|
||
void Restore_Error(void) {
|
||
quiet_on_error = 0; /* the default is to output errors */
|
||
save_error_state(1);
|
||
}
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: Module_Error **
|
||
** **
|
||
** Description: Error handling for the modules package **
|
||
** **
|
||
** First Edition: 95/08/06 **
|
||
** **
|
||
** Parameters: ErrType error_type Type of the error **
|
||
** char *module Affected module **
|
||
** int lineo Line number **
|
||
** ... Argument list **
|
||
** **
|
||
** Result: ErrCode OK No error **
|
||
** PROBLEM Problem. Program may **
|
||
** continue running **
|
||
** ERROR Caller should try to **
|
||
** exit gracefully **
|
||
** **
|
||
** Attached Globals: **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
int Module_Error( ErrType error_type,
|
||
char *module,
|
||
int lineno,
|
||
... )
|
||
{
|
||
int listsize = ARGLIST_SIZE, /** Initial size of the argu-**/
|
||
/** ment list **/
|
||
argc = 0; /** Actual number of args **/
|
||
char **argv, /** Argument array **/
|
||
*arg; /** A single argument **/
|
||
va_list parptr; /** Varargs scan pointer **/
|
||
ErrTransTab *TransPtr; /** Error transtab entry **/
|
||
ErrMeasr *MeasPtr; /** Measurement pointer **/
|
||
ErrCode ret_code;
|
||
int NoArgs = (error_type == ERR_ALLOC);
|
||
|
||
if( quiet_on_error ) return OK; /* do nothing - just OK */
|
||
|
||
/**
|
||
** Argument check
|
||
**/
|
||
if( NO_ERR_VERBOSE == error_type && !sw_verbose)
|
||
return( OK);
|
||
|
||
if( !module)
|
||
module = unknown;
|
||
|
||
/**
|
||
** Build the argument array at first
|
||
**/
|
||
|
||
if( NULL == (argv = (char **) malloc( listsize * sizeof( char *)))) {
|
||
module = module_name;
|
||
error_type = ERR_ALLOC;
|
||
NoArgs = 1;
|
||
}
|
||
|
||
va_start( parptr, lineno);
|
||
while( !NoArgs && (NULL != (arg = va_arg( parptr, char *)))) {
|
||
|
||
/**
|
||
** Conditionally realloc
|
||
**/
|
||
while( argc >= listsize) {
|
||
listsize += ARGLIST_SIZE;
|
||
if( NULL == (argv = (char **) realloc( argv,
|
||
listsize * sizeof(char *)))) {
|
||
module = module_name;
|
||
error_type = ERR_ALLOC;
|
||
NoArgs = 1;
|
||
break;
|
||
}
|
||
}
|
||
|
||
argv[ argc++] = arg;
|
||
|
||
} /** while **/
|
||
|
||
if( NO_ERR_VERBOSE == error_type && !argc)
|
||
return( OK);
|
||
|
||
/**
|
||
** Locate the error translation table entry according to the
|
||
** passed error type
|
||
**/
|
||
if( NULL == (TransPtr = ErrorLookup( error_type))) {
|
||
if( argv)
|
||
null_free((void *) &argv);
|
||
return( ErrorLogger( ERR_INVAL, LOC, (sprintf( buffer, "%d",
|
||
error_type), buffer), NULL));
|
||
}
|
||
|
||
/**
|
||
** Now locate the assigned error weight ...
|
||
**/
|
||
|
||
if( NULL == (MeasPtr = MeasLookup( TransPtr->error_weight))) {
|
||
if( argv)
|
||
null_free((void *) &argv);
|
||
argc = 0;
|
||
return( ErrorLogger( ERR_INVWGHT, LOC, (sprintf( buffer, "%d",
|
||
TransPtr->error_weight), buffer), NULL));
|
||
}
|
||
|
||
/**
|
||
** Use the return code as defined for the current user level
|
||
**/
|
||
switch( sw_userlvl) {
|
||
case UL_NOVICE:
|
||
ret_code = MeasPtr->ret_nov;
|
||
break;
|
||
case UL_ADVANCED:
|
||
ret_code = MeasPtr->ret_adv;
|
||
break;
|
||
case UL_EXPERT:
|
||
ret_code = MeasPtr->ret_exp;
|
||
break;
|
||
}
|
||
|
||
/**
|
||
** Print the error message
|
||
**/
|
||
if( TransPtr->error_weight <= WGHT_TRACE || ret_code != OK)
|
||
if( !FlushError( error_type, module, lineno, TransPtr->error_weight,
|
||
MeasPtr->message, TransPtr->messages, argc, argv)) {
|
||
if( argv)
|
||
null_free((void *) &argv);
|
||
argc = 0;
|
||
return( ErrorLogger( ERR_INTERRL, LOC, NULL));
|
||
}
|
||
|
||
/**
|
||
** Return to the caller ... conditionally ...
|
||
**/
|
||
if( WARN == ret_code)
|
||
ret_code = OK;
|
||
|
||
if( argv)
|
||
null_free((void *) &argv);
|
||
argc = 0;
|
||
|
||
if( ret_code > ERROR)
|
||
exit( ret_code);
|
||
|
||
return( ret_code);
|
||
} /** End of 'Module_Error' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: ErrorLookup **
|
||
** **
|
||
** Description: Look up the passed error type in the translation tab.**
|
||
** **
|
||
** First Edition: 95/08/06 **
|
||
** **
|
||
** Parameters: ErrType error_type Type of the error **
|
||
** **
|
||
** Result: ErrTransTab* NULL Not found **
|
||
** else Pointer to the acc. entry **
|
||
** **
|
||
** Attached Globals: **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static ErrTransTab *ErrorLookup( ErrType error_type )
|
||
{
|
||
ErrTransTab *low, *mid, *high, *save; /** Search pointers **/
|
||
|
||
/**
|
||
** Init serach pointers
|
||
**/
|
||
|
||
low = TransTab;
|
||
high = TransTab + (sizeof( TransTab) / sizeof( TransTab[0]) -1);
|
||
mid = (ErrTransTab *) NULL;
|
||
|
||
/**
|
||
** Search loop
|
||
**/
|
||
|
||
while( low < high) {
|
||
|
||
save = mid;
|
||
mid = low + ((high - low) / 2);
|
||
if( save == mid)
|
||
low = mid = high; /** Just for safety ... **/
|
||
|
||
if( mid->error_type < error_type ) {
|
||
low = mid;
|
||
} else if( mid->error_type > error_type ) {
|
||
high = mid;
|
||
} else
|
||
return( mid); /** Yep! Got it! **/
|
||
|
||
} /** while **/
|
||
|
||
/**
|
||
** Maybe the loop has been finished before the comparison took place
|
||
** (low == high) and hit!
|
||
**/
|
||
|
||
if( mid->error_type == error_type )
|
||
return( mid); /** Yep! Got it! **/
|
||
|
||
/**
|
||
** If this point is reached, nothing has been found ...
|
||
**/
|
||
|
||
return( NULL);
|
||
|
||
} /** End of 'ErrorLookup' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: MeasLookup **
|
||
** **
|
||
** Description: Look up the passed error weight in the measurement **
|
||
** table **
|
||
** **
|
||
** First Edition: 95/08/06 **
|
||
** **
|
||
** Parameters: ErrWeights weigth Weight of the error **
|
||
** **
|
||
** Result: ErrMeasr* NULL Not found **
|
||
** else Pointer to the acc. entry **
|
||
** **
|
||
** Attached Globals: **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static ErrMeasr *MeasLookup( ErrWeights weigth )
|
||
{
|
||
ErrMeasr *low, *mid, *high, *save; /** Search pointers **/
|
||
|
||
/**
|
||
** Init serach pointers
|
||
**/
|
||
|
||
low = Measurements;
|
||
high = Measurements + (sizeof( Measurements) / sizeof( Measurements[0]) -1);
|
||
save = (ErrMeasr *) NULL;
|
||
mid = (ErrMeasr *) NULL;
|
||
|
||
/**
|
||
** Search loop
|
||
**/
|
||
|
||
while( low < high) {
|
||
|
||
save = mid;
|
||
mid = low + ((high - low) / 2);
|
||
if( save == mid)
|
||
low = mid = high; /** Just to be sure ... **/
|
||
|
||
if( mid->error_weight < weigth ) {
|
||
low = mid;
|
||
} else if( mid->error_weight > weigth ) {
|
||
high = mid;
|
||
} else
|
||
return( mid); /** Yep! Got it! **/
|
||
|
||
} /** while **/
|
||
|
||
/**
|
||
** Maybe the loop has been finished before the comparison took place
|
||
** (low == high) and hit!
|
||
**/
|
||
|
||
if( mid->error_weight == weigth )
|
||
return( mid); /** Yep! Got it! **/
|
||
|
||
/**
|
||
** If this point is reached, nothing has been found ...
|
||
**/
|
||
|
||
return( NULL);
|
||
|
||
} /** End of 'MeasLookup' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: FlushError **
|
||
** **
|
||
** Description: Print the error message. Decide which facility to **
|
||
** use and schedule the according logger routine **
|
||
** **
|
||
** First Edition: 95/12/21 **
|
||
** **
|
||
** Parameters: ErrType Type Error type as passed **
|
||
** char *module Module name **
|
||
** int lineno Line number **
|
||
** ErrWeights Weight Error Weight **
|
||
** char *WeightMsg Printable Weight **
|
||
** char *ErrMsgs Error message **
|
||
** int argc Number of arguments **
|
||
** char **argv Argument array **
|
||
** **
|
||
** Result: int 1 Everything OK **
|
||
** 0 Error occured while printing **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static int FlushError( ErrType Type,
|
||
char *module,
|
||
int lineno,
|
||
ErrWeights Weight,
|
||
char *WeightMsg,
|
||
char *ErrMsgs,
|
||
int argc,
|
||
char **argv)
|
||
{
|
||
char *facilities, *buffer;
|
||
char *fac;
|
||
FILE *facfp;
|
||
char *errmsg_buffer;
|
||
int fac_alloc = 0;
|
||
|
||
/**
|
||
** get the error facilities at first. If there isn't any, we may
|
||
** return on success immediatelly.
|
||
**/
|
||
if((char *) NULL == (facilities = GetFacility( Weight)))
|
||
goto success0;
|
||
|
||
/**
|
||
** PANIC and FATAL error messages ought to be on stderr at least!
|
||
**/
|
||
if( WGHT_FATAL == Weight || WGHT_PANIC == Weight)
|
||
if( !strstr( facilities, _stderr)) {
|
||
|
||
if((char *) NULL == (buffer = stringer(NULL,0,
|
||
_stderr,":", facilities, NULL))) {
|
||
ErrorLogger( ERR_STRING, LOC, NULL);
|
||
goto unwind0;
|
||
}
|
||
|
||
facilities = buffer;
|
||
fac_alloc = 1;
|
||
}
|
||
|
||
/**
|
||
** Print the error message into the buffer
|
||
**/
|
||
if((char *) NULL == (errmsg_buffer = stringer(NULL, ERR_BUFSIZE, NULL))) {
|
||
ErrorLogger( ERR_ALLOC, LOC, NULL);
|
||
goto unwind1;
|
||
}
|
||
|
||
/**
|
||
** In case of verbosity, the first argument is the ErrMsgs format string
|
||
**/
|
||
if( WGHT_VERBOSE == Weight) {
|
||
ErrMsgs = *argv++;
|
||
--argc;
|
||
}
|
||
|
||
if( WGHT_TRACE == Weight)
|
||
Print_Tracing( errmsg_buffer, lineno, argc, argv);
|
||
else if( !PrintError( errmsg_buffer, Type, module, lineno, Weight,
|
||
WeightMsg, ErrMsgs, argc, argv))
|
||
goto unwind2;
|
||
|
||
/**
|
||
** Now tokenize the facilities string and schedule the error messge
|
||
** for every single facility
|
||
**/
|
||
for( fac = strtok( facilities, ":");
|
||
fac;
|
||
fac = strtok( (char *) NULL, ":") ) {
|
||
|
||
/**
|
||
** Check for filenames. Two specials are defined: stderr and stdout
|
||
** Otherwise filenames are expected to begin on '.' or '/'.
|
||
** Everthing not recognized as a filename is assumed to be a
|
||
** syslog facility
|
||
** 'null' and 'none' are known as 'no logging'
|
||
**/
|
||
if( !strcmp( fac, _null) || !strcmp( fac, _none))
|
||
continue;
|
||
|
||
else if( !strcmp( fac, _stderr))
|
||
fprintf( stderr, "%s", errmsg_buffer);
|
||
|
||
else if( !strcmp( fac, _stdout))
|
||
fprintf( stdout, "%s", errmsg_buffer);
|
||
|
||
/**
|
||
** Syslog
|
||
**/
|
||
else if( '.' != *fac && '/' != *fac) {
|
||
#if defined(HAVE_SYSLOG) && defined(WITH_LOGGING)
|
||
int syslog_fac, syslog_lvl;
|
||
|
||
if( CheckFacility( fac, &syslog_fac, &syslog_lvl)) {
|
||
openlog( "modulecmd", LOG_PID, syslog_fac);
|
||
setlogmask( LOG_UPTO( syslog_lvl));
|
||
syslog( (syslog_fac | syslog_lvl), "%s", errmsg_buffer);
|
||
closelog();
|
||
|
||
/**
|
||
** Invalid facilities ... take care not to end up in
|
||
** infinite loops
|
||
**/
|
||
} else if( Type == ERR_INVFAC ||
|
||
OK == ErrorLogger( ERR_INVFAC, LOC, fac, NULL))
|
||
continue;
|
||
|
||
#else
|
||
# ifdef SYSLOG_DIR
|
||
/* this is an intential memory leak */
|
||
buffer = stringer(NULL,0, SYSLOG_DIR, "/", fac);
|
||
fac = buffer;
|
||
# endif
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
** Custom files ...
|
||
** This may result from the syslog part above
|
||
**/
|
||
if( '.' == *fac || '/' == *fac) {
|
||
if((FILE *) NULL == (facfp = fopen( fac, "a"))) {
|
||
|
||
if( WGHT_PANIC == Weight) /** Avoid endless loops! **/
|
||
goto unwind2;
|
||
|
||
/**
|
||
** Invalid facilities ... take care not to end up in
|
||
** infinite loops
|
||
**/
|
||
if( Type == ERR_INVFAC ||
|
||
OK == ErrorLogger( ERR_INVFAC, LOC, fac, NULL))
|
||
continue;
|
||
else
|
||
goto unwind2;
|
||
}
|
||
|
||
fprintf( facfp, "%s", errmsg_buffer);
|
||
|
||
if( EOF == fclose( facfp))
|
||
if( OK != ErrorLogger( ERR_CLOSE, LOC, fac, NULL))
|
||
goto unwind2;
|
||
|
||
}
|
||
} /** for **/
|
||
|
||
/**
|
||
** Return on success
|
||
**/
|
||
null_free((void *) &errmsg_buffer);
|
||
if( fac_alloc)
|
||
null_free((void *) &facilities);
|
||
success0:
|
||
return( 1); /** -------- EXIT (SUCCESS) -------> **/
|
||
|
||
unwind2:
|
||
null_free((void *) &errmsg_buffer);
|
||
unwind1:
|
||
if( fac_alloc)
|
||
null_free((void *) &facilities);
|
||
unwind0:
|
||
return( 0); /** -------- EXIT (FAILURE) -------> **/
|
||
|
||
} /** End of 'FlushError' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: GetFacility **
|
||
** **
|
||
** Description: Get the log facility according to the passed error **
|
||
** weight **
|
||
** **
|
||
** First Edition: 95/12/21 **
|
||
** **
|
||
** Parameters: ErrWeights Weight Error Weight **
|
||
** **
|
||
** Result: char* NULL No facility found **
|
||
** Otherwise Pointer to the colon separa- **
|
||
** ted facility string **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static char *GetFacility( ErrWeights Weight)
|
||
{
|
||
ErrFacilities *facility;
|
||
|
||
/**
|
||
** Get the facility table entry at first
|
||
**/
|
||
if( !(facility = GetFacility_sub( Weight)))
|
||
return((char *) NULL);
|
||
|
||
/**
|
||
** Now we've got two possibilities:
|
||
** First of all there may be a custom facilitiy defined
|
||
** Otherwise the default facility is to be returned now
|
||
**/
|
||
return( facility->facility ? facility->facility : facility->def_facility);
|
||
|
||
} /** End of 'GetFacility' **/
|
||
|
||
static ErrFacilities *GetFacility_sub( ErrWeights Weight)
|
||
{
|
||
ErrFacilities *low, *mid, *high, *save;
|
||
char buffer[ 20];
|
||
|
||
/**
|
||
** Binary search for the passed facility in the Facilities table.
|
||
** This requires the table to be sorted on ascending error weight
|
||
**/
|
||
low = Facilities;
|
||
high = Facilities + (sizeof( Facilities) / sizeof( Facilities[0]));
|
||
save = (ErrFacilities *) NULL;
|
||
mid = (ErrFacilities *) NULL;
|
||
|
||
while( low < high) {
|
||
save = mid;
|
||
mid = low + ((high - low) / 2);
|
||
if( save == mid)
|
||
low = mid = high; /** Just to be sure ... **/
|
||
|
||
if( mid->Weight > Weight)
|
||
high = mid;
|
||
else if( mid->Weight < Weight)
|
||
low = mid;
|
||
else
|
||
break; /** found! **/
|
||
}
|
||
|
||
/**
|
||
** We have to check, if we've found something or if there's an internal
|
||
** error (wrong weight)
|
||
**/
|
||
if( mid->Weight != Weight) {
|
||
if( OK == ErrorLogger( ERR_INVWGHT, LOC, (sprintf( buffer, "%d",
|
||
Weight), buffer), NULL))
|
||
return( NULL);
|
||
}
|
||
|
||
return( mid);
|
||
|
||
} /** End of 'GetFacility_sub' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: CheckFacility **
|
||
** **
|
||
** Description: Check the passwd string to be a valid combination **
|
||
** of <syslog_facility>.<syslog_level> **
|
||
** **
|
||
** First Edition: 95/12/21 **
|
||
** **
|
||
** Parameters: char *string Input facility string **
|
||
** int *facility Buffer for the real facility **
|
||
** int *level Buffer for the real level **
|
||
** **
|
||
** Result: int 1 Success **
|
||
** 0 Failure. String not valid **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
int CheckFacility( char *string, int *facility, int *level)
|
||
{
|
||
char *s, *buf;
|
||
int x;
|
||
|
||
/**
|
||
** We do not want to change the strings ... so allocate a buffer here
|
||
**/
|
||
if((char *) NULL == (buf = stringer(NULL,0, string,NULL)))
|
||
if( OK == ErrorLogger( ERR_STRING, LOC, NULL))
|
||
goto unwind0;
|
||
|
||
/**
|
||
** We cannot use strtok here, because there's one initialized in an
|
||
** outter loop!
|
||
**/
|
||
for( s=buf; s && *s && *s != '.'; s++);
|
||
if( !s || !*s)
|
||
goto unwind1;
|
||
*s = '\0';
|
||
|
||
/**
|
||
** This should be the facility
|
||
**/
|
||
if( -1 == (x = scan_facility( buf, facility_names,
|
||
(sizeof( facility_names) / sizeof( facility_names[0])) )))
|
||
goto unwind1;
|
||
*facility = x;
|
||
|
||
/**
|
||
** This should be the level
|
||
**/
|
||
if( -1 == (x = scan_facility( ++s, level_names,
|
||
(sizeof( level_names) / sizeof( level_names[0])) )))
|
||
goto unwind1;
|
||
*level = x;
|
||
|
||
/**
|
||
** Success
|
||
**/
|
||
null_free((void *) &buf);
|
||
return( 1); /** -------- EXIT (SUCCESS) -------> **/
|
||
|
||
unwind1:
|
||
null_free((void *) &buf);
|
||
unwind0:
|
||
return( 0); /** -------- EXIT (FAILURE) -------> **/
|
||
|
||
} /** End of 'CheckFacility' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: scan_facility **
|
||
** **
|
||
** Description: Scan the passed facility names table for the given **
|
||
** string and pass back the assigned token **
|
||
** **
|
||
** First Edition: 95/12/21 **
|
||
** **
|
||
** Parameters: char *s String to be checked **
|
||
** FacilityNames *table Table of valid names and **
|
||
** tokens **
|
||
** int size Size of the table **
|
||
** **
|
||
** Result: int -1 name not found in the table **
|
||
** Otherwise Assigned token **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static int scan_facility( char *s, FacilityNames *table, int size)
|
||
{
|
||
FacilityNames *low, *mid, *high, *save;
|
||
|
||
low = table;
|
||
high = table + size;
|
||
save = (FacilityNames *) NULL;
|
||
|
||
while( low < high) {
|
||
int x; /** Have to use this, because strcmp will **/
|
||
/** not return -1 and 1 on Solaris 2.x **/
|
||
save = mid;
|
||
mid = low + ((high -low) / 2);
|
||
if( save == mid)
|
||
low = mid = high; /** To prevent endless loops **/
|
||
|
||
x = strcmp( mid->name, s);
|
||
|
||
if( x < 0 )
|
||
low = mid;
|
||
else if( x > 0)
|
||
high = mid;
|
||
else
|
||
return( mid->token);
|
||
|
||
} /** while **/
|
||
|
||
return( !strcmp( mid->name, s) ? mid->token : -1 );
|
||
|
||
} /** End of 'scan_facility' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: GetFacilityPtr **
|
||
** **
|
||
** Description: Scan the passed facility names table for the given **
|
||
** string and pass back the assigned token **
|
||
** **
|
||
** First Edition: 95/12/21 **
|
||
** **
|
||
** Parameters: char *facility Name of the facility **
|
||
** **
|
||
** Result: char** NULL Invalid facility name **
|
||
** Otherwise Pointer to the facilty string**
|
||
** reference **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
char **GetFacilityPtr( char *facility)
|
||
{
|
||
int i, len;
|
||
ErrMeasr *measptr;
|
||
char *buf, *s, *t;
|
||
ErrFacilities *facptr;
|
||
|
||
/**
|
||
** Try to figure out the error weight at first
|
||
** Need the given weight in upper case for this
|
||
**/
|
||
len = strlen( facility);
|
||
|
||
if((char *) NULL == (buf = stringer(NULL, 0, facility, NULL)))
|
||
if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL))
|
||
goto unwind0;
|
||
|
||
for( t = buf; *t; ++t) *t = toupper(*t);
|
||
|
||
/**
|
||
** Now look up the measurements table for the uppercase weight
|
||
**/
|
||
i = sizeof( Measurements) / sizeof( Measurements[ 0]);
|
||
measptr = Measurements;
|
||
|
||
while( i) {
|
||
if( !strncmp( measptr->message, buf, len))
|
||
break;
|
||
i--; measptr++;
|
||
}
|
||
|
||
null_free((void *) &buf);
|
||
|
||
if( !i) /** not found **/
|
||
goto unwind0;
|
||
|
||
/**
|
||
** Now get the facility table entry
|
||
**/
|
||
|
||
if((ErrFacilities *) NULL == (facptr = GetFacility_sub(
|
||
measptr->error_weight))) {
|
||
ErrorLogger( ERR_INVWGHT_WARN, LOC, facility, NULL);
|
||
goto unwind0;
|
||
}
|
||
|
||
/**
|
||
** Got it ... return the desired pointer
|
||
**/
|
||
return( &facptr->facility); /** -------- EXIT (RESULT) -------> **/
|
||
|
||
unwind0:
|
||
return((char **) NULL); /** -------- EXIT (FAILURE) -------> **/
|
||
|
||
} /** End of 'GetFacilityPtr' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: PrintError **
|
||
** **
|
||
** Description: Print the error message **
|
||
** **
|
||
** First Edition: 95/08/06 **
|
||
** **
|
||
** Parameters: char *errbuffer Buffer to hold the **
|
||
** error messge **
|
||
** ErrType Type Error type as passed **
|
||
** char *module Module name **
|
||
** int lineno Line number **
|
||
** ErrWeights Weight Error Weight **
|
||
** char *WeightMsg Printable Weight **
|
||
** char *ErrMsgs Error message **
|
||
** int argc Number of arguments **
|
||
** char **argv Argument array **
|
||
** **
|
||
** Result: int 1 Everything OK **
|
||
** 0 Error occured while printing **
|
||
** **
|
||
** Notes: According to the error type, the passed module and line num- **
|
||
** ber will be handled as a module-file related one or depending**
|
||
** on the packages source code: **
|
||
** **
|
||
** src -> ERR_IN_MODULEFILE -> modulefile -> ERR_INTERNAL -> src**
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static int PrintError( char *errbuffer,
|
||
ErrType Type,
|
||
char *module,
|
||
int lineno,
|
||
ErrWeights Weight,
|
||
char *WeightMsg,
|
||
char *ErrMsgs,
|
||
int argc,
|
||
char **argv)
|
||
{
|
||
char *error_string;
|
||
|
||
/**
|
||
** Build the error string at first. Note - we cannot alloc memory any
|
||
** more!
|
||
**/
|
||
if( ERR_ALLOC == Type)
|
||
error_string = ErrMsgs;
|
||
else
|
||
if( NULL == (error_string = ErrorString( ErrMsgs, argc, argv)))
|
||
return( 0);
|
||
|
||
/**
|
||
** Print
|
||
**/
|
||
|
||
if( ERR_INTERNAL > Type && ERR_IN_MODULEFILE < Type &&
|
||
linenum && g_current_module )
|
||
|
||
sprintf( errbuffer, "%s(%s):%s:%d: %s\n", g_current_module,
|
||
(sprintf( buffer, "%d", linenum), buffer),
|
||
WeightMsg, Type, (error_string ? error_string : "") );
|
||
else
|
||
|
||
sprintf( errbuffer, "%s(%s):%s:%d: %s\n", (module ? module : "??"),
|
||
( lineno ? (sprintf( buffer, "%d", lineno), buffer) : "??" ),
|
||
WeightMsg, Type, (error_string ? error_string : "") );
|
||
|
||
/**
|
||
** Success
|
||
**/
|
||
return( 1);
|
||
|
||
} /** End of 'PrintError' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: ErrorString **
|
||
** **
|
||
** Description: Print the error message **
|
||
** **
|
||
** First Edition: 95/08/06 **
|
||
** **
|
||
** Parameters: char *ErrMsgs Error message **
|
||
** int argc Number of arguments **
|
||
** char **argv Argument array **
|
||
** **
|
||
** Result: char* NULL Parse or alloc error **
|
||
** else Pointer to the error string **
|
||
** **
|
||
** Attached Globals: - **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static char *ErrorString( char *ErrMsgs,
|
||
int argc,
|
||
char **argv)
|
||
{
|
||
char *s; /** Insertion pointer **/
|
||
int len = 0; /** Current length **/
|
||
int backslash = 0; /** backslash found ? **/
|
||
|
||
if( !ErrMsgs)
|
||
return( NULL);
|
||
|
||
/**
|
||
** Allocate memory if neccessary
|
||
**/
|
||
if( !error_line)
|
||
if((char *) NULL ==(error_line = stringer(NULL,strsize = ERR_LINELEN,
|
||
NULL))){
|
||
ErrorLogger( ERR_STRING, LOC, NULL);
|
||
return( NULL);
|
||
}
|
||
|
||
s = error_line;
|
||
|
||
/**
|
||
** Scan the error strings to be printed
|
||
**/
|
||
while( *ErrMsgs) {
|
||
|
||
/**
|
||
** Check for special characters
|
||
**/
|
||
switch( *ErrMsgs) {
|
||
case '\\': if( !backslash) {
|
||
backslash = 1;
|
||
ErrMsgs++;
|
||
continue; /** while( *ErrMsgs) **/
|
||
}
|
||
break; /** switch **/
|
||
|
||
case '$': if( !backslash) {
|
||
ErrMsgs++;
|
||
add_param( &ErrMsgs, &s, &len, argc, argv);
|
||
error_line = s - len;
|
||
continue; /** while( *ErrMsgs) **/
|
||
}
|
||
break; /** switch **/
|
||
} /** switch **/
|
||
|
||
/**
|
||
** Add a single character to the error string
|
||
**/
|
||
if( ++len >= strsize - 5) { /** 5 Bytes for safety **/
|
||
if( NULL == (error_line = (char *) realloc( error_line,
|
||
strsize += ERR_LINELEN))) {
|
||
ErrorLogger( ERR_ALLOC, LOC, NULL);
|
||
return( NULL);
|
||
}
|
||
s = error_line + len - 1;
|
||
}
|
||
|
||
*s++ = *ErrMsgs++;
|
||
backslash = 0;
|
||
|
||
} /** while( *ErrMsgs) **/
|
||
|
||
/**
|
||
** Success. Return a pointer to the newly created string
|
||
**/
|
||
*s++ = '\0';
|
||
return( error_line);
|
||
|
||
} /** End of 'ErrorString' **/
|
||
|
||
/*++++
|
||
** ** Function-Header ***************************************************** **
|
||
** **
|
||
** Function: add_param **
|
||
** **
|
||
** Description: Put an argument to the error string **
|
||
** **
|
||
** First Edition: 95/08/06 **
|
||
** **
|
||
** Parameters: char **Control Parameter control **
|
||
** char **Target Target to print to **
|
||
** int *Length Current length of the**
|
||
** output string **
|
||
** int argc Number of arguments **
|
||
** char **argv Argument array **
|
||
** **
|
||
** Result: - **
|
||
** **
|
||
** Attached Globals: - **
|
||
** **
|
||
** ************************************************************************ **
|
||
++++*/
|
||
|
||
static void add_param( char **Control,
|
||
char **Target,
|
||
int *Length,
|
||
int argc,
|
||
char **argv)
|
||
{
|
||
char *s; /** Scan pointer fot the ctrl field **/
|
||
int index, last = 0; /** parameter index **/
|
||
int len = 0; /** Parameter string length **/
|
||
|
||
/**
|
||
** Copy the current control field into the buffer
|
||
**/
|
||
|
||
for( s = buffer; **Control; (*Control)++ ) {
|
||
|
||
if( **Control == '*') {
|
||
last = argc;
|
||
continue;
|
||
} else if( **Control < '0' || **Control > '9')
|
||
break;
|
||
|
||
*s++ = **Control;
|
||
}
|
||
|
||
*s = '\0';
|
||
|
||
/**
|
||
** Has something been found ? If not, print a '$'
|
||
**/
|
||
if( s == buffer && !last) {
|
||
|
||
if( ++(*Length) >= strsize) {
|
||
if( NULL == (error_line = (char*) realloc( error_line,
|
||
strsize += ERR_LINELEN))) {
|
||
ErrorLogger( ERR_ALLOC, LOC, NULL);
|
||
return;
|
||
}
|
||
*Target = error_line + *Length - 1;
|
||
}
|
||
|
||
*(*Target++) = '$';
|
||
|
||
} else {
|
||
|
||
/**
|
||
** Something has been found. Form the parameter index at first
|
||
**/
|
||
if( s == buffer)
|
||
index = 0;
|
||
else
|
||
index = atoi( buffer) - 1;
|
||
|
||
if( !last)
|
||
last = index + 1;
|
||
if( last > argc)
|
||
last = argc;
|
||
|
||
/**
|
||
** Spool them all out
|
||
**/
|
||
while( index < last) {
|
||
|
||
len = strlen( argv[ index]);
|
||
|
||
while(( *Length + len + 1) >= strsize - 5) {
|
||
if( NULL == (error_line = (char*) realloc( error_line,
|
||
strsize += ERR_LINELEN))) {
|
||
ErrorLogger( ERR_ALLOC, LOC, NULL);
|
||
return;
|
||
}
|
||
*Target = error_line + *Length;
|
||
}
|
||
|
||
strcpy( *Target, argv[ index]);
|
||
*Target += len;
|
||
*Length += len;
|
||
|
||
index++;
|
||
|
||
} /** while **/
|
||
} /** if **/
|
||
|
||
} /** End of 'add_param' **/
|