Sync usage with man page.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / local / token.c
blobe3c6dd7275b7b84d9b7515f2ebd1e74f742797e5
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* token 3
6 /* SUMMARY
7 /* tokenize alias/include/.forward entries and deliver
8 /* SYNOPSIS
9 /* #include "local.h"
11 /* int deliver_token(state, usr_attr, addr)
12 /* LOCAL_STATE state;
13 /* USER_ATTR usr_attr;
14 /* TOK822 *addr;
16 /* int deliver_token_string(state, usr_attr, string, addr_count)
17 /* LOCAL_STATE state;
18 /* USER_ATTR usr_attr;
19 /* char *string;
20 /* int *addr_count;
22 /* int deliver_token_stream(state, usr_attr, fp, addr_count)
23 /* LOCAL_STATE state;
24 /* USER_ATTR usr_attr;
25 /* VSTREAM *fp;
26 /* int *addr_count;
27 /* DESCRIPTION
28 /* This module delivers to addresses listed in an alias database
29 /* entry, in an include file, or in a .forward file.
31 /* deliver_token() delivers to the address in the given token:
32 /* an absolute /path/name, a ~/path/name relative to the recipient's
33 /* home directory, an :include:/path/name request, an external
34 /* "|command", or a mail address.
36 /* deliver_token_string() delivers to all addresses listed in
37 /* the specified string.
39 /* deliver_token_stream() delivers to all addresses listed in
40 /* the specified stream. Input records > \fIline_length_limit\fR
41 /* are broken up into multiple records, to prevent the mail
42 /* system from using unreasonable amounts of memory.
44 /* Arguments:
45 /* .IP state
46 /* The attributes that specify the message, recipient and more.
47 /* Attributes describing alias, include or forward expansion.
48 /* A table with the results from expanding aliases or lists.
49 /* A table with delivered-to: addresses taken from the message.
50 /* .IP usr_attr
51 /* Attributes describing user rights and environment.
52 /* .IP addr
53 /* A parsed address from an include file, alias file or .forward file.
54 /* .IP string
55 /* A null-terminated string.
56 /* .IP fp
57 /* A readable stream.
58 /* .IP addr_count
59 /* Null pointer, or the address of a counter that is incremented
60 /* by the number of destinations found by the tokenizer.
61 /* DIAGNOSTICS
62 /* Fatal errors: out of memory. The result is non-zero when the
63 /* operation should be tried again. Warnings: malformed address.
64 /* SEE ALSO
65 /* list_token(3) tokenize list
66 /* LICENSE
67 /* .ad
68 /* .fi
69 /* The Secure Mailer license must be distributed with this software.
70 /* AUTHOR(S)
71 /* Wietse Venema
72 /* IBM T.J. Watson Research
73 /* P.O. Box 704
74 /* Yorktown Heights, NY 10598, USA
75 /*--*/
77 /* System library. */
79 #include <sys_defs.h>
80 #include <unistd.h>
81 #include <string.h>
83 #ifdef STRCASECMP_IN_STRINGS_H
84 #include <strings.h>
85 #endif
87 /* Utility library. */
89 #include <msg.h>
90 #include <vstring.h>
91 #include <vstream.h>
92 #include <htable.h>
93 #include <readlline.h>
94 #include <mymalloc.h>
95 #include <vstring_vstream.h>
96 #include <stringops.h>
98 /* Global library. */
100 #include <tok822.h>
101 #include <mail_params.h>
102 #include <bounce.h>
103 #include <defer.h>
105 /* Application-specific. */
107 #include "local.h"
109 /* deliver_token_home - expand ~token */
111 static int deliver_token_home(LOCAL_STATE state, USER_ATTR usr_attr, char *addr)
113 char *full_path;
114 int status;
116 if (addr[1] != '/') { /* disallow ~user */
117 msg_warn("bad home directory syntax for: %s", addr);
118 dsb_simple(state.msg_attr.why, "5.3.5",
119 "mail system configuration error");
120 status = bounce_append(BOUNCE_FLAGS(state.request),
121 BOUNCE_ATTR(state.msg_attr));
122 } else if (usr_attr.home == 0) { /* require user context */
123 msg_warn("unknown home directory for: %s", addr);
124 dsb_simple(state.msg_attr.why, "5.3.5",
125 "mail system configuration error");
126 status = bounce_append(BOUNCE_FLAGS(state.request),
127 BOUNCE_ATTR(state.msg_attr));
128 } else if (usr_attr.home[0] == '/' && usr_attr.home[1] == 0) {
129 status = deliver_file(state, usr_attr, addr + 1);
130 } else { /* expand ~ to home */
131 full_path = concatenate(usr_attr.home, addr + 1, (char *) 0);
132 status = deliver_file(state, usr_attr, full_path);
133 myfree(full_path);
135 return (status);
138 /* deliver_token - deliver to expansion of include file or alias */
140 int deliver_token(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr)
142 VSTRING *addr_buf = vstring_alloc(100);
143 static char include[] = ":include:";
144 int status;
145 char *path;
147 tok822_internalize(addr_buf, addr->head, TOK822_STR_DEFL);
148 if (msg_verbose)
149 msg_info("deliver_token: %s", STR(addr_buf));
151 if (*STR(addr_buf) == '/') {
152 status = deliver_file(state, usr_attr, STR(addr_buf));
153 } else if (*STR(addr_buf) == '~') {
154 status = deliver_token_home(state, usr_attr, STR(addr_buf));
155 } else if (*STR(addr_buf) == '|') {
156 if ((local_cmd_deliver_mask & state.msg_attr.exp_type) == 0) {
157 dsb_simple(state.msg_attr.why, "5.7.1",
158 "mail to command is restricted");
159 status = bounce_append(BOUNCE_FLAGS(state.request),
160 BOUNCE_ATTR(state.msg_attr));
161 } else
162 status = deliver_command(state, usr_attr, STR(addr_buf) + 1);
163 } else if (strncasecmp(STR(addr_buf), include, sizeof(include) - 1) == 0) {
164 path = STR(addr_buf) + sizeof(include) - 1;
165 status = deliver_include(state, usr_attr, path);
166 } else {
167 status = deliver_resolve_tree(state, usr_attr, addr);
169 vstring_free(addr_buf);
171 return (status);
174 /* deliver_token_string - tokenize string and deliver */
176 int deliver_token_string(LOCAL_STATE state, USER_ATTR usr_attr,
177 char *string, int *addr_count)
179 TOK822 *tree;
180 TOK822 *addr;
181 int status = 0;
183 if (msg_verbose)
184 msg_info("deliver_token_string: %s", string);
186 tree = tok822_parse(string);
187 for (addr = tree; addr != 0; addr = addr->next) {
188 if (addr->type == TOK822_ADDR) {
189 if (addr_count)
190 (*addr_count)++;
191 status |= deliver_token(state, usr_attr, addr);
194 tok822_free_tree(tree);
195 return (status);
198 /* deliver_token_stream - tokenize stream and deliver */
200 int deliver_token_stream(LOCAL_STATE state, USER_ATTR usr_attr,
201 VSTREAM *fp, int *addr_count)
203 VSTRING *buf = vstring_alloc(100);
204 int status = 0;
206 if (msg_verbose)
207 msg_info("deliver_token_stream: %s", VSTREAM_PATH(fp));
209 while (vstring_fgets_bound(buf, fp, var_line_limit)) {
210 if (*STR(buf) != '#') {
211 status = deliver_token_string(state, usr_attr, STR(buf), addr_count);
212 if (status != 0)
213 break;
216 if (vstream_ferror(fp)) {
217 dsb_simple(state.msg_attr.why, "4.3.0",
218 "error reading forwarding file: %m");
219 status = defer_append(BOUNCE_FLAGS(state.request),
220 BOUNCE_ATTR(state.msg_attr));
222 vstring_free(buf);
223 return (status);