/*++ /* NAME /* token 3 /* SUMMARY /* tokenize alias/include/.forward entries and deliver /* SYNOPSIS /* #include "local.h" /* /* int deliver_token(state, usr_attr, addr) /* LOCAL_STATE state; /* USER_ATTR usr_attr; /* TOK822 *addr; /* /* int deliver_token_string(state, usr_attr, string, addr_count) /* LOCAL_STATE state; /* USER_ATTR usr_attr; /* char *string; /* int *addr_count; /* /* int deliver_token_stream(state, usr_attr, fp, addr_count) /* LOCAL_STATE state; /* USER_ATTR usr_attr; /* VSTREAM *fp; /* int *addr_count; /* DESCRIPTION /* This module delivers to addresses listed in an alias database /* entry, in an include file, or in a .forward file. /* /* deliver_token() delivers to the address in the given token: /* an absolute /path/name, a ~/path/name relative to the recipient's /* home directory, an :include:/path/name request, an external /* "|command", or a mail address. /* /* deliver_token_string() delivers to all addresses listed in /* the specified string. /* /* deliver_token_stream() delivers to all addresses listed in /* the specified stream. Input records > \fIline_length_limit\fR /* are broken up into multiple records, to prevent the mail /* system from using unreasonable amounts of memory. /* /* Arguments: /* .IP state /* The attributes that specify the message, recipient and more. /* Attributes describing alias, include or forward expansion. /* A table with the results from expanding aliases or lists. /* A table with delivered-to: addresses taken from the message. /* .IP usr_attr /* Attributes describing user rights and environment. /* .IP addr /* A parsed address from an include file, alias file or .forward file. /* .IP string /* A null-terminated string. /* .IP fp /* A readable stream. /* .IP addr_count /* Null pointer, or the address of a counter that is incremented /* by the number of destinations found by the tokenizer. /* DIAGNOSTICS /* Fatal errors: out of memory. The result is non-zero when the /* operation should be tried again. Warnings: malformed address. /* SEE ALSO /* list_token(3) tokenize list /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include #include #include #ifdef STRCASECMP_IN_STRINGS_H #include #endif /* Utility library. */ #include #include #include #include #include #include #include #include /* Global library. */ #include #include #include #include /* Application-specific. */ #include "local.h" /* deliver_token_home - expand ~token */ static int deliver_token_home(LOCAL_STATE state, USER_ATTR usr_attr, char *addr) { char *full_path; int status; if (addr[1] != '/') { /* disallow ~user */ msg_warn("bad home directory syntax for: %s", addr); dsb_simple(state.msg_attr.why, "5.3.5", "mail system configuration error"); status = bounce_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); } else if (usr_attr.home == 0) { /* require user context */ msg_warn("unknown home directory for: %s", addr); dsb_simple(state.msg_attr.why, "5.3.5", "mail system configuration error"); status = bounce_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); } else if (usr_attr.home[0] == '/' && usr_attr.home[1] == 0) { status = deliver_file(state, usr_attr, addr + 1); } else { /* expand ~ to home */ full_path = concatenate(usr_attr.home, addr + 1, (char *) 0); status = deliver_file(state, usr_attr, full_path); myfree(full_path); } return (status); } /* deliver_token - deliver to expansion of include file or alias */ int deliver_token(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr) { VSTRING *addr_buf = vstring_alloc(100); static char include[] = ":include:"; int status; char *path; tok822_internalize(addr_buf, addr->head, TOK822_STR_DEFL); if (msg_verbose) msg_info("deliver_token: %s", STR(addr_buf)); if (*STR(addr_buf) == '/') { status = deliver_file(state, usr_attr, STR(addr_buf)); } else if (*STR(addr_buf) == '~') { status = deliver_token_home(state, usr_attr, STR(addr_buf)); } else if (*STR(addr_buf) == '|') { if ((local_cmd_deliver_mask & state.msg_attr.exp_type) == 0) { dsb_simple(state.msg_attr.why, "5.7.1", "mail to command is restricted"); status = bounce_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); } else status = deliver_command(state, usr_attr, STR(addr_buf) + 1); } else if (strncasecmp(STR(addr_buf), include, sizeof(include) - 1) == 0) { path = STR(addr_buf) + sizeof(include) - 1; status = deliver_include(state, usr_attr, path); } else { status = deliver_resolve_tree(state, usr_attr, addr); } vstring_free(addr_buf); return (status); } /* deliver_token_string - tokenize string and deliver */ int deliver_token_string(LOCAL_STATE state, USER_ATTR usr_attr, char *string, int *addr_count) { TOK822 *tree; TOK822 *addr; int status = 0; if (msg_verbose) msg_info("deliver_token_string: %s", string); tree = tok822_parse(string); for (addr = tree; addr != 0; addr = addr->next) { if (addr->type == TOK822_ADDR) { if (addr_count) (*addr_count)++; status |= deliver_token(state, usr_attr, addr); } } tok822_free_tree(tree); return (status); } /* deliver_token_stream - tokenize stream and deliver */ int deliver_token_stream(LOCAL_STATE state, USER_ATTR usr_attr, VSTREAM *fp, int *addr_count) { VSTRING *buf = vstring_alloc(100); int status = 0; if (msg_verbose) msg_info("deliver_token_stream: %s", VSTREAM_PATH(fp)); while (vstring_fgets_bound(buf, fp, var_line_limit)) { if (*STR(buf) != '#') { status = deliver_token_string(state, usr_attr, STR(buf), addr_count); if (status != 0) break; } } if (vstream_ferror(fp)) { dsb_simple(state.msg_attr.why, "4.3.0", "error reading forwarding file: %m"); status = defer_append(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr)); } vstring_free(buf); return (status); }