1 /* $NetBSD: dict_surrogate.c,v 1.1.1.2 2014/07/06 19:27:57 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* dict_surrogate 3 6 /* SUMMARY 7 /* surrogate table for graceful "open" failure 8 /* SYNOPSIS 9 /* #include <dict_surrogate.h> 10 /* 11 /* DICT *dict_surrogate(dict_type, dict_name, 12 /* open_flags, dict_flags, 13 /* format, ...) 14 /* const char *dict_type; 15 /* const char *dict_name; 16 /* int open_flags; 17 /* int dict_flags; 18 /* const char *format; 19 /* 20 /* int dict_allow_surrogate; 21 /* DESCRIPTION 22 /* dict_surrogate() either terminates the program with a fatal 23 /* error, or provides a dummy dictionary that fails all 24 /* operations with an error message, allowing the program to 25 /* continue with reduced functionality. 26 /* 27 /* The global dict_allow_surrogate variable controls the choice 28 /* between fatal error or reduced functionality. The default 29 /* value is zero (fatal error). This is appropriate for user 30 /* commands; the non-default is more appropriate for daemons. 31 /* 32 /* Arguments: 33 /* .IP dict_type 34 /* .IP dict_name 35 /* .IP open_flags 36 /* .IP dict_flags 37 /* The parameters to the failed dictionary open() request. 38 /* .IP format, ... 39 /* The reason why the table could not be opened. This text is 40 /* logged immediately as an "error" class message, and is logged 41 /* as a "warning" class message upon every attempt to access the 42 /* surrogate dictionary, before returning a "failed" completion 43 /* status. 44 /* SEE ALSO 45 /* dict(3) generic dictionary manager 46 /* LICENSE 47 /* .ad 48 /* .fi 49 /* The Secure Mailer license must be distributed with this software. 50 /* AUTHOR(S) 51 /* Wietse Venema 52 /* IBM T.J. Watson Research 53 /* P.O. Box 704 54 /* Yorktown Heights, NY 10598, USA 55 /*--*/ 56 57 /* System library. */ 58 59 #include <sys_defs.h> 60 #include <errno.h> 61 62 /* Utility library. */ 63 64 #include <mymalloc.h> 65 #include <msg.h> 66 #include <compat_va_copy.h> 67 #include <dict.h> 68 69 /* Application-specific. */ 70 71 typedef struct { 72 DICT dict; /* generic members */ 73 char *reason; /* open failure reason */ 74 } DICT_SURROGATE; 75 76 /* dict_surrogate_sequence - fail lookup */ 77 78 static int dict_surrogate_sequence(DICT *dict, int unused_func, 79 const char **key, const char **value) 80 { 81 DICT_SURROGATE *dp = (DICT_SURROGATE *) dict; 82 83 msg_warn("%s:%s is unavailable. %s", 84 dict->type, dict->name, dp->reason); 85 DICT_ERR_VAL_RETURN(dict, DICT_ERR_RETRY, DICT_STAT_ERROR); 86 } 87 88 /* dict_surrogate_update - fail lookup */ 89 90 static int dict_surrogate_update(DICT *dict, const char *unused_name, 91 const char *unused_value) 92 { 93 DICT_SURROGATE *dp = (DICT_SURROGATE *) dict; 94 95 msg_warn("%s:%s is unavailable. %s", 96 dict->type, dict->name, dp->reason); 97 DICT_ERR_VAL_RETURN(dict, DICT_ERR_RETRY, DICT_STAT_ERROR); 98 } 99 100 /* dict_surrogate_lookup - fail lookup */ 101 102 static const char *dict_surrogate_lookup(DICT *dict, const char *unused_name) 103 { 104 DICT_SURROGATE *dp = (DICT_SURROGATE *) dict; 105 106 msg_warn("%s:%s is unavailable. %s", 107 dict->type, dict->name, dp->reason); 108 DICT_ERR_VAL_RETURN(dict, DICT_ERR_RETRY, (char *) 0); 109 } 110 111 /* dict_surrogate_delete - fail delete */ 112 113 static int dict_surrogate_delete(DICT *dict, const char *unused_name) 114 { 115 DICT_SURROGATE *dp = (DICT_SURROGATE *) dict; 116 117 msg_warn("%s:%s is unavailable. %s", 118 dict->type, dict->name, dp->reason); 119 DICT_ERR_VAL_RETURN(dict, DICT_ERR_RETRY, DICT_STAT_ERROR); 120 } 121 122 /* dict_surrogate_close - close fail dictionary */ 123 124 static void dict_surrogate_close(DICT *dict) 125 { 126 DICT_SURROGATE *dp = (DICT_SURROGATE *) dict; 127 128 myfree((char *) dp->reason); 129 dict_free(dict); 130 } 131 132 int dict_allow_surrogate = 0; 133 134 /* dict_surrogate - terminate or provide surrogate dictionary */ 135 136 DICT *dict_surrogate(const char *dict_type, const char *dict_name, 137 int open_flags, int dict_flags, 138 const char *fmt,...) 139 { 140 va_list ap; 141 va_list ap2; 142 DICT_SURROGATE *dp; 143 VSTRING *buf; 144 void (*log_fn) (const char *, va_list); 145 int saved_errno = errno; 146 147 /* 148 * Initialize argument lists. 149 */ 150 va_start(ap, fmt); 151 VA_COPY(ap2, ap); 152 153 /* 154 * Log the problem immediately when it is detected. The table may not be 155 * accessed in every program execution (that is the whole point of 156 * continuing with reduced functionality) but we don't want the problem 157 * to remain unnoticed until long after a configuration mistake is made. 158 */ 159 log_fn = dict_allow_surrogate ? vmsg_error : vmsg_fatal; 160 log_fn(fmt, ap); 161 va_end(ap); 162 163 /* 164 * Log the problem upon each access. 165 */ 166 dp = (DICT_SURROGATE *) dict_alloc(dict_type, dict_name, sizeof(*dp)); 167 dp->dict.lookup = dict_surrogate_lookup; 168 if (open_flags & O_RDWR) { 169 dp->dict.update = dict_surrogate_update; 170 dp->dict.delete = dict_surrogate_delete; 171 } 172 dp->dict.sequence = dict_surrogate_sequence; 173 dp->dict.close = dict_surrogate_close; 174 dp->dict.flags = dict_flags | DICT_FLAG_PATTERN; 175 dp->dict.owner.status = DICT_OWNER_TRUSTED; 176 buf = vstring_alloc(10); 177 errno = saved_errno; 178 vstring_vsprintf(buf, fmt, ap2); 179 va_end(ap2); 180 dp->reason = vstring_export(buf); 181 return (DICT_DEBUG (&dp->dict)); 182 } 183