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