1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 * Logger Object Functions
44 #include "pkix_logger.h"
46 /* Global variable to keep PKIX_Logger List */
47 PKIX_List
*pkixLoggers
= NULL
;
50 * Once the Logger has been set, for any logging related operations, we have
51 * to go through the List to find a match, and if found, issue the
52 * corresponding callback. The overhead to check for DEBUG and TRACE in each
53 * PKIX function entering and exiting is very expensive (400X), and redundant
54 * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
55 * pkixLoggers is separated into two lists based on its Loggers' trace level.
57 * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
58 * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
59 * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
60 * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
61 * pkixLoggersDebugTrace.
63 * Currently we provide five logging levels and the default setting are by:
65 * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
66 * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
67 * WARNING is not invoked as default
68 * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
69 * compilation -DPKIX_<component>DEBUG flag to turn on
70 * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
71 * level. TRACE provides duplicate information of DEBUG, but needs no
72 * recompilation and cannot choose component. To allow application
73 * to use DEBUG level, TRACE is put as last.
76 PKIX_List
*pkixLoggersErrors
= NULL
;
77 PKIX_List
*pkixLoggersDebugTrace
= NULL
;
79 /* To ensure atomic update on pkixLoggers lists */
80 PKIX_PL_MonitorLock
*pkixLoggerLock
= NULL
;
82 /* --Private-Functions-------------------------------------------- */
85 * FUNCTION: pkix_Logger_CheckErrors
88 * This function goes through each PKIX_Logger at "pkixLoggersList" and
89 * checks if "maxLevel" and "logComponent" satisfies what is specified in the
90 * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
91 * passes a PKIX_PL_String that is the concatenation of "message" and
92 * "message2" to the application for processing.
93 * Since this call is inserted into a handful of PKIX macros, no macros are
94 * applied in this function, to avoid infinite recursion.
95 * If an error occurs, this call is aborted.
99 * A list of PKIX_Loggers to be examined for invoking callback. Must be
102 * Address of "message" to be logged. Must be non-NULL.
104 * Address of "message2" to be concatenated and logged. May be NULL.
106 * A PKIX_UInt32 that indicates the component the message is from.
108 * A PKIX_UInt32 that represents the level of severity of the message.
110 * Platform-specific context pointer.
112 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
114 * Returns NULL if the function succeeds
115 * Returns a Fatal Error if the function fails in an unrecoverable way
119 PKIX_List
*pkixLoggersList
,
121 const char *message2
,
122 PKIX_ERRORCLASS logComponent
,
123 PKIX_UInt32 currentLevel
,
126 PKIX_Logger
*logger
= NULL
;
127 PKIX_List
*savedPkixLoggersErrors
= NULL
;
128 PKIX_List
*savedPkixLoggersDebugTrace
= NULL
;
129 PKIX_PL_String
*formatString
= NULL
;
130 PKIX_PL_String
*messageString
= NULL
;
131 PKIX_PL_String
*message2String
= NULL
;
132 PKIX_PL_String
*msgString
= NULL
;
133 PKIX_Error
*error
= NULL
;
134 PKIX_Boolean needLogging
= PKIX_FALSE
;
135 PKIX_UInt32 i
, length
;
138 * We cannot use any the PKIX_ macros here, since this function is
139 * called from some of these macros. It can create infinite recursion.
142 if ((pkixLoggersList
== NULL
) || (message
== NULL
)) {
147 * Disable all subsequent loggings to avoid recursion. The result is
148 * if other thread is calling this function at the same time, there
149 * won't be any logging because the pkixLoggersErrors and
150 * pkixLoggersDebugTrace are set to null.
151 * It would be nice if we provide control per thread (e.g. make
152 * plContext threadable) then we can avoid the recursion by setting
153 * flag at plContext. Then other thread's logging won't be affected.
155 * Also we need to use a reentrant Lock. Although we avoid recursion
156 * for TRACE. When there is an ERROR occurs in subsequent call, this
157 * function will be called.
160 error
= PKIX_PL_MonitorLock_Enter(pkixLoggerLock
, plContext
);
161 if (error
) { return(NULL
); }
163 savedPkixLoggersDebugTrace
= pkixLoggersDebugTrace
;
164 pkixLoggersDebugTrace
= NULL
;
165 savedPkixLoggersErrors
= pkixLoggersErrors
;
166 pkixLoggersErrors
= NULL
;
168 /* Convert message and message2 to String */
169 error
= PKIX_PL_String_Create
170 (PKIX_ESCASCII
, message
, 0, &messageString
, plContext
);
171 if (error
) { goto cleanup
; }
174 error
= PKIX_PL_String_Create
175 (PKIX_ESCASCII
, message2
, 0, &message2String
, plContext
);
176 if (error
) { goto cleanup
; }
177 error
= PKIX_PL_String_Create
178 (PKIX_ESCASCII
, "%s %s", 0, &formatString
, plContext
);
179 if (error
) { goto cleanup
; }
182 error
= PKIX_PL_String_Create
183 (PKIX_ESCASCII
, "%s", 0, &formatString
, plContext
);
184 if (error
) { goto cleanup
; }
188 error
= PKIX_PL_Sprintf
194 if (error
) { goto cleanup
; }
196 /* Go through the Logger list */
198 error
= PKIX_List_GetLength(pkixLoggersList
, &length
, plContext
);
199 if (error
) { goto cleanup
; }
201 for (i
= 0; i
< length
; i
++) {
203 error
= PKIX_List_GetItem
206 (PKIX_PL_Object
**) &logger
,
208 if (error
) { goto cleanup
; }
210 /* Intended logging level less or equal than the max */
211 needLogging
= (currentLevel
<= logger
->maxLevel
);
213 if (needLogging
&& (logger
->callback
)) {
216 * We separate Logger into two lists based on log level
217 * but log level is not modified. We need to check here to
218 * avoid logging the higher log level (lower value) twice.
220 if (pkixLoggersList
== pkixLoggersErrors
) {
221 needLogging
= needLogging
&&
222 (currentLevel
<= PKIX_LOGGER_LEVEL_WARNING
);
223 } else if (pkixLoggersList
== pkixLoggersDebugTrace
) {
224 needLogging
= needLogging
&&
225 (currentLevel
> PKIX_LOGGER_LEVEL_WARNING
);
229 if (logComponent
== logger
->logComponent
) {
230 needLogging
= PKIX_TRUE
;
232 needLogging
= PKIX_FALSE
;
237 error
= logger
->callback
243 if (error
) { goto cleanup
; }
247 error
= PKIX_PL_Object_DecRef
248 ((PKIX_PL_Object
*)logger
, plContext
);
250 if (error
) { goto cleanup
; }
257 error
= PKIX_PL_Object_DecRef
258 ((PKIX_PL_Object
*)formatString
, plContext
);
262 error
= PKIX_PL_Object_DecRef
263 ((PKIX_PL_Object
*)messageString
, plContext
);
266 if (message2String
) {
267 error
= PKIX_PL_Object_DecRef
268 ((PKIX_PL_Object
*)message2String
, plContext
);
272 error
= PKIX_PL_Object_DecRef
273 ((PKIX_PL_Object
*)msgString
, plContext
);
277 error
= PKIX_PL_Object_DecRef
278 ((PKIX_PL_Object
*)logger
, plContext
);
281 if (pkixLoggersErrors
== NULL
&& savedPkixLoggersErrors
!= NULL
) {
282 pkixLoggersErrors
= savedPkixLoggersErrors
;
285 if (pkixLoggersDebugTrace
== NULL
&&
286 savedPkixLoggersDebugTrace
!= NULL
) {
287 pkixLoggersDebugTrace
= savedPkixLoggersDebugTrace
;
290 error
= PKIX_PL_MonitorLock_Exit(pkixLoggerLock
, plContext
);
291 if (error
) { return(NULL
); }
297 * FUNCTION: pkix_Logger_Destroy
298 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
302 PKIX_PL_Object
*object
,
305 PKIX_Logger
*logger
= NULL
;
307 PKIX_ENTER(LOGGER
, "pkix_Logger_Destroy");
308 PKIX_NULLCHECK_ONE(object
);
310 /* Check that this object is a logger */
311 PKIX_CHECK(pkix_CheckType(object
, PKIX_LOGGER_TYPE
, plContext
),
312 PKIX_OBJECTNOTLOGGER
);
314 logger
= (PKIX_Logger
*)object
;
316 /* We have a valid logger. DecRef its item and recurse on next */
318 logger
->callback
= NULL
;
319 PKIX_DECREF(logger
->context
);
320 logger
->logComponent
= (PKIX_ERRORCLASS
)NULL
;
328 * FUNCTION: pkix_Logger_ToString
329 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
332 pkix_Logger_ToString(
333 PKIX_PL_Object
*object
,
334 PKIX_PL_String
**pString
,
337 PKIX_Logger
*logger
= NULL
;
338 char *asciiFormat
= NULL
;
339 PKIX_PL_String
*formatString
= NULL
;
340 PKIX_PL_String
*contextString
= NULL
;
341 PKIX_PL_String
*componentString
= NULL
;
342 PKIX_PL_String
*loggerString
= NULL
;
344 PKIX_ENTER(LOGGER
, "pkix_Logger_ToString_Helper");
345 PKIX_NULLCHECK_TWO(object
, pString
);
347 /* Check that this object is a logger */
348 PKIX_CHECK(pkix_CheckType(object
, PKIX_LOGGER_TYPE
, plContext
),
349 PKIX_OBJECTNOTLOGGER
);
351 logger
= (PKIX_Logger
*)object
;
357 "\tMaximum Level: %d\n"
358 "\tComponent Name: %s\n"
361 PKIX_CHECK(PKIX_PL_String_Create
367 PKIX_STRINGCREATEFAILED
);
369 PKIX_TOSTRING(logger
->context
, &contextString
, plContext
,
370 PKIX_OBJECTTOSTRINGFAILED
);
372 PKIX_CHECK(PKIX_PL_String_Create
374 (void *)PKIX_ERRORCLASSNAMES
[logger
->logComponent
],
378 PKIX_STRINGCREATEFAILED
);
380 PKIX_CHECK(PKIX_PL_Sprintf
389 *pString
= loggerString
;
393 PKIX_DECREF(formatString
);
394 PKIX_DECREF(contextString
);
399 * FUNCTION: pkix_Logger_Equals
400 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
404 PKIX_PL_Object
*first
,
405 PKIX_PL_Object
*second
,
406 PKIX_Boolean
*pResult
,
409 PKIX_UInt32 secondType
;
410 PKIX_Boolean cmpResult
;
411 PKIX_Logger
*firstLogger
= NULL
;
412 PKIX_Logger
*secondLogger
= NULL
;
415 PKIX_ENTER(LOGGER
, "pkix_Logger_Equals");
416 PKIX_NULLCHECK_THREE(first
, second
, pResult
);
418 /* test that first is a Logger */
419 PKIX_CHECK(pkix_CheckType(first
, PKIX_LOGGER_TYPE
, plContext
),
420 PKIX_FIRSTOBJECTNOTLOGGER
);
423 * Since we know first is a Logger, if both references are
424 * identical, they must be equal
426 if (first
== second
){
427 *pResult
= PKIX_TRUE
;
432 * If second isn't a Logger, we don't throw an error.
433 * We simply return a Boolean result of FALSE
435 *pResult
= PKIX_FALSE
;
436 PKIX_CHECK(PKIX_PL_Object_GetType(second
, &secondType
, plContext
),
437 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
438 if (secondType
!= PKIX_LOGGER_TYPE
) goto cleanup
;
440 firstLogger
= (PKIX_Logger
*)first
;
441 secondLogger
= (PKIX_Logger
*)second
;
443 cmpResult
= PKIX_FALSE
;
445 if (firstLogger
->callback
!= secondLogger
->callback
) {
449 if (firstLogger
->logComponent
!= secondLogger
->logComponent
) {
454 (firstLogger
->context
,
455 secondLogger
->context
,
458 PKIX_OBJECTEQUALSFAILED
);
460 if (cmpResult
== PKIX_FALSE
) {
464 if (firstLogger
->maxLevel
!= secondLogger
->maxLevel
) {
468 *pResult
= cmpResult
;
476 * FUNCTION: pkix_Logger_Hashcode
477 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
480 pkix_Logger_Hashcode(
481 PKIX_PL_Object
*object
,
482 PKIX_UInt32
*pHashcode
,
485 PKIX_Logger
*logger
= NULL
;
486 PKIX_UInt32 hash
= 0;
487 PKIX_UInt32 tempHash
= 0;
489 PKIX_ENTER(LOGGER
, "pkix_Logger_Hashcode");
490 PKIX_NULLCHECK_TWO(object
, pHashcode
);
492 PKIX_CHECK(pkix_CheckType(object
, PKIX_LOGGER_TYPE
, plContext
),
493 PKIX_OBJECTNOTLOGGER
);
495 logger
= (PKIX_Logger
*)object
;
497 PKIX_HASHCODE(logger
->context
, &tempHash
, plContext
,
498 PKIX_OBJECTHASHCODEFAILED
);
500 hash
= (((((PKIX_UInt32
) logger
->callback
+ tempHash
) << 7) +
501 logger
->maxLevel
) << 7) + (PKIX_UInt32
)logger
->logComponent
;
512 * FUNCTION: pkix_Logger_Duplicate
513 * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
516 pkix_Logger_Duplicate(
517 PKIX_PL_Object
*object
,
518 PKIX_PL_Object
**pNewObject
,
521 PKIX_Logger
*logger
= NULL
;
522 PKIX_Logger
*dupLogger
= NULL
;
524 PKIX_ENTER(LOGGER
, "pkix_Logger_Duplicate");
525 PKIX_NULLCHECK_TWO(object
, pNewObject
);
527 PKIX_CHECK(pkix_CheckType
528 ((PKIX_PL_Object
*)object
, PKIX_LOGGER_TYPE
, plContext
),
529 PKIX_OBJECTNOTLOGGER
);
531 logger
= (PKIX_Logger
*) object
;
533 PKIX_CHECK(PKIX_PL_Object_Alloc
535 sizeof (PKIX_Logger
),
536 (PKIX_PL_Object
**)&dupLogger
,
538 PKIX_COULDNOTCREATELOGGEROBJECT
);
540 dupLogger
->callback
= logger
->callback
;
541 dupLogger
->maxLevel
= logger
->maxLevel
;
547 PKIX_OBJECTDUPLICATEFAILED
);
549 dupLogger
->logComponent
= logger
->logComponent
;
551 *pNewObject
= (PKIX_PL_Object
*) dupLogger
;
555 if (PKIX_ERROR_RECEIVED
){
556 PKIX_DECREF(dupLogger
);
563 * FUNCTION: pkix_Logger_RegisterSelf
565 * Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
567 * Not Thread Safe - for performance and complexity reasons
569 * Since this function is only called by PKIX_PL_Initialize, which should
570 * only be called once, it is acceptable that this function is not
574 pkix_Logger_RegisterSelf(void *plContext
)
576 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
577 pkix_ClassTable_Entry entry
;
579 PKIX_ENTER(LOGGER
, "pkix_Logger_RegisterSelf");
581 entry
.description
= "Logger";
582 entry
.objCounter
= 0;
583 entry
.typeObjectSize
= sizeof(PKIX_Logger
);
584 entry
.destructor
= pkix_Logger_Destroy
;
585 entry
.equalsFunction
= pkix_Logger_Equals
;
586 entry
.hashcodeFunction
= pkix_Logger_Hashcode
;
587 entry
.toStringFunction
= pkix_Logger_ToString
;
588 entry
.comparator
= NULL
;
589 entry
.duplicateFunction
= pkix_Logger_Duplicate
;
591 systemClasses
[PKIX_LOGGER_TYPE
] = entry
;
596 /* --Public-Logger-Functions--------------------------------------------- */
599 * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
603 PKIX_Logger_LogCallback callback
,
604 PKIX_PL_Object
*loggerContext
,
605 PKIX_Logger
**pLogger
,
608 PKIX_Logger
*logger
= NULL
;
610 PKIX_ENTER(LOGGER
, "PKIX_Logger_Create");
611 PKIX_NULLCHECK_ONE(pLogger
);
613 PKIX_CHECK(PKIX_PL_Object_Alloc
615 sizeof (PKIX_Logger
),
616 (PKIX_PL_Object
**)&logger
,
618 PKIX_COULDNOTCREATELOGGEROBJECT
);
620 logger
->callback
= callback
;
621 logger
->maxLevel
= 0;
622 logger
->logComponent
= (PKIX_ERRORCLASS
)NULL
;
624 PKIX_INCREF(loggerContext
);
625 logger
->context
= loggerContext
;
638 * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
641 PKIX_Logger_GetLogCallback(
643 PKIX_Logger_LogCallback
*pCallback
,
646 PKIX_ENTER(LOGGER
, "PKIX_Logger_GetLogCallback");
647 PKIX_NULLCHECK_TWO(logger
, pCallback
);
649 *pCallback
= logger
->callback
;
655 * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
658 PKIX_Logger_GetLoggerContext(
660 PKIX_PL_Object
**pLoggerContext
,
663 PKIX_ENTER(LOGGER
, "PKIX_Logger_GetLoggerContex");
664 PKIX_NULLCHECK_TWO(logger
, pLoggerContext
);
666 PKIX_INCREF(logger
->context
);
667 *pLoggerContext
= logger
->context
;
674 * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
677 PKIX_Logger_GetMaxLoggingLevel(
682 PKIX_ENTER(LOGGER
, "PKIX_Logger_GetMaxLoggingLevel");
683 PKIX_NULLCHECK_TWO(logger
, pLevel
);
685 *pLevel
= logger
->maxLevel
;
691 * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
694 PKIX_Logger_SetMaxLoggingLevel(
699 PKIX_ENTER(LOGGER
, "PKIX_Logger_SetMaxLoggingLevel");
700 PKIX_NULLCHECK_ONE(logger
);
702 if (level
> PKIX_LOGGER_LEVEL_MAX
) {
703 PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM
);
705 logger
->maxLevel
= level
;
714 * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
717 PKIX_Logger_GetLoggingComponent(
719 PKIX_ERRORCLASS
*pComponent
,
722 PKIX_ENTER(LOGGER
, "PKIX_Logger_GetLoggingComponent");
723 PKIX_NULLCHECK_TWO(logger
, pComponent
);
725 *pComponent
= logger
->logComponent
;
731 * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
734 PKIX_Logger_SetLoggingComponent(
736 PKIX_ERRORCLASS component
,
739 PKIX_ENTER(LOGGER
, "PKIX_Logger_SetLoggingComponent");
740 PKIX_NULLCHECK_ONE(logger
);
742 logger
->logComponent
= component
;
749 * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
750 * documented as not thread-safe. However they are thread-safe now. We need
751 * the lock when accessing the logger lists.
755 * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
759 PKIX_List
**pLoggers
, /* list of PKIX_Logger */
762 PKIX_List
*list
= NULL
;
763 PKIX_List
*savedPkixLoggersDebugTrace
= NULL
;
764 PKIX_List
*savedPkixLoggersErrors
= NULL
;
765 PKIX_Logger
*logger
= NULL
;
766 PKIX_Logger
*dupLogger
= NULL
;
767 PKIX_UInt32 i
, length
;
768 PKIX_Boolean locked
= PKIX_FALSE
;
770 PKIX_ENTER(LOGGER
, "PKIX_Logger_GetLoggers");
771 PKIX_NULLCHECK_ONE(pLoggers
);
773 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock
, plContext
),
774 PKIX_MONITORLOCKENTERFAILED
);
778 * Temporarily disable DEBUG/TRACE Logging to avoid possible
780 * When the Logger List is being accessed, e.g. by PKIX_ENTER or
781 * PKIX_DECREF, pkix_Logger_Check may check whether logging
782 * is requested, creating a deadlock situation.
784 savedPkixLoggersDebugTrace
= pkixLoggersDebugTrace
;
785 pkixLoggersDebugTrace
= NULL
;
786 savedPkixLoggersErrors
= pkixLoggersErrors
;
787 pkixLoggersErrors
= NULL
;
789 if (pkixLoggers
== NULL
) {
792 PKIX_CHECK(PKIX_List_GetLength
793 (pkixLoggers
, &length
, plContext
),
794 PKIX_LISTGETLENGTHFAILED
);
797 /* Create a list and copy the pkixLoggers item to the list */
798 PKIX_CHECK(PKIX_List_Create(&list
, plContext
),
799 PKIX_LISTCREATEFAILED
);
801 for (i
= 0; i
< length
; i
++) {
803 PKIX_CHECK(PKIX_List_GetItem
806 (PKIX_PL_Object
**) &logger
,
808 PKIX_LISTGETITEMFAILED
);
810 PKIX_CHECK(pkix_Logger_Duplicate
811 ((PKIX_PL_Object
*)logger
,
812 (PKIX_PL_Object
**)&dupLogger
,
814 PKIX_LOGGERDUPLICATEFAILED
);
816 PKIX_CHECK(PKIX_List_AppendItem
818 (PKIX_PL_Object
*) dupLogger
,
820 PKIX_LISTAPPENDITEMFAILED
);
823 PKIX_DECREF(dupLogger
);
826 /* Set the list to be immutable */
827 PKIX_CHECK(PKIX_List_SetImmutable(list
, plContext
),
828 PKIX_LISTSETIMMUTABLEFAILED
);
836 /* Restore logging capability */
837 pkixLoggersDebugTrace
= savedPkixLoggersDebugTrace
;
838 pkixLoggersErrors
= savedPkixLoggersErrors
;
841 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock
, plContext
),
842 PKIX_MONITORLOCKEXITFAILED
);
849 * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
853 PKIX_List
*loggers
, /* list of PKIX_Logger */
856 PKIX_List
*list
= NULL
;
857 PKIX_List
*savedPkixLoggersErrors
= NULL
;
858 PKIX_List
*savedPkixLoggersDebugTrace
= NULL
;
859 PKIX_Logger
*logger
= NULL
;
860 PKIX_Logger
*dupLogger
= NULL
;
861 PKIX_Boolean locked
= PKIX_FALSE
;
862 PKIX_UInt32 i
, length
;
864 PKIX_ENTER(LOGGER
, "PKIX_SetLoggers");
866 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock
, plContext
),
867 PKIX_MONITORLOCKENTERFAILED
);
870 /* Disable tracing, etc. to avoid recursion and deadlock */
871 savedPkixLoggersDebugTrace
= pkixLoggersDebugTrace
;
872 pkixLoggersDebugTrace
= NULL
;
873 savedPkixLoggersErrors
= pkixLoggersErrors
;
874 pkixLoggersErrors
= NULL
;
876 /* discard any prior loggers */
877 PKIX_DECREF(pkixLoggers
);
878 PKIX_DECREF(savedPkixLoggersErrors
);
879 PKIX_DECREF(savedPkixLoggersDebugTrace
);
881 if (loggers
!= NULL
) {
883 PKIX_CHECK(PKIX_List_Create(&list
, plContext
),
884 PKIX_LISTCREATEFAILED
);
886 PKIX_CHECK(PKIX_List_GetLength(loggers
, &length
, plContext
),
887 PKIX_LISTGETLENGTHFAILED
);
889 for (i
= 0; i
< length
; i
++) {
891 PKIX_CHECK(PKIX_List_GetItem
894 (PKIX_PL_Object
**) &logger
,
896 PKIX_LISTGETITEMFAILED
);
898 PKIX_CHECK(pkix_Logger_Duplicate
899 ((PKIX_PL_Object
*)logger
,
900 (PKIX_PL_Object
**)&dupLogger
,
902 PKIX_LOGGERDUPLICATEFAILED
);
904 PKIX_CHECK(PKIX_List_AppendItem
906 (PKIX_PL_Object
*) dupLogger
,
908 PKIX_LISTAPPENDITEMFAILED
);
912 /* Put in pkixLoggersErrors in any case*/
914 if (savedPkixLoggersErrors
== NULL
) {
916 PKIX_CHECK(PKIX_List_Create
917 (&savedPkixLoggersErrors
,
919 PKIX_LISTCREATEFAILED
);
922 PKIX_CHECK(PKIX_List_AppendItem
923 (savedPkixLoggersErrors
,
924 (PKIX_PL_Object
*) dupLogger
,
926 PKIX_LISTAPPENDITEMFAILED
);
928 if (logger
->maxLevel
> PKIX_LOGGER_LEVEL_WARNING
) {
930 /* Put in pkixLoggersDebugTrace */
932 if (savedPkixLoggersDebugTrace
== NULL
) {
934 PKIX_CHECK(PKIX_List_Create
935 (&savedPkixLoggersDebugTrace
,
937 PKIX_LISTCREATEFAILED
);
940 PKIX_CHECK(PKIX_List_AppendItem
941 (savedPkixLoggersDebugTrace
,
942 (PKIX_PL_Object
*) dupLogger
,
944 PKIX_LISTAPPENDITEMFAILED
);
947 PKIX_DECREF(dupLogger
);
956 if (PKIX_ERROR_RECEIVED
){
958 PKIX_DECREF(savedPkixLoggersErrors
);
959 PKIX_DECREF(savedPkixLoggersDebugTrace
);
965 /* Reenable logging capability with new lists */
966 pkixLoggersErrors
= savedPkixLoggersErrors
;
967 pkixLoggersDebugTrace
= savedPkixLoggersDebugTrace
;
970 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock
, plContext
),
971 PKIX_MONITORLOCKEXITFAILED
);
978 * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
985 PKIX_Logger
*dupLogger
= NULL
;
986 PKIX_Logger
*addLogger
= NULL
;
987 PKIX_List
*savedPkixLoggersErrors
= NULL
;
988 PKIX_List
*savedPkixLoggersDebugTrace
= NULL
;
989 PKIX_Boolean locked
= PKIX_FALSE
;
990 PKIX_UInt32 i
, length
;
992 PKIX_ENTER(LOGGER
, "PKIX_Logger_AddLogger");
993 PKIX_NULLCHECK_ONE(logger
);
995 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock
, plContext
),
996 PKIX_MONITORLOCKENTERFAILED
);
999 savedPkixLoggersDebugTrace
= pkixLoggersDebugTrace
;
1000 pkixLoggersDebugTrace
= NULL
;
1001 savedPkixLoggersErrors
= pkixLoggersErrors
;
1002 pkixLoggersErrors
= NULL
;
1004 PKIX_DECREF(savedPkixLoggersErrors
);
1005 PKIX_DECREF(savedPkixLoggersDebugTrace
);
1007 if (pkixLoggers
== NULL
) {
1009 PKIX_CHECK(PKIX_List_Create(&pkixLoggers
, plContext
),
1010 PKIX_LISTCREATEFAILED
);
1013 PKIX_CHECK(pkix_Logger_Duplicate
1014 ((PKIX_PL_Object
*)logger
,
1015 (PKIX_PL_Object
**)&dupLogger
,
1017 PKIX_LOGGERDUPLICATEFAILED
);
1019 PKIX_CHECK(PKIX_List_AppendItem
1021 (PKIX_PL_Object
*) dupLogger
,
1023 PKIX_LISTAPPENDITEMFAILED
);
1025 PKIX_CHECK(PKIX_List_GetLength(pkixLoggers
, &length
, plContext
),
1026 PKIX_LISTGETLENGTHFAILED
);
1028 /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
1029 for (i
= 0; i
< length
; i
++) {
1031 PKIX_CHECK(PKIX_List_GetItem
1034 (PKIX_PL_Object
**) &addLogger
,
1036 PKIX_LISTGETITEMFAILED
);
1039 /* Put in pkixLoggersErrors */
1041 if (savedPkixLoggersErrors
== NULL
) {
1043 PKIX_CHECK(PKIX_List_Create
1044 (&savedPkixLoggersErrors
,
1046 PKIX_LISTCREATEFAILED
);
1049 PKIX_CHECK(PKIX_List_AppendItem
1050 (savedPkixLoggersErrors
,
1051 (PKIX_PL_Object
*) addLogger
,
1053 PKIX_LISTAPPENDITEMFAILED
);
1055 if (addLogger
->maxLevel
> PKIX_LOGGER_LEVEL_WARNING
) {
1057 /* Put in pkixLoggersDebugTrace */
1059 if (savedPkixLoggersDebugTrace
== NULL
) {
1061 PKIX_CHECK(PKIX_List_Create
1062 (&savedPkixLoggersDebugTrace
,
1064 PKIX_LISTCREATEFAILED
);
1067 PKIX_CHECK(PKIX_List_AppendItem
1068 (savedPkixLoggersDebugTrace
,
1069 (PKIX_PL_Object
*) addLogger
,
1071 PKIX_LISTAPPENDITEMFAILED
);
1074 PKIX_DECREF(addLogger
);
1080 PKIX_DECREF(dupLogger
);
1081 PKIX_DECREF(addLogger
);
1083 /* Restore logging capability */
1084 pkixLoggersErrors
= savedPkixLoggersErrors
;
1085 pkixLoggersDebugTrace
= savedPkixLoggersDebugTrace
;
1088 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock
, plContext
),
1089 PKIX_MONITORLOCKEXITFAILED
);
1092 PKIX_RETURN(LOGGER
);