OpenDNSSEC-enforcer 1.3.0
|
00001 /* 00002 * $Id: message.c 5320 2011-07-12 10:42:26Z jakob $ 00003 * 00004 * Copyright (c) 2008-2009 Nominet UK. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00029 /*+ 00030 * message.c - Message Functions 00031 * 00032 * Abstract: 00033 * The message module outputs error messages to the stdout. 00034 * 00035 * Modules register their message text and message code ranges with this 00036 * module. When invoked, this module searches all the registered code 00037 * ranges for one containing the status code in question, and takes the 00038 * appropriate action. 00039 -*/ 00040 00041 #include <stdarg.h> 00042 #include <stdio.h> 00043 #include <string.h> 00044 00045 #include "ksm/message.h" 00046 #include "ksm/string_util.h" 00047 00048 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) 00049 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) 00050 00051 MSG_CODEBLOCK* m_codeblock = NULL; 00052 int m_numblocks = 0; /* Count of code blocks */ 00053 00054 00055 00056 /*+ 00057 * MsgInit - Initialize Message Processing 00058 * 00059 * Description: 00060 * Initialises the message module. 00061 * 00062 * Arguments: 00063 * None. 00064 -*/ 00065 00066 void MsgInit(void) 00067 { 00068 m_codeblock = NULL; 00069 m_numblocks = 0; 00070 00071 return; 00072 } 00073 00074 00075 00076 /*+ 00077 * MsgDefaultOutput 00078 * 00079 * Description: 00080 * Default output function; outputs a line of text to stdout. 00081 * 00082 * Arguments: 00083 * const char* text 00084 * Text to output. 00085 -*/ 00086 00087 void MsgDefaultOutput(const char* text) 00088 { 00089 printf("%s\n", text); 00090 00091 return; 00092 } 00093 00094 00095 00096 /*+ 00097 * MsgNoOutput - Produce No Output 00098 * 00099 * Description: 00100 * Null output function; does not output anything. 00101 * 00102 * Arguments: 00103 * const char* text 00104 * Text (not) to output. 00105 -*/ 00106 00107 void MsgNoOutput(const char* text) 00108 { 00109 /* Unused parameter*/ 00110 (void)text; 00111 00112 return; 00113 } 00114 00115 00116 00117 /*+ 00118 * MsgRegister - Register Status Codes 00119 * 00120 * Description: 00121 * Registers a block of status codes (and associated text) with the message 00122 * module. 00123 * 00124 * Arguments: 00125 * int min 00126 * Minimum status code value in the range. 00127 * 00128 * int max 00129 * Maximum status code value in the range. 00130 * 00131 * const char** message 00132 * List of messages for each code. message[0] corresponds to 00133 * a value of "min", message 1 to "min + 1" etc. There should be 00134 * (max - min + 1) entries in this list. 00135 * 00136 * If a message entry is NULL, default text will be used. 00137 * 00138 * MSG_OUTPUT_FUNCTION output 00139 * Output function used to output the text when MsgLog is called. 00140 * If NULL, the default function (which outputs to stdout) will be 00141 * used. 00142 -*/ 00143 00144 void MsgRegister(int min, int max, const char** message, 00145 MSG_OUTPUT_FUNCTION output) 00146 { 00147 if (m_numblocks == 0) { 00148 m_codeblock = MemCalloc(1, sizeof(MSG_CODEBLOCK)); 00149 } 00150 else { 00151 m_codeblock = MemRealloc(m_codeblock, 00152 (m_numblocks + 1) * sizeof(MSG_CODEBLOCK)); 00153 } 00154 00155 /* 00156 * Fill in the code block. On the principle of "being liberal with what 00157 * you accept", allow the caller to get max and min confused. 00158 */ 00159 00160 m_codeblock[m_numblocks].min = MIN(min, max); 00161 m_codeblock[m_numblocks].max = MAX(min, max); 00162 m_codeblock[m_numblocks].message = message; 00163 m_codeblock[m_numblocks].output = output ? output : MsgDefaultOutput; 00164 00165 ++m_numblocks; 00166 00167 return; 00168 } 00169 00170 00171 00172 /*+ 00173 * MsgFindCodeBlock - Find Code Block 00174 * 00175 * Description: 00176 * Local function used to locate the code block for a particular status 00177 * code. 00178 * 00179 * Arguments: 00180 * int status 00181 * Status code for which the block is sought. 00182 * 00183 * Returns: 00184 * int 00185 * Index into the code block array of the appropriate block, or -1 00186 * if no block contains that status code. 00187 -*/ 00188 00189 int MsgFindCodeBlock(int status) 00190 { 00191 int block = -1; /* Returned code block */ 00192 int i; /* Loop counter */ 00193 00194 for (i = 0; i < m_numblocks; ++i) { 00195 if ((status >= m_codeblock[i].min) && (status <= m_codeblock[i].max)) { 00196 block = i; 00197 break; 00198 } 00199 } 00200 00201 return block; 00202 } 00203 00204 00205 00206 /*+ 00207 * MsgText - Return Error Message Text 00208 * 00209 * Description: 00210 * Returns message text associated with the status code. 00211 * 00212 * Arguments: 00213 * int status 00214 * Status code. If one of the registered message codes, the 00215 * corresponding text will be returned, otherwise it will be the text 00216 * returned by strerror. 00217 * 00218 * Returns: 00219 * const char* 00220 * Pointer to the message text. This is a pointer to internal 00221 * memory, and should not be modified or freed by the caller. 00222 * 00223 * Note that this could be NULL if strerror() felt so inclined. 00224 -*/ 00225 00226 const char* MsgText(int status) 00227 { 00228 int block; /* Code block associated with the message */ 00229 const char* text = NULL; /* Returned message */ 00230 00231 block = MsgFindCodeBlock(status); 00232 if (block >= 0) { 00233 text = m_codeblock[block].message[status - m_codeblock[block].min]; 00234 } 00235 00236 if (text == NULL) { 00237 text = strerror(status); 00238 } 00239 00240 return text; 00241 } 00242 00243 00244 00245 /*+ 00246 * MsgGetOutput - Get Current Output Function 00247 * 00248 * Description: 00249 * Returns the current output function for a particular status code range. 00250 * 00251 * Arguments: 00252 * int status 00253 * Status code within the specified range. 00254 * 00255 * Returns: 00256 * MSG_OUTPUT_FUNCTION 00257 * Pointer to the current output function. NULL if the code is not 00258 * recognised. 00259 -*/ 00260 00261 MSG_OUTPUT_FUNCTION MsgGetOutput(int status) 00262 { 00263 int block; /* Block number */ 00264 MSG_OUTPUT_FUNCTION output = NULL; /* Returned function */ 00265 00266 /* Locate the output function */ 00267 00268 block = MsgFindCodeBlock(status); 00269 if (block != -1) { 00270 output = m_codeblock[block].output; 00271 } 00272 00273 return output; 00274 } 00275 00276 00277 00278 /*+ 00279 * MsgSetOutput - Set Current Output Function 00280 * 00281 * Description: 00282 * Sets the current output function for a particular status code range. 00283 * 00284 * Arguments: 00285 * int status 00286 * Status code within the specified range. 00287 * 00288 * MSG_OUTPUT_FUNCTION output 00289 * Output function. If NULL, the default output function (which 00290 * outputs to stdout) will be used. 00291 -*/ 00292 00293 void MsgSetOutput(int status, MSG_OUTPUT_FUNCTION output) 00294 { 00295 int block; /* Block number */ 00296 00297 /* Locate the output function */ 00298 00299 block = MsgFindCodeBlock(status); 00300 if (block != -1) { 00301 m_codeblock[block].output = output ? output : MsgDefaultOutput; 00302 } 00303 00304 return; 00305 } 00306 00307 00308 00309 /*+ 00310 * MsgLog - Log Message 00311 * 00312 * Description: 00313 * Obtains the message text, substitutes any parameters, and uses the 00314 * output function associated with that status code to output it. 00315 * 00316 * Note that it uses an internal buffer to expand the message, so there is 00317 * a 4096-byte limit on the size of the message output. 00318 * 00319 * Arguments: 00320 * int status 00321 * Status code used to access a format string that is the used to 00322 * format the remaining arguments. 00323 * 00324 * ... 00325 * Arguments for the format string. 00326 * 00327 * Returns: 00328 * int 00329 * Always identical to the status passed in. This allows constructs 00330 * of the form: 00331 * 00332 * return MsgLog(error_number...) 00333 * 00334 * ... which both reports the stored error and returns the error number 00335 * to the caller. 00336 */ 00337 00338 int MsgLog(int status, ...) 00339 { 00340 va_list ap; /* Variable arguments */ 00341 int retstat; /* Return status */ 00342 00343 va_start(ap, status); 00344 retstat = MsgLogAp(status, ap); 00345 va_end(ap); 00346 00347 return retstat; 00348 } 00349 00350 00351 00352 /*+ 00353 * MsgLogAp - Log Message With Variable Arguments 00354 * 00355 * Description: 00356 * See MsgLog. 00357 * 00358 * This function is used when the variable arguments are in the form of 00359 * a variable argument list. 00360 * 00361 * Arguments: 00362 * int status 00363 * Status code. This is a format string that is used to format 00364 * the remaining arguments. 00365 * 00366 * va_list ap 00367 * Arguments for the format 00368 * 00369 * Returns: 00370 * int 00371 * See MsgLog. 00372 */ 00373 00374 int MsgLogAp(int status, va_list ap) 00375 { 00376 char buffer[4096]; /* Buffer to store the text */ 00377 const char* message; /* Message string */ 00378 MSG_OUTPUT_FUNCTION output = NULL; 00379 00380 /* Locate the text for the message and use it to format the text */ 00381 00382 message = MsgText(status); 00383 if (message) { 00384 vsnprintf(buffer, sizeof(buffer), message, ap); 00385 buffer[sizeof(buffer) - 1] = '\0'; /* Ensure trailing NULL */ 00386 00387 output = MsgGetOutput(status); 00388 } 00389 else { 00390 snprintf(buffer, sizeof(buffer), "?????: unknown message number %d", status); 00391 output = MsgDefaultOutput; 00392 } 00393 00394 /* If a function is available, use it to output the error */ 00395 00396 if (output) { 00397 (*output)(buffer); 00398 } 00399 00400 return status; 00401 } 00402 00403 00404 /*+ 00405 * MsgRundown - Rundown Message Module 00406 * 00407 * Description: 00408 * Frees up any resources allocated to the message module and resets it to 00409 * the initial conditions. 00410 * 00411 * Arguments: 00412 * None. 00413 -*/ 00414 00415 void MsgRundown(void) 00416 { 00417 if (m_codeblock) { 00418 MemFree(m_codeblock); 00419 m_codeblock = NULL; 00420 } 00421 00422 m_numblocks = 0; 00423 00424 return; 00425 }