5
/* support for master.cf
7
/* #include <postconf.h>
9
/* void read_master(fail_on_open)
12
/* void show_master(mode, filters)
16
/* read_master() reads entries from master.cf into memory.
18
/* show_master() writes the entries in the master.cf file
19
/* to standard output.
23
/* Specify FAIL_ON_OPEN if open failure is a fatal error,
24
/* WARN_ON_OPEN if a warning should be logged instead.
26
/* If the FOLD_LINE flag is set, show_master() wraps long
29
/* A list of zero or more expressions in master_service(3)
30
/* format. If no list is specified, show_master() outputs
31
/* all master.cf entries in the specified order.
33
/* Problems are reported to the standard error stream.
37
/* The Secure Mailer license must be distributed with this software.
40
/* IBM T.J. Watson Research
42
/* Yorktown Heights, NY 10598, USA
50
/* Utility library. */
57
#include <readlline.h>
58
#include <stringops.h>
62
#include <mail_params.h>
63
#include <match_service.h>
65
/* Application-specific. */
69
#define STR(x) vstring_str(x)
71
/* normalize_options - bring options into canonical form */
73
static void normalize_options(ARGV *argv)
79
* Normalize options to simplify later processing.
81
for (field = PC_MASTER_MIN_FIELDS; argv->argv[field] != 0; field++) {
82
arg = argv->argv[field];
83
if (arg[0] != '-' || strcmp(arg, "--") == 0)
85
if (strncmp(arg, "-o", 2) == 0) {
87
/* Split "-oname=value" into "-o" "name=value". */
88
argv_insert_one(argv, field + 1, arg + 2);
89
argv_replace_one(argv, field, "-o");
90
/* arg is now a dangling pointer. */
92
} else if (argv->argv[field + 1] != 0) {
93
/* Already in "-o" "name=value" form. */
100
/* read_master - read and digest the master.cf file */
102
void read_master(int fail_on_open_error)
104
const char *myname = "read_master";
115
if (master_table != 0)
116
msg_panic("%s: master table is already initialized", myname);
119
* Get the location of master.cf.
121
if (var_config_dir == 0)
123
path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
126
* We can't use the master daemon's master_ent routines in their current
127
* form. They convert everything to internal form, and they skip disabled
130
* The postconf command needs to show default fields as "-", and needs to
131
* know about all service names so that it can generate service-dependent
132
* parameter names (transport-dependent etc.).
134
#define MASTER_BLANKS " \t\r\n" /* XXX */
137
* Initialize the in-memory master table.
139
master_table = (PC_MASTER_ENT *) mymalloc(sizeof(*master_table));
142
* Skip blank lines and comment lines. Degrade gracefully if master.cf is
143
* not available, and master.cf is not the primary target.
145
if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0) {
146
if (fail_on_open_error)
147
msg_fatal("open %s: %m", path);
148
msg_warn("open %s: %m", path);
150
buf = vstring_alloc(100);
151
while (readlline(buf, fp, &line_count) != 0) {
152
master_table = (PC_MASTER_ENT *) myrealloc((char *) master_table,
153
(entry_count + 2) * sizeof(*master_table));
154
argv = argv_split(STR(buf), MASTER_BLANKS);
155
if (argv->argc < PC_MASTER_MIN_FIELDS)
156
msg_fatal("file %s: line %d: bad field count",
158
normalize_options(argv);
159
master_table[entry_count].name_space =
160
concatenate(argv->argv[0], ".", argv->argv[1], (char *) 0);
161
master_table[entry_count].argv = argv;
162
master_table[entry_count].valid_names = 0;
163
master_table[entry_count].all_params = 0;
171
* Null-terminate the master table and clean up.
173
master_table[entry_count].argv = 0;
177
/* print_master_line - print one master line */
179
static void print_master_line(int mode, ARGV *argv)
185
int in_daemon_options;
186
static int column_goal[] = {
197
#define ADD_TEXT(text, len) do { \
198
vstream_fputs(text, VSTREAM_OUT); line_len += len; } \
200
#define ADD_SPACE ADD_TEXT(" ", 1)
203
* Show the standard fields at their preferred column position. Use at
204
* least one-space column separation.
206
for (line_len = 0, field = 0; field < PC_MASTER_MIN_FIELDS; field++) {
207
arg = argv->argv[field];
211
} while (line_len < column_goal[field]);
213
ADD_TEXT(arg, strlen(arg));
217
* Format the daemon command-line options and non-option arguments. Here,
218
* we have no data-dependent preference for column positions, but we do
219
* have argument grouping preferences.
221
in_daemon_options = 1;
222
for ( /* void */ ; argv->argv[field] != 0; field++) {
223
arg = argv->argv[field];
224
if (in_daemon_options) {
227
* Try to show the generic options (-v -D) on the first line, and
228
* non-options on a later line.
230
if (arg[0] != '-' || strcmp(arg, "--") == 0) {
231
in_daemon_options = 0;
232
if ((mode & FOLD_LINE)
233
&& line_len > column_goal[PC_MASTER_MIN_FIELDS - 1]) {
234
vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
235
line_len = INDENT_LEN;
240
* Try to avoid breaking "-o name=value" over multiple lines if
241
* it would fit on one line.
243
else if ((mode & FOLD_LINE)
244
&& line_len > INDENT_LEN && strcmp(arg, "-o") == 0
245
&& (aval = argv->argv[field + 1]) != 0
246
&& INDENT_LEN + 3 + strlen(aval) < LINE_LIMIT) {
247
vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
248
line_len = INDENT_LEN;
249
ADD_TEXT(arg, strlen(arg));
256
* Insert a line break when the next argument won't fit (unless, of
257
* course, we just inserted a line break).
259
if (line_len > INDENT_LEN) {
260
if ((mode & FOLD_LINE) == 0
261
|| line_len + 1 + strlen(arg) < LINE_LIMIT) {
264
vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
265
line_len = INDENT_LEN;
268
ADD_TEXT(arg, strlen(arg));
270
vstream_fputs("\n", VSTREAM_OUT);
273
/* show_master - show master.cf entries */
275
void show_master(int mode, char **filters)
277
PC_MASTER_ENT *masterp;
279
ARGV *service_filter = 0;
282
* Initialize the service filter.
285
service_filter = match_service_init_argv(filters);
288
* Iterate over the master table.
290
for (masterp = master_table; (argv = masterp->argv) != 0; masterp++)
291
if (service_filter == 0
292
|| match_service_match(service_filter, masterp->name_space) != 0)
293
print_master_line(mode, argv);
298
if (service_filter != 0)
299
argv_free(service_filter);