home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* a l i a s . c */
- /* */
- /* Smart routing and alias routines for UUPC/extend mail */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* Changes Copyright (c) 1989-1993 by Kendra Electronic */
- /* Wonderworks. */
- /* */
- /* All rights reserved except those explicitly granted by the */
- /* UUPC/extended license agreement. */
- /* */
- /* Additional code */
- /* Copyright (c) Richard H. Lamb 1985, 1986, 1987 */
- /* Changes Copyright (c) Stuart Lynne 1987 */
- /*--------------------------------------------------------------------*/
-
- /*--------------------------------------------------------------------*/
- /* RCS Information */
- /*--------------------------------------------------------------------*/
-
- /*
- * $Id: alias.c 1.6 1993/07/21 01:19:16 ahd Exp $
- *
- * Revision history:
- * $Log: alias.c $
- * Revision 1.6 1993/07/21 01:19:16 ahd
- * Incr elements after filling info from passwd, not before!
- *
- * Revision 1.5 1993/07/19 02:52:11 ahd
- * Don't load alias for empty names
- *
- * Revision 1.4 1993/05/06 03:41:48 ahd
- * Use expand_path to get reasonable correct drive for aliases file
- *
- * Revision 1.3 1993/04/11 00:33:05 ahd
- * Global edits for year, TEXT, etc.
- *
- * Revision 1.2 1992/11/22 21:06:14 ahd
- * Use strpool for memory allocation
- *
- * 02 Oct 89 Alter large strings/structures to use
- * malloc()/free() ahd
- * 08 Feb 90 Correct failure of ExtractAddress to return
- * non-names ahd
- * 18 Mar 90 Move checkname() and associated routines into
- * hostable.c ahd
- * 22 Apr 90 Modify user_at_node to correctly handle .UUCP
- * alias on local host. ahd
- *
- */
-
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <sys/types.h>
-
- #ifndef __TURBOC__
- #include <search.h>
- #endif
-
- #include "lib.h"
- #include "hostable.h"
- #include "security.h"
- #include "usertabl.h"
- #include "hlib.h"
- #include "alias.h"
- #include "address.h"
- #include "expath.h"
-
- static size_t AliasCount = 0;
-
- static struct AliasTable *alias = NULL;
-
- int nickcmp( const void *a, const void *b );
-
- static size_t LoadAliases( void ) ;
-
- currentfile();
-
- /*--------------------------------------------------------------------*/
- /* I n i t R o u t e r */
- /* */
- /* Verify, initialize the global routing data */
- /*--------------------------------------------------------------------*/
-
- boolean InitRouter()
- {
- boolean success = TRUE; /* Assume the input data is good */
- struct HostTable *Hptr;
-
- /*--------------------------------------------------------------------*/
- /* Verify that the user gave us a good name server */
- /*--------------------------------------------------------------------*/
-
- Hptr = checkreal(E_mailserv);
- if (Hptr == BADHOST)
- {
- printmsg(0,"mail server '%s' must be listed in SYSTEMS file",
- E_mailserv);
- success = FALSE;
- }
- else if (Hptr->hstatus == localhost) /* local system? */
- {
- printmsg(0,"'%s' is name of this host and cannot be mail server",
- E_mailserv);
- success = FALSE;
- }
-
- /*--------------------------------------------------------------------*/
- /* Return to caller */
- /*--------------------------------------------------------------------*/
-
- return success;
- } /* InitRouter */
-
- /*--------------------------------------------------------------------*/
- /* E x t r a c t N a m e */
- /* */
- /* Returns full name of user, and returns address if name */
- /* is not available. */
- /*--------------------------------------------------------------------*/
-
- void ExtractName(char *result, char *column)
- {
- static int recursion = 0;
-
- recursion++;
-
- printmsg((recursion > 2) ? 1:8,
- "ExtractName: Getting name from '%s'",column);
-
- ExtractAddress(result, column, TRUE); /* Get the full name */
- if (!strlen(result)) /* Did we get the name? */
- { /* No --> Get the e-mail address */
- char addr[MAXADDR];
- char path[MAXADDR];
- char node[MAXADDR];
- char *fullname;
-
- ExtractAddress(addr,column, FALSE);
- user_at_node(addr,path,node,result);
- /* Reduce address to basics */
- fullname = AliasByAddr(node,result);
- if (fullname == NULL)
- {
- strcat(result,"@");
- strcat(result,node);
- }
- else
- strcpy(result,fullname);
- }
-
- printmsg((recursion > 2) ? 1: 8,"ExtractName: name is '%s'",result);
-
- recursion--;
-
- return;
- } /*ExtractName*/
-
- /*--------------------------------------------------------------------*/
- /* B u i l d A d d r e s s */
- /* */
- /* Builds a standard address format, with aliasing as */
- /* required. */
- /*--------------------------------------------------------------------*/
-
- void BuildAddress(char *result, const char *input)
- {
- char addr[MAXADDR];
- char name[MAXADDR];
- char user[MAXADDR];
- char path[MAXADDR];
- char node[MAXADDR];
- char *fulladdr;
-
- /*--------------------------------------------------------------------*/
- /* It must be a real address, possibly with a name attached; get */
- /* the address portion, break the address into user and node, and */
- /* then see if we know the person by address */
- /*--------------------------------------------------------------------*/
-
- ExtractAddress(addr,input,FALSE); /* Get user e-mail addr */
- user_at_node(addr,path,node,user); /* Break address down */
-
- fulladdr = AliasByAddr(node,user); /* Alias for the address? */
- if (fulladdr != NULL) /* Yes --> Use it */
- {
- strcpy(result,fulladdr);
- return;
- } /* if */
-
- /*--------------------------------------------------------------------*/
- /* We don't know the address yet; get the name the user provided, */
- /* and then normalize the address */
- /*--------------------------------------------------------------------*/
-
- ExtractAddress(name,input,TRUE); /* Also get their name */
-
- if (strlen(name)) /* Did we find a name for user? */
- { /* Yes --> Return it */
- char *s = strchr(node, '.');
- if ((s == NULL) || equalni( s, ".UUCP", 5))
- /* Simple name or UUCP domain? */
- { /* Yes--> Use original address */
- size_t pathlen = strlen(path);/* Save len of orig path */
- if ((pathlen > strlen(addr)) &&
- (!equal(node,path)) && /* Target not a known host? */
- equaln(addr,path, strlen(path)) && /* & host starts */
- (addr[pathlen] == '!')) /* ...the address? */
- fulladdr = &addr[pathlen + 1]; /* Yes --> Drop it */
- else
- fulladdr = addr; /* No --> Use full address */
- sprintf(result,"(%s) %s", name, addr);
- } /* (strchr(node, '.') == NULL) */
- else /* No --> Use RFC-822 format */
- sprintf(result,"\"%s\" <%s@%s>", name, user, node);
- } /* if strlen(name) */
- else
- strcpy(result,addr); /* No name, just use the original */
- } /* BuildAddress */
-
-
- /*--------------------------------------------------------------------*/
- /* A l i a s B y N i c k */
- /* */
- /* Locate a mail address by search the alias table. Returns TRUE */
- /* if alias found and has address, otherwise FALSE. */
- /*--------------------------------------------------------------------*/
-
- char *AliasByNick(const char *nick)
- {
- int upper;
- int lower;
-
- if (!AliasCount)
- AliasCount = LoadAliases();
-
- upper = AliasCount - 1;
- lower = 0;
-
- while (upper >= lower)
- {
- int midpoint;
- int hit;
-
- midpoint = ( upper + lower ) / 2;
- hit = stricmp(nick,alias[midpoint].anick);
- if (!hit)
- return alias[midpoint].afull;
- if ( hit > 0 )
- lower = midpoint + 1;
- else
- upper = midpoint - 1;
- }
- return NULL;
- }
-
-
- /*--------------------------------------------------------------------*/
- /* A l i a s B y A d d r */
- /* */
- /* Locate a mail address by search the alias table. Returns TRUE */
- /* if alias found and has address, otherwise FALSE */
- /*--------------------------------------------------------------------*/
-
- char *AliasByAddr(const char *node, const char *user)
- {
- size_t current = 0;
-
- if (!AliasCount)
- AliasCount = LoadAliases();
-
- while (current < AliasCount)
- {
- int hit;
-
- hit = stricmp(node,alias[current].anode);
- if (!hit)
- {
- hit = stricmp(user,alias[current].auser);
- if (!hit)
- return alias[current].afull;
- }
- current++;
- }
- return NULL;
-
- }
-
-
- /*--------------------------------------------------------------------*/
- /* L o a d A l i a s e s */
- /* */
- /* Initializes the address alias table; returns number of aliases */
- /* loaded */
- /*--------------------------------------------------------------------*/
-
- size_t LoadAliases(void)
- {
- FILE *ff;
- char buf[BUFSIZ];
- char *token;
- size_t elements = 0;
- size_t max_elements = UserElements + 20;
- size_t subscript;
- struct AliasTable *hit; /* temporary pointer for searching */
- struct AliasTable target;
-
-
- checkuser( E_mailbox ); /* Force the table to be loaded */
- alias = calloc(max_elements, sizeof(*alias));
- checkref(alias);
-
- /*--------------------------------------------------------------------*/
- /* Actually load the alias table */
- /*--------------------------------------------------------------------*/
-
- if (E_aliases != NULL ) /* Did the user specify aliases file? */
- {
- char fname[FILENAME_MAX];
-
- strcpy( fname, E_aliases);
- expand_path( fname, E_homedir, E_homedir , NULL );
- ff = FOPEN(fname , "r",TEXT_MODE);
-
- if (ff == NULL)
- {
- printerr(fname);
- return elements;
- } /* if */
-
- while (! feof(ff))
- {
- if (fgets(buf,BUFSIZ,ff) == NULL) /* Try to read a line */
- break; /* Exit if end of file */
- token = strtok(buf," \t\n");
- if (token == NULL) /* Any data? */
- continue; /* No --> read another line */
- if (token[0] == '#')
- continue; /* Line is a comment; loop again */
-
- /* Add the alias to the table. Note that we must add the nick */
- /* to the table ourselves (rather than use lsearch) because */
- /* we must make a copy of the string; the *token we use for */
- /* the search is in the middle of our I/O buffer! */
- /*
- /* I was burned, _you_ have been warned. */
-
- target.anick = token;
-
- hit = (void *) lfind(&target, alias, &elements , sizeof(alias[0]),
- nickcmp);
- if (hit == NULL)
- {
- char node[MAXADDR];
- char user[MAXADDR];
- char path[MAXADDR];
- char addr[MAXADDR];
- char *eos;
-
- if (elements == max_elements)
- {
- max_elements = max_elements * 2;
- alias = realloc(alias, max_elements * sizeof(*alias));
- checkref(alias);
- }
-
- alias[elements].anick = newstr(token);
- token = strtok(NULL,""); /* Get rest of string */
-
- while ( strlen(token) && isspace(*token))
- token++;
- eos = token + strlen(token) - 1;
- while ( strlen(token) && isspace(*eos))
- {
- *eos = '\0';
- eos--;
- }
-
- alias[elements].afull = newstr(token);
- ExtractAddress(addr,alias[elements].afull,FALSE);
- user_at_node(addr,path,node,user);
- alias[elements].anode = newstr(node);
- alias[elements].auser = newstr(user);
- elements += 1;
- }
- else
- printmsg(0,"LoadAliases: Duplicate alias '%s' in table",token);
- }
- fclose(ff);
- } /* if (E_aliases != NULL ) */
-
- /*--------------------------------------------------------------------*/
- /* Add the local users as final aliases in table */
- /*--------------------------------------------------------------------*/
-
- alias = realloc(alias, (elements + UserElements) * sizeof(*alias));
- /* Resize table to final known size */
- checkref(alias);
-
- for ( subscript = 0; subscript < UserElements; subscript++)
- {
- if ( equal(users[subscript].realname,EMPTY_GCOS) )
- continue;
-
- alias[elements].anick = ""; /* No nickname, only good for addr */
- if (bflag[F_BANG])
- sprintf(buf, "(%s) %s!%s",
- users[subscript].realname, E_fdomain,
- users[subscript].uid);
- else
- sprintf(buf, "\"%s\" <%s@%s>", users[subscript].realname,
- users[subscript].uid, E_fdomain );
- alias[elements].afull = newstr(buf);
- alias[elements].anode = E_nodename;
- alias[elements].auser = users[subscript].uid;
-
- elements++;
- } /* for */
-
- /*--------------------------------------------------------------------*/
- /* Now sort the table */
- /*--------------------------------------------------------------------*/
-
- qsort(alias, elements ,sizeof(alias[0]) , nickcmp);
-
- return (elements) ;
- } /*LoadAliases*/
-
-
- /*--------------------------------------------------------------------*/
- /* n i c k c m p */
- /* */
- /* Accepts indirect pointers to two strings and compares them using */
- /* stricmp (case insensitive string compare) */
- /*--------------------------------------------------------------------*/
-
- int nickcmp( const void *a, const void *b )
- {
- return stricmp(((struct AliasTable *)a)->anick,
- ((struct AliasTable *)b)->anick);
- } /*nickcmp*/
-