7 /* map names to bit mask
9 /* #include <name_mask.h>
11 /* int name_mask(context, table, names)
12 /* const char *context;
13 /* const NAME_MASK *table;
16 /* const char *str_name_mask(context, table, mask)
17 /* const char *context;
18 /* const NAME_MASK *table;
21 /* int name_mask_opt(context, table, names, flags)
22 /* const char *context;
23 /* const NAME_MASK *table;
27 /* int name_mask_delim_opt(context, table, names, delim, flags)
28 /* const char *context;
29 /* const NAME_MASK *table;
34 /* const char *str_name_mask_opt(buf, context, table, mask, flags)
36 /* const char *context;
37 /* const NAME_MASK *table;
41 /* name_mask() takes a null-terminated \fItable\fR with (name, mask)
42 /* values and computes the bit-wise OR of the masks that correspond
43 /* to the names listed in the \fInames\fR argument, separated by
44 /* comma and/or whitespace characters.
46 /* str_name_mask() translates a mask into its equivalent names.
47 /* The result is written to a static buffer that is overwritten
50 /* name_mask_opt() and str_name_mask_opt() are extended versions
51 /* with additional fine control. name_mask_delim_opt() supports
52 /* non-default delimiter characters.
56 /* Null pointer or pointer to buffer storage.
58 /* What kind of names and
59 /* masks are being manipulated, in order to make error messages
60 /* more understandable. Typically, this would be the name of a
61 /* user-configurable parameter.
63 /* Table with (name, bit mask) pairs.
65 /* A list of names that is to be converted into a bit mask.
69 /* Bit-wise OR of zero or more of the following:
71 /* Delimiter characters to use instead of whitespace and commas.
73 /* .IP NAME_MASK_FATAL
74 /* Require that all names listed in \fIname\fR exist in \fItable\fR,
75 /* and that all bits listed in \fImask\fR exist in \fItable\fR.
76 /* Terminate with a fatal run-time error if this condition is not met.
77 /* This feature is enabled by default when calling name_mask()
78 /* or str_name_mask().
79 /* .IP NAME_MASK_RETURN
80 /* Require that all names listed in \fIname\fR exist in \fItable\fR,
81 /* and that all bits listed in \fImask\fR exist in \fItable\fR.
82 /* Log a warning, and return 0 (name_mask()) or a null pointer
83 /* (str_name_mask()) if this condition is not met.
84 /* .IP NAME_MASK_NUMBER
85 /* Require that all bits listed in \fImask\fR exist in \fItable\fR.
86 /* For unrecognized bits, print the numerical hexadecimal form.
87 /* .IP NAME_MASK_ANY_CASE
88 /* Enable case-insensitive matching.
89 /* This feature is not enabled by default when calling name_mask();
90 /* it has no effect with str_name_mask().
91 /* .IP NAME_MASK_COMMA
92 /* Use comma instead of space when converting a mask to string.
94 /* Use "|" instead of space when converting a mask to string.
96 /* The value NAME_MASK_NONE explicitly requests no features,
97 /* and NAME_MASK_DEFAULT enables the default options.
99 /* Fatal: the \fInames\fR argument specifies a name not found in
100 /* \fItable\fR, or the \fImask\fR specifies a bit not found in
105 /* The Secure Mailer license must be distributed with this software.
108 /* IBM T.J. Watson Research
110 /* Yorktown Heights, NY 10598, USA
113 /* System library. */
115 #include <sys_defs.h>
118 #ifdef STRCASECMP_IN_STRINGS_H
122 /* Utility library. */
125 #include <mymalloc.h>
126 #include <stringops.h>
127 #include <name_mask.h>
130 #define STR(x) vstring_str(x)
132 /* name_mask_delim_opt - compute mask corresponding to list of names */
134 int name_mask_delim_opt(const char *context
, const NAME_MASK
*table
,
135 const char *names
, const char *delim
, int flags
)
137 const char *myname
= "name_mask";
138 char *saved_names
= mystrdup(names
);
139 char *bp
= saved_names
;
143 int (*lookup
) (const char *, const char *);
145 if (flags
& NAME_MASK_ANY_CASE
)
151 * Break up the names string, and look up each component in the table. If
152 * the name is found, merge its mask with the result.
154 while ((name
= mystrtok(&bp
, delim
)) != 0) {
155 for (np
= table
; /* void */ ; np
++) {
157 if (flags
& NAME_MASK_FATAL
)
158 msg_fatal("unknown %s value \"%s\" in \"%s\"",
159 context
, name
, names
);
160 if (flags
& NAME_MASK_RETURN
) {
161 msg_warn("unknown %s value \"%s\" in \"%s\"",
162 context
, name
, names
);
167 if (lookup(name
, np
->name
) == 0) {
169 msg_info("%s: %s", myname
, name
);
179 /* str_name_mask_opt - mask to string */
181 const char *str_name_mask_opt(VSTRING
*buf
, const char *context
,
182 const NAME_MASK
*table
,
185 const char *myname
= "name_mask";
188 static VSTRING
*my_buf
= 0;
189 int delim
= (flags
& NAME_MASK_COMMA
? ',' :
190 (flags
& NAME_MASK_PIPE
? '|' : ' '));
194 my_buf
= vstring_alloc(1);
199 for (np
= table
; mask
!= 0; np
++) {
201 if (flags
& NAME_MASK_FATAL
) {
202 msg_fatal("%s: unknown %s bit in mask: 0x%x",
203 myname
, context
, mask
);
204 } else if (flags
& NAME_MASK_RETURN
) {
205 msg_warn("%s: unknown %s bit in mask: 0x%x",
206 myname
, context
, mask
);
208 } else if (flags
& NAME_MASK_NUMBER
) {
209 vstring_sprintf_append(buf
, "0x%x%c", mask
, delim
);
213 if (mask
& np
->mask
) {
215 vstring_sprintf_append(buf
, "%s%c", np
->name
, delim
);
218 if ((len
= VSTRING_LEN(buf
)) > 0)
219 vstring_truncate(buf
, len
- 1);
220 VSTRING_TERMINATE(buf
);
228 * Stand-alone test program.
233 int main(int argc
, char **argv
)
235 static const NAME_MASK table
[] = {
243 VSTRING
*buf
= vstring_alloc(1);
245 while (--argc
&& *++argv
) {
246 mask
= name_mask("test", table
, *argv
);
247 vstream_printf("%s -> 0x%x -> %s\n",
248 *argv
, mask
, str_name_mask("mask_test", table
, mask
));
249 vstream_fflush(VSTREAM_OUT
);