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