xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_random.c (revision 5dd36a3bc8bf2a9dec29ceb6349550414570c447)
1 /*	$NetBSD: dict_random.c,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	dict_random 3
6 /* SUMMARY
7 /*	dictionary manager interface for randomized tables
8 /* SYNOPSIS
9 /*	#include <dict_random.h>
10 /*
11 /*	DICT	*dict_random_open(name, open_flags, dict_flags)
12 /*	const char *name;
13 /*	int	open_flags;
14 /*	int	dict_flags;
15 /* DESCRIPTION
16 /*	dict_random_open() opens an in-memory, read-only, table.
17 /*	Example: "\fBrandmap:{\fIresult_1, ... ,result_n}\fR".
18 /*
19 /*	Each table query returns a random choice from the specified
20 /*	results. Other table access methods are not supported.
21 /*
22 /*	The first and last characters of the "randmap:" table name
23 /*	must be '{' and '}'. Within these, individual maps are
24 /*	separated with comma or whitespace.
25 /* SEE ALSO
26 /*	dict(3) generic dictionary manager
27 /* LICENSE
28 /* .ad
29 /* .fi
30 /*	The Secure Mailer license must be distributed with this software.
31 /* AUTHOR(S)
32 /*	Wietse Venema
33 /*	IBM T.J. Watson Research
34 /*	P.O. Box 704
35 /*	Yorktown Heights, NY 10598, USA
36 /*--*/
37 
38 /* System library. */
39 
40 #include <sys_defs.h>
41 #include <string.h>
42 
43 /* Utility library. */
44 
45 #include <msg.h>
46 #include <mymalloc.h>
47 #include <myrand.h>
48 #include <stringops.h>
49 #include <dict_random.h>
50 
51 /* Application-specific. */
52 
53 typedef struct {
54     DICT    dict;			/* generic members */
55     ARGV   *replies;			/* reply values */
56 } DICT_RANDOM;
57 
58 #define STR(x) vstring_str(x)
59 
60 /* dict_random_lookup - find randomized-table entry */
61 
62 static const char *dict_random_lookup(DICT *dict, const char *unused_query)
63 {
64     DICT_RANDOM *dict_random = (DICT_RANDOM *) dict;
65 
66     DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE,
67 	 dict_random->replies->argv[myrand() % dict_random->replies->argc]);
68 }
69 
70 /* dict_random_close - disassociate from randomized table */
71 
72 static void dict_random_close(DICT *dict)
73 {
74     DICT_RANDOM *dict_random = (DICT_RANDOM *) dict;
75 
76     argv_free(dict_random->replies);
77     dict_free(dict);
78 }
79 
80 /* dict_random_open - open a randomized table */
81 
82 DICT   *dict_random_open(const char *name, int open_flags, int dict_flags)
83 {
84     DICT_RANDOM *dict_random;
85     char   *saved_name = 0;
86     ARGV   *argv;
87     size_t  len;
88 
89     /*
90      * Clarity first. Let the optimizer worry about redundant code.
91      */
92 #define DICT_RANDOM_RETURN(x) do { \
93 	if (saved_name != 0) \
94 	    myfree(saved_name); \
95 	return (x); \
96     } while (0)
97 
98     /*
99      * Sanity checks.
100      */
101     if (open_flags != O_RDONLY)
102 	DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name,
103 					  open_flags, dict_flags,
104 				  "%s:%s map requires O_RDONLY access mode",
105 					  DICT_TYPE_RANDOM, name));
106 
107     /*
108      * Split the name name into its constituent parts.
109      */
110     if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0
111 	|| *(saved_name = mystrndup(name + 1, len - 2)) == 0
112 	|| ((argv = argv_splitq(saved_name, CHARS_COMMA_SP, CHARS_BRACE)),
113 	    (argv->argc == 0)))
114 	DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name,
115 					  open_flags, dict_flags,
116 					  "bad syntax: \"%s:%s\"; "
117 					  "need \"%s:{value...}\"",
118 					  DICT_TYPE_RANDOM, name,
119 					  DICT_TYPE_RANDOM));
120 
121     /*
122      * Bundle up the result.
123      */
124     dict_random =
125 	(DICT_RANDOM *) dict_alloc(DICT_TYPE_RANDOM, name, sizeof(*dict_random));
126     dict_random->dict.lookup = dict_random_lookup;
127     dict_random->dict.close = dict_random_close;
128     dict_random->dict.flags = dict_flags | DICT_FLAG_PATTERN;
129     dict_random->replies = argv;
130     dict_random->dict.owner.status = DICT_OWNER_TRUSTED;
131     dict_random->dict.owner.uid = 0;
132 
133     DICT_RANDOM_RETURN(DICT_DEBUG (&dict_random->dict));
134 }
135