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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4 /*
michael@0 5 * pkix_logger.c
michael@0 6 *
michael@0 7 * Logger Object Functions
michael@0 8 *
michael@0 9 */
michael@0 10
michael@0 11 #include "pkix_logger.h"
michael@0 12 #ifndef PKIX_ERROR_DESCRIPTION
michael@0 13 #include "prprf.h"
michael@0 14 #endif
michael@0 15
michael@0 16 /* Global variable to keep PKIX_Logger List */
michael@0 17 PKIX_List *pkixLoggers = NULL;
michael@0 18
michael@0 19 /*
michael@0 20 * Once the Logger has been set, for any logging related operations, we have
michael@0 21 * to go through the List to find a match, and if found, issue the
michael@0 22 * corresponding callback. The overhead to check for DEBUG and TRACE in each
michael@0 23 * PKIX function entering and exiting is very expensive (400X), and redundant
michael@0 24 * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
michael@0 25 * pkixLoggers is separated into two lists based on its Loggers' trace level.
michael@0 26 *
michael@0 27 * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
michael@0 28 * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
michael@0 29 * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
michael@0 30 * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
michael@0 31 * pkixLoggersDebugTrace.
michael@0 32 *
michael@0 33 * Currently we provide five logging levels and the default setting are by:
michael@0 34 *
michael@0 35 * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
michael@0 36 * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
michael@0 37 * WARNING is not invoked as default
michael@0 38 * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
michael@0 39 * compilation -DPKIX_<component>DEBUG flag to turn on
michael@0 40 * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
michael@0 41 * level. TRACE provides duplicate information of DEBUG, but needs no
michael@0 42 * recompilation and cannot choose component. To allow application
michael@0 43 * to use DEBUG level, TRACE is put as last.
michael@0 44 *
michael@0 45 */
michael@0 46 PKIX_List *pkixLoggersErrors = NULL;
michael@0 47 PKIX_List *pkixLoggersDebugTrace = NULL;
michael@0 48
michael@0 49 /* To ensure atomic update on pkixLoggers lists */
michael@0 50 PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
michael@0 51
michael@0 52 /* --Private-Functions-------------------------------------------- */
michael@0 53
michael@0 54 /*
michael@0 55 * FUNCTION: pkix_Logger_CheckErrors
michael@0 56 * DESCRIPTION:
michael@0 57 *
michael@0 58 * This function goes through each PKIX_Logger at "pkixLoggersList" and
michael@0 59 * checks if "maxLevel" and "logComponent" satisfies what is specified in the
michael@0 60 * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
michael@0 61 * passes a PKIX_PL_String that is the concatenation of "message" and
michael@0 62 * "message2" to the application for processing.
michael@0 63 * Since this call is inserted into a handful of PKIX macros, no macros are
michael@0 64 * applied in this function, to avoid infinite recursion.
michael@0 65 * If an error occurs, this call is aborted.
michael@0 66 *
michael@0 67 * PARAMETERS:
michael@0 68 * "pkixLoggersList"
michael@0 69 * A list of PKIX_Loggers to be examined for invoking callback. Must be
michael@0 70 * non-NULL.
michael@0 71 * "message"
michael@0 72 * Address of "message" to be logged. Must be non-NULL.
michael@0 73 * "message2"
michael@0 74 * Address of "message2" to be concatenated and logged. May be NULL.
michael@0 75 * "logComponent"
michael@0 76 * A PKIX_UInt32 that indicates the component the message is from.
michael@0 77 * "maxLevel"
michael@0 78 * A PKIX_UInt32 that represents the level of severity of the message.
michael@0 79 * "plContext"
michael@0 80 * Platform-specific context pointer.
michael@0 81 * THREAD SAFETY:
michael@0 82 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
michael@0 83 * RETURNS:
michael@0 84 * Returns NULL if the function succeeds
michael@0 85 * Returns a Fatal Error if the function fails in an unrecoverable way
michael@0 86 */
michael@0 87 PKIX_Error *
michael@0 88 pkix_Logger_Check(
michael@0 89 PKIX_List *pkixLoggersList,
michael@0 90 const char *message,
michael@0 91 const char *message2,
michael@0 92 PKIX_ERRORCLASS logComponent,
michael@0 93 PKIX_UInt32 currentLevel,
michael@0 94 void *plContext)
michael@0 95 {
michael@0 96 PKIX_Logger *logger = NULL;
michael@0 97 PKIX_List *savedPkixLoggersErrors = NULL;
michael@0 98 PKIX_List *savedPkixLoggersDebugTrace = NULL;
michael@0 99 PKIX_PL_String *formatString = NULL;
michael@0 100 PKIX_PL_String *messageString = NULL;
michael@0 101 PKIX_PL_String *message2String = NULL;
michael@0 102 PKIX_PL_String *msgString = NULL;
michael@0 103 PKIX_Error *error = NULL;
michael@0 104 PKIX_Boolean needLogging = PKIX_FALSE;
michael@0 105 PKIX_UInt32 i, length;
michael@0 106
michael@0 107 /*
michael@0 108 * We cannot use any the PKIX_ macros here, since this function is
michael@0 109 * called from some of these macros. It can create infinite recursion.
michael@0 110 */
michael@0 111
michael@0 112 if ((pkixLoggersList == NULL) || (message == NULL)) {
michael@0 113 return(NULL);
michael@0 114 }
michael@0 115
michael@0 116 /*
michael@0 117 * Disable all subsequent loggings to avoid recursion. The result is
michael@0 118 * if other thread is calling this function at the same time, there
michael@0 119 * won't be any logging because the pkixLoggersErrors and
michael@0 120 * pkixLoggersDebugTrace are set to null.
michael@0 121 * It would be nice if we provide control per thread (e.g. make
michael@0 122 * plContext threadable) then we can avoid the recursion by setting
michael@0 123 * flag at plContext. Then other thread's logging won't be affected.
michael@0 124 *
michael@0 125 * Also we need to use a reentrant Lock. Although we avoid recursion
michael@0 126 * for TRACE. When there is an ERROR occurs in subsequent call, this
michael@0 127 * function will be called.
michael@0 128 */
michael@0 129
michael@0 130 error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
michael@0 131 if (error) { return(NULL); }
michael@0 132
michael@0 133 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
michael@0 134 pkixLoggersDebugTrace = NULL;
michael@0 135 savedPkixLoggersErrors = pkixLoggersErrors;
michael@0 136 pkixLoggersErrors = NULL;
michael@0 137
michael@0 138 /* Convert message and message2 to String */
michael@0 139 error = PKIX_PL_String_Create
michael@0 140 (PKIX_ESCASCII, message, 0, &messageString, plContext);
michael@0 141 if (error) { goto cleanup; }
michael@0 142
michael@0 143 if (message2) {
michael@0 144 error = PKIX_PL_String_Create
michael@0 145 (PKIX_ESCASCII, message2, 0, &message2String, plContext);
michael@0 146 if (error) { goto cleanup; }
michael@0 147 error = PKIX_PL_String_Create
michael@0 148 (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
michael@0 149 if (error) { goto cleanup; }
michael@0 150
michael@0 151 } else {
michael@0 152 error = PKIX_PL_String_Create
michael@0 153 (PKIX_ESCASCII, "%s", 0, &formatString, plContext);
michael@0 154 if (error) { goto cleanup; }
michael@0 155
michael@0 156 }
michael@0 157
michael@0 158 error = PKIX_PL_Sprintf
michael@0 159 (&msgString,
michael@0 160 plContext,
michael@0 161 formatString,
michael@0 162 messageString,
michael@0 163 message2String);
michael@0 164 if (error) { goto cleanup; }
michael@0 165
michael@0 166 /* Go through the Logger list */
michael@0 167
michael@0 168 error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
michael@0 169 if (error) { goto cleanup; }
michael@0 170
michael@0 171 for (i = 0; i < length; i++) {
michael@0 172
michael@0 173 error = PKIX_List_GetItem
michael@0 174 (pkixLoggersList,
michael@0 175 i,
michael@0 176 (PKIX_PL_Object **) &logger,
michael@0 177 plContext);
michael@0 178 if (error) { goto cleanup; }
michael@0 179
michael@0 180 /* Intended logging level less or equal than the max */
michael@0 181 needLogging = (currentLevel <= logger->maxLevel);
michael@0 182
michael@0 183 if (needLogging && (logger->callback)) {
michael@0 184
michael@0 185 /*
michael@0 186 * We separate Logger into two lists based on log level
michael@0 187 * but log level is not modified. We need to check here to
michael@0 188 * avoid logging the higher log level (lower value) twice.
michael@0 189 */
michael@0 190 if (pkixLoggersList == pkixLoggersErrors) {
michael@0 191 needLogging = needLogging &&
michael@0 192 (currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
michael@0 193 } else if (pkixLoggersList == pkixLoggersDebugTrace) {
michael@0 194 needLogging = needLogging &&
michael@0 195 (currentLevel > PKIX_LOGGER_LEVEL_WARNING);
michael@0 196 }
michael@0 197
michael@0 198 if (needLogging) {
michael@0 199 if (logComponent == logger->logComponent) {
michael@0 200 needLogging = PKIX_TRUE;
michael@0 201 } else {
michael@0 202 needLogging = PKIX_FALSE;
michael@0 203 }
michael@0 204 }
michael@0 205
michael@0 206 if (needLogging) {
michael@0 207 error = logger->callback
michael@0 208 (logger,
michael@0 209 msgString,
michael@0 210 currentLevel,
michael@0 211 logComponent,
michael@0 212 plContext);
michael@0 213 if (error) { goto cleanup; }
michael@0 214 }
michael@0 215 }
michael@0 216
michael@0 217 error = PKIX_PL_Object_DecRef
michael@0 218 ((PKIX_PL_Object *)logger, plContext);
michael@0 219 logger = NULL;
michael@0 220 if (error) { goto cleanup; }
michael@0 221
michael@0 222 }
michael@0 223
michael@0 224 cleanup:
michael@0 225
michael@0 226 if (formatString) {
michael@0 227 error = PKIX_PL_Object_DecRef
michael@0 228 ((PKIX_PL_Object *)formatString, plContext);
michael@0 229 }
michael@0 230
michael@0 231 if (messageString) {
michael@0 232 error = PKIX_PL_Object_DecRef
michael@0 233 ((PKIX_PL_Object *)messageString, plContext);
michael@0 234 }
michael@0 235
michael@0 236 if (message2String) {
michael@0 237 error = PKIX_PL_Object_DecRef
michael@0 238 ((PKIX_PL_Object *)message2String, plContext);
michael@0 239 }
michael@0 240
michael@0 241 if (msgString) {
michael@0 242 error = PKIX_PL_Object_DecRef
michael@0 243 ((PKIX_PL_Object *)msgString, plContext);
michael@0 244 }
michael@0 245
michael@0 246 if (logger) {
michael@0 247 error = PKIX_PL_Object_DecRef
michael@0 248 ((PKIX_PL_Object *)logger, plContext);
michael@0 249 }
michael@0 250
michael@0 251 if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
michael@0 252 pkixLoggersErrors = savedPkixLoggersErrors;
michael@0 253 }
michael@0 254
michael@0 255 if (pkixLoggersDebugTrace == NULL &&
michael@0 256 savedPkixLoggersDebugTrace != NULL) {
michael@0 257 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
michael@0 258 }
michael@0 259
michael@0 260 error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
michael@0 261 if (error) { return(NULL); }
michael@0 262
michael@0 263 return(NULL);
michael@0 264 }
michael@0 265
michael@0 266 PKIX_Error *
michael@0 267 pkix_Logger_CheckWithCode(
michael@0 268 PKIX_List *pkixLoggersList,
michael@0 269 PKIX_UInt32 errorCode,
michael@0 270 const char *message2,
michael@0 271 PKIX_ERRORCLASS logComponent,
michael@0 272 PKIX_UInt32 currentLevel,
michael@0 273 void *plContext)
michael@0 274 {
michael@0 275 char error[32];
michael@0 276 char *errorString = NULL;
michael@0 277
michael@0 278 PKIX_ENTER(LOGGER, "pkix_Logger_CheckWithCode");
michael@0 279 #if defined PKIX_ERROR_DESCRIPTION
michael@0 280 errorString = PKIX_ErrorText[errorCode];
michael@0 281 #else
michael@0 282 PR_snprintf(error, 32, "Error code: %d", errorCode);
michael@0 283 errorString = error;
michael@0 284 #endif /* PKIX_ERROR_DESCRIPTION */
michael@0 285
michael@0 286 pkixErrorResult = pkix_Logger_Check(pkixLoggersList, errorString,
michael@0 287 message2, logComponent,
michael@0 288 currentLevel, plContext);
michael@0 289 PKIX_RETURN(LOGGER);
michael@0 290 }
michael@0 291
michael@0 292 /*
michael@0 293 * FUNCTION: pkix_Logger_Destroy
michael@0 294 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
michael@0 295 */
michael@0 296 static PKIX_Error *
michael@0 297 pkix_Logger_Destroy(
michael@0 298 PKIX_PL_Object *object,
michael@0 299 void *plContext)
michael@0 300 {
michael@0 301 PKIX_Logger *logger = NULL;
michael@0 302
michael@0 303 PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
michael@0 304 PKIX_NULLCHECK_ONE(object);
michael@0 305
michael@0 306 /* Check that this object is a logger */
michael@0 307 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
michael@0 308 PKIX_OBJECTNOTLOGGER);
michael@0 309
michael@0 310 logger = (PKIX_Logger *)object;
michael@0 311
michael@0 312 /* We have a valid logger. DecRef its item and recurse on next */
michael@0 313
michael@0 314 logger->callback = NULL;
michael@0 315 PKIX_DECREF(logger->context);
michael@0 316 logger->logComponent = (PKIX_ERRORCLASS)NULL;
michael@0 317
michael@0 318 cleanup:
michael@0 319
michael@0 320 PKIX_RETURN(LOGGER);
michael@0 321 }
michael@0 322
michael@0 323 /*
michael@0 324 * FUNCTION: pkix_Logger_ToString
michael@0 325 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
michael@0 326 */
michael@0 327 static PKIX_Error *
michael@0 328 pkix_Logger_ToString(
michael@0 329 PKIX_PL_Object *object,
michael@0 330 PKIX_PL_String **pString,
michael@0 331 void *plContext)
michael@0 332 {
michael@0 333 PKIX_Logger *logger = NULL;
michael@0 334 char *asciiFormat = NULL;
michael@0 335 PKIX_PL_String *formatString = NULL;
michael@0 336 PKIX_PL_String *contextString = NULL;
michael@0 337 PKIX_PL_String *componentString = NULL;
michael@0 338 PKIX_PL_String *loggerString = NULL;
michael@0 339
michael@0 340 PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
michael@0 341 PKIX_NULLCHECK_TWO(object, pString);
michael@0 342
michael@0 343 /* Check that this object is a logger */
michael@0 344 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
michael@0 345 PKIX_OBJECTNOTLOGGER);
michael@0 346
michael@0 347 logger = (PKIX_Logger *)object;
michael@0 348
michael@0 349 asciiFormat =
michael@0 350 "[\n"
michael@0 351 "\tLogger: \n"
michael@0 352 "\tContext: %s\n"
michael@0 353 "\tMaximum Level: %d\n"
michael@0 354 "\tComponent Name: %s\n"
michael@0 355 "]\n";
michael@0 356
michael@0 357 PKIX_CHECK(PKIX_PL_String_Create
michael@0 358 (PKIX_ESCASCII,
michael@0 359 asciiFormat,
michael@0 360 0,
michael@0 361 &formatString,
michael@0 362 plContext),
michael@0 363 PKIX_STRINGCREATEFAILED);
michael@0 364
michael@0 365 PKIX_TOSTRING(logger->context, &contextString, plContext,
michael@0 366 PKIX_OBJECTTOSTRINGFAILED);
michael@0 367
michael@0 368 PKIX_CHECK(PKIX_PL_String_Create
michael@0 369 (PKIX_ESCASCII,
michael@0 370 (void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
michael@0 371 0,
michael@0 372 &componentString,
michael@0 373 plContext),
michael@0 374 PKIX_STRINGCREATEFAILED);
michael@0 375
michael@0 376 PKIX_CHECK(PKIX_PL_Sprintf
michael@0 377 (&loggerString,
michael@0 378 plContext,
michael@0 379 formatString,
michael@0 380 contextString,
michael@0 381 logger->maxLevel,
michael@0 382 componentString),
michael@0 383 PKIX_SPRINTFFAILED);
michael@0 384
michael@0 385 *pString = loggerString;
michael@0 386
michael@0 387 cleanup:
michael@0 388
michael@0 389 PKIX_DECREF(formatString);
michael@0 390 PKIX_DECREF(contextString);
michael@0 391 PKIX_RETURN(LOGGER);
michael@0 392 }
michael@0 393
michael@0 394 /*
michael@0 395 * FUNCTION: pkix_Logger_Equals
michael@0 396 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
michael@0 397 */
michael@0 398 static PKIX_Error *
michael@0 399 pkix_Logger_Equals(
michael@0 400 PKIX_PL_Object *first,
michael@0 401 PKIX_PL_Object *second,
michael@0 402 PKIX_Boolean *pResult,
michael@0 403 void *plContext)
michael@0 404 {
michael@0 405 PKIX_UInt32 secondType;
michael@0 406 PKIX_Boolean cmpResult;
michael@0 407 PKIX_Logger *firstLogger = NULL;
michael@0 408 PKIX_Logger *secondLogger = NULL;
michael@0 409
michael@0 410 PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
michael@0 411 PKIX_NULLCHECK_THREE(first, second, pResult);
michael@0 412
michael@0 413 /* test that first is a Logger */
michael@0 414 PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
michael@0 415 PKIX_FIRSTOBJECTNOTLOGGER);
michael@0 416
michael@0 417 /*
michael@0 418 * Since we know first is a Logger, if both references are
michael@0 419 * identical, they must be equal
michael@0 420 */
michael@0 421 if (first == second){
michael@0 422 *pResult = PKIX_TRUE;
michael@0 423 goto cleanup;
michael@0 424 }
michael@0 425
michael@0 426 /*
michael@0 427 * If second isn't a Logger, we don't throw an error.
michael@0 428 * We simply return a Boolean result of FALSE
michael@0 429 */
michael@0 430 *pResult = PKIX_FALSE;
michael@0 431 PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
michael@0 432 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
michael@0 433 if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
michael@0 434
michael@0 435 firstLogger = (PKIX_Logger *)first;
michael@0 436 secondLogger = (PKIX_Logger *)second;
michael@0 437
michael@0 438 cmpResult = PKIX_FALSE;
michael@0 439
michael@0 440 if (firstLogger->callback != secondLogger->callback) {
michael@0 441 goto cleanup;
michael@0 442 }
michael@0 443
michael@0 444 if (firstLogger->logComponent != secondLogger->logComponent) {
michael@0 445 goto cleanup;
michael@0 446 }
michael@0 447
michael@0 448 PKIX_EQUALS
michael@0 449 (firstLogger->context,
michael@0 450 secondLogger->context,
michael@0 451 &cmpResult,
michael@0 452 plContext,
michael@0 453 PKIX_OBJECTEQUALSFAILED);
michael@0 454
michael@0 455 if (cmpResult == PKIX_FALSE) {
michael@0 456 goto cleanup;
michael@0 457 }
michael@0 458
michael@0 459 if (firstLogger->maxLevel != secondLogger->maxLevel) {
michael@0 460 goto cleanup;
michael@0 461 }
michael@0 462
michael@0 463 *pResult = cmpResult;
michael@0 464
michael@0 465 cleanup:
michael@0 466
michael@0 467 PKIX_RETURN(LOGGER);
michael@0 468 }
michael@0 469
michael@0 470 /*
michael@0 471 * FUNCTION: pkix_Logger_Hashcode
michael@0 472 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
michael@0 473 */
michael@0 474 static PKIX_Error *
michael@0 475 pkix_Logger_Hashcode(
michael@0 476 PKIX_PL_Object *object,
michael@0 477 PKIX_UInt32 *pHashcode,
michael@0 478 void *plContext)
michael@0 479 {
michael@0 480 PKIX_Logger *logger = NULL;
michael@0 481 PKIX_UInt32 hash = 0;
michael@0 482 PKIX_UInt32 tempHash = 0;
michael@0 483
michael@0 484 PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
michael@0 485 PKIX_NULLCHECK_TWO(object, pHashcode);
michael@0 486
michael@0 487 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
michael@0 488 PKIX_OBJECTNOTLOGGER);
michael@0 489
michael@0 490 logger = (PKIX_Logger *)object;
michael@0 491
michael@0 492 PKIX_HASHCODE(logger->context, &tempHash, plContext,
michael@0 493 PKIX_OBJECTHASHCODEFAILED);
michael@0 494
michael@0 495 hash = (((((PKIX_UInt32) logger->callback + tempHash) << 7) +
michael@0 496 logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
michael@0 497
michael@0 498 *pHashcode = hash;
michael@0 499
michael@0 500 cleanup:
michael@0 501
michael@0 502 PKIX_RETURN(LOGGER);
michael@0 503 }
michael@0 504
michael@0 505
michael@0 506 /*
michael@0 507 * FUNCTION: pkix_Logger_Duplicate
michael@0 508 * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
michael@0 509 */
michael@0 510 static PKIX_Error *
michael@0 511 pkix_Logger_Duplicate(
michael@0 512 PKIX_PL_Object *object,
michael@0 513 PKIX_PL_Object **pNewObject,
michael@0 514 void *plContext)
michael@0 515 {
michael@0 516 PKIX_Logger *logger = NULL;
michael@0 517 PKIX_Logger *dupLogger = NULL;
michael@0 518
michael@0 519 PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
michael@0 520 PKIX_NULLCHECK_TWO(object, pNewObject);
michael@0 521
michael@0 522 PKIX_CHECK(pkix_CheckType
michael@0 523 ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
michael@0 524 PKIX_OBJECTNOTLOGGER);
michael@0 525
michael@0 526 logger = (PKIX_Logger *) object;
michael@0 527
michael@0 528 PKIX_CHECK(PKIX_PL_Object_Alloc
michael@0 529 (PKIX_LOGGER_TYPE,
michael@0 530 sizeof (PKIX_Logger),
michael@0 531 (PKIX_PL_Object **)&dupLogger,
michael@0 532 plContext),
michael@0 533 PKIX_COULDNOTCREATELOGGEROBJECT);
michael@0 534
michael@0 535 dupLogger->callback = logger->callback;
michael@0 536 dupLogger->maxLevel = logger->maxLevel;
michael@0 537
michael@0 538 PKIX_DUPLICATE
michael@0 539 (logger->context,
michael@0 540 &dupLogger->context,
michael@0 541 plContext,
michael@0 542 PKIX_OBJECTDUPLICATEFAILED);
michael@0 543
michael@0 544 dupLogger->logComponent = logger->logComponent;
michael@0 545
michael@0 546 *pNewObject = (PKIX_PL_Object *) dupLogger;
michael@0 547
michael@0 548 cleanup:
michael@0 549
michael@0 550 if (PKIX_ERROR_RECEIVED){
michael@0 551 PKIX_DECREF(dupLogger);
michael@0 552 }
michael@0 553
michael@0 554 PKIX_RETURN(LOGGER);
michael@0 555 }
michael@0 556
michael@0 557 /*
michael@0 558 * FUNCTION: pkix_Logger_RegisterSelf
michael@0 559 * DESCRIPTION:
michael@0 560 * Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
michael@0 561 * THREAD SAFETY:
michael@0 562 * Not Thread Safe - for performance and complexity reasons
michael@0 563 *
michael@0 564 * Since this function is only called by PKIX_PL_Initialize, which should
michael@0 565 * only be called once, it is acceptable that this function is not
michael@0 566 * thread-safe.
michael@0 567 */
michael@0 568 PKIX_Error *
michael@0 569 pkix_Logger_RegisterSelf(void *plContext)
michael@0 570 {
michael@0 571 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
michael@0 572 pkix_ClassTable_Entry entry;
michael@0 573
michael@0 574 PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
michael@0 575
michael@0 576 entry.description = "Logger";
michael@0 577 entry.objCounter = 0;
michael@0 578 entry.typeObjectSize = sizeof(PKIX_Logger);
michael@0 579 entry.destructor = pkix_Logger_Destroy;
michael@0 580 entry.equalsFunction = pkix_Logger_Equals;
michael@0 581 entry.hashcodeFunction = pkix_Logger_Hashcode;
michael@0 582 entry.toStringFunction = pkix_Logger_ToString;
michael@0 583 entry.comparator = NULL;
michael@0 584 entry.duplicateFunction = pkix_Logger_Duplicate;
michael@0 585
michael@0 586 systemClasses[PKIX_LOGGER_TYPE] = entry;
michael@0 587
michael@0 588 PKIX_RETURN(LOGGER);
michael@0 589 }
michael@0 590
michael@0 591 /* --Public-Logger-Functions--------------------------------------------- */
michael@0 592
michael@0 593 /*
michael@0 594 * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
michael@0 595 */
michael@0 596 PKIX_Error *
michael@0 597 PKIX_Logger_Create(
michael@0 598 PKIX_Logger_LogCallback callback,
michael@0 599 PKIX_PL_Object *loggerContext,
michael@0 600 PKIX_Logger **pLogger,
michael@0 601 void *plContext)
michael@0 602 {
michael@0 603 PKIX_Logger *logger = NULL;
michael@0 604
michael@0 605 PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
michael@0 606 PKIX_NULLCHECK_ONE(pLogger);
michael@0 607
michael@0 608 PKIX_CHECK(PKIX_PL_Object_Alloc
michael@0 609 (PKIX_LOGGER_TYPE,
michael@0 610 sizeof (PKIX_Logger),
michael@0 611 (PKIX_PL_Object **)&logger,
michael@0 612 plContext),
michael@0 613 PKIX_COULDNOTCREATELOGGEROBJECT);
michael@0 614
michael@0 615 logger->callback = callback;
michael@0 616 logger->maxLevel = 0;
michael@0 617 logger->logComponent = (PKIX_ERRORCLASS)NULL;
michael@0 618
michael@0 619 PKIX_INCREF(loggerContext);
michael@0 620 logger->context = loggerContext;
michael@0 621
michael@0 622 *pLogger = logger;
michael@0 623 logger = NULL;
michael@0 624
michael@0 625 cleanup:
michael@0 626
michael@0 627 PKIX_DECREF(logger);
michael@0 628
michael@0 629 PKIX_RETURN(LOGGER);
michael@0 630 }
michael@0 631
michael@0 632 /*
michael@0 633 * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
michael@0 634 */
michael@0 635 PKIX_Error *
michael@0 636 PKIX_Logger_GetLogCallback(
michael@0 637 PKIX_Logger *logger,
michael@0 638 PKIX_Logger_LogCallback *pCallback,
michael@0 639 void *plContext)
michael@0 640 {
michael@0 641 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
michael@0 642 PKIX_NULLCHECK_TWO(logger, pCallback);
michael@0 643
michael@0 644 *pCallback = logger->callback;
michael@0 645
michael@0 646 PKIX_RETURN(LOGGER);
michael@0 647 }
michael@0 648
michael@0 649 /*
michael@0 650 * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
michael@0 651 */
michael@0 652 PKIX_Error *
michael@0 653 PKIX_Logger_GetLoggerContext(
michael@0 654 PKIX_Logger *logger,
michael@0 655 PKIX_PL_Object **pLoggerContext,
michael@0 656 void *plContext)
michael@0 657 {
michael@0 658 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
michael@0 659 PKIX_NULLCHECK_TWO(logger, pLoggerContext);
michael@0 660
michael@0 661 PKIX_INCREF(logger->context);
michael@0 662 *pLoggerContext = logger->context;
michael@0 663
michael@0 664 cleanup:
michael@0 665 PKIX_RETURN(LOGGER);
michael@0 666 }
michael@0 667
michael@0 668 /*
michael@0 669 * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
michael@0 670 */
michael@0 671 PKIX_Error *
michael@0 672 PKIX_Logger_GetMaxLoggingLevel(
michael@0 673 PKIX_Logger *logger,
michael@0 674 PKIX_UInt32 *pLevel,
michael@0 675 void *plContext)
michael@0 676 {
michael@0 677 PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
michael@0 678 PKIX_NULLCHECK_TWO(logger, pLevel);
michael@0 679
michael@0 680 *pLevel = logger->maxLevel;
michael@0 681
michael@0 682 PKIX_RETURN(LOGGER);
michael@0 683 }
michael@0 684
michael@0 685 /*
michael@0 686 * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
michael@0 687 */
michael@0 688 PKIX_Error *
michael@0 689 PKIX_Logger_SetMaxLoggingLevel(
michael@0 690 PKIX_Logger *logger,
michael@0 691 PKIX_UInt32 level,
michael@0 692 void *plContext)
michael@0 693 {
michael@0 694 PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
michael@0 695 PKIX_NULLCHECK_ONE(logger);
michael@0 696
michael@0 697 if (level > PKIX_LOGGER_LEVEL_MAX) {
michael@0 698 PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
michael@0 699 } else {
michael@0 700 logger->maxLevel = level;
michael@0 701 }
michael@0 702
michael@0 703 cleanup:
michael@0 704
michael@0 705 PKIX_RETURN(LOGGER);
michael@0 706 }
michael@0 707
michael@0 708 /*
michael@0 709 * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
michael@0 710 */
michael@0 711 PKIX_Error *
michael@0 712 PKIX_Logger_GetLoggingComponent(
michael@0 713 PKIX_Logger *logger,
michael@0 714 PKIX_ERRORCLASS *pComponent,
michael@0 715 void *plContext)
michael@0 716 {
michael@0 717 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
michael@0 718 PKIX_NULLCHECK_TWO(logger, pComponent);
michael@0 719
michael@0 720 *pComponent = logger->logComponent;
michael@0 721
michael@0 722 PKIX_RETURN(LOGGER);
michael@0 723 }
michael@0 724
michael@0 725 /*
michael@0 726 * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
michael@0 727 */
michael@0 728 PKIX_Error *
michael@0 729 PKIX_Logger_SetLoggingComponent(
michael@0 730 PKIX_Logger *logger,
michael@0 731 PKIX_ERRORCLASS component,
michael@0 732 void *plContext)
michael@0 733 {
michael@0 734 PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
michael@0 735 PKIX_NULLCHECK_ONE(logger);
michael@0 736
michael@0 737 logger->logComponent = component;
michael@0 738
michael@0 739 PKIX_RETURN(LOGGER);
michael@0 740 }
michael@0 741
michael@0 742
michael@0 743 /*
michael@0 744 * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
michael@0 745 * documented as not thread-safe. However they are thread-safe now. We need
michael@0 746 * the lock when accessing the logger lists.
michael@0 747 */
michael@0 748
michael@0 749 /*
michael@0 750 * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
michael@0 751 */
michael@0 752 PKIX_Error *
michael@0 753 PKIX_GetLoggers(
michael@0 754 PKIX_List **pLoggers, /* list of PKIX_Logger */
michael@0 755 void *plContext)
michael@0 756 {
michael@0 757 PKIX_List *list = NULL;
michael@0 758 PKIX_List *savedPkixLoggersDebugTrace = NULL;
michael@0 759 PKIX_List *savedPkixLoggersErrors = NULL;
michael@0 760 PKIX_Logger *logger = NULL;
michael@0 761 PKIX_Logger *dupLogger = NULL;
michael@0 762 PKIX_UInt32 i, length;
michael@0 763 PKIX_Boolean locked = PKIX_FALSE;
michael@0 764
michael@0 765 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
michael@0 766 PKIX_NULLCHECK_ONE(pLoggers);
michael@0 767
michael@0 768 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
michael@0 769 PKIX_MONITORLOCKENTERFAILED);
michael@0 770 locked = PKIX_TRUE;
michael@0 771
michael@0 772 /*
michael@0 773 * Temporarily disable DEBUG/TRACE Logging to avoid possible
michael@0 774 * deadlock:
michael@0 775 * When the Logger List is being accessed, e.g. by PKIX_ENTER or
michael@0 776 * PKIX_DECREF, pkix_Logger_Check may check whether logging
michael@0 777 * is requested, creating a deadlock situation.
michael@0 778 */
michael@0 779 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
michael@0 780 pkixLoggersDebugTrace = NULL;
michael@0 781 savedPkixLoggersErrors = pkixLoggersErrors;
michael@0 782 pkixLoggersErrors = NULL;
michael@0 783
michael@0 784 if (pkixLoggers == NULL) {
michael@0 785 length = 0;
michael@0 786 } else {
michael@0 787 PKIX_CHECK(PKIX_List_GetLength
michael@0 788 (pkixLoggers, &length, plContext),
michael@0 789 PKIX_LISTGETLENGTHFAILED);
michael@0 790 }
michael@0 791
michael@0 792 /* Create a list and copy the pkixLoggers item to the list */
michael@0 793 PKIX_CHECK(PKIX_List_Create(&list, plContext),
michael@0 794 PKIX_LISTCREATEFAILED);
michael@0 795
michael@0 796 for (i = 0; i < length; i++) {
michael@0 797
michael@0 798 PKIX_CHECK(PKIX_List_GetItem
michael@0 799 (pkixLoggers,
michael@0 800 i,
michael@0 801 (PKIX_PL_Object **) &logger,
michael@0 802 plContext),
michael@0 803 PKIX_LISTGETITEMFAILED);
michael@0 804
michael@0 805 PKIX_CHECK(pkix_Logger_Duplicate
michael@0 806 ((PKIX_PL_Object *)logger,
michael@0 807 (PKIX_PL_Object **)&dupLogger,
michael@0 808 plContext),
michael@0 809 PKIX_LOGGERDUPLICATEFAILED);
michael@0 810
michael@0 811 PKIX_CHECK(PKIX_List_AppendItem
michael@0 812 (list,
michael@0 813 (PKIX_PL_Object *) dupLogger,
michael@0 814 plContext),
michael@0 815 PKIX_LISTAPPENDITEMFAILED);
michael@0 816
michael@0 817 PKIX_DECREF(logger);
michael@0 818 PKIX_DECREF(dupLogger);
michael@0 819 }
michael@0 820
michael@0 821 /* Set the list to be immutable */
michael@0 822 PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
michael@0 823 PKIX_LISTSETIMMUTABLEFAILED);
michael@0 824
michael@0 825 *pLoggers = list;
michael@0 826
michael@0 827 cleanup:
michael@0 828
michael@0 829 PKIX_DECREF(logger);
michael@0 830
michael@0 831 /* Restore logging capability */
michael@0 832 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
michael@0 833 pkixLoggersErrors = savedPkixLoggersErrors;
michael@0 834
michael@0 835 if (locked) {
michael@0 836 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
michael@0 837 PKIX_MONITORLOCKEXITFAILED);
michael@0 838 }
michael@0 839
michael@0 840 PKIX_RETURN(LOGGER);
michael@0 841 }
michael@0 842
michael@0 843 /*
michael@0 844 * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
michael@0 845 */
michael@0 846 PKIX_Error *
michael@0 847 PKIX_SetLoggers(
michael@0 848 PKIX_List *loggers, /* list of PKIX_Logger */
michael@0 849 void *plContext)
michael@0 850 {
michael@0 851 PKIX_List *list = NULL;
michael@0 852 PKIX_List *savedPkixLoggersErrors = NULL;
michael@0 853 PKIX_List *savedPkixLoggersDebugTrace = NULL;
michael@0 854 PKIX_Logger *logger = NULL;
michael@0 855 PKIX_Logger *dupLogger = NULL;
michael@0 856 PKIX_Boolean locked = PKIX_FALSE;
michael@0 857 PKIX_UInt32 i, length;
michael@0 858
michael@0 859 PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
michael@0 860
michael@0 861 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
michael@0 862 PKIX_MONITORLOCKENTERFAILED);
michael@0 863 locked = PKIX_TRUE;
michael@0 864
michael@0 865 /* Disable tracing, etc. to avoid recursion and deadlock */
michael@0 866 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
michael@0 867 pkixLoggersDebugTrace = NULL;
michael@0 868 savedPkixLoggersErrors = pkixLoggersErrors;
michael@0 869 pkixLoggersErrors = NULL;
michael@0 870
michael@0 871 /* discard any prior loggers */
michael@0 872 PKIX_DECREF(pkixLoggers);
michael@0 873 PKIX_DECREF(savedPkixLoggersErrors);
michael@0 874 PKIX_DECREF(savedPkixLoggersDebugTrace);
michael@0 875
michael@0 876 if (loggers != NULL) {
michael@0 877
michael@0 878 PKIX_CHECK(PKIX_List_Create(&list, plContext),
michael@0 879 PKIX_LISTCREATEFAILED);
michael@0 880
michael@0 881 PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
michael@0 882 PKIX_LISTGETLENGTHFAILED);
michael@0 883
michael@0 884 for (i = 0; i < length; i++) {
michael@0 885
michael@0 886 PKIX_CHECK(PKIX_List_GetItem
michael@0 887 (loggers,
michael@0 888 i,
michael@0 889 (PKIX_PL_Object **) &logger,
michael@0 890 plContext),
michael@0 891 PKIX_LISTGETITEMFAILED);
michael@0 892
michael@0 893 PKIX_CHECK(pkix_Logger_Duplicate
michael@0 894 ((PKIX_PL_Object *)logger,
michael@0 895 (PKIX_PL_Object **)&dupLogger,
michael@0 896 plContext),
michael@0 897 PKIX_LOGGERDUPLICATEFAILED);
michael@0 898
michael@0 899 PKIX_CHECK(PKIX_List_AppendItem
michael@0 900 (list,
michael@0 901 (PKIX_PL_Object *) dupLogger,
michael@0 902 plContext),
michael@0 903 PKIX_LISTAPPENDITEMFAILED);
michael@0 904
michael@0 905 /* Make two lists */
michael@0 906
michael@0 907 /* Put in pkixLoggersErrors in any case*/
michael@0 908
michael@0 909 if (savedPkixLoggersErrors == NULL) {
michael@0 910
michael@0 911 PKIX_CHECK(PKIX_List_Create
michael@0 912 (&savedPkixLoggersErrors,
michael@0 913 plContext),
michael@0 914 PKIX_LISTCREATEFAILED);
michael@0 915 }
michael@0 916
michael@0 917 PKIX_CHECK(PKIX_List_AppendItem
michael@0 918 (savedPkixLoggersErrors,
michael@0 919 (PKIX_PL_Object *) dupLogger,
michael@0 920 plContext),
michael@0 921 PKIX_LISTAPPENDITEMFAILED);
michael@0 922
michael@0 923 if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
michael@0 924
michael@0 925 /* Put in pkixLoggersDebugTrace */
michael@0 926
michael@0 927 if (savedPkixLoggersDebugTrace == NULL) {
michael@0 928
michael@0 929 PKIX_CHECK(PKIX_List_Create
michael@0 930 (&savedPkixLoggersDebugTrace,
michael@0 931 plContext),
michael@0 932 PKIX_LISTCREATEFAILED);
michael@0 933 }
michael@0 934
michael@0 935 PKIX_CHECK(PKIX_List_AppendItem
michael@0 936 (savedPkixLoggersDebugTrace,
michael@0 937 (PKIX_PL_Object *) dupLogger,
michael@0 938 plContext),
michael@0 939 PKIX_LISTAPPENDITEMFAILED);
michael@0 940 }
michael@0 941 PKIX_DECREF(logger);
michael@0 942 PKIX_DECREF(dupLogger);
michael@0 943
michael@0 944 }
michael@0 945
michael@0 946 pkixLoggers = list;
michael@0 947 }
michael@0 948
michael@0 949 cleanup:
michael@0 950
michael@0 951 if (PKIX_ERROR_RECEIVED){
michael@0 952 PKIX_DECREF(list);
michael@0 953 PKIX_DECREF(savedPkixLoggersErrors);
michael@0 954 PKIX_DECREF(savedPkixLoggersDebugTrace);
michael@0 955 pkixLoggers = NULL;
michael@0 956 }
michael@0 957
michael@0 958 PKIX_DECREF(logger);
michael@0 959
michael@0 960 /* Reenable logging capability with new lists */
michael@0 961 pkixLoggersErrors = savedPkixLoggersErrors;
michael@0 962 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
michael@0 963
michael@0 964 if (locked) {
michael@0 965 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
michael@0 966 PKIX_MONITORLOCKEXITFAILED);
michael@0 967 }
michael@0 968
michael@0 969 PKIX_RETURN(LOGGER);
michael@0 970 }
michael@0 971
michael@0 972 /*
michael@0 973 * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
michael@0 974 */
michael@0 975 PKIX_Error *
michael@0 976 PKIX_AddLogger(
michael@0 977 PKIX_Logger *logger,
michael@0 978 void *plContext)
michael@0 979 {
michael@0 980 PKIX_Logger *dupLogger = NULL;
michael@0 981 PKIX_Logger *addLogger = NULL;
michael@0 982 PKIX_List *savedPkixLoggersErrors = NULL;
michael@0 983 PKIX_List *savedPkixLoggersDebugTrace = NULL;
michael@0 984 PKIX_Boolean locked = PKIX_FALSE;
michael@0 985 PKIX_UInt32 i, length;
michael@0 986
michael@0 987 PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
michael@0 988 PKIX_NULLCHECK_ONE(logger);
michael@0 989
michael@0 990 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
michael@0 991 PKIX_MONITORLOCKENTERFAILED);
michael@0 992 locked = PKIX_TRUE;
michael@0 993
michael@0 994 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
michael@0 995 pkixLoggersDebugTrace = NULL;
michael@0 996 savedPkixLoggersErrors = pkixLoggersErrors;
michael@0 997 pkixLoggersErrors = NULL;
michael@0 998
michael@0 999 PKIX_DECREF(savedPkixLoggersErrors);
michael@0 1000 PKIX_DECREF(savedPkixLoggersDebugTrace);
michael@0 1001
michael@0 1002 if (pkixLoggers == NULL) {
michael@0 1003
michael@0 1004 PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
michael@0 1005 PKIX_LISTCREATEFAILED);
michael@0 1006 }
michael@0 1007
michael@0 1008 PKIX_CHECK(pkix_Logger_Duplicate
michael@0 1009 ((PKIX_PL_Object *)logger,
michael@0 1010 (PKIX_PL_Object **)&dupLogger,
michael@0 1011 plContext),
michael@0 1012 PKIX_LOGGERDUPLICATEFAILED);
michael@0 1013
michael@0 1014 PKIX_CHECK(PKIX_List_AppendItem
michael@0 1015 (pkixLoggers,
michael@0 1016 (PKIX_PL_Object *) dupLogger,
michael@0 1017 plContext),
michael@0 1018 PKIX_LISTAPPENDITEMFAILED);
michael@0 1019
michael@0 1020 PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
michael@0 1021 PKIX_LISTGETLENGTHFAILED);
michael@0 1022
michael@0 1023 /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
michael@0 1024 for (i = 0; i < length; i++) {
michael@0 1025
michael@0 1026 PKIX_CHECK(PKIX_List_GetItem
michael@0 1027 (pkixLoggers,
michael@0 1028 i,
michael@0 1029 (PKIX_PL_Object **) &addLogger,
michael@0 1030 plContext),
michael@0 1031 PKIX_LISTGETITEMFAILED);
michael@0 1032
michael@0 1033
michael@0 1034 /* Put in pkixLoggersErrors */
michael@0 1035
michael@0 1036 if (savedPkixLoggersErrors == NULL) {
michael@0 1037
michael@0 1038 PKIX_CHECK(PKIX_List_Create
michael@0 1039 (&savedPkixLoggersErrors,
michael@0 1040 plContext),
michael@0 1041 PKIX_LISTCREATEFAILED);
michael@0 1042 }
michael@0 1043
michael@0 1044 PKIX_CHECK(PKIX_List_AppendItem
michael@0 1045 (savedPkixLoggersErrors,
michael@0 1046 (PKIX_PL_Object *) addLogger,
michael@0 1047 plContext),
michael@0 1048 PKIX_LISTAPPENDITEMFAILED);
michael@0 1049
michael@0 1050 if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
michael@0 1051
michael@0 1052 /* Put in pkixLoggersDebugTrace */
michael@0 1053
michael@0 1054 if (savedPkixLoggersDebugTrace == NULL) {
michael@0 1055
michael@0 1056 PKIX_CHECK(PKIX_List_Create
michael@0 1057 (&savedPkixLoggersDebugTrace,
michael@0 1058 plContext),
michael@0 1059 PKIX_LISTCREATEFAILED);
michael@0 1060 }
michael@0 1061
michael@0 1062 PKIX_CHECK(PKIX_List_AppendItem
michael@0 1063 (savedPkixLoggersDebugTrace,
michael@0 1064 (PKIX_PL_Object *) addLogger,
michael@0 1065 plContext),
michael@0 1066 PKIX_LISTAPPENDITEMFAILED);
michael@0 1067 }
michael@0 1068
michael@0 1069 PKIX_DECREF(addLogger);
michael@0 1070
michael@0 1071 }
michael@0 1072
michael@0 1073 cleanup:
michael@0 1074
michael@0 1075 PKIX_DECREF(dupLogger);
michael@0 1076 PKIX_DECREF(addLogger);
michael@0 1077
michael@0 1078 /* Restore logging capability */
michael@0 1079 pkixLoggersErrors = savedPkixLoggersErrors;
michael@0 1080 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
michael@0 1081
michael@0 1082 if (locked) {
michael@0 1083 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
michael@0 1084 PKIX_MONITORLOCKEXITFAILED);
michael@0 1085 }
michael@0 1086
michael@0 1087 PKIX_RETURN(LOGGER);
michael@0 1088 }

mercurial