181 #define STR vstring_str
185 static const NAME_MASK strategy_table[] = {
201 static int strategy_from_string(
const char *strategy_string)
204 strategy_string,
"|",
210 static const char *strategy_to_string(
VSTRING *res_buf,
int strategy_mask)
214 if (res_buf == 0 && (res_buf = my_buf) == 0)
217 strategy_table, strategy_mask,
228 #define PARTIAL DICT_FLAG_FIXED
232 static const char *find_addr(
MAPS *path,
const char *address,
int flags,
233 int with_domain,
int query_form,
VSTRING *ext_addr_buf)
237 #define SANS_DOMAIN 0
238 #define WITH_DOMAIN 1
240 switch (query_form) {
252 if (result != 0 || path->
error != 0
254 || strcmp(address,
STR(ext_addr_buf)) == 0)
256 result =
maps_find(path, address, flags);
265 result =
maps_find(path, address, flags);
266 if (result != 0 || path->
error != 0
272 if (strcmp(address,
STR(ext_addr_buf)) == 0)
281 msg_panic(
"mail_addr_find: bad query_form: %d", query_form);
288 static const char *find_local(
MAPS *path,
char *ratsign,
int rats_offs,
289 char *int_full_key,
char *int_bare_key,
290 int query_form,
char **extp,
char **saved_ext,
293 const char *myname =
"mail_addr_find";
304 saved_ch = *(
unsigned char *) (ratsign + rats_offs);
305 *(ratsign + rats_offs) = 0;
306 result = find_addr(path, int_full_key,
PARTIAL, with_domain,
307 query_form, ext_addr_buf);
308 *(ratsign + rats_offs) = saved_ch;
309 if (result == 0 && path->
error == 0 && int_bare_key != 0) {
310 if ((ratsign = strrchr(int_bare_key,
'@')) == 0)
312 saved_ch = *(
unsigned char *) (ratsign + rats_offs);
313 *(ratsign + rats_offs) = 0;
314 if ((result = find_addr(path, int_bare_key,
PARTIAL, with_domain,
315 query_form, ext_addr_buf)) != 0
320 *(ratsign + rats_offs) = saved_ch;
328 int in_form,
int query_form,
329 int out_form,
int strategy)
331 const char *myname =
"mail_addr_find";
334 const char *int_addr;
335 static VSTRING *int_result = 0;
349 int_addr =
STR(int_addr_buf);
362 int_bare_key = saved_ext = 0;
374 query_form, ext_addr_buf);
380 if (result == 0 && path->
error == 0 && int_bare_key != 0
382 query_form, ext_addr_buf)) != 0
393 if (result == 0 && path->
error == 0
394 && (ratsign = strrchr(int_full_key,
'@')) != 0
400 result = find_local(path, ratsign, 0, int_full_key,
401 int_bare_key, query_form, extp, &saved_ext,
403 if (result == 0 && path->
error == 0
405 result = find_local(path, ratsign, 1, int_full_key,
406 int_bare_key, query_form, extp, &saved_ext,
415 if (result == 0 && path->
error == 0 && ratsign != 0
422 if (result == 0 && path->
error == 0 && ratsign != 0
428 msg_warn(
"mail_addr_find_opt: do not specify both "
429 "MA_FIND_PDMS and MA_FIND_PDDMDS");
430 for (name = ratsign + 1; *name != 0; name = next) {
433 || (strategy & (MA_FIND_PDMS | MA_FIND_PDDMDS)) == 0
434 || (next = strchr(name + 1,
'.')) == 0)
436 if ((strategy & MA_FIND_PDDMDS) == 0)
445 &&result == 0 && path->
error == 0)
446 result = find_local(path, ratsign, 1, int_full_key,
447 int_bare_key, query_form, extp, &saved_ext,
458 result =
STR(int_result);
465 msg_info(
"%s: %s -> %s", myname, address,
467 path->
error ?
"(try again)" :
494 static NORETURN usage(
const char *progname)
499 int main(
int argc,
char **argv)
510 char *strategy_field;
524 while ((ch =
GETOPT(argc, argv,
"v")) > 0) {
539 #define UPDATE(var, val) do { myfree(var); var = mystrdup(val); } while (0)
562 if (strcmp(cmd,
"echo") == 0) {
569 else if (strcmp(cmd,
"maps") == 0) {
581 else if (path && strcmp(cmd,
"test") == 0) {
587 if ((in_field =
mystrtok(&bp,
":")) == 0)
590 msg_fatal(
"bad input form: '%s'", in_field);
591 if ((query_field =
mystrtok(&bp,
":")) == 0)
595 msg_fatal(
"bad query form: '%s'", query_field);
596 if ((out_field =
mystrtok(&bp,
":")) == 0)
600 msg_fatal(
"bad output form: '%s'", out_field);
601 if ((strategy_field =
mystrtok(&bp,
":")) == 0)
603 if ((strategy_flags = strategy_from_string(strategy_field)) < 0)
604 msg_fatal(
"bad strategy field: '%s'", strategy_field);
605 if ((key_field =
mystrtok(&bp,
":")) == 0)
610 msg_fatal(
"garbage after extension field");
617 in_form, query_form, out_form,
620 in_field, key_field, query_field, out_field, result ? result :
621 path->
error ?
"(try again)" :
622 "(not found)", extent ? extent :
"null extension");
628 if (expect_res && result) {
629 if (strcmp(expect_res, result) != 0) {
630 msg_warn(
"expect result '%s' but got '%s'", expect_res, result);
632 if (expect_ext && extent) {
633 if (strcmp(expect_ext, extent) != 0)
634 msg_warn(
"expect extension '%s' but got '%s'",
637 }
else if (expect_ext && !extent) {
638 msg_warn(
"expect extension '%s' but got none", expect_ext);
640 }
else if (!expect_ext && extent) {
641 msg_warn(
"expect no extension but got '%s'", extent);
645 }
else if (expect_res && !result) {
646 msg_warn(
"expect result '%s' but got none", expect_res);
648 }
else if (!expect_res && result) {
649 msg_warn(
"expected no result but got '%s'", result);
#define vstring_fgets_nonl(s, p)
char * mystrdup(const char *str)
#define MA_FIND_LOCALPART_AT_IF_LOCAL
NORETURN msg_panic(const char *fmt,...)
int main(int argc, char **argv)
VSTRING * unquote_822_local(VSTRING *dst, const char *mbox)
int resolve_local(const char *addr)
#define DICT_FLAG_UTF8_REQUEST
#define strcasecmp_utf8(s1, s2)
char * mystrtok(char **src, const char *sep)
#define DICT_FLAG_FOLD_FIX
VSTRING * quote_822_local_flags(VSTRING *dst, const char *mbox, int flags)
const char * str_name_mask_opt(VSTRING *buf, const char *context, const NAME_MASK *table, int mask, int flags)
const char * mail_addr_find_opt(MAPS *path, const char *address, char **extp, int in_form, int query_form, int out_form, int strategy)
MAPS * maps_create(const char *title, const char *map_names, int dict_flags)
#define QUOTE_FLAG_BARE_LOCALPART
VSTREAM * vstream_printf(const char *fmt,...)
void msg_warn(const char *fmt,...)
int name_mask_delim_opt(const char *context, const NAME_MASK *table, const char *names, const char *delim, int flags)
VSTRING * vstring_alloc(ssize_t len)
#define QUOTE_FLAG_DEFAULT
NORETURN msg_fatal(const char *fmt,...)
MAPS * maps_free(MAPS *maps)
int vstream_fflush(VSTREAM *stream)
#define GETOPT(argc, argv, str)
#define MA_FIND_LOCALPART_AT
#define MA_FIND_LOCALPART_IF_LOCAL
VSTRING * vstring_free(VSTRING *vp)
#define MA_FIND_AT_DOMAIN
#define NAME_MASK_ANY_CASE
char * strip_addr_internal(const char *full, char **extension, const char *delimiter_set)
const char * maps_find(MAPS *maps, const char *name, int flags)
void msg_info(const char *fmt,...)