security/nss/lib/libpkix/pkix/util/pkix_logger.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/libpkix/pkix/util/pkix_logger.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1088 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +/*
     1.8 + * pkix_logger.c
     1.9 + *
    1.10 + * Logger Object Functions
    1.11 + *
    1.12 + */
    1.13 +
    1.14 +#include "pkix_logger.h"
    1.15 +#ifndef PKIX_ERROR_DESCRIPTION
    1.16 +#include "prprf.h"
    1.17 +#endif
    1.18 +
    1.19 +/* Global variable to keep PKIX_Logger List */
    1.20 +PKIX_List *pkixLoggers = NULL;
    1.21 +
    1.22 +/*
    1.23 + * Once the Logger has been set, for any logging related operations, we have
    1.24 + * to go through the List to find a match, and if found, issue the
    1.25 + * corresponding callback. The overhead to check for DEBUG and TRACE in each
    1.26 + * PKIX function entering and exiting is very expensive (400X), and redundant
    1.27 + * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
    1.28 + * pkixLoggers is separated into two lists based on its Loggers' trace level.
    1.29 + *
    1.30 + * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
    1.31 + * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
    1.32 + * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
    1.33 + * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
    1.34 + * pkixLoggersDebugTrace.
    1.35 + *
    1.36 + * Currently we provide five logging levels and the default setting are by:
    1.37 + *
    1.38 + *     PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
    1.39 + *     PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
    1.40 + *     WARNING is not invoked as default
    1.41 + *     PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
    1.42 + *         compilation -DPKIX_<component>DEBUG flag to turn on 
    1.43 + *     PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
    1.44 + *         level. TRACE provides duplicate information of DEBUG, but needs no
    1.45 + *         recompilation and cannot choose component. To allow application
    1.46 + *         to use DEBUG level, TRACE is put as last.
    1.47 + *
    1.48 + */
    1.49 +PKIX_List *pkixLoggersErrors = NULL;
    1.50 +PKIX_List *pkixLoggersDebugTrace = NULL;
    1.51 +
    1.52 +/* To ensure atomic update on pkixLoggers lists */
    1.53 +PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
    1.54 +
    1.55 +/* --Private-Functions-------------------------------------------- */
    1.56 +
    1.57 +/*
    1.58 + * FUNCTION: pkix_Logger_CheckErrors
    1.59 + * DESCRIPTION:
    1.60 + *
    1.61 + *  This function goes through each PKIX_Logger at "pkixLoggersList" and
    1.62 + *  checks if "maxLevel" and "logComponent" satisfies what is specified in the
    1.63 + *  PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
    1.64 + *  passes a PKIX_PL_String that is the concatenation of "message" and 
    1.65 + *  "message2" to the application for processing. 
    1.66 + *  Since this call is inserted into a handful of PKIX macros, no macros are
    1.67 + *  applied in this function, to avoid infinite recursion.
    1.68 + *  If an error occurs, this call is aborted.
    1.69 + *
    1.70 + * PARAMETERS:
    1.71 + *  "pkixLoggersList"
    1.72 + *      A list of PKIX_Loggers to be examined for invoking callback. Must be
    1.73 + *      non-NULL.
    1.74 + *  "message"
    1.75 + *      Address of "message" to be logged. Must be non-NULL.
    1.76 + *  "message2"
    1.77 + *      Address of "message2" to be concatenated and logged. May be NULL.
    1.78 + *  "logComponent"
    1.79 + *      A PKIX_UInt32 that indicates the component the message is from.
    1.80 + *  "maxLevel"
    1.81 + *      A PKIX_UInt32 that represents the level of severity of the message.
    1.82 + *  "plContext"
    1.83 + *      Platform-specific context pointer.
    1.84 + * THREAD SAFETY:
    1.85 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    1.86 + * RETURNS:
    1.87 + *  Returns NULL if the function succeeds
    1.88 + *  Returns a Fatal Error if the function fails in an unrecoverable way
    1.89 + */
    1.90 +PKIX_Error *
    1.91 +pkix_Logger_Check(
    1.92 +        PKIX_List *pkixLoggersList,
    1.93 +        const char *message,
    1.94 +        const char *message2,
    1.95 +        PKIX_ERRORCLASS logComponent,
    1.96 +        PKIX_UInt32 currentLevel,
    1.97 +        void *plContext)
    1.98 +{
    1.99 +        PKIX_Logger *logger = NULL;
   1.100 +        PKIX_List *savedPkixLoggersErrors = NULL;
   1.101 +        PKIX_List *savedPkixLoggersDebugTrace = NULL;
   1.102 +        PKIX_PL_String *formatString = NULL;
   1.103 +        PKIX_PL_String *messageString = NULL;
   1.104 +        PKIX_PL_String *message2String = NULL;
   1.105 +        PKIX_PL_String *msgString = NULL;
   1.106 +        PKIX_Error *error = NULL;
   1.107 +        PKIX_Boolean needLogging = PKIX_FALSE;
   1.108 +        PKIX_UInt32 i, length;
   1.109 +
   1.110 +        /*
   1.111 +         * We cannot use any the PKIX_ macros here, since this function is
   1.112 +         * called from some of these macros. It can create infinite recursion.
   1.113 +         */
   1.114 +
   1.115 +        if ((pkixLoggersList == NULL) || (message == NULL)) {
   1.116 +                return(NULL);
   1.117 +        }
   1.118 +
   1.119 +        /*
   1.120 +         * Disable all subsequent loggings to avoid recursion. The result is
   1.121 +         * if other thread is calling this function at the same time, there
   1.122 +         * won't be any logging because the pkixLoggersErrors and
   1.123 +         * pkixLoggersDebugTrace are set to null.
   1.124 +         * It would be nice if we provide control per thread (e.g. make
   1.125 +         * plContext threadable) then we can avoid the recursion by setting
   1.126 +         * flag at plContext. Then other thread's logging won't be affected.
   1.127 +         *
   1.128 +         * Also we need to use a reentrant Lock. Although we avoid recursion
   1.129 +         * for TRACE. When there is an ERROR occurs in subsequent call, this
   1.130 +         * function will be called.
   1.131 +         */
   1.132 +
   1.133 +        error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
   1.134 +        if (error) { return(NULL); }
   1.135 +
   1.136 +        savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
   1.137 +        pkixLoggersDebugTrace = NULL;
   1.138 +        savedPkixLoggersErrors = pkixLoggersErrors;
   1.139 +        pkixLoggersErrors = NULL;
   1.140 +
   1.141 +        /* Convert message and message2 to String */
   1.142 +        error = PKIX_PL_String_Create
   1.143 +                    (PKIX_ESCASCII, message, 0, &messageString, plContext);
   1.144 +        if (error) { goto cleanup; }
   1.145 +
   1.146 +        if (message2) {
   1.147 +                error = PKIX_PL_String_Create
   1.148 +                    (PKIX_ESCASCII, message2, 0, &message2String, plContext);
   1.149 +                if (error) { goto cleanup; }
   1.150 +                error = PKIX_PL_String_Create
   1.151 +                    (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
   1.152 +                if (error) { goto cleanup; }
   1.153 +
   1.154 +        } else {
   1.155 +                error = PKIX_PL_String_Create
   1.156 +                    (PKIX_ESCASCII, "%s", 0, &formatString, plContext);
   1.157 +                if (error) { goto cleanup; }
   1.158 +
   1.159 +        }
   1.160 +
   1.161 +        error = PKIX_PL_Sprintf
   1.162 +                    (&msgString,
   1.163 +                    plContext,
   1.164 +                    formatString,
   1.165 +                    messageString,
   1.166 +                    message2String);
   1.167 +        if (error) { goto cleanup; }
   1.168 +
   1.169 +        /* Go through the Logger list */
   1.170 +
   1.171 +        error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
   1.172 +        if (error) { goto cleanup; }
   1.173 +
   1.174 +        for (i = 0; i < length; i++) {
   1.175 +
   1.176 +                error = PKIX_List_GetItem
   1.177 +                    (pkixLoggersList,
   1.178 +                    i,
   1.179 +                    (PKIX_PL_Object **) &logger,
   1.180 +                    plContext);
   1.181 +                if (error) { goto cleanup; }
   1.182 +
   1.183 +                /* Intended logging level less or equal than the max */
   1.184 +                needLogging = (currentLevel <= logger->maxLevel);
   1.185 +
   1.186 +                if (needLogging && (logger->callback)) {
   1.187 +
   1.188 +                    /*
   1.189 +                     * We separate Logger into two lists based on log level
   1.190 +                     * but log level is not modified. We need to check here to
   1.191 +                     * avoid logging the higher log level (lower value) twice.
   1.192 +                     */
   1.193 +                    if (pkixLoggersList == pkixLoggersErrors) {
   1.194 +                            needLogging = needLogging && 
   1.195 +                                (currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
   1.196 +                    } else if (pkixLoggersList == pkixLoggersDebugTrace) {
   1.197 +                            needLogging = needLogging && 
   1.198 +                                (currentLevel > PKIX_LOGGER_LEVEL_WARNING);
   1.199 +                    }
   1.200 +                
   1.201 +                    if (needLogging) {
   1.202 +                        if (logComponent == logger->logComponent) {
   1.203 +                            needLogging = PKIX_TRUE;
   1.204 +                        } else {
   1.205 +                            needLogging = PKIX_FALSE;
   1.206 +                        }
   1.207 +                    }
   1.208 +
   1.209 +                    if (needLogging) {
   1.210 +                        error = logger->callback
   1.211 +                                (logger,
   1.212 +                                msgString,
   1.213 +                                currentLevel,
   1.214 +                                logComponent,
   1.215 +                                plContext);
   1.216 +                        if (error) { goto cleanup; }
   1.217 +                    }
   1.218 +                }
   1.219 +
   1.220 +                error = PKIX_PL_Object_DecRef
   1.221 +                        ((PKIX_PL_Object *)logger, plContext);
   1.222 +                logger = NULL;
   1.223 +                if (error) { goto cleanup; }
   1.224 +
   1.225 +        }
   1.226 +
   1.227 +cleanup:
   1.228 +
   1.229 +        if (formatString) {
   1.230 +                error = PKIX_PL_Object_DecRef
   1.231 +                        ((PKIX_PL_Object *)formatString, plContext);
   1.232 +        }
   1.233 +
   1.234 +        if (messageString) {
   1.235 +                error = PKIX_PL_Object_DecRef
   1.236 +                         ((PKIX_PL_Object *)messageString, plContext);
   1.237 +        }
   1.238 +
   1.239 +        if (message2String) {
   1.240 +                error = PKIX_PL_Object_DecRef
   1.241 +                        ((PKIX_PL_Object *)message2String, plContext);
   1.242 +        }
   1.243 +
   1.244 +        if (msgString) {
   1.245 +                error = PKIX_PL_Object_DecRef
   1.246 +                        ((PKIX_PL_Object *)msgString, plContext);
   1.247 +        }
   1.248 +
   1.249 +        if (logger) {
   1.250 +                error = PKIX_PL_Object_DecRef
   1.251 +                        ((PKIX_PL_Object *)logger, plContext);
   1.252 +        }
   1.253 +
   1.254 +        if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
   1.255 +                pkixLoggersErrors = savedPkixLoggersErrors;
   1.256 +        } 
   1.257 +
   1.258 +        if (pkixLoggersDebugTrace == NULL && 
   1.259 +           savedPkixLoggersDebugTrace != NULL) {
   1.260 +                pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
   1.261 +        }
   1.262 +
   1.263 +        error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
   1.264 +        if (error) { return(NULL); }
   1.265 +
   1.266 +        return(NULL);
   1.267 +}
   1.268 +
   1.269 +PKIX_Error *
   1.270 +pkix_Logger_CheckWithCode(
   1.271 +        PKIX_List *pkixLoggersList,
   1.272 +        PKIX_UInt32 errorCode,
   1.273 +        const char *message2,
   1.274 +        PKIX_ERRORCLASS logComponent,
   1.275 +        PKIX_UInt32 currentLevel,
   1.276 +        void *plContext)
   1.277 +{
   1.278 +    char error[32];
   1.279 +    char *errorString = NULL;
   1.280 +
   1.281 +    PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode");
   1.282 +#if defined PKIX_ERROR_DESCRIPTION
   1.283 +    errorString = PKIX_ErrorText[errorCode];
   1.284 +#else
   1.285 +    PR_snprintf(error, 32, "Error code: %d", errorCode);
   1.286 +    errorString = error;
   1.287 +#endif /* PKIX_ERROR_DESCRIPTION */
   1.288 +
   1.289 +    pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString,
   1.290 +                                        message2, logComponent,
   1.291 +                                        currentLevel, plContext);
   1.292 +    PKIX_RETURN(LOGGER);
   1.293 +}
   1.294 +
   1.295 +/*
   1.296 + * FUNCTION: pkix_Logger_Destroy
   1.297 + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
   1.298 + */
   1.299 +static PKIX_Error *
   1.300 +pkix_Logger_Destroy(
   1.301 +        PKIX_PL_Object *object,
   1.302 +        void *plContext)
   1.303 +{
   1.304 +        PKIX_Logger *logger = NULL;
   1.305 +
   1.306 +        PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
   1.307 +        PKIX_NULLCHECK_ONE(object);
   1.308 +
   1.309 +        /* Check that this object is a logger */
   1.310 +        PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
   1.311 +                    PKIX_OBJECTNOTLOGGER);
   1.312 +
   1.313 +        logger = (PKIX_Logger *)object;
   1.314 +
   1.315 +        /* We have a valid logger. DecRef its item and recurse on next */
   1.316 +
   1.317 +        logger->callback = NULL;
   1.318 +        PKIX_DECREF(logger->context);
   1.319 +        logger->logComponent = (PKIX_ERRORCLASS)NULL;
   1.320 +
   1.321 +cleanup:
   1.322 +
   1.323 +        PKIX_RETURN(LOGGER);
   1.324 +}
   1.325 +
   1.326 +/*
   1.327 + * FUNCTION: pkix_Logger_ToString
   1.328 + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
   1.329 + */
   1.330 +static PKIX_Error *
   1.331 +pkix_Logger_ToString(
   1.332 +        PKIX_PL_Object *object,
   1.333 +        PKIX_PL_String **pString,
   1.334 +        void *plContext)
   1.335 +{
   1.336 +        PKIX_Logger *logger = NULL;
   1.337 +        char *asciiFormat = NULL;
   1.338 +        PKIX_PL_String *formatString = NULL;
   1.339 +        PKIX_PL_String *contextString = NULL;
   1.340 +        PKIX_PL_String *componentString = NULL;
   1.341 +        PKIX_PL_String *loggerString = NULL;
   1.342 +
   1.343 +        PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
   1.344 +        PKIX_NULLCHECK_TWO(object, pString);
   1.345 +
   1.346 +        /* Check that this object is a logger */
   1.347 +        PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
   1.348 +                    PKIX_OBJECTNOTLOGGER);
   1.349 +
   1.350 +        logger = (PKIX_Logger *)object;
   1.351 +
   1.352 +        asciiFormat =
   1.353 +                "[\n"
   1.354 +                "\tLogger: \n"
   1.355 +                "\tContext:          %s\n"
   1.356 +                "\tMaximum Level:    %d\n"
   1.357 +                "\tComponent Name:   %s\n"
   1.358 +                "]\n";
   1.359 +
   1.360 +        PKIX_CHECK(PKIX_PL_String_Create
   1.361 +                    (PKIX_ESCASCII,
   1.362 +                    asciiFormat,
   1.363 +                    0,
   1.364 +                    &formatString,
   1.365 +                    plContext),
   1.366 +                    PKIX_STRINGCREATEFAILED);
   1.367 +
   1.368 +        PKIX_TOSTRING(logger->context, &contextString, plContext,
   1.369 +                PKIX_OBJECTTOSTRINGFAILED);
   1.370 +
   1.371 +        PKIX_CHECK(PKIX_PL_String_Create
   1.372 +                (PKIX_ESCASCII,
   1.373 +                (void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
   1.374 +                0,
   1.375 +                &componentString,
   1.376 +                plContext),
   1.377 +                PKIX_STRINGCREATEFAILED);
   1.378 +
   1.379 +        PKIX_CHECK(PKIX_PL_Sprintf
   1.380 +                (&loggerString,
   1.381 +                plContext,
   1.382 +                formatString,
   1.383 +                contextString,
   1.384 +                logger->maxLevel,
   1.385 +                componentString),
   1.386 +                PKIX_SPRINTFFAILED);
   1.387 +
   1.388 +        *pString = loggerString;
   1.389 +
   1.390 +cleanup:
   1.391 +
   1.392 +        PKIX_DECREF(formatString);
   1.393 +        PKIX_DECREF(contextString);
   1.394 +        PKIX_RETURN(LOGGER);
   1.395 +}
   1.396 +
   1.397 +/*
   1.398 + * FUNCTION: pkix_Logger_Equals
   1.399 + * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
   1.400 + */
   1.401 +static PKIX_Error *
   1.402 +pkix_Logger_Equals(
   1.403 +        PKIX_PL_Object *first,
   1.404 +        PKIX_PL_Object *second,
   1.405 +        PKIX_Boolean *pResult,
   1.406 +        void *plContext)
   1.407 +{
   1.408 +        PKIX_UInt32 secondType;
   1.409 +        PKIX_Boolean cmpResult;
   1.410 +        PKIX_Logger *firstLogger = NULL;
   1.411 +        PKIX_Logger *secondLogger = NULL;
   1.412 +
   1.413 +        PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
   1.414 +        PKIX_NULLCHECK_THREE(first, second, pResult);
   1.415 +
   1.416 +        /* test that first is a Logger */
   1.417 +        PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
   1.418 +                PKIX_FIRSTOBJECTNOTLOGGER);
   1.419 +
   1.420 +        /*
   1.421 +         * Since we know first is a Logger, if both references are
   1.422 +         * identical, they must be equal
   1.423 +         */
   1.424 +        if (first == second){
   1.425 +                *pResult = PKIX_TRUE;
   1.426 +                goto cleanup;
   1.427 +        }
   1.428 +
   1.429 +        /*
   1.430 +         * If second isn't a Logger, we don't throw an error.
   1.431 +         * We simply return a Boolean result of FALSE
   1.432 +         */
   1.433 +        *pResult = PKIX_FALSE;
   1.434 +        PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
   1.435 +                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
   1.436 +        if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
   1.437 +
   1.438 +        firstLogger = (PKIX_Logger *)first;
   1.439 +        secondLogger = (PKIX_Logger *)second;
   1.440 +
   1.441 +        cmpResult = PKIX_FALSE;
   1.442 +
   1.443 +        if (firstLogger->callback != secondLogger->callback) {
   1.444 +                goto cleanup;
   1.445 +        }
   1.446 +
   1.447 +        if (firstLogger->logComponent != secondLogger->logComponent) {
   1.448 +                goto cleanup;
   1.449 +        }
   1.450 +
   1.451 +        PKIX_EQUALS  
   1.452 +                (firstLogger->context,
   1.453 +                secondLogger->context,
   1.454 +                &cmpResult,
   1.455 +                plContext,
   1.456 +                PKIX_OBJECTEQUALSFAILED);
   1.457 +
   1.458 +        if (cmpResult == PKIX_FALSE) {
   1.459 +                goto cleanup;
   1.460 +        }
   1.461 +
   1.462 +        if (firstLogger->maxLevel != secondLogger->maxLevel) {
   1.463 +                goto cleanup;
   1.464 +        }
   1.465 +
   1.466 +        *pResult = cmpResult;
   1.467 +
   1.468 +cleanup:
   1.469 +
   1.470 +        PKIX_RETURN(LOGGER);
   1.471 +}
   1.472 +
   1.473 +/*
   1.474 + * FUNCTION: pkix_Logger_Hashcode
   1.475 + * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
   1.476 + */
   1.477 +static PKIX_Error *
   1.478 +pkix_Logger_Hashcode(
   1.479 +        PKIX_PL_Object *object,
   1.480 +        PKIX_UInt32 *pHashcode,
   1.481 +        void *plContext)
   1.482 +{
   1.483 +        PKIX_Logger *logger = NULL;
   1.484 +        PKIX_UInt32 hash = 0;
   1.485 +        PKIX_UInt32 tempHash = 0;
   1.486 +
   1.487 +        PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
   1.488 +        PKIX_NULLCHECK_TWO(object, pHashcode);
   1.489 +
   1.490 +        PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
   1.491 +                    PKIX_OBJECTNOTLOGGER);
   1.492 +
   1.493 +        logger = (PKIX_Logger *)object;
   1.494 +
   1.495 +        PKIX_HASHCODE(logger->context, &tempHash, plContext,
   1.496 +                PKIX_OBJECTHASHCODEFAILED);
   1.497 +
   1.498 +        hash = (((((PKIX_UInt32) logger->callback + tempHash) << 7) +
   1.499 +                logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
   1.500 +
   1.501 +        *pHashcode = hash;
   1.502 +
   1.503 +cleanup:
   1.504 +
   1.505 +        PKIX_RETURN(LOGGER);
   1.506 +}
   1.507 +
   1.508 +
   1.509 +/*
   1.510 + * FUNCTION: pkix_Logger_Duplicate
   1.511 + * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
   1.512 + */
   1.513 +static PKIX_Error *
   1.514 +pkix_Logger_Duplicate(
   1.515 +        PKIX_PL_Object *object,
   1.516 +        PKIX_PL_Object **pNewObject,
   1.517 +        void *plContext)
   1.518 +{
   1.519 +        PKIX_Logger *logger = NULL;
   1.520 +        PKIX_Logger *dupLogger = NULL;
   1.521 +
   1.522 +        PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
   1.523 +        PKIX_NULLCHECK_TWO(object, pNewObject);
   1.524 +
   1.525 +        PKIX_CHECK(pkix_CheckType
   1.526 +                    ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
   1.527 +                    PKIX_OBJECTNOTLOGGER);
   1.528 +
   1.529 +        logger = (PKIX_Logger *) object;
   1.530 +
   1.531 +        PKIX_CHECK(PKIX_PL_Object_Alloc
   1.532 +                    (PKIX_LOGGER_TYPE,
   1.533 +                    sizeof (PKIX_Logger),
   1.534 +                    (PKIX_PL_Object **)&dupLogger,
   1.535 +                    plContext),
   1.536 +                    PKIX_COULDNOTCREATELOGGEROBJECT);
   1.537 +
   1.538 +        dupLogger->callback = logger->callback;
   1.539 +        dupLogger->maxLevel = logger->maxLevel;
   1.540 +        
   1.541 +        PKIX_DUPLICATE
   1.542 +                    (logger->context,
   1.543 +                    &dupLogger->context,
   1.544 +                    plContext,
   1.545 +                    PKIX_OBJECTDUPLICATEFAILED);
   1.546 +
   1.547 +        dupLogger->logComponent = logger->logComponent;
   1.548 +
   1.549 +        *pNewObject = (PKIX_PL_Object *) dupLogger;
   1.550 +
   1.551 +cleanup:
   1.552 +
   1.553 +        if (PKIX_ERROR_RECEIVED){
   1.554 +                PKIX_DECREF(dupLogger);
   1.555 +        }
   1.556 +
   1.557 +        PKIX_RETURN(LOGGER);
   1.558 +}
   1.559 +
   1.560 +/*
   1.561 + * FUNCTION: pkix_Logger_RegisterSelf
   1.562 + * DESCRIPTION:
   1.563 + *  Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
   1.564 + * THREAD SAFETY:
   1.565 + *  Not Thread Safe - for performance and complexity reasons
   1.566 + *
   1.567 + *  Since this function is only called by PKIX_PL_Initialize, which should
   1.568 + *  only be called once, it is acceptable that this function is not
   1.569 + *  thread-safe.
   1.570 + */
   1.571 +PKIX_Error *
   1.572 +pkix_Logger_RegisterSelf(void *plContext)
   1.573 +{
   1.574 +        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
   1.575 +        pkix_ClassTable_Entry entry;
   1.576 +
   1.577 +        PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
   1.578 +
   1.579 +        entry.description = "Logger";
   1.580 +        entry.objCounter = 0;
   1.581 +        entry.typeObjectSize = sizeof(PKIX_Logger);
   1.582 +        entry.destructor = pkix_Logger_Destroy;
   1.583 +        entry.equalsFunction = pkix_Logger_Equals;
   1.584 +        entry.hashcodeFunction = pkix_Logger_Hashcode;
   1.585 +        entry.toStringFunction = pkix_Logger_ToString;
   1.586 +        entry.comparator = NULL;
   1.587 +        entry.duplicateFunction = pkix_Logger_Duplicate;
   1.588 +
   1.589 +        systemClasses[PKIX_LOGGER_TYPE] = entry;
   1.590 +
   1.591 +        PKIX_RETURN(LOGGER);
   1.592 +}
   1.593 +
   1.594 +/* --Public-Logger-Functions--------------------------------------------- */
   1.595 +
   1.596 +/*
   1.597 + * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
   1.598 + */
   1.599 +PKIX_Error *
   1.600 +PKIX_Logger_Create(
   1.601 +        PKIX_Logger_LogCallback callback,
   1.602 +        PKIX_PL_Object *loggerContext,
   1.603 +        PKIX_Logger **pLogger,
   1.604 +        void *plContext)
   1.605 +{
   1.606 +        PKIX_Logger *logger = NULL;
   1.607 +
   1.608 +        PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
   1.609 +        PKIX_NULLCHECK_ONE(pLogger);
   1.610 +
   1.611 +        PKIX_CHECK(PKIX_PL_Object_Alloc
   1.612 +                    (PKIX_LOGGER_TYPE,
   1.613 +                    sizeof (PKIX_Logger),
   1.614 +                    (PKIX_PL_Object **)&logger,
   1.615 +                    plContext),
   1.616 +                    PKIX_COULDNOTCREATELOGGEROBJECT);
   1.617 +
   1.618 +        logger->callback = callback;
   1.619 +        logger->maxLevel = 0;
   1.620 +        logger->logComponent = (PKIX_ERRORCLASS)NULL;
   1.621 +
   1.622 +        PKIX_INCREF(loggerContext);
   1.623 +        logger->context = loggerContext;
   1.624 +
   1.625 +        *pLogger = logger;
   1.626 +        logger = NULL;
   1.627 +
   1.628 +cleanup:
   1.629 +
   1.630 +        PKIX_DECREF(logger);
   1.631 +
   1.632 +        PKIX_RETURN(LOGGER);
   1.633 +}
   1.634 +
   1.635 +/*
   1.636 + * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
   1.637 + */
   1.638 +PKIX_Error *
   1.639 +PKIX_Logger_GetLogCallback(
   1.640 +        PKIX_Logger *logger,
   1.641 +        PKIX_Logger_LogCallback *pCallback,
   1.642 +        void *plContext)
   1.643 +{
   1.644 +        PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
   1.645 +        PKIX_NULLCHECK_TWO(logger, pCallback);
   1.646 +
   1.647 +        *pCallback = logger->callback;
   1.648 +
   1.649 +        PKIX_RETURN(LOGGER);
   1.650 +}
   1.651 +
   1.652 +/*
   1.653 + * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
   1.654 + */
   1.655 +PKIX_Error *
   1.656 +PKIX_Logger_GetLoggerContext(
   1.657 +        PKIX_Logger *logger,
   1.658 +        PKIX_PL_Object **pLoggerContext,
   1.659 +        void *plContext)
   1.660 +{
   1.661 +        PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
   1.662 +        PKIX_NULLCHECK_TWO(logger, pLoggerContext);
   1.663 +
   1.664 +        PKIX_INCREF(logger->context);
   1.665 +        *pLoggerContext = logger->context;
   1.666 +
   1.667 +cleanup:
   1.668 +        PKIX_RETURN(LOGGER);
   1.669 +}
   1.670 +
   1.671 +/*
   1.672 + * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
   1.673 + */
   1.674 +PKIX_Error *
   1.675 +PKIX_Logger_GetMaxLoggingLevel(
   1.676 +        PKIX_Logger *logger,
   1.677 +        PKIX_UInt32 *pLevel,
   1.678 +        void *plContext)
   1.679 +{
   1.680 +        PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
   1.681 +        PKIX_NULLCHECK_TWO(logger, pLevel);
   1.682 +
   1.683 +        *pLevel = logger->maxLevel;
   1.684 +
   1.685 +        PKIX_RETURN(LOGGER);
   1.686 +}
   1.687 +
   1.688 +/*
   1.689 + * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
   1.690 + */
   1.691 +PKIX_Error *
   1.692 +PKIX_Logger_SetMaxLoggingLevel(
   1.693 +        PKIX_Logger *logger,
   1.694 +        PKIX_UInt32 level,
   1.695 +        void *plContext)
   1.696 +{
   1.697 +        PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
   1.698 +        PKIX_NULLCHECK_ONE(logger);
   1.699 +
   1.700 +        if (level > PKIX_LOGGER_LEVEL_MAX) {
   1.701 +                PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
   1.702 +        } else {
   1.703 +                logger->maxLevel = level;
   1.704 +        }
   1.705 +
   1.706 +cleanup:
   1.707 +
   1.708 +        PKIX_RETURN(LOGGER);
   1.709 +}
   1.710 +
   1.711 +/*
   1.712 + * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
   1.713 + */
   1.714 +PKIX_Error *
   1.715 +PKIX_Logger_GetLoggingComponent(
   1.716 +        PKIX_Logger *logger,
   1.717 +        PKIX_ERRORCLASS *pComponent,
   1.718 +        void *plContext)
   1.719 +{
   1.720 +        PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
   1.721 +        PKIX_NULLCHECK_TWO(logger, pComponent);
   1.722 +
   1.723 +        *pComponent = logger->logComponent;
   1.724 +
   1.725 +        PKIX_RETURN(LOGGER);
   1.726 +}
   1.727 +
   1.728 +/*
   1.729 + * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
   1.730 + */
   1.731 +PKIX_Error *
   1.732 +PKIX_Logger_SetLoggingComponent(
   1.733 +        PKIX_Logger *logger,
   1.734 +        PKIX_ERRORCLASS component,
   1.735 +        void *plContext)
   1.736 +{
   1.737 +        PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
   1.738 +        PKIX_NULLCHECK_ONE(logger);
   1.739 +
   1.740 +        logger->logComponent = component;
   1.741 +
   1.742 +        PKIX_RETURN(LOGGER);
   1.743 +}
   1.744 +
   1.745 +
   1.746 +/*
   1.747 + * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
   1.748 + * documented as not thread-safe. However they are thread-safe now. We need
   1.749 + * the lock when accessing the logger lists.
   1.750 + */
   1.751 +
   1.752 +/*
   1.753 + * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
   1.754 + */
   1.755 +PKIX_Error *
   1.756 +PKIX_GetLoggers(
   1.757 +        PKIX_List **pLoggers,  /* list of PKIX_Logger */
   1.758 +        void *plContext)
   1.759 +{
   1.760 +        PKIX_List *list = NULL;
   1.761 +        PKIX_List *savedPkixLoggersDebugTrace = NULL;
   1.762 +        PKIX_List *savedPkixLoggersErrors = NULL;
   1.763 +        PKIX_Logger *logger = NULL;
   1.764 +        PKIX_Logger *dupLogger = NULL;
   1.765 +        PKIX_UInt32 i, length;
   1.766 +        PKIX_Boolean locked = PKIX_FALSE;
   1.767 +
   1.768 +        PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
   1.769 +        PKIX_NULLCHECK_ONE(pLoggers);
   1.770 +
   1.771 +        PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
   1.772 +                PKIX_MONITORLOCKENTERFAILED);
   1.773 +        locked = PKIX_TRUE;
   1.774 +
   1.775 +        /*
   1.776 +         * Temporarily disable DEBUG/TRACE Logging to avoid possible
   1.777 +         * deadlock:
   1.778 +         * When the Logger List is being accessed, e.g. by PKIX_ENTER or
   1.779 +         * PKIX_DECREF, pkix_Logger_Check may check whether logging
   1.780 +         * is requested, creating a deadlock situation.
   1.781 +         */
   1.782 +        savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
   1.783 +        pkixLoggersDebugTrace = NULL;
   1.784 +        savedPkixLoggersErrors = pkixLoggersErrors;
   1.785 +        pkixLoggersErrors = NULL;
   1.786 +
   1.787 +        if (pkixLoggers == NULL) {
   1.788 +                length = 0;
   1.789 +        } else {
   1.790 +                PKIX_CHECK(PKIX_List_GetLength
   1.791 +                    (pkixLoggers, &length, plContext),
   1.792 +                    PKIX_LISTGETLENGTHFAILED);
   1.793 +        }
   1.794 +
   1.795 +        /* Create a list and copy the pkixLoggers item to the list */
   1.796 +        PKIX_CHECK(PKIX_List_Create(&list, plContext),
   1.797 +                    PKIX_LISTCREATEFAILED);
   1.798 +
   1.799 +        for (i = 0; i < length; i++) {
   1.800 +
   1.801 +            PKIX_CHECK(PKIX_List_GetItem
   1.802 +                        (pkixLoggers,
   1.803 +                        i,
   1.804 +                        (PKIX_PL_Object **) &logger,
   1.805 +                        plContext),
   1.806 +                        PKIX_LISTGETITEMFAILED);
   1.807 +
   1.808 +            PKIX_CHECK(pkix_Logger_Duplicate
   1.809 +                        ((PKIX_PL_Object *)logger,
   1.810 +                        (PKIX_PL_Object **)&dupLogger,
   1.811 +                        plContext),
   1.812 +                        PKIX_LOGGERDUPLICATEFAILED);
   1.813 +
   1.814 +            PKIX_CHECK(PKIX_List_AppendItem
   1.815 +                        (list,
   1.816 +                        (PKIX_PL_Object *) dupLogger,
   1.817 +                        plContext),
   1.818 +                        PKIX_LISTAPPENDITEMFAILED);
   1.819 +
   1.820 +            PKIX_DECREF(logger);
   1.821 +            PKIX_DECREF(dupLogger);
   1.822 +        }
   1.823 +
   1.824 +        /* Set the list to be immutable */
   1.825 +        PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
   1.826 +                        PKIX_LISTSETIMMUTABLEFAILED);
   1.827 +
   1.828 +        *pLoggers = list;
   1.829 +
   1.830 +cleanup:
   1.831 +
   1.832 +        PKIX_DECREF(logger);
   1.833 +
   1.834 +        /* Restore logging capability */
   1.835 +        pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
   1.836 +        pkixLoggersErrors = savedPkixLoggersErrors;
   1.837 +
   1.838 +        if (locked) {
   1.839 +                PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
   1.840 +                        PKIX_MONITORLOCKEXITFAILED);
   1.841 +        }
   1.842 +
   1.843 +        PKIX_RETURN(LOGGER);
   1.844 +}
   1.845 +
   1.846 +/*
   1.847 + * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
   1.848 + */
   1.849 +PKIX_Error *
   1.850 +PKIX_SetLoggers(
   1.851 +        PKIX_List *loggers,  /* list of PKIX_Logger */
   1.852 +        void *plContext)
   1.853 +{
   1.854 +        PKIX_List *list = NULL;
   1.855 +        PKIX_List *savedPkixLoggersErrors = NULL;
   1.856 +        PKIX_List *savedPkixLoggersDebugTrace = NULL;
   1.857 +        PKIX_Logger *logger = NULL;
   1.858 +        PKIX_Logger *dupLogger = NULL;
   1.859 +        PKIX_Boolean locked = PKIX_FALSE;
   1.860 +        PKIX_UInt32 i, length;
   1.861 +
   1.862 +        PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
   1.863 +
   1.864 +        PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
   1.865 +                PKIX_MONITORLOCKENTERFAILED);
   1.866 +        locked = PKIX_TRUE;
   1.867 +
   1.868 +        /* Disable tracing, etc. to avoid recursion and deadlock */
   1.869 +        savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
   1.870 +        pkixLoggersDebugTrace = NULL;
   1.871 +        savedPkixLoggersErrors = pkixLoggersErrors;
   1.872 +        pkixLoggersErrors = NULL;
   1.873 +
   1.874 +        /* discard any prior loggers */
   1.875 +        PKIX_DECREF(pkixLoggers);
   1.876 +        PKIX_DECREF(savedPkixLoggersErrors);
   1.877 +        PKIX_DECREF(savedPkixLoggersDebugTrace);
   1.878 +
   1.879 +        if (loggers != NULL) {
   1.880 +
   1.881 +                PKIX_CHECK(PKIX_List_Create(&list, plContext),
   1.882 +                    PKIX_LISTCREATEFAILED);
   1.883 +
   1.884 +                PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
   1.885 +                    PKIX_LISTGETLENGTHFAILED);
   1.886 +
   1.887 +                for (i = 0; i < length; i++) {
   1.888 +
   1.889 +                    PKIX_CHECK(PKIX_List_GetItem
   1.890 +                        (loggers,
   1.891 +                        i,
   1.892 +                        (PKIX_PL_Object **) &logger,
   1.893 +                        plContext),
   1.894 +                        PKIX_LISTGETITEMFAILED);
   1.895 +
   1.896 +                    PKIX_CHECK(pkix_Logger_Duplicate
   1.897 +                        ((PKIX_PL_Object *)logger,
   1.898 +                        (PKIX_PL_Object **)&dupLogger,
   1.899 +                        plContext),
   1.900 +                        PKIX_LOGGERDUPLICATEFAILED);
   1.901 +
   1.902 +                    PKIX_CHECK(PKIX_List_AppendItem
   1.903 +                        (list,
   1.904 +                        (PKIX_PL_Object *) dupLogger,
   1.905 +                        plContext),
   1.906 +                        PKIX_LISTAPPENDITEMFAILED);
   1.907 +
   1.908 +                    /* Make two lists */
   1.909 +
   1.910 +                    /* Put in pkixLoggersErrors in any case*/
   1.911 +
   1.912 +                    if (savedPkixLoggersErrors == NULL) {
   1.913 +
   1.914 +                        PKIX_CHECK(PKIX_List_Create
   1.915 +                                (&savedPkixLoggersErrors,
   1.916 +                                plContext),
   1.917 +                                PKIX_LISTCREATEFAILED);
   1.918 +                    }
   1.919 +        
   1.920 +                    PKIX_CHECK(PKIX_List_AppendItem
   1.921 +                            (savedPkixLoggersErrors,
   1.922 +                            (PKIX_PL_Object *) dupLogger,
   1.923 +                            plContext),
   1.924 +                            PKIX_LISTAPPENDITEMFAILED);
   1.925 +
   1.926 +                    if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
   1.927 +
   1.928 +                        /* Put in pkixLoggersDebugTrace */
   1.929 +
   1.930 +                        if (savedPkixLoggersDebugTrace == NULL) {
   1.931 +
   1.932 +                            PKIX_CHECK(PKIX_List_Create
   1.933 +                                    (&savedPkixLoggersDebugTrace,
   1.934 +                                    plContext),
   1.935 +                                    PKIX_LISTCREATEFAILED);
   1.936 +                        }
   1.937 +        
   1.938 +                        PKIX_CHECK(PKIX_List_AppendItem
   1.939 +                                (savedPkixLoggersDebugTrace,
   1.940 +                                (PKIX_PL_Object *) dupLogger,
   1.941 +                                plContext),
   1.942 +                                PKIX_LISTAPPENDITEMFAILED);
   1.943 +                    }
   1.944 +                    PKIX_DECREF(logger);
   1.945 +                    PKIX_DECREF(dupLogger);
   1.946 +
   1.947 +                }
   1.948 +
   1.949 +                pkixLoggers = list;
   1.950 +        }
   1.951 +
   1.952 +cleanup:
   1.953 +
   1.954 +        if (PKIX_ERROR_RECEIVED){
   1.955 +                PKIX_DECREF(list);
   1.956 +                PKIX_DECREF(savedPkixLoggersErrors);
   1.957 +                PKIX_DECREF(savedPkixLoggersDebugTrace);
   1.958 +                pkixLoggers = NULL;
   1.959 +        }
   1.960 +
   1.961 +        PKIX_DECREF(logger);
   1.962 +
   1.963 +        /* Reenable logging capability with new lists */
   1.964 +        pkixLoggersErrors = savedPkixLoggersErrors;
   1.965 +        pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
   1.966 +
   1.967 +        if (locked) {
   1.968 +                PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
   1.969 +                        PKIX_MONITORLOCKEXITFAILED);
   1.970 +        }
   1.971 +
   1.972 +        PKIX_RETURN(LOGGER);
   1.973 +}
   1.974 +
   1.975 +/*
   1.976 + * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
   1.977 + */
   1.978 +PKIX_Error *
   1.979 +PKIX_AddLogger(
   1.980 +        PKIX_Logger *logger,
   1.981 +        void *plContext)
   1.982 +{
   1.983 +        PKIX_Logger *dupLogger = NULL;
   1.984 +        PKIX_Logger *addLogger = NULL;
   1.985 +        PKIX_List *savedPkixLoggersErrors = NULL;
   1.986 +        PKIX_List *savedPkixLoggersDebugTrace = NULL;
   1.987 +        PKIX_Boolean locked = PKIX_FALSE;
   1.988 +        PKIX_UInt32 i, length;
   1.989 +
   1.990 +        PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
   1.991 +        PKIX_NULLCHECK_ONE(logger);
   1.992 +
   1.993 +        PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
   1.994 +                PKIX_MONITORLOCKENTERFAILED);
   1.995 +        locked = PKIX_TRUE;
   1.996 +
   1.997 +        savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
   1.998 +        pkixLoggersDebugTrace = NULL;
   1.999 +        savedPkixLoggersErrors = pkixLoggersErrors;
  1.1000 +        pkixLoggersErrors = NULL;
  1.1001 +
  1.1002 +        PKIX_DECREF(savedPkixLoggersErrors);
  1.1003 +        PKIX_DECREF(savedPkixLoggersDebugTrace);
  1.1004 +
  1.1005 +        if (pkixLoggers == NULL) {
  1.1006 +
  1.1007 +            PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
  1.1008 +                    PKIX_LISTCREATEFAILED);
  1.1009 +        }
  1.1010 +
  1.1011 +        PKIX_CHECK(pkix_Logger_Duplicate
  1.1012 +                    ((PKIX_PL_Object *)logger,
  1.1013 +                    (PKIX_PL_Object **)&dupLogger,
  1.1014 +                    plContext),
  1.1015 +                    PKIX_LOGGERDUPLICATEFAILED);
  1.1016 +
  1.1017 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1018 +                    (pkixLoggers,
  1.1019 +                    (PKIX_PL_Object *) dupLogger,
  1.1020 +                    plContext),
  1.1021 +                    PKIX_LISTAPPENDITEMFAILED);
  1.1022 +
  1.1023 +        PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
  1.1024 +                    PKIX_LISTGETLENGTHFAILED);
  1.1025 +
  1.1026 +        /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
  1.1027 +        for (i = 0; i < length; i++) {
  1.1028 +
  1.1029 +                PKIX_CHECK(PKIX_List_GetItem
  1.1030 +                        (pkixLoggers,
  1.1031 +                        i,
  1.1032 +                        (PKIX_PL_Object **) &addLogger,
  1.1033 +                        plContext),
  1.1034 +                        PKIX_LISTGETITEMFAILED);
  1.1035 +
  1.1036 +
  1.1037 +                /* Put in pkixLoggersErrors */
  1.1038 +
  1.1039 +                if (savedPkixLoggersErrors == NULL) {
  1.1040 +
  1.1041 +                        PKIX_CHECK(PKIX_List_Create
  1.1042 +                                    (&savedPkixLoggersErrors,
  1.1043 +                                    plContext),
  1.1044 +                                    PKIX_LISTCREATEFAILED);
  1.1045 +                }
  1.1046 +        
  1.1047 +                PKIX_CHECK(PKIX_List_AppendItem
  1.1048 +                        (savedPkixLoggersErrors,
  1.1049 +                        (PKIX_PL_Object *) addLogger,
  1.1050 +                        plContext),
  1.1051 +                        PKIX_LISTAPPENDITEMFAILED);
  1.1052 +                            
  1.1053 +                if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
  1.1054 +
  1.1055 +                        /* Put in pkixLoggersDebugTrace */
  1.1056 +
  1.1057 +                        if (savedPkixLoggersDebugTrace == NULL) {
  1.1058 +
  1.1059 +                            PKIX_CHECK(PKIX_List_Create
  1.1060 +                                    (&savedPkixLoggersDebugTrace,
  1.1061 +                                    plContext),
  1.1062 +                                    PKIX_LISTCREATEFAILED);
  1.1063 +                        }
  1.1064 +
  1.1065 +                        PKIX_CHECK(PKIX_List_AppendItem
  1.1066 +                                (savedPkixLoggersDebugTrace,
  1.1067 +                                (PKIX_PL_Object *) addLogger,
  1.1068 +                                plContext),
  1.1069 +                                PKIX_LISTAPPENDITEMFAILED);
  1.1070 +                }
  1.1071 +
  1.1072 +                PKIX_DECREF(addLogger);
  1.1073 +
  1.1074 +        }
  1.1075 +
  1.1076 +cleanup:
  1.1077 +
  1.1078 +        PKIX_DECREF(dupLogger);
  1.1079 +        PKIX_DECREF(addLogger);
  1.1080 +
  1.1081 +        /* Restore logging capability */
  1.1082 +        pkixLoggersErrors = savedPkixLoggersErrors;
  1.1083 +        pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
  1.1084 +
  1.1085 +        if (locked) {
  1.1086 +                PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
  1.1087 +                        PKIX_MONITORLOCKEXITFAILED);
  1.1088 +        }
  1.1089 +
  1.1090 +       PKIX_RETURN(LOGGER);
  1.1091 +}

mercurial