OpenDNSSEC-enforcer 1.3.0
/build/buildd/opendnssec-1.3.0/enforcer/ksm/message.c
Go to the documentation of this file.
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 }