7 /* Postfix alias database maintenance
10 /* \fBpostalias\fR [\fB-Nfinoprsvw\fR] [\fB-c \fIconfig_dir\fR]
11 /* [\fB-d \fIkey\fR] [\fB-q \fIkey\fR]
12 /* [\fIfile_type\fR:]\fIfile_name\fR ...
14 /* The \fBpostalias\fR(1) command creates or queries one or more Postfix
15 /* alias databases, or updates an existing one. The input and output
16 /* file formats are expected to be compatible with Sendmail version 8,
17 /* and are expected to be suitable for the use as NIS alias maps.
19 /* If the result files do not exist they will be created with the
20 /* same group and other read permissions as their source file.
22 /* While a database update is in progress, signal delivery is
23 /* postponed, and an exclusive, advisory, lock is placed on the
24 /* entire database, in order to avoid surprises in spectator
27 /* The format of Postfix alias input files is described in
30 /* By default the lookup key is mapped to lowercase to make
31 /* the lookups case insensitive; as of Postfix 2.3 this case
32 /* folding happens only with tables whose lookup keys are
33 /* fixed-case strings such as btree:, dbm: or hash:. With
34 /* earlier versions, the lookup key is folded even with tables
35 /* where a lookup field can match both upper and lower case
36 /* text, such as regexp: and pcre:. This resulted in loss of
37 /* information with $\fInumber\fR substitutions.
40 /* .IP "\fB-c \fIconfig_dir\fR"
41 /* Read the \fBmain.cf\fR configuration file in the named directory
42 /* instead of the default configuration directory.
43 /* .IP "\fB-d \fIkey\fR"
44 /* Search the specified maps for \fIkey\fR and remove one entry per map.
45 /* The exit status is zero when the requested information was found.
47 /* If a key value of \fB-\fR is specified, the program reads key
48 /* values from the standard input stream. The exit status is zero
49 /* when at least one of the requested keys was found.
51 /* Do not fold the lookup key to lower case while creating or querying
54 /* With Postfix version 2.3 and later, this option has no
55 /* effect for regular expression tables. There, case folding
56 /* is controlled by appending a flag to a pattern.
58 /* Incremental mode. Read entries from standard input and do not
59 /* truncate an existing database. By default, \fBpostalias\fR(1) creates
60 /* a new database from the entries in \fIfile_name\fR.
62 /* Include the terminating null character that terminates lookup keys
63 /* and values. By default, \fBpostalias\fR(1) does whatever
65 /* the host operating system.
67 /* Don't include the terminating null character that terminates lookup
68 /* keys and values. By default, \fBpostalias\fR(1) does whatever
70 /* the host operating system.
72 /* Do not release root privileges when processing a non-root
73 /* input file. By default, \fBpostalias\fR(1) drops root privileges
74 /* and runs as the source file owner instead.
76 /* Do not inherit the file access permissions from the input file
77 /* when creating a new file. Instead, create a new file with default
78 /* access permissions (mode 0644).
79 /* .IP "\fB-q \fIkey\fR"
80 /* Search the specified maps for \fIkey\fR and write the first value
81 /* found to the standard output stream. The exit status is zero
82 /* when the requested information was found.
84 /* If a key value of \fB-\fR is specified, the program reads key
85 /* values from the standard input stream and writes one line of
86 /* \fIkey: value\fR output for each key that was found. The exit
87 /* status is zero when at least one of the requested keys was found.
89 /* When updating a table, do not complain about attempts to update
90 /* existing entries, and make those updates anyway.
92 /* Retrieve all database elements, and write one line of
93 /* \fIkey: value\fR output for each element. The elements are
94 /* printed in database order, which is not necessarily the same
95 /* as the original input order.
96 /* This feature is available in Postfix version 2.2 and later,
97 /* and is not available for all database types.
99 /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
100 /* options make the software increasingly verbose.
102 /* When updating a table, do not complain about attempts to update
103 /* existing entries, and ignore those attempts.
106 /* .IP \fIfile_type\fR
107 /* The database type. To find out what types are supported, use
108 /* the "\fBpostconf -m\fR" command.
110 /* The \fBpostalias\fR(1) command can query any supported file type,
111 /* but it can create only the following file types:
114 /* The output is a btree file, named \fIfile_name\fB.db\fR.
115 /* This is available on systems with support for \fBdb\fR databases.
117 /* The output is one file named \fIfile_name\fB.cdb\fR.
118 /* This is available on systems with support for \fBcdb\fR databases.
120 /* The output consists of two files, named \fIfile_name\fB.pag\fR and
121 /* \fIfile_name\fB.dir\fR.
122 /* This is available on systems with support for \fBdbm\fR databases.
124 /* The output is a hashed file, named \fIfile_name\fB.db\fR.
125 /* This is available on systems with support for \fBdb\fR databases.
127 /* The output consists of two files, named \fIfile_name\fB.pag\fR and
128 /* \fIfile_name\fB.dir\fR.
129 /* This is available on systems with support for \fBsdbm\fR databases.
131 /* When no \fIfile_type\fR is specified, the software uses the database
132 /* type specified via the \fBdefault_database_type\fR configuration
134 /* The default value for this parameter depends on the host environment.
136 /* .IP \fIfile_name\fR
137 /* The name of the alias database source file when creating a database.
139 /* Problems are logged to the standard error stream and to
140 /* \fBsyslogd\fR(8). No output means that
141 /* no problems were detected. Duplicate entries are skipped and are
142 /* flagged with a warning.
144 /* \fBpostalias\fR(1) terminates with zero exit status in case of success
145 /* (including successful "\fBpostalias -q\fR" lookup) and terminates
146 /* with non-zero exit status in case of failure.
150 /* .IP \fBMAIL_CONFIG\fR
151 /* Directory with Postfix configuration files.
152 /* .IP \fBMAIL_VERBOSE\fR
153 /* Enable verbose logging for debugging purposes.
154 /* CONFIGURATION PARAMETERS
157 /* The following \fBmain.cf\fR parameters are especially relevant to
160 /* The text below provides only a parameter summary. See
161 /* \fBpostconf\fR(5) for more details including examples.
162 /* .IP "\fBalias_database (see 'postconf -d' output)\fR"
163 /* The alias databases for \fBlocal\fR(8) delivery that are updated with
164 /* "\fBnewaliases\fR" or with "\fBsendmail -bi\fR".
165 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
166 /* The default location of the Postfix main.cf and master.cf
167 /* configuration files.
168 /* .IP "\fBberkeley_db_create_buffer_size (16777216)\fR"
169 /* The per-table I/O buffer size for programs that create Berkeley DB
170 /* hash or btree tables.
171 /* .IP "\fBberkeley_db_read_buffer_size (131072)\fR"
172 /* The per-table I/O buffer size for programs that read Berkeley DB
173 /* hash or btree tables.
174 /* .IP "\fBdefault_database_type (see 'postconf -d' output)\fR"
175 /* The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1)
176 /* and \fBpostmap\fR(1) commands.
177 /* .IP "\fBsyslog_facility (mail)\fR"
178 /* The syslog facility of Postfix logging.
179 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
180 /* The mail system name that is prepended to the process name in syslog
181 /* records, so that "smtpd" becomes, for example, "postfix/smtpd".
183 /* RFC 822 (ARPA Internet Text Messages)
185 /* aliases(5), format of alias database input file.
186 /* local(8), Postfix local delivery agent.
187 /* postconf(1), supported database types
188 /* postconf(5), configuration parameters
189 /* postmap(1), create/update/query lookup tables
190 /* newaliases(1), Sendmail compatibility interface.
191 /* syslogd(8), system logging
195 /* Use "\fBpostconf readme_directory\fR" or
196 /* "\fBpostconf html_directory\fR" to locate this information.
199 /* DATABASE_README, Postfix lookup table overview
203 /* The Secure Mailer license must be distributed with this software.
206 /* IBM T.J. Watson Research
208 /* Yorktown Heights, NY 10598, USA
211 /* System library. */
213 #include <sys_defs.h>
214 #include <sys/stat.h>
221 /* Utility library. */
224 #include <mymalloc.h>
227 #include <msg_vstream.h>
228 #include <msg_syslog.h>
229 #include <readlline.h>
230 #include <stringops.h>
231 #include <split_at.h>
232 #include <vstring_vstream.h>
233 #include <set_eugid.h>
235 /* Global library. */
238 #include <mail_conf.h>
239 #include <mail_dict.h>
240 #include <mail_params.h>
241 #include <mail_version.h>
243 #include <mail_task.h>
244 #include <dict_proxy.h>
246 /* Application-specific. */
248 #define STR vstring_str
250 #define POSTALIAS_FLAG_AS_OWNER (1<<0) /* open dest as owner of source */
251 #define POSTALIAS_FLAG_SAVE_PERM (1<<1) /* copy access permission
254 /* postalias - create or update alias database */
256 static void postalias(char *map_type
, char *path_name
, int postalias_flags
,
257 int open_flags
, int dict_flags
)
260 VSTRING
*line_buffer
;
264 VSTRING
*value_buffer
;
275 line_buffer
= vstring_alloc(100);
276 key_buffer
= vstring_alloc(100);
277 value_buffer
= vstring_alloc(100);
278 if ((open_flags
& O_TRUNC
) == 0) {
279 source_fp
= VSTREAM_IN
;
280 vstream_control(source_fp
, VSTREAM_CTL_PATH
, "stdin", VSTREAM_CTL_END
);
281 } else if (strcmp(map_type
, DICT_TYPE_PROXY
) == 0) {
282 msg_fatal("can't create maps via the proxy service");
283 } else if ((source_fp
= vstream_fopen(path_name
, O_RDONLY
, 0)) == 0) {
284 msg_fatal("open %s: %m", path_name
);
286 if (fstat(vstream_fileno(source_fp
), &st
) < 0)
287 msg_fatal("fstat %s: %m", path_name
);
290 * Turn off group/other read permissions as indicated in the source file.
292 if ((postalias_flags
& POSTALIAS_FLAG_SAVE_PERM
) && S_ISREG(st
.st_mode
))
293 saved_mask
= umask(022 | (~st
.st_mode
& 077));
296 * If running as root, run as the owner of the source file, so that the
297 * result shows proper ownership, and so that a bug in postalias does not
298 * allow privilege escalation.
300 if ((postalias_flags
& POSTALIAS_FLAG_AS_OWNER
) && getuid() == 0
301 && (st
.st_uid
!= geteuid() || st
.st_gid
!= getegid()))
302 set_eugid(st
.st_uid
, st
.st_gid
);
306 * Open the database, create it when it does not exist, truncate it when
307 * it does exist, and lock out any spectators.
309 mkmap
= mkmap_open(map_type
, path_name
, open_flags
, dict_flags
);
312 * And restore the umask, in case it matters.
314 if ((postalias_flags
& POSTALIAS_FLAG_SAVE_PERM
) && S_ISREG(st
.st_mode
))
318 * Add records to the database.
321 while (readlline(line_buffer
, source_fp
, &lineno
)) {
324 * Tokenize the input, so that we do the right thing when a quoted
325 * localpart contains special characters such as "@", ":" and so on.
327 if ((tok_list
= tok822_scan(STR(line_buffer
), (TOK822
**) 0)) == 0)
331 * Enforce the key:value format. Disallow missing keys, multi-address
332 * keys, or missing values. In order to specify an empty string or
333 * value, enclose it in double quotes.
335 if ((colon
= tok822_find_type(tok_list
, ':')) == 0
336 || colon
->prev
== 0 || colon
->next
== 0
337 || tok822_rfind_type(colon
, ',')) {
338 msg_warn("%s, line %d: need name:value pair",
339 VSTREAM_PATH(source_fp
), lineno
);
340 tok822_free_tree(tok_list
);
345 * Key must be local. XXX We should use the Postfix rewriting and
346 * resolving services to handle all address forms correctly. However,
347 * we can't count on the mail system being up when the alias database
348 * is being built, so we're guessing a bit.
350 if (tok822_rfind_type(colon
, '@') || tok822_rfind_type(colon
, '%')) {
351 msg_warn("%s, line %d: name must be local",
352 VSTREAM_PATH(source_fp
), lineno
);
353 tok822_free_tree(tok_list
);
358 * Split the input into key and value parts, and convert from token
359 * representation back to string representation. Convert the key to
360 * internal (unquoted) form, because the resolver produces addresses
361 * in internal form. Convert the value to external (quoted) form,
362 * because it will have to be re-parsed upon lookup. Discard the
363 * token representation when done.
367 value_list
= tok822_cut_after(colon
);
368 tok822_unlink(colon
);
371 tok822_internalize(key_buffer
, key_list
, TOK822_STR_DEFL
);
372 tok822_free_tree(key_list
);
374 tok822_externalize(value_buffer
, value_list
, TOK822_STR_DEFL
);
375 tok822_free_tree(value_list
);
378 * Store the value under a case-insensitive key.
380 mkmap_append(mkmap
, STR(key_buffer
), STR(value_buffer
));
384 * Update or append sendmail and NIS signatures.
386 if ((open_flags
& O_TRUNC
) == 0)
387 mkmap
->dict
->flags
|= DICT_FLAG_DUP_REPLACE
;
390 * Sendmail compatibility: add the @:@ signature to indicate that the
391 * database is complete. This might be needed by NIS clients running
394 mkmap_append(mkmap
, "@", "@");
397 * NIS compatibility: add time and master info. Unlike other information,
398 * this information MUST be written without a trailing null appended to
401 mkmap
->dict
->flags
&= ~DICT_FLAG_TRY1NULL
;
402 mkmap
->dict
->flags
|= DICT_FLAG_TRY0NULL
;
403 vstring_sprintf(value_buffer
, "%010ld", (long) time((time_t *) 0));
404 #if (defined(HAS_NIS) || defined(HAS_NISPLUS))
405 mkmap
->dict
->flags
&= ~DICT_FLAG_FOLD_FIX
;
406 mkmap_append(mkmap
, "YP_LAST_MODIFIED", STR(value_buffer
));
407 mkmap_append(mkmap
, "YP_MASTER_NAME", var_myhostname
);
411 * Close the alias database, and release the lock.
416 * Cleanup. We're about to terminate, but it is a good sanity check.
418 vstring_free(value_buffer
);
419 vstring_free(key_buffer
);
420 vstring_free(line_buffer
);
421 if (source_fp
!= VSTREAM_IN
)
422 vstream_fclose(source_fp
);
425 /* postalias_queries - apply multiple requests from stdin */
427 static int postalias_queries(VSTREAM
*in
, char **maps
, const int map_count
,
428 const int dict_flags
)
431 VSTRING
*keybuf
= vstring_alloc(100);
433 const char *map_name
;
441 msg_panic("postalias_queries: bad map count");
444 * Prepare to open maps lazily.
446 dicts
= (DICT
**) mymalloc(sizeof(*dicts
) * map_count
);
447 for (n
= 0; n
< map_count
; n
++)
451 * Perform all queries. Open maps on the fly, to avoid opening unecessary
454 while (vstring_get_nonl(keybuf
, in
) != VSTREAM_EOF
) {
455 for (n
= 0; n
< map_count
; n
++) {
457 dicts
[n
] = ((map_name
= split_at(maps
[n
], ':')) != 0 ?
458 dict_open3(maps
[n
], map_name
, O_RDONLY
, dict_flags
) :
459 dict_open3(var_db_type
, maps
[n
], O_RDONLY
, dict_flags
));
460 if ((value
= dict_get(dicts
[n
], STR(keybuf
))) != 0) {
462 msg_warn("table %s:%s: key %s: empty string result is not allowed",
463 dicts
[n
]->type
, dicts
[n
]->name
, STR(keybuf
));
464 msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
465 dicts
[n
]->type
, dicts
[n
]->name
);
467 vstream_printf("%s: %s\n", STR(keybuf
), value
);
474 vstream_fflush(VSTREAM_OUT
);
479 for (n
= 0; n
< map_count
; n
++)
481 dict_close(dicts
[n
]);
482 myfree((char *) dicts
);
483 vstring_free(keybuf
);
488 /* postalias_query - query a map and print the result to stdout */
490 static int postalias_query(const char *map_type
, const char *map_name
,
491 const char *key
, int dict_flags
)
496 dict
= dict_open3(map_type
, map_name
, O_RDONLY
, dict_flags
);
497 if ((value
= dict_get(dict
, key
)) != 0) {
499 msg_warn("table %s:%s: key %s: empty string result is not allowed",
500 map_type
, map_name
, key
);
501 msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
504 vstream_printf("%s\n", value
);
506 vstream_fflush(VSTREAM_OUT
);
511 /* postalias_deletes - apply multiple requests from stdin */
513 static int postalias_deletes(VSTREAM
*in
, char **maps
, const int map_count
,
517 VSTRING
*keybuf
= vstring_alloc(100);
519 const char *map_name
;
527 msg_panic("postalias_deletes: bad map count");
530 * Open maps ahead of time.
532 dicts
= (DICT
**) mymalloc(sizeof(*dicts
) * map_count
);
533 for (n
= 0; n
< map_count
; n
++) {
534 map_name
= split_at(maps
[n
], ':');
535 if (map_name
&& strcmp(maps
[n
], DICT_TYPE_PROXY
) == 0)
536 open_flags
= O_RDWR
| O_CREAT
; /* XXX */
539 dicts
[n
] = (map_name
!= 0 ?
540 dict_open3(maps
[n
], map_name
, open_flags
, dict_flags
) :
541 dict_open3(var_db_type
, maps
[n
], open_flags
, dict_flags
));
545 * Perform all requests.
547 while (vstring_get_nonl(keybuf
, in
) != VSTREAM_EOF
)
548 for (n
= 0; n
< map_count
; n
++)
549 found
|= (dict_del(dicts
[n
], STR(keybuf
)) == 0);
554 for (n
= 0; n
< map_count
; n
++)
556 dict_close(dicts
[n
]);
557 myfree((char *) dicts
);
558 vstring_free(keybuf
);
563 /* postalias_delete - delete a key value pair from a map */
565 static int postalias_delete(const char *map_type
, const char *map_name
,
566 const char *key
, int dict_flags
)
572 if (strcmp(map_type
, DICT_TYPE_PROXY
) == 0)
573 open_flags
= O_RDWR
| O_CREAT
; /* XXX */
576 dict
= dict_open3(map_type
, map_name
, open_flags
, dict_flags
);
577 status
= dict_del(dict
, key
);
579 return (status
== 0);
582 /* postalias_seq - print all map entries to stdout */
584 static void postalias_seq(const char *map_type
, const char *map_name
,
592 if (strcmp(map_type
, DICT_TYPE_PROXY
) == 0)
593 msg_fatal("can't sequence maps via the proxy service");
594 dict
= dict_open3(map_type
, map_name
, O_RDONLY
, dict_flags
);
595 for (func
= DICT_SEQ_FUN_FIRST
; /* void */ ; func
= DICT_SEQ_FUN_NEXT
) {
596 if (dict_seq(dict
, func
, &key
, &value
) != 0)
599 msg_warn("table %s:%s: empty lookup key value is not allowed",
601 } else if (*value
== 0) {
602 msg_warn("table %s:%s: key %s: empty string result is not allowed",
603 map_type
, map_name
, key
);
604 msg_warn("table %s:%s should return NO RESULT in case of NOT FOUND",
607 vstream_printf("%s: %s\n", key
, value
);
609 vstream_fflush(VSTREAM_OUT
);
613 /* usage - explain */
615 static NORETURN
usage(char *myname
)
617 msg_fatal("usage: %s [-Nfinoprsvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
621 MAIL_VERSION_STAMP_DECLARE
;
623 int main(int argc
, char **argv
)
630 int postalias_flags
= POSTALIAS_FLAG_AS_OWNER
| POSTALIAS_FLAG_SAVE_PERM
;
631 int open_flags
= O_RDWR
| O_CREAT
| O_TRUNC
;
632 int dict_flags
= DICT_FLAG_DUP_WARN
| DICT_FLAG_FOLD_FIX
;
639 * Fingerprint executables and core dumps.
641 MAIL_VERSION_STAMP_ALLOCATE
;
644 * Be consistent with file permissions.
649 * To minimize confusion, make sure that the standard file descriptors
650 * are open before opening anything else. XXX Work around for 44BSD where
651 * fstat can return EBADF on an open file descriptor.
653 for (fd
= 0; fd
< 3; fd
++)
654 if (fstat(fd
, &st
) == -1
655 && (close(fd
), open("/dev/null", O_RDWR
, 0)) != fd
)
656 msg_fatal("open /dev/null: %m");
659 * Process environment options as early as we can. We are not set-uid,
660 * and we are supposed to be running in a controlled environment.
662 if (getenv(CONF_ENV_VERB
))
666 * Initialize. Set up logging, read the global configuration file and
667 * extract configuration information.
669 if ((slash
= strrchr(argv
[0], '/')) != 0 && slash
[1])
671 msg_vstream_init(argv
[0], VSTREAM_ERR
);
672 msg_syslog_init(mail_task(argv
[0]), LOG_PID
, LOG_FACILITY
);
677 while ((ch
= GETOPT(argc
, argv
, "Nc:d:finopq:rsvw")) > 0) {
683 dict_flags
|= DICT_FLAG_TRY1NULL
;
684 dict_flags
&= ~DICT_FLAG_TRY0NULL
;
687 if (setenv(CONF_ENV_PATH
, optarg
, 1) < 0)
688 msg_fatal("out of memory");
691 if (sequence
|| query
|| delkey
)
692 msg_fatal("specify only one of -s -q or -d");
696 dict_flags
&= ~DICT_FLAG_FOLD_FIX
;
699 open_flags
&= ~O_TRUNC
;
702 dict_flags
|= DICT_FLAG_TRY0NULL
;
703 dict_flags
&= ~DICT_FLAG_TRY1NULL
;
706 postalias_flags
&= ~POSTALIAS_FLAG_AS_OWNER
;
709 postalias_flags
&= ~POSTALIAS_FLAG_SAVE_PERM
;
712 if (sequence
|| query
|| delkey
)
713 msg_fatal("specify only one of -s -q or -d");
717 dict_flags
&= ~(DICT_FLAG_DUP_WARN
| DICT_FLAG_DUP_IGNORE
);
718 dict_flags
|= DICT_FLAG_DUP_REPLACE
;
722 msg_fatal("specify only one of -s or -q or -d");
729 dict_flags
&= ~(DICT_FLAG_DUP_WARN
| DICT_FLAG_DUP_REPLACE
);
730 dict_flags
|= DICT_FLAG_DUP_IGNORE
;
735 if (strcmp(var_syslog_name
, DEF_SYSLOG_NAME
) != 0)
736 msg_syslog_init(mail_task(argv
[0]), LOG_PID
, LOG_FACILITY
);
740 * Use the map type specified by the user, or fall back to a default
743 if (delkey
) { /* remove entry */
744 if (optind
+ 1 > argc
)
746 if (strcmp(delkey
, "-") == 0)
747 exit(postalias_deletes(VSTREAM_IN
, argv
+ optind
, argc
- optind
,
748 dict_flags
| DICT_FLAG_LOCK
) == 0);
750 while (optind
< argc
) {
751 if ((path_name
= split_at(argv
[optind
], ':')) != 0) {
752 found
|= postalias_delete(argv
[optind
], path_name
, delkey
,
753 dict_flags
| DICT_FLAG_LOCK
);
755 found
|= postalias_delete(var_db_type
, argv
[optind
], delkey
,
756 dict_flags
| DICT_FLAG_LOCK
);
761 } else if (query
) { /* query map(s) */
762 if (optind
+ 1 > argc
)
764 if (strcmp(query
, "-") == 0)
765 exit(postalias_queries(VSTREAM_IN
, argv
+ optind
, argc
- optind
,
766 dict_flags
| DICT_FLAG_LOCK
) == 0);
767 while (optind
< argc
) {
768 if ((path_name
= split_at(argv
[optind
], ':')) != 0) {
769 found
= postalias_query(argv
[optind
], path_name
, query
,
770 dict_flags
| DICT_FLAG_LOCK
);
772 found
= postalias_query(var_db_type
, argv
[optind
], query
,
773 dict_flags
| DICT_FLAG_LOCK
);
780 } else if (sequence
) {
781 while (optind
< argc
) {
782 if ((path_name
= split_at(argv
[optind
], ':')) != 0) {
783 postalias_seq(argv
[optind
], path_name
,
784 dict_flags
| DICT_FLAG_LOCK
);
786 postalias_seq(var_db_type
, argv
[optind
],
787 dict_flags
| DICT_FLAG_LOCK
);
792 } else { /* create/update map(s) */
793 if (optind
+ 1 > argc
)
795 while (optind
< argc
) {
796 if ((path_name
= split_at(argv
[optind
], ':')) != 0) {
797 postalias(argv
[optind
], path_name
, postalias_flags
,
798 open_flags
, dict_flags
);
800 postalias(var_db_type
, argv
[optind
], postalias_flags
,
801 open_flags
, dict_flags
);