13
13
/* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR]
14
14
/* [\fIparameter=value ...\fR]
16
/* \fBpostconf\fR [\fB-#v\fR] [\fB-c \fIconfig_dir\fR]
17
/* [\fIparameter ...\fR]
16
19
/* \fBpostconf\fR [\fB-btv\fR] [\fB-c \fIconfig_dir\fR] [\fItemplate_file\fR]
18
21
/* The \fBpostconf\fR(1) command displays the actual values
31
34
/* This server plug-in is available when Postfix is built with
32
35
/* Cyrus SASL support.
33
36
/* .IP \fBdovecot\fR
34
/* This server plug-in requires the Dovecot authentication
37
/* This server plug-in uses the Dovecot authentication server,
38
/* and is available when Postfix is built with any form of SASL
38
42
/* This feature is available with Postfix 2.3 and later.
178
182
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
179
183
/* options make the software increasingly verbose.
185
/* Edit the \fBmain.cf\fR configuration file. The file is copied
186
/* to a temporary file then renamed into place. The parameters
187
/* specified on the command line are commented-out, so that they
188
/* revert to their default values. Specify a list of parameter
189
/* names, not name=value pairs. There is no \fBpostconf\fR command
190
/* to perform the reverse operation.
192
/* This feature is available with Postfix 2.6 and later.
181
194
/* Problems are reported to the standard error stream.
282
296
#define SHOW_EVAL (1<<6) /* expand right-hand sides */
283
297
#define SHOW_SASL_SERV (1<<7) /* show server auth plugin types */
284
298
#define SHOW_SASL_CLNT (1<<8) /* show client auth plugin types */
299
#define COMMENT_OUT (1<<9) /* #-out selected main.cf entries */
287
302
* Lookup table for in-core parameter info.
451
472
/* edit_parameters - edit parameter file */
453
static void edit_parameters(int argc, char **argv)
474
static void edit_parameters(int cmd_mode, int argc, char **argv)
455
476
char *config_dir;
460
481
VSTRING *buf = vstring_alloc(100);
479
500
table = htable_create(argc);
480
501
while ((cp = *argv++) != 0) {
481
502
if (strchr(cp, '\n') != 0)
482
msg_fatal("edit accepts no multi-line input");
503
msg_fatal("-e or -# accepts no multi-line input");
483
504
while (ISSPACE(*cp))
486
msg_fatal("edit accepts no comment input");
487
if ((err = split_nameval(cp, &edit_key, &edit_val)) != 0)
488
msg_fatal("%s: \"%s\"", err, cp);
507
msg_fatal("-e or -# accepts no comment input");
508
if (cmd_mode & EDIT_MAIN) {
509
if ((err = split_nameval(cp, &edit_key, &edit_val)) != 0)
510
msg_fatal("%s: \"%s\"", err, cp);
511
} else if (cmd_mode & COMMENT_OUT) {
513
msg_fatal("-# requires non-blank parameter names");
514
if (strchr(cp, '=') != 0)
515
msg_fatal("-# requires parameter names only");
516
edit_key = mystrdup(cp);
517
trimblanks(edit_key, 0);
520
msg_panic("edit_parameters: unknown mode %d", cmd_mode);
489
522
cvalue = (struct cvalue *) mymalloc(sizeof(*cvalue));
490
523
cvalue->value = edit_val;
491
524
cvalue->found = 0;
502
535
set_mail_conf_str(VAR_CONFIG_DIR, var_config_dir);
538
* Open a temp file for the result. This uses a deterministic name so we
539
* don't leave behind thrash with random names.
541
path = concatenate(var_config_dir, "/", "main.cf", (char *) 0);
542
if ((ep = edit_file_open(path, O_CREAT | O_WRONLY, 0644)) == 0)
543
msg_fatal("open %s%s: %m", path, EDIT_FILE_SUFFIX);
505
547
* Open the original file for input.
507
path = concatenate(var_config_dir, "/", "main.cf", (char *) 0);
508
if ((src = vstream_fopen(path, O_RDONLY, 0)) == 0)
549
if ((src = vstream_fopen(path, O_RDONLY, 0)) == 0) {
550
/* OK to delete, since we control the temp file name exclusively. */
551
(void) unlink(ep->tmp_path);
509
552
msg_fatal("open %s for reading: %m", path);
512
* Open a temp file for the result. We use a fixed name so we don't leave
513
* behind thrash with random names. Lock the temp file to avoid
514
* accidents. Truncate the file only after we have an exclusive lock.
516
temp = concatenate(path, ".tmp", (char *) 0);
517
if ((dst = vstream_fopen(temp, O_CREAT | O_WRONLY, 0644)) == 0)
518
msg_fatal("open %s: %m", temp);
519
if (myflock(vstream_fileno(dst), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
520
msg_fatal("lock %s: %m", temp);
521
if (ftruncate(vstream_fileno(dst), 0) < 0)
522
msg_fatal("truncate %s: %m", temp);
525
556
* Copy original file to temp file, while replacing parameters on the
535
566
if (*cp == '#' || *cp == 0) {
536
567
vstream_fputs(STR(buf), dst);
538
/* Copy or skip continued text. */
569
/* Copy, skip or replace continued text. */
539
570
else if (cp > STR(buf)) {
540
571
if (interesting == 0)
541
572
vstream_fputs(STR(buf), dst);
573
else if (cmd_mode & COMMENT_OUT)
574
vstream_fprintf(dst, "#%s", STR(buf));
543
576
/* Copy or replace start of logical line. */
547
580
if ((interesting = !!cvalue) != 0) {
548
581
if (cvalue->found++ == 1)
549
582
msg_warn("%s: multiple entries for \"%s\"", path, STR(key));
550
vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value);
583
if (cmd_mode & EDIT_MAIN)
584
vstream_fprintf(dst, "%s = %s\n", STR(key), cvalue->value);
585
else if (cmd_mode & COMMENT_OUT)
586
vstream_fprintf(dst, "#%s", cp);
588
msg_panic("edit_parameters: unknown mode %d", cmd_mode);
552
590
vstream_fputs(STR(buf), dst);
558
596
* Generate new entries for parameters that were not found.
560
for (ht_info = ht = htable_list(table); *ht; ht++) {
561
cvalue = (struct cvalue *) ht[0]->value;
562
if (cvalue->found == 0)
563
vstream_fprintf(dst, "%s = %s\n", ht[0]->key, cvalue->value);
598
if (cmd_mode & EDIT_MAIN) {
599
for (ht_info = ht = htable_list(table); *ht; ht++) {
600
cvalue = (struct cvalue *) ht[0]->value;
601
if (cvalue->found == 0)
602
vstream_fprintf(dst, "%s = %s\n", ht[0]->key, cvalue->value);
604
myfree((char *) ht_info);
565
myfree((char *) ht_info);
568
608
* When all is well, rename the temp file to the original one.
570
610
if (vstream_fclose(src))
571
611
msg_fatal("read %s: %m", path);
572
if (vstream_fclose(dst))
573
msg_fatal("write %s: %m", temp);
574
if (rename(temp, path) < 0)
575
msg_fatal("rename %s to %s: %m", temp, path);
612
if (edit_file_close(ep) != 0)
613
msg_fatal("close %s%s: %m", path, EDIT_FILE_SUFFIX);
582
619
vstring_free(buf);
583
620
vstring_free(key);
584
621
htable_free(table, myfree);
640
677
const CONFIG_STR_TABLE *cst;
641
678
const CONFIG_STR_FN_TABLE *csft;
642
679
const CONFIG_RAW_TABLE *rst;
680
const CONFIG_NINT_TABLE *nst;
644
682
param_table = htable_create(100);
657
695
htable_enter(param_table, csft->name, (char *) csft);
658
696
for (rst = raw_table; rst->name; rst++)
659
697
htable_enter(param_table, rst->name, (char *) rst);
698
for (nst = nint_table; nst->name; nst++)
699
htable_enter(param_table, nst->name, (char *) nst);
662
702
/* show_strval - show string-valued parameter */
892
/* print_nint - print new integer parameter */
894
static void print_nint(int mode, CONFIG_NINT_TABLE * rst)
898
if (mode & SHOW_EVAL)
899
msg_warn("parameter %s expands at run-time", rst->name);
902
if (mode & SHOW_DEFS) {
903
show_strval(mode, rst->name, rst->defval);
905
value = dict_lookup(CONFIG_DICT, rst->name);
906
if ((mode & SHOW_NONDEF) == 0) {
908
show_strval(mode, rst->name, rst->defval);
910
show_strval(mode, rst->name, value);
914
show_strval(mode, rst->name, value);
852
919
/* print_parameter - show specific parameter */
854
921
static void print_parameter(int mode, char *ptr)
873
940
print_str_fn_2(mode, (CONFIG_STR_FN_TABLE *) ptr);
874
941
if (INSIDE(ptr, raw_table))
875
942
print_raw(mode, (CONFIG_RAW_TABLE *) ptr);
943
if (INSIDE(ptr, nint_table))
944
print_nint(mode, (CONFIG_NINT_TABLE *) ptr);
877
946
vstream_fflush(VSTREAM_OUT);
1013
while ((ch = GETOPT(argc, argv, "aAbc:deEhmlntv")) > 0) {
1082
while ((ch = GETOPT(argc, argv, "aAbc:deE#hmlntv")) > 0) {
1016
1085
cmd_mode |= SHOW_SASL_SERV;
1071
msg_fatal("usage: %s [-a (server SASL types)] [-A (client SASL types)] [-b (bounce templates)] [-c config_dir] [-d (defaults)] [-e (edit)] [-h (no names)] [-l (lock types)] [-m (map types)] [-n (non-defaults)] [-v] [name...]", argv[0]);
1144
msg_fatal("usage: %s [-a (server SASL types)] [-A (client SASL types)] [-b (bounce templates)] [-c config_dir] [-d (defaults)] [-e (edit)] [-# (comment-out)] [-h (no names)] [-l (lock types)] [-m (map types)] [-n (non-defaults)] [-v] [name...]", argv[0]);
1076
1149
* Sanity check.
1078
junk = (cmd_mode & (SHOW_DEFS | SHOW_NONDEF | SHOW_MAPS | SHOW_LOCKS | EDIT_MAIN | SHOW_SASL_SERV | SHOW_SASL_CLNT));
1151
junk = (cmd_mode & (SHOW_DEFS | SHOW_NONDEF | SHOW_MAPS | SHOW_LOCKS | EDIT_MAIN | SHOW_SASL_SERV | SHOW_SASL_CLNT | COMMENT_OUT));
1079
1152
if (junk != 0 && ((junk != SHOW_DEFS && junk != SHOW_NONDEF
1080
1153
&& junk != SHOW_MAPS && junk != SHOW_LOCKS && junk != EDIT_MAIN
1081
&& junk != SHOW_SASL_SERV && junk != SHOW_SASL_CLNT)
1154
&& junk != SHOW_SASL_SERV && junk != SHOW_SASL_CLNT
1155
&& junk != COMMENT_OUT)
1082
1156
|| ext_argv != 0))
1083
msg_fatal("specify one of -a, -A, -b, -d, -e, -m, -l and -n");
1157
msg_fatal("specify one of -a, -A, -b, -d, -e, -#, -m, -l and -n");
1086
1160
* Display bounce template information and exit.
1131
1205
* Edit main.cf.
1133
else if (cmd_mode & EDIT_MAIN) {
1134
edit_parameters(argc - optind, argv + optind);
1207
else if (cmd_mode & (EDIT_MAIN | COMMENT_OUT)) {
1208
edit_parameters(cmd_mode, argc - optind, argv + optind);