~ubuntu-branches/ubuntu/vivid/postfix/vivid-proposed

« back to all changes in this revision

Viewing changes to src/postconf/postconf_master.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2012-03-20 13:47:16 UTC
  • mfrom: (1.1.33)
  • mto: This revision was merged to the branch mainline in revision 44.
  • Revision ID: package-import@ubuntu.com-20120320134716-v7ab94fmor2z9pvp
Tags: upstream-2.9.1
ImportĀ upstreamĀ versionĀ 2.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      postconf_master 3
 
4
/* SUMMARY
 
5
/*      support for master.cf
 
6
/* SYNOPSIS
 
7
/*      #include <postconf.h>
 
8
/*
 
9
/*      void    read_master(fail_on_open)
 
10
/*      int     fail_on_open;
 
11
/*
 
12
/*      void    show_master(mode, filters)
 
13
/*      int     mode;
 
14
/*      char    **filters;
 
15
/* DESCRIPTION
 
16
/*      read_master() reads entries from master.cf into memory.
 
17
/*
 
18
/*      show_master() writes the entries in the master.cf file
 
19
/*      to standard output.
 
20
/*
 
21
/*      Arguments
 
22
/* .IP fail_on_open
 
23
/*      Specify FAIL_ON_OPEN if open failure is a fatal error,
 
24
/*      WARN_ON_OPEN if a warning should be logged instead.
 
25
/* .IP mode
 
26
/*      If the FOLD_LINE flag is set, show_master() wraps long
 
27
/*      output lines.
 
28
/* .IP filters
 
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.
 
32
/* DIAGNOSTICS
 
33
/*      Problems are reported to the standard error stream.
 
34
/* LICENSE
 
35
/* .ad
 
36
/* .fi
 
37
/*      The Secure Mailer license must be distributed with this software.
 
38
/* AUTHOR(S)
 
39
/*      Wietse Venema
 
40
/*      IBM T.J. Watson Research
 
41
/*      P.O. Box 704
 
42
/*      Yorktown Heights, NY 10598, USA
 
43
/*--*/
 
44
 
 
45
/* System library. */
 
46
 
 
47
#include <sys_defs.h>
 
48
#include <string.h>
 
49
 
 
50
/* Utility library. */
 
51
 
 
52
#include <msg.h>
 
53
#include <mymalloc.h>
 
54
#include <vstring.h>
 
55
#include <argv.h>
 
56
#include <vstream.h>
 
57
#include <readlline.h>
 
58
#include <stringops.h>
 
59
 
 
60
/* Global library. */
 
61
 
 
62
#include <mail_params.h>
 
63
#include <match_service.h>
 
64
 
 
65
/* Application-specific. */
 
66
 
 
67
#include <postconf.h>
 
68
 
 
69
#define STR(x) vstring_str(x)
 
70
 
 
71
/* normalize_options - bring options into canonical form */
 
72
 
 
73
static void normalize_options(ARGV *argv)
 
74
{
 
75
    int     field;
 
76
    char   *arg;
 
77
 
 
78
    /*
 
79
     * Normalize options to simplify later processing.
 
80
     */
 
81
    for (field = PC_MASTER_MIN_FIELDS; argv->argv[field] != 0; field++) {
 
82
        arg = argv->argv[field];
 
83
        if (arg[0] != '-' || strcmp(arg, "--") == 0)
 
84
            break;
 
85
        if (strncmp(arg, "-o", 2) == 0) {
 
86
            if (arg[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. */
 
91
                field += 1;
 
92
            } else if (argv->argv[field + 1] != 0) {
 
93
                /* Already in "-o" "name=value" form. */
 
94
                field += 1;
 
95
            }
 
96
        }
 
97
    }
 
98
}
 
99
 
 
100
/* read_master - read and digest the master.cf file */
 
101
 
 
102
void    read_master(int fail_on_open_error)
 
103
{
 
104
    const char *myname = "read_master";
 
105
    char   *path;
 
106
    VSTRING *buf;
 
107
    ARGV   *argv;
 
108
    VSTREAM *fp;
 
109
    int     entry_count = 0;
 
110
    int     line_count = 0;
 
111
 
 
112
    /*
 
113
     * Sanity check.
 
114
     */
 
115
    if (master_table != 0)
 
116
        msg_panic("%s: master table is already initialized", myname);
 
117
 
 
118
    /*
 
119
     * Get the location of master.cf.
 
120
     */
 
121
    if (var_config_dir == 0)
 
122
        set_config_dir();
 
123
    path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
 
124
 
 
125
    /*
 
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
 
128
     * services.
 
129
     * 
 
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.).
 
133
     */
 
134
#define MASTER_BLANKS   " \t\r\n"               /* XXX */
 
135
 
 
136
    /*
 
137
     * Initialize the in-memory master table.
 
138
     */
 
139
    master_table = (PC_MASTER_ENT *) mymalloc(sizeof(*master_table));
 
140
 
 
141
    /*
 
142
     * Skip blank lines and comment lines. Degrade gracefully if master.cf is
 
143
     * not available, and master.cf is not the primary target.
 
144
     */
 
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);
 
149
    } else {
 
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",
 
157
                          path, line_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;
 
164
            entry_count += 1;
 
165
        }
 
