1
2 static char rcsid[] = "@(#)$Id: aliaslib.c,v 1.4 1996/05/09 15:51:15 wfp5p Exp $";
3
4 /*******************************************************************************
5 * The Elm Mail System - $Revision: 1.4 $ $State: Exp $
6 *
7 * Copyright (c) 1988-1995 USENET Community Trust
8 * Copyright (c) 1986,1987 Dave Taylor
9 *******************************************************************************
10 * Bug reports, patches, comments, suggestions should be sent to:
11 *
12 * Bill Pemberton, Elm Coordinator
13 * flash@virginia.edu
14 *
15 *******************************************************************************
16 * $Log: aliaslib.c,v $
17 * Revision 1.4 1996/05/09 15:51:15 wfp5p
18 * Alpha 10
19 *
20 * Revision 1.3 1996/03/14 17:27:51 wfp5p
21 * Alpha 9
22 *
23 * Revision 1.2 1995/09/29 17:41:58 wfp5p
24 * Alpha 8 (Chip's big changes)
25 *
26 * Revision 1.1.1.1 1995/04/19 20:38:34 wfp5p
27 * Initial import of elm 2.4 PL0 as base for elm 2.5.
28 *
29 ******************************************************************************/
30
31 /** Library of functions dealing with the alias system...
32
33 **/
34
35 #include "elm_defs.h"
36 #include "elm_globals.h"
37 #include "s_elm.h"
38
39 /*
40 * Expand "name" as an alias and return a pointer to static data containing
41 * the expansion. If "name" is not an alias, then NULL is returned.
42 */
get_alias_address(name,mailing,too_longp)43 char *get_alias_address(name, mailing, too_longp)
44 char *name; /* name to expand as an alias */
45 int mailing; /* TRUE to fully expand group names & recursive aliases */
46 int *too_longp; /* error code if expansion overflows buffer */
47 {
48 static char buffer[VERY_LONG_STRING];
49 char *bufptr;
50 int bufsize, are_in_aliases = TRUE;
51
52 if (!inalias) {
53 main_state();
54 are_in_aliases = FALSE;
55 }
56 /*
57 * Reopens files iff changed since last read
58 */
59 open_alias_files(are_in_aliases);
60 /*
61 * If name is an alias then return its expansion
62 */
63 bufptr = buffer;
64 bufsize = sizeof(buffer);
65 if (do_get_alias(name,&bufptr,&bufsize,mailing,FALSE,0,too_longp)) {
66 /*
67 * Skip comma/space from add_name_to_list()
68 */
69 bufptr = buffer+2;
70 }
71 else {
72 /*
73 * Nope...not an alias (or it was too long to expand)
74 */
75 dprint(2, (debugfile,
76 "Could not expand alias in get_alias_address()%s\n",
77 *too_longp ? "\t...alias buffer overflowed." : ""));
78 bufptr = NULL;
79 }
80
81 if (! are_in_aliases)
82 main_state();
83
84 return(bufptr);
85 }
86
87
88 /*
89 * Determine if "name" is an alias, and if so expand it and store the result in
90 * "*bufptr". TRUE returned if any expansion occurs, else FALSE is returned.
91 */
do_get_alias(name,bufptr,bufsizep,mailing,sysalias,depth,too_longp)92 int do_get_alias(name, bufptr, bufsizep, mailing, sysalias, depth, too_longp)
93 char *name; /* name to expand as an alias */
94 char **bufptr; /* place to store result of expansion */
95 int *bufsizep; /* available space in the buffer */
96 int mailing; /* TRUE to fully expand group names & recursive aliases */
97 int sysalias; /* TRUE to suppress checks of the user's aliases */
98 int depth; /* recursion depth - initially call at depth=0 */
99 int *too_longp; /* error code if expansion overflows buffer */
100 {
101 struct alias_rec *match;
102 char abuf[VERY_LONG_STRING];
103 int loc;
104
105 /* update the recursion depth counter */
106 ++depth;
107
108 dprint(6, (debugfile, "%*s->attempting alias expansion on \"%s\"\n",
109 (depth*2), "", name));
110
111 /* strip out (comments) and leading/trailing whitespace */
112 remove_possible_trailing_spaces( name = strip_parens(name) );
113 for ( ; isspace(*name) ; ++name ) ;
114
115 /* throw back empty addresses */
116 if ( *name == '\0' )
117 return FALSE;
118
119 /* The next two blocks could be merged somewhat */
120 /* check for a user alias, unless in the midst of sys alias expansion */
121 if ( !sysalias ) {
122 if ( (loc = find_alias(name, USER)) >= 0 ) {
123 match = aliases[loc];
124 strcpy(abuf, match->address);
125 if ( match->type & PERSON ) {
126 if (strlen(match->name) > 0) {
127 sprintf(abuf+strlen(abuf), " (%s)", match->name);
128 }
129 }
130 goto do_expand;
131 }
132 }
133
134 /* check for a system alias */
135 if ( (loc = find_alias(name, SYSTEM)) >= 0 ) {
136 match = aliases[loc];
137 strcpy(abuf, match->address);
138 if ( match->type & PERSON ) {
139 if (strlen(match->name) > 0) {
140 sprintf(abuf+strlen(abuf), " (%s)", match->name);
141 }
142 }
143 sysalias = TRUE;
144 goto do_expand;
145 }
146
147 /* nope...this name wasn't an alias */
148 return FALSE;
149
150 do_expand:
151
152 /* at this point, alias is expanded into "abuf" - now what to do... */
153
154 dprint(7, (debugfile, "%*s ->expanded alias to \"%s\"\n",
155 (depth*2), "", abuf));
156
157 /* check for an exact match */
158 loc = strlen(name);
159 if ( strncmp(name, abuf, loc) == 0 &&
160 (isspace(abuf[loc]) || abuf[loc] == '\0') ) {
161 if (add_name_to_list(abuf, bufptr, bufsizep)) {
162 return TRUE;
163 }
164 else {
165 *too_longp = TRUE;
166 return FALSE;
167 }
168 }
169
170 /* see if we are stuck in a loop */
171 if ( depth > 12 ) {
172 dprint(2, (debugfile,
173 "alias expansion loop detected at \"%s\" - bailing out\n", name));
174 error1(catgets(elm_msg_cat, ElmSet, ElmErrorExpanding,
175 "Error expanding \"%s\" - probable alias definition loop."),
176 name);
177 return FALSE;
178 }
179
180 /* see if the alias equivalence is a group name */
181 if ( mailing && match->type & GROUP )
182 return do_expand_group(abuf,bufptr,bufsizep,sysalias,depth,too_longp);
183
184 /* see if the alias equivalence is an email address */
185 if ( qstrpbrk(abuf,"!@:") != NULL ) {
186 if (add_name_to_list(abuf, bufptr, bufsizep)) {
187 return TRUE;
188 }
189 else {
190 *too_longp = TRUE;
191 return FALSE;
192 }
193 }
194
195 /* see if the alias equivalence is itself an alias */
196 if ( mailing &&
197 do_get_alias(abuf,bufptr,bufsizep,TRUE,sysalias,depth,too_longp) )
198 return TRUE;
199
200 /* the alias equivalence must just be a local address */
201 if (add_name_to_list(abuf, bufptr, bufsizep)) {
202 return TRUE;
203 }
204 else {
205 *too_longp = TRUE;
206 return FALSE;
207 }
208 }
209
210
211 /*
212 * Expand the comma-delimited group of names in "group", storing the result
213 * in "*bufptr". Returns TRUE if expansion occurs OK, else FALSE in the
214 * event of errors.
215 */
do_expand_group(group,bufptr,bufsizep,sysalias,depth,too_longp)216 int do_expand_group(group, bufptr, bufsizep, sysalias, depth, too_longp)
217 char *group; /* group list to expand */
218 char **bufptr; /* place to store result of expansion */
219 int *bufsizep; /* available space in the buffer */
220 int sysalias; /* TRUE to suppress checks of the user's aliases */
221 int depth; /* nesting depth */
222 int *too_longp; /* error code if expansion overflows buffer */
223 {
224 char *name, *gecos;
225 char expanded_address[LONG_STRING];
226
227 /* go through each comma-delimited name in the group */
228 while ( group != NULL ) {
229
230 /* extract the next name from the list */
231 for ( name = group ; isspace(*name) ; ++name ) ;
232 if ( (group = index(name,',')) != NULL )
233 *group++ = '\0';
234 remove_possible_trailing_spaces(name);
235 if ( *name == '\0' )
236 continue;
237
238 /* see if this name is really an alias */
239 if (do_get_alias(name,bufptr,bufsizep,TRUE,sysalias,depth,too_longp))
240 continue;
241
242 if ( *too_longp )
243 return FALSE;
244
245 /* verify it is a valid address */
246 if ( valid_name(name) ) {
247 gecos = get_full_name(name);
248
249 if (gecos && (strlen(gecos) > 0)) {
250 sprintf(expanded_address, "%s (%s)", name, gecos);
251 name = expanded_address;
252 }
253 }
254
255 /* add it to the list */
256 if ( !add_name_to_list(name, bufptr, bufsizep) ) {
257 *too_longp = TRUE;
258 return FALSE;
259 }
260
261 }
262
263 return TRUE;
264 }
265
266
267 /*
268 * Append "<comma><space>name" to the list, checking to ensure the buffer
269 * does not overflow. Upon return, *bufptr and *bufsizep will be updated to
270 * reflect the stuff added to the buffer. If a buffer overflow would occur,
271 * an error message is printed and FALSE is returned, else TRUE is returned.
272 */
add_name_to_list(name,bufptr,bufsizep)273 int add_name_to_list(name,bufptr,bufsizep)
274 register char *name; /* name to append to buffer */
275 register char **bufptr; /* pointer to pointer to end of buffer */
276 register int *bufsizep; /* pointer to space remaining in buffer */
277 {
278 if ( *bufsizep < 0 )
279 return FALSE;
280
281 *bufsizep -= strlen(name)+2;
282 if ( *bufsizep <= 0 ) {
283 *bufsizep = -1;
284 dprint(2, (debugfile,
285 "Alias expansion is too long in add_name_to_list()\n"));
286 error(catgets(elm_msg_cat, ElmSet, ElmAliasExpTooLong,
287 "Alias expansion is too long."));
288 return FALSE;
289 }
290
291 *(*bufptr)++ = ',';
292 *(*bufptr)++ = ' ';
293 while ( *name != '\0' )
294 *(*bufptr)++ = *name++ ;
295 **bufptr = '\0';
296
297 return TRUE;
298 }
299