Coverage Report

Created: 2025-02-03 06:29

/src/postfix/postfix/src/util/dict_random.c
Line
Count
Source (jump to first uncovered line)
1
/*++
2
/* NAME
3
/*  dict_random 3
4
/* SUMMARY
5
/*  dictionary manager interface for randomized tables
6
/* SYNOPSIS
7
/*  #include <dict_random.h>
8
/*
9
/*  DICT  *dict_random_open(name, open_flags, dict_flags)
10
/*  const char *name;
11
/*  int open_flags;
12
/*  int dict_flags;
13
/* DESCRIPTION
14
/*  dict_random_open() opens an in-memory, read-only, table.
15
/*  Example: "\fBrandmap:{\fIresult_1, ... ,result_n}\fR".
16
/*
17
/*  Each table query returns a random choice from the specified
18
/*  results. Other table access methods are not supported.
19
/*
20
/*  The first and last characters of the "randmap:" table name
21
/*  must be '{' and '}'. Within these, individual maps are
22
/*  separated with comma or whitespace.
23
/* SEE ALSO
24
/*  dict(3) generic dictionary manager
25
/* LICENSE
26
/* .ad
27
/* .fi
28
/*  The Secure Mailer license must be distributed with this software.
29
/* AUTHOR(S)
30
/*  Wietse Venema
31
/*  IBM T.J. Watson Research
32
/*  P.O. Box 704
33
/*  Yorktown Heights, NY 10598, USA
34
/*
35
/*  Wietse Venema
36
/*  Google, Inc.
37
/*  111 8th Avenue
38
/*  New York, NY 10011, USA
39
/*--*/
40
41
/* System library. */
42
43
#include <sys_defs.h>
44
#include <string.h>
45
46
/* Utility library. */
47
48
#include <msg.h>
49
#include <mymalloc.h>
50
#include <myrand.h>
51
#include <stringops.h>
52
#include <dict_random.h>
53
54
/* Application-specific. */
55
56
typedef struct {
57
    DICT    dict;     /* generic members */
58
    ARGV   *replies;      /* reply values */
59
} DICT_RANDOM;
60
61
#define STR(x) vstring_str(x)
62
63
/* dict_random_lookup - find randomized-table entry */
64
65
static const char *dict_random_lookup(DICT *dict, const char *unused_query)
66
0
{
67
0
    DICT_RANDOM *dict_random = (DICT_RANDOM *) dict;
68
69
0
    DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE,
70
0
   dict_random->replies->argv[myrand() % dict_random->replies->argc]);
71
0
}
72
73
/* dict_random_close - disassociate from randomized table */
74
75
static void dict_random_close(DICT *dict)
76
0
{
77
0
    DICT_RANDOM *dict_random = (DICT_RANDOM *) dict;
78
79
0
    if (dict_random->replies)
80
0
  argv_free(dict_random->replies);
81
0
    dict_free(dict);
82
0
}
83
84
static char *dict_random_parse_name(DICT *dict, ARGV **argv,
85
                    const char *string,
86
                    const char *delim,
87
                    const char *parens)
88
0
{
89
0
    ARGV   *argvp = argv_alloc(1);
90
0
    char   *saved_string = mystrdup(string);
91
0
    char   *bp = saved_string;
92
0
    char   *arg;
93
0
    VSTRING *b64 = 0;
94
0
    char   *err = 0;
95
96
0
    while ((arg = mystrtokq(&bp, delim, parens)) != 0) {
97
0
  if (dict->flags & DICT_FLAG_SRC_RHS_IS_FILE) {
98
0
      if ((b64 = dict_file_to_b64(dict, arg)) != 0) {
99
0
    argv_add(argvp, vstring_str(b64), (char *) 0);
100
0
      } else {
101
0
    err = dict_file_get_error(dict);
102
0
    break;
103
0
      }
104
0
  } else {
105
0
      argv_add(argvp, arg, (char *) 0);
106
0
  }
107
0
    }
108
0
    argv_terminate(argvp);
109
0
    myfree(saved_string);
110
0
    *argv = argvp;
111
0
    return (err);
112
0
}
113
114
/* dict_random_open - open a randomized table */
115
116
DICT   *dict_random_open(const char *name, int open_flags, int dict_flags)
117
0
{
118
0
    DICT_RANDOM *dict_random;
119
0
    char   *saved_name = 0;
120
0
    size_t  len;
121
0
    char   *err = 0;
122
123
    /*
124
     * Clarity first. Let the optimizer worry about redundant code.
125
     */
126
0
#define DICT_RANDOM_RETURN(x) do { \
127
0
  DICT *__d = (x); \
128
0
  if (saved_name != 0) \
129
0
      myfree(saved_name); \
130
0
  if (err != 0) \
131
0
      myfree(err); \
132
0
  return (__d); \
133
0
    } while (0)
134
135
    /*
136
     * Sanity checks.
137
     */
138
0
    if (open_flags != O_RDONLY)
139
0
  DICT_RANDOM_RETURN(dict_surrogate(DICT_TYPE_RANDOM, name,
140
0
            open_flags, dict_flags,
141
0
          "%s:%s map requires O_RDONLY access mode",
142
0
            DICT_TYPE_RANDOM, name));
143
144
    /*
145
     * Bundle up preliminary results.
146
     */
147
0
    dict_random =
148
0
  (DICT_RANDOM *) dict_alloc(DICT_TYPE_RANDOM, name, sizeof(*dict_random));
149
0
    dict_random->dict.lookup = dict_random_lookup;
150
0
    dict_random->dict.close = dict_random_close;
151
0
    dict_random->dict.flags = dict_flags | DICT_FLAG_PATTERN;
152
0
    dict_random->replies = 0;
153
0
    dict_random->dict.owner.status = DICT_OWNER_TRUSTED;
154
0
    dict_random->dict.owner.uid = 0;
155
156
    /*
157
     * Split the table name into its constituent parts.
158
     */
159
0
    if ((len = balpar(name, CHARS_BRACE)) == 0 || name[len] != 0
160
0
  || *(saved_name = mystrndup(name + 1, len - 2)) == 0
161
0
  || (err = dict_random_parse_name(&dict_random->dict,
162
0
           &dict_random->replies, saved_name,
163
0
           CHARS_COMMA_SP, CHARS_BRACE)) != 0
164
0
  || dict_random->replies->argc == 0) {
165
0
  dict_random_close(&dict_random->dict);
166
0
  DICT_RANDOM_RETURN(err == 0 ?
167
0
         dict_surrogate(DICT_TYPE_RANDOM, name,
168
0
            open_flags, dict_flags,
169
0
            "bad syntax: \"%s:%s\"; "
170
0
            "need \"%s:{value...}\"",
171
0
            DICT_TYPE_RANDOM, name,
172
0
            DICT_TYPE_RANDOM) :
173
0
         dict_surrogate(DICT_TYPE_RANDOM, name,
174
0
            open_flags, dict_flags,
175
0
            "%s", err));
176
0
    }
177
0
    dict_file_purge_buffers(&dict_random->dict);
178
0
    DICT_RANDOM_RETURN(DICT_DEBUG (&dict_random->dict));
179
0
}