summaryrefslogtreecommitdiffstats
path: root/src/local/token.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/local/token.c')
-rw-r--r--src/local/token.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/local/token.c b/src/local/token.c
new file mode 100644
index 0000000..2eb0c28
--- /dev/null
+++ b/src/local/token.c
@@ -0,0 +1,222 @@
+/*++
+/* 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 <sys_defs.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <htable.h>
+#include <readlline.h>
+#include <mymalloc.h>
+#include <vstring_vstream.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <tok822.h>
+#include <mail_params.h>
+#include <bounce.h>
+#include <defer.h>
+
+/* 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);
+}