1/*++ 2/* NAME 3/* dict_debug 3 4/* SUMMARY 5/* dictionary manager, logging proxy 6/* SYNOPSIS 7/* #include <dict.h> 8/* 9/* DICT *dict_debug(dict_handle) 10/* DICT *dict_handle; 11/* 12/* DICT *DICT_DEBUG(dict_handle) 13/* DICT *dict_handle; 14/* DESCRIPTION 15/* dict_debug() encapsulates the given dictionary object and returns 16/* a proxy object that logs all access to the encapsulated object. 17/* This is more convenient than having to add logging capability 18/* to each individual dictionary access method. 19/* 20/* DICT_DEBUG() is an unsafe macro that returns the original object if 21/* the object's debugging flag is not set, and that otherwise encapsulates 22/* the object with dict_debug(). This macro simplifies usage by avoiding 23/* clumsy expressions. The macro evaluates its argument multiple times. 24/* DIAGNOSTICS 25/* Fatal errors: out of memory. 26/* LICENSE 27/* .ad 28/* .fi 29/* The Secure Mailer license must be distributed with this software. 30/* AUTHOR(S) 31/* Wietse Venema 32/* IBM T.J. Watson Research 33/* P.O. Box 704 34/* Yorktown Heights, NY 10598, USA 35/*--*/ 36 37/* System libraries. */ 38 39#include <sys_defs.h> 40 41/* Utility library. */ 42 43#include <msg.h> 44#include <mymalloc.h> 45#include <dict.h> 46 47/* Application-specific. */ 48 49typedef struct { 50 DICT dict; /* the proxy service */ 51 DICT *real_dict; /* encapsulated object */ 52} DICT_DEBUG; 53 54/* dict_debug_lookup - log lookup operation */ 55 56static const char *dict_debug_lookup(DICT *dict, const char *key) 57{ 58 DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict; 59 DICT *real_dict = dict_debug->real_dict; 60 const char *result; 61 62 result = dict_get(real_dict, key); 63 msg_info("%s:%s lookup: \"%s\" = \"%s\"", dict->type, dict->name, key, 64 result ? result : real_dict->error ? "error" : "not_found"); 65 DICT_ERR_VAL_RETURN(dict, real_dict->error, result); 66} 67 68/* dict_debug_update - log update operation */ 69 70static int dict_debug_update(DICT *dict, const char *key, const char *value) 71{ 72 DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict; 73 DICT *real_dict = dict_debug->real_dict; 74 int result; 75 76 result = dict_put(real_dict, key, value); 77 msg_info("%s:%s update: \"%s\" = \"%s\": %s", dict->type, dict->name, 78 key, value, result == 0 ? "success" : real_dict->error ? 79 "error" : "failed"); 80 DICT_ERR_VAL_RETURN(dict, real_dict->error, result); 81} 82 83/* dict_debug_delete - log delete operation */ 84 85static int dict_debug_delete(DICT *dict, const char *key) 86{ 87 DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict; 88 DICT *real_dict = dict_debug->real_dict; 89 int result; 90 91 result = dict_del(real_dict, key); 92 msg_info("%s:%s delete: \"%s\": %s", dict->type, dict->name, key, 93 result == 0 ? "success" : real_dict->error ? 94 "error" : "failed"); 95 DICT_ERR_VAL_RETURN(dict, real_dict->error, result); 96} 97 98/* dict_debug_sequence - log sequence operation */ 99 100static int dict_debug_sequence(DICT *dict, int function, 101 const char **key, const char **value) 102{ 103 DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict; 104 DICT *real_dict = dict_debug->real_dict; 105 int result; 106 107 result = dict_seq(real_dict, function, key, value); 108 if (result == 0) 109 msg_info("%s:%s sequence: \"%s\" = \"%s\"", dict->type, dict->name, 110 *key, *value); 111 else 112 msg_info("%s:%s sequence: found EOF", dict->type, dict->name); 113 DICT_ERR_VAL_RETURN(dict, real_dict->error, result); 114} 115 116/* dict_debug_close - log operation */ 117 118static void dict_debug_close(DICT *dict) 119{ 120 DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict; 121 122 dict_close(dict_debug->real_dict); 123 dict_free(dict); 124} 125 126/* dict_debug - encapsulate dictionary object and install proxies */ 127 128DICT *dict_debug(DICT *real_dict) 129{ 130 DICT_DEBUG *dict_debug; 131 132 dict_debug = (DICT_DEBUG *) dict_alloc(real_dict->type, 133 real_dict->name, sizeof(*dict_debug)); 134 dict_debug->dict.flags = real_dict->flags; /* XXX not synchronized */ 135 dict_debug->dict.lookup = dict_debug_lookup; 136 dict_debug->dict.update = dict_debug_update; 137 dict_debug->dict.delete = dict_debug_delete; 138 dict_debug->dict.sequence = dict_debug_sequence; 139 dict_debug->dict.close = dict_debug_close; 140 dict_debug->real_dict = real_dict; 141 return (&dict_debug->dict); 142} 143