static char rcsid[] = "@(#)$Id: aliaslib.c,v 1.4 1996/05/09 15:51:15 wfp5p Exp $"; /******************************************************************************* * The Elm Mail System - $Revision: 1.4 $ $State: Exp $ * * Copyright (c) 1988-1995 USENET Community Trust * Copyright (c) 1986,1987 Dave Taylor ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * Bill Pemberton, Elm Coordinator * flash@virginia.edu * ******************************************************************************* * $Log: aliaslib.c,v $ * Revision 1.4 1996/05/09 15:51:15 wfp5p * Alpha 10 * * Revision 1.3 1996/03/14 17:27:51 wfp5p * Alpha 9 * * Revision 1.2 1995/09/29 17:41:58 wfp5p * Alpha 8 (Chip's big changes) * * Revision 1.1.1.1 1995/04/19 20:38:34 wfp5p * Initial import of elm 2.4 PL0 as base for elm 2.5. * ******************************************************************************/ /** Library of functions dealing with the alias system... **/ #include "elm_defs.h" #include "elm_globals.h" #include "s_elm.h" /* * Expand "name" as an alias and return a pointer to static data containing * the expansion. If "name" is not an alias, then NULL is returned. */ char *get_alias_address(name, mailing, too_longp) char *name; /* name to expand as an alias */ int mailing; /* TRUE to fully expand group names & recursive aliases */ int *too_longp; /* error code if expansion overflows buffer */ { static char buffer[VERY_LONG_STRING]; char *bufptr; int bufsize, are_in_aliases = TRUE; if (!inalias) { main_state(); are_in_aliases = FALSE; } /* * Reopens files iff changed since last read */ open_alias_files(are_in_aliases); /* * If name is an alias then return its expansion */ bufptr = buffer; bufsize = sizeof(buffer); if (do_get_alias(name,&bufptr,&bufsize,mailing,FALSE,0,too_longp)) { /* * Skip comma/space from add_name_to_list() */ bufptr = buffer+2; } else { /* * Nope...not an alias (or it was too long to expand) */ dprint(2, (debugfile, "Could not expand alias in get_alias_address()%s\n", *too_longp ? "\t...alias buffer overflowed." : "")); bufptr = NULL; } if (! are_in_aliases) main_state(); return(bufptr); } /* * Determine if "name" is an alias, and if so expand it and store the result in * "*bufptr". TRUE returned if any expansion occurs, else FALSE is returned. */ int do_get_alias(name, bufptr, bufsizep, mailing, sysalias, depth, too_longp) char *name; /* name to expand as an alias */ char **bufptr; /* place to store result of expansion */ int *bufsizep; /* available space in the buffer */ int mailing; /* TRUE to fully expand group names & recursive aliases */ int sysalias; /* TRUE to suppress checks of the user's aliases */ int depth; /* recursion depth - initially call at depth=0 */ int *too_longp; /* error code if expansion overflows buffer */ { struct alias_rec *match; char abuf[VERY_LONG_STRING]; int loc; /* update the recursion depth counter */ ++depth; dprint(6, (debugfile, "%*s->attempting alias expansion on \"%s\"\n", (depth*2), "", name)); /* strip out (comments) and leading/trailing whitespace */ remove_possible_trailing_spaces( name = strip_parens(name) ); for ( ; isspace(*name) ; ++name ) ; /* throw back empty addresses */ if ( *name == '\0' ) return FALSE; /* The next two blocks could be merged somewhat */ /* check for a user alias, unless in the midst of sys alias expansion */ if ( !sysalias ) { if ( (loc = find_alias(name, USER)) >= 0 ) { match = aliases[loc]; strcpy(abuf, match->address); if ( match->type & PERSON ) { if (strlen(match->name) > 0) { sprintf(abuf+strlen(abuf), " (%s)", match->name); } } goto do_expand; } } /* check for a system alias */ if ( (loc = find_alias(name, SYSTEM)) >= 0 ) { match = aliases[loc]; strcpy(abuf, match->address); if ( match->type & PERSON ) { if (strlen(match->name) > 0) { sprintf(abuf+strlen(abuf), " (%s)", match->name); } } sysalias = TRUE; goto do_expand; } /* nope...this name wasn't an alias */ return FALSE; do_expand: /* at this point, alias is expanded into "abuf" - now what to do... */ dprint(7, (debugfile, "%*s ->expanded alias to \"%s\"\n", (depth*2), "", abuf)); /* check for an exact match */ loc = strlen(name); if ( strncmp(name, abuf, loc) == 0 && (isspace(abuf[loc]) || abuf[loc] == '\0') ) { if (add_name_to_list(abuf, bufptr, bufsizep)) { return TRUE; } else { *too_longp = TRUE; return FALSE; } } /* see if we are stuck in a loop */ if ( depth > 12 ) { dprint(2, (debugfile, "alias expansion loop detected at \"%s\" - bailing out\n", name)); error1(catgets(elm_msg_cat, ElmSet, ElmErrorExpanding, "Error expanding \"%s\" - probable alias definition loop."), name); return FALSE; } /* see if the alias equivalence is a group name */ if ( mailing && match->type & GROUP ) return do_expand_group(abuf,bufptr,bufsizep,sysalias,depth,too_longp); /* see if the alias equivalence is an email address */ if ( qstrpbrk(abuf,"!@:") != NULL ) { if (add_name_to_list(abuf, bufptr, bufsizep)) { return TRUE; } else { *too_longp = TRUE; return FALSE; } } /* see if the alias equivalence is itself an alias */ if ( mailing && do_get_alias(abuf,bufptr,bufsizep,TRUE,sysalias,depth,too_longp) ) return TRUE; /* the alias equivalence must just be a local address */ if (add_name_to_list(abuf, bufptr, bufsizep)) { return TRUE; } else { *too_longp = TRUE; return FALSE; } } /* * Expand the comma-delimited group of names in "group", storing the result * in "*bufptr". Returns TRUE if expansion occurs OK, else FALSE in the * event of errors. */ int do_expand_group(group, bufptr, bufsizep, sysalias, depth, too_longp) char *group; /* group list to expand */ char **bufptr; /* place to store result of expansion */ int *bufsizep; /* available space in the buffer */ int sysalias; /* TRUE to suppress checks of the user's aliases */ int depth; /* nesting depth */ int *too_longp; /* error code if expansion overflows buffer */ { char *name, *gecos; char expanded_address[LONG_STRING]; /* go through each comma-delimited name in the group */ while ( group != NULL ) { /* extract the next name from the list */ for ( name = group ; isspace(*name) ; ++name ) ; if ( (group = index(name,',')) != NULL ) *group++ = '\0'; remove_possible_trailing_spaces(name); if ( *name == '\0' ) continue; /* see if this name is really an alias */ if (do_get_alias(name,bufptr,bufsizep,TRUE,sysalias,depth,too_longp)) continue; if ( *too_longp ) return FALSE; /* verify it is a valid address */ if ( valid_name(name) ) { gecos = get_full_name(name); if (gecos && (strlen(gecos) > 0)) { sprintf(expanded_address, "%s (%s)", name, gecos); name = expanded_address; } } /* add it to the list */ if ( !add_name_to_list(name, bufptr, bufsizep) ) { *too_longp = TRUE; return FALSE; } } return TRUE; } /* * Append "name" to the list, checking to ensure the buffer * does not overflow. Upon return, *bufptr and *bufsizep will be updated to * reflect the stuff added to the buffer. If a buffer overflow would occur, * an error message is printed and FALSE is returned, else TRUE is returned. */ int add_name_to_list(name,bufptr,bufsizep) register char *name; /* name to append to buffer */ register char **bufptr; /* pointer to pointer to end of buffer */ register int *bufsizep; /* pointer to space remaining in buffer */ { if ( *bufsizep < 0 ) return FALSE; *bufsizep -= strlen(name)+2; if ( *bufsizep <= 0 ) { *bufsizep = -1; dprint(2, (debugfile, "Alias expansion is too long in add_name_to_list()\n")); error(catgets(elm_msg_cat, ElmSet, ElmAliasExpTooLong, "Alias expansion is too long.")); return FALSE; } *(*bufptr)++ = ','; *(*bufptr)++ = ' '; while ( *name != '\0' ) *(*bufptr)++ = *name++ ; **bufptr = '\0'; return TRUE; }