232 #include <sys/stat.h>
269 #define STR vstring_str
270 #define LEN VSTRING_LEN
272 #define POSTALIAS_FLAG_AS_OWNER (1<<0)
273 #define POSTALIAS_FLAG_SAVE_PERM (1<<1)
278 static void postalias(
char *map_type,
char *path_name,
int postalias_flags,
279 int open_flags,
int dict_flags)
301 if ((open_flags & O_TRUNC) == 0) {
308 msg_fatal(
"can't create maps via the proxy service");
310 if ((source_fp =
vstream_fopen(path_name, O_RDONLY, 0)) == 0)
320 saved_mask = umask(022 | (~st.st_mode & 077));
328 && (st.st_uid != geteuid() || st.st_gid != getegid()))
335 mkmap =
mkmap_open(map_type, path_name, open_flags, dict_flags);
340 if ((postalias_flags & POSTALIAS_FLAG_SAVE_PERM) && S_ISREG(st.st_mode))
357 while (
readllines(line_buffer, source_fp, &last_line, &lineno)) {
365 msg_warn(
"%s, line %d: non-UTF-8 input \"%s\""
366 " -- ignoring this line",
385 || colon->
prev == 0 || colon->
next == 0
387 msg_warn(
"%s, line %d: need name:value pair",
400 msg_warn(
"%s, line %d: name must be local",
431 msg_fatal(
"table %s:%s: write error: %m",
440 if ((open_flags & O_TRUNC) == 0)
450 msg_fatal(
"table %s:%s: write error: %m",
461 #if (defined(HAS_NIS) || defined(HAS_NISPLUS))
484 static int postalias_queries(
VSTREAM *in,
char **maps,
const int map_count,
485 const int dict_flags)
490 const char *map_name;
498 msg_panic(
"postalias_queries: bad map count");
504 for (n = 0; n < map_count; n++)
512 for (n = 0; n < map_count; n++) {
514 dicts[n] = ((map_name =
split_at(maps[n],
':')) != 0 ?
515 dict_open3(maps[n], map_name, O_RDONLY, dict_flags) :
517 if ((value =
dict_get(dicts[n],
STR(keybuf))) != 0) {
519 msg_warn(
"table %s:%s: key %s: empty string result is not allowed",
520 dicts[n]->type, dicts[n]->name,
STR(keybuf));
521 msg_warn(
"table %s:%s should return NO RESULT in case of NOT FOUND",
522 dicts[n]->type, dicts[n]->name);
529 msg_fatal(
"table %s:%s: query error: %m",
530 dicts[n]->type, dicts[n]->name);
539 for (n = 0; n < map_count; n++)
550 static int postalias_query(
const char *map_type,
const char *map_name,
551 const char *key,
int dict_flags)
556 dict =
dict_open3(map_type, map_name, O_RDONLY, dict_flags);
557 if ((value =
dict_get(dict, key)) != 0) {
559 msg_warn(
"table %s:%s: key %s: empty string result is not allowed",
560 map_type, map_name, key);
561 msg_warn(
"table %s:%s should return NO RESULT in case of NOT FOUND",
575 static int postalias_deletes(
VSTREAM *in,
char **maps,
const int map_count,
581 const char *map_name;
589 msg_panic(
"postalias_deletes: bad map count");
595 for (n = 0; n < map_count; n++) {
598 open_flags = O_RDWR | O_CREAT;
601 dicts[n] = (map_name != 0 ?
602 dict_open3(maps[n], map_name, open_flags, dict_flags) :
610 for (n = 0; n < map_count; n++) {
613 msg_fatal(
"table %s:%s: delete error: %m",
614 dicts[n]->type, dicts[n]->name);
621 for (n = 0; n < map_count; n++)
632 static int postalias_delete(
const char *map_type,
const char *map_name,
633 const char *key,
int dict_flags)
640 open_flags = O_RDWR | O_CREAT;
643 dict =
dict_open3(map_type, map_name, open_flags, dict_flags);
648 return (status == 0);
653 static void postalias_seq(
const char *map_type,
const char *map_name,
662 msg_fatal(
"can't sequence maps via the proxy service");
663 dict =
dict_open3(map_type, map_name, O_RDONLY, dict_flags);
665 if (
dict_seq(dict, func, &key, &value) != 0)
668 msg_warn(
"table %s:%s: empty lookup key value is not allowed",
670 }
else if (*value == 0) {
671 msg_warn(
"table %s:%s: key %s: empty string result is not allowed",
672 map_type, map_name, key);
673 msg_warn(
"table %s:%s should return NO RESULT in case of NOT FOUND",
688 msg_fatal(
"usage: %s [-Nfinoprsuvw] [-c config_dir] [-d key] [-q key] [map_type:]file...",
694 int main(
int argc,
char **argv)
702 int open_flags = O_RDWR | O_CREAT | O_TRUNC;
726 for (fd = 0; fd < 3; fd++)
727 if (
fstat(fd, &st) == -1
728 && (close(fd), open(
"/dev/null", O_RDWR, 0)) != fd)
742 if ((slash = strrchr(argv[0],
'/')) != 0 && slash[1])
755 while ((ch =
GETOPT(argc, argv,
"Nc:d:finopq:rsuvw")) > 0) {
769 if (sequence || query || delkey)
770 msg_fatal(
"specify only one of -s -q or -d");
777 open_flags &= ~O_TRUNC;
790 if (sequence || query || delkey)
791 msg_fatal(
"specify only one of -s -q or -d");
800 msg_fatal(
"specify only one of -s or -q or -d");
829 if (optind + 1 > argc)
831 if (strcmp(delkey,
"-") == 0)
832 exit(postalias_deletes(
VSTREAM_IN, argv + optind, argc - optind,
835 while (optind < argc) {
836 if ((path_name =
split_at(argv[optind],
':')) != 0) {
837 found |= postalias_delete(argv[optind], path_name, delkey,
840 found |= postalias_delete(
var_db_type, argv[optind], delkey,
847 if (optind + 1 > argc)
849 if (strcmp(query,
"-") == 0)
850 exit(postalias_queries(
VSTREAM_IN, argv + optind, argc - optind,
852 while (optind < argc) {
853 if ((path_name =
split_at(argv[optind],
':')) != 0) {
854 found = postalias_query(argv[optind], path_name, query,
857 found = postalias_query(
var_db_type, argv[optind], query,
865 }
else if (sequence) {
866 while (optind < argc) {
867 if ((path_name =
split_at(argv[optind],
':')) != 0) {
868 postalias_seq(argv[optind], path_name,
878 if (optind + 1 > argc)
880 while (optind < argc) {
881 if ((path_name =
split_at(argv[optind],
':')) != 0) {
882 postalias(argv[optind], path_name, postalias_flags,
883 open_flags, dict_flags);
885 postalias(
var_db_type, argv[optind], postalias_flags,
886 open_flags, dict_flags);
#define DICT_FLAG_DUP_IGNORE
int main(int argc, char **argv)
const char * mail_task(const char *argv0)
char * var_import_environ
int vstring_get_nonl(VSTRING *vp, VSTREAM *fp)
ARGV * argv_free(ARGV *argvp)
#define DICT_SEQ_FUN_FIRST
#define VAR_IMPORT_ENVIRON
NORETURN msg_panic(const char *fmt,...)
TOK822 * tok822_rfind_type(TOK822 *, int)
#define DICT_SEQ_FUN_NEXT
#define tok822_scan(cp, ptr)
int valid_utf8_string(const char *, ssize_t)
MAIL_VERSION_STAMP_DECLARE
#define DICT_FLAG_UTF8_REQUEST
#define DICT_FLAG_FOLD_FIX
TOK822 * tok822_free_tree(TOK822 *)
void mail_conf_read(void)
VSTREAM * vstream_fopen(const char *path, int flags, mode_t mode)
DICT * dict_open3(const char *, const char *, int, int)
ARGV * mail_parm_split(const char *name, const char *value)
#define dict_get(dp, key)
#define DICT_FLAG_DUP_REPLACE
int vstream_fclose(VSTREAM *stream)
void mkmap_close(MKMAP *)
#define DICT_FLAG_TRY1NULL
TOK822 * tok822_find_type(TOK822 *, int)
#define dict_seq(dp, f, key, val)
VSTREAM * vstream_printf(const char *fmt,...)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
MKMAP * mkmap_open(const char *, const char *, int, int)
void mail_dict_init(void)
VSTRING * tok822_externalize(VSTRING *, TOK822 *, int)
#define MAIL_VERSION_STAMP_ALLOCATE
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
#define POSTALIAS_FLAG_AS_OWNER
VSTRING * tok822_internalize(VSTRING *, TOK822 *, int)
#define DICT_FLAG_DUP_WARN
NORETURN msg_fatal(const char *fmt,...)
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
#define MAIL_VERSION_CHECK
VSTRING * readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
int vstream_fflush(VSTREAM *stream)
void update_env(char **preserve_list)
void set_eugid(uid_t euid, gid_t egid)
#define GETOPT(argc, argv, str)
void msg_syslog_init(const char *name, int logopt, int facility)
TOK822 * tok822_free(TOK822 *)
#define dict_setjmp(dict)
VSTRING * vstring_free(VSTRING *vp)
char * split_at(char *string, int delimiter)
#define vstream_fileno(vp)
#define mkmap_append(map, key, val)
void msg_vstream_init(const char *name, VSTREAM *vp)
TOK822 * tok822_cut_after(TOK822 *)
#define CA_VSTREAM_CTL_END
#define CA_VSTREAM_CTL_PATH(v)
void vstream_control(VSTREAM *stream, int name,...)
TOK822 * tok822_unlink(TOK822 *)
#define dict_del(dp, key)
#define DICT_FLAG_BULK_UPDATE
#define POSTALIAS_FLAG_SAVE_PERM
#define DICT_FLAG_TRY0NULL
#define DICT_FLAG_UTF8_ACTIVE
void * mymalloc(ssize_t len)