166
        vstream_fclose(fp);
 
167
        vstring_free(buf);
 
168
    }
 
169
 
 
170
    /*
 
171
     * Null-terminate the master table and clean up.
 
172
     */
 
173
    master_table[entry_count].argv = 0;
 
174
    myfree(path);
 
175
}
 
176
 
 
177
/* print_master_line - print one master line */
 
178
 
 
179
static void print_master_line(int mode, ARGV *argv)
 
180
{
 
181
    char   *arg;
 
182
    char   *aval;
 
183
    int     line_len;
 
184
    int     field;
 
185
    int     in_daemon_options;
 
186
    static int column_goal[] = {
 
187
        0,                              /* service */
 
188
        11,                             /* type */
 
189
        17,                             /* private */
 
190
        25,                             /* unpriv */
 
191
        33,                             /* chroot */
 
192
        41,                             /* wakeup */
 
193
        49,                             /* maxproc */
 
194
        57,                             /* command */
 
195
    };
 
196
 
 
197
#define ADD_TEXT(text, len) do { \
 
198
        vstream_fputs(text, VSTREAM_OUT); line_len += len; } \
 
199
    while (0)
 
200
#define ADD_SPACE ADD_TEXT(" ", 1)
 
201
 
 
202
    /*
 
203
     * Show the standard fields at their preferred column position. Use at
 
204
     * least one-space column separation.
 
205
     */
 
206
    for (line_len = 0, field = 0; field < PC_MASTER_MIN_FIELDS; field++) {
 
207
        arg = argv->argv[field];
 
208
        if (line_len > 0) {
 
209
            do {
 
210
                ADD_SPACE;
 
211
            } while (line_len < column_goal[field]);
 
212
        }
 
213
        ADD_TEXT(arg, strlen(arg));
 
214
    }
 
215
 
 
216
    /*
 
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.
 
220
     */
 
221
    in_daemon_options = 1;
 
222
    for ( /* void */ ; argv->argv[field] != 0; field++) {
 
223
        arg = argv->argv[field];
 
224
        if (in_daemon_options) {
 
225
 
 
226
            /*
 
227
             * Try to show the generic options (-v -D) on the first line, and
 
228
             * non-options on a later line.
 
229
             */
 
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;
 
236
                }
 
237
            }
 
238
 
 
239
            /*
 
240
             * Try to avoid breaking "-o name=value" over multiple lines if
 
241
             * it would fit on one line.
 
242
             */
 
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));
 
250
                arg = aval;
 
251
                field += 1;
 
252
            }
 
253
        }
 
254
 
 
255
        /*
 
256
         * Insert a line break when the next argument won't fit (unless, of
 
257
         * course, we just inserted a line break).
 
258
         */
 
259
        if (line_len > INDENT_LEN) {
 
260
            if ((mode & FOLD_LINE) == 0
 
261
                || line_len + 1 + strlen(arg) < LINE_LIMIT) {
 
262
                ADD_SPACE;
 
263
            } else {
 
264
                vstream_fputs("\n" INDENT_TEXT, VSTREAM_OUT);
 
265
                line_len = INDENT_LEN;
 
266
            }
 
267
        }
 
268
        ADD_TEXT(arg, strlen(arg));
 
269
    }
 
270
    vstream_fputs("\n", VSTREAM_OUT);
 
271
}
 
272
 
 
273
/* show_master - show master.cf entries */
 
274
 
 
275
void    show_master(int mode, char **filters)
 
276
{
 
277
    PC_MASTER_ENT *masterp;
 
278
    ARGV   *argv;
 
279
    ARGV   *service_filter = 0;
 
280
 
 
281
    /*
 
282
     * Initialize the service filter.
 
283
     */
 
284
    if (filters[0])
 
285
        service_filter = match_service_init_argv(filters);
 
286
 
 
287
    /*
 
288
     * Iterate over the master table.
 
289
     */
 
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);
 
294
 
 
295
    /*
 
296
     * Cleanup.
 
297
     */
 
298
    if (service_filter != 0)
 
299
        argv_free(service_filter);
 
300
}