home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES3.ZIP / MAIL / alias.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-25  |  16.5 KB  |  453 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    a l i a s . c                                                   */
  3. /*                                                                    */
  4. /*    Smart routing and alias routines for UUPC/extend mail           */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1989-1993 by Kendra Electronic            */
  9. /*    Wonderworks.                                                    */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*                                                                    */
  14. /*    Additional code                                                 */
  15. /*       Copyright (c) Richard H. Lamb 1985, 1986, 1987               */
  16. /*       Changes Copyright (c) Stuart Lynne 1987                      */
  17. /*--------------------------------------------------------------------*/
  18.  
  19. /*--------------------------------------------------------------------*/
  20. /*                          RCS Information                           */
  21. /*--------------------------------------------------------------------*/
  22.  
  23. /*
  24.  *    $Id: alias.c 1.9 1993/10/25 01:21:22 ahd Exp $
  25.  *
  26.  *    Revision history:
  27.  *    $Log: alias.c $
  28.  * Revision 1.9  1993/10/25  01:21:22  ahd
  29.  * Rename Aliases to Nickname to make more unique for end users; allow
  30.  * Aliases as obsolete alias for now.
  31.  *
  32.  * Revision 1.8  1993/10/12  01:32:08  ahd
  33.  * Normalize comments to PL/I style
  34.  *
  35.  * Revision 1.6  1993/07/21  01:19:16  ahd
  36.  * Incr elements after filling info from passwd, not before!
  37.  *
  38.  * Revision 1.5  1993/07/19  02:52:11  ahd
  39.  * Don't load alias for empty names
  40.  *
  41.  * Revision 1.4  1993/05/06  03:41:48  ahd
  42.  * Use expand_path to get reasonable correct drive for aliases file
  43.  *
  44.  * Revision 1.3  1993/04/11  00:33:05  ahd
  45.  * Global edits for year, TEXT, etc.
  46.  *
  47.  * Revision 1.2  1992/11/22  21:06:14  ahd
  48.  * Use strpool for memory allocation
  49.  *
  50.  *    02 Oct 89   Alter large strings/structures to use
  51.  *                malloc()/free()                              ahd
  52.  *    08 Feb 90   Correct failure of ExtractAddress to return
  53.  *                non-names                                    ahd
  54.  *    18 Mar 90   Move checkname() and associated routines into
  55.  *                hostable.c                                   ahd
  56.  *    22 Apr 90   Modify user_at_node to correctly handle .UUCP
  57.  *                alias on local host.                         ahd
  58.  *
  59.  */
  60.  
  61. #include <ctype.h>
  62. #include <stdio.h>
  63. #include <string.h>
  64. #include <stdlib.h>
  65. #include <sys/types.h>
  66.  
  67. #ifndef __TURBOC__
  68. #include <search.h>
  69. #endif
  70.  
  71. #include "lib.h"
  72. #include "hostable.h"
  73. #include "security.h"
  74. #include "usertabl.h"
  75. #include "hlib.h"
  76. #include "alias.h"
  77. #include "address.h"
  78. #include "expath.h"
  79.  
  80. static size_t AliasCount = 0;
  81.  
  82. static struct AliasTable *alias = NULL;
  83.  
  84. int nickcmp( const void *a, const void *b );
  85.  
  86. static size_t LoadAliases( void ) ;
  87.  
  88. currentfile();
  89.  
  90. /*--------------------------------------------------------------------*/
  91. /*    I n i t R o u t e r                                             */
  92. /*                                                                    */
  93. /*    Verify, initialize the global routing data                      */
  94. /*--------------------------------------------------------------------*/
  95.  
  96. boolean InitRouter()
  97. {
  98.    boolean success = TRUE;       /* Assume the input data is good      */
  99.    struct HostTable *Hptr;
  100.  
  101. /*--------------------------------------------------------------------*/
  102. /*          Verify that the user gave us a good name server           */
  103. /*--------------------------------------------------------------------*/
  104.  
  105.    Hptr = checkreal(E_mailserv);
  106.    if (Hptr == BADHOST)
  107.    {
  108.       printmsg(0,"mail server '%s' must be listed in SYSTEMS file",
  109.          E_mailserv);
  110.       success = FALSE;
  111.    }
  112.    else if (Hptr->hstatus == localhost)  /* local system?     */
  113.    {
  114.       printmsg(0,"'%s' is name of this host and cannot be mail server",
  115.             E_mailserv);
  116.       success = FALSE;
  117.    }
  118.  
  119. /*--------------------------------------------------------------------*/
  120. /*                          Return to caller                          */
  121. /*--------------------------------------------------------------------*/
  122.  
  123.    return success;
  124. } /* InitRouter */
  125.  
  126. /*--------------------------------------------------------------------*/
  127. /*    E x t r a c t N a m e                                           */
  128. /*                                                                    */
  129. /*    Returns full name of user, and returns address if name          */
  130. /*    is not available.                                               */
  131. /*--------------------------------------------------------------------*/
  132.  
  133. void ExtractName(char *result, char *column)
  134. {
  135.       static int recursion = 0;
  136.  
  137.       recursion++;
  138.  
  139.       printmsg((recursion > 2) ? 1:8,
  140.             "ExtractName: Getting name from '%s'",column);
  141.  
  142.       ExtractAddress(result, column, TRUE);  /* Get the full name     */
  143.       if (!strlen(result))       /* Did we get the name?              */
  144.       {                          /* No --> Get the e-mail address     */
  145.          char addr[MAXADDR];
  146.          char path[MAXADDR];
  147.          char node[MAXADDR];
  148.          char *fullname;
  149.  
  150.          ExtractAddress(addr,column, FALSE);
  151.          user_at_node(addr,path,node,result);
  152.                                  /* Reduce address to basics */
  153.          fullname = AliasByAddr(node,result);
  154.          if (fullname == NULL)
  155.          {
  156.             strcat(result,"@");
  157.             strcat(result,node);
  158.          }
  159.          else
  160.             strcpy(result,fullname);
  161.       }
  162.  
  163.       printmsg((recursion > 2) ? 1: 8,"ExtractName: name is '%s'",result);
  164.  
  165.       recursion--;
  166.  
  167.       return;
  168. }  /*ExtractName*/
  169.  
  170. /*--------------------------------------------------------------------*/
  171. /*    B u i l d A d d r e s s                                         */
  172. /*                                                                    */
  173. /*    Builds a standard address format, with aliasing as              */
  174. /*    required.                                                       */
  175. /*--------------------------------------------------------------------*/
  176.  
  177. void BuildAddress(char *result, const char *input)
  178. {
  179.    char addr[MAXADDR];
  180.    char name[MAXADDR];
  181.    char user[MAXADDR];
  182.    char path[MAXADDR];
  183.    char node[MAXADDR];
  184.    char *fulladdr;
  185.  
  186. /*--------------------------------------------------------------------*/
  187. /*   It must be a real address, possibly with a name attached; get    */
  188. /*   the address portion, break the address into user and node, and   */
  189. /*   then see if we know the person by address                        */
  190. /*--------------------------------------------------------------------*/
  191.  
  192.       ExtractAddress(addr,input,FALSE);   /* Get user e-mail addr     */
  193.       user_at_node(addr,path,node,user);  /* Break address down       */
  194.  
  195.       fulladdr = AliasByAddr(node,user);  /* Alias for the address?   */
  196.       if (fulladdr != NULL)            /* Yes --> Use it              */
  197.       {
  198.          strcpy(result,fulladdr);
  199.          return;
  200.       } /* if */
  201.  
  202. /*--------------------------------------------------------------------*/
  203. /*   We don't know the address yet; get the name the user provided,   */
  204. /*   and then normalize the address                                   */
  205. /*--------------------------------------------------------------------*/
  206.  
  207.       ExtractAddress(name,input,TRUE);    /* Also get their name      */
  208.  
  209.       if (strlen(name))             /* Did we find a name for user?   */
  210.       {                             /* Yes --> Return it              */
  211.          char *s = strchr(node, '.');
  212.          if ((s == NULL) || equalni( s, ".UUCP", 5))
  213.                                     /* Simple name or UUCP domain?    */
  214.          {                          /* Yes--> Use original address    */
  215.             size_t pathlen = strlen(path);/* Save len of orig path    */
  216.             if ((pathlen > strlen(addr)) &&
  217.                 (!equal(node,path)) && /* Target not a known host?    */
  218.                 equaln(addr,path, strlen(path)) && /* & host starts   */
  219.                 (addr[pathlen] == '!'))   /* ...the address?          */
  220.                fulladdr = &addr[pathlen + 1];   /* Yes --> Drop it    */
  221.             else
  222.                fulladdr = addr;  /* No --> Use full address           */
  223.             sprintf(result,"(%s) %s", name, addr);
  224.          } /* (strchr(node, '.') == NULL) */
  225.          else                    /* No --> Use RFC-822 format         */
  226.             sprintf(result,"\"%s\" <%s@%s>", name, user, node);
  227.       } /* if strlen(name) */
  228.       else
  229.          strcpy(result,addr);    /* No name, just use the original    */
  230. } /* BuildAddress */
  231.  
  232.  
  233. /*--------------------------------------------------------------------*/
  234. /*    A l i a s B y N i c k                                           */
  235. /*                                                                    */
  236. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  237. /*    if alias found and has address, otherwise FALSE.                */
  238. /*--------------------------------------------------------------------*/
  239.  
  240. char *AliasByNick(const char *nick)
  241. {
  242.    int   upper;
  243.    int   lower;
  244.  
  245.    if (!AliasCount)
  246.       AliasCount = LoadAliases();
  247.  
  248.    upper = AliasCount - 1;
  249.    lower = 0;
  250.  
  251.    while (upper >= lower)
  252.    {
  253.       int midpoint;
  254.       int hit;
  255.  
  256.       midpoint = ( upper + lower ) / 2;
  257.       hit = stricmp(nick,alias[midpoint].anick);
  258.       if (!hit)
  259.          return alias[midpoint].afull;
  260.       if ( hit > 0 )
  261.          lower = midpoint + 1;
  262.       else
  263.          upper = midpoint - 1;
  264.    }
  265.    return NULL;
  266. }
  267.  
  268.  
  269. /*--------------------------------------------------------------------*/
  270. /*    A l i a s B y A d d r                                           */
  271. /*                                                                    */
  272. /*    Locate a mail address by search the alias table.  Returns TRUE  */
  273. /*    if alias found and has address, otherwise FALSE                 */
  274. /*--------------------------------------------------------------------*/
  275.  
  276. char *AliasByAddr(const char *node, const char *user)
  277. {
  278.    size_t current = 0;
  279.  
  280.    if (!AliasCount)
  281.       AliasCount = LoadAliases();
  282.  
  283.    while (current < AliasCount)
  284.    {
  285.       int hit;
  286.  
  287.       hit = stricmp(node,alias[current].anode);
  288.       if (!hit)
  289.       {
  290.          hit = stricmp(user,alias[current].auser);
  291.          if (!hit)
  292.             return alias[current].afull;
  293.       }
  294.       current++;
  295.    }
  296.    return NULL;
  297.  
  298. }
  299.  
  300.  
  301. /*--------------------------------------------------------------------*/
  302. /*    L o a d A l i a s e s                                           */
  303. /*                                                                    */
  304. /*    Initializes the address alias table; returns number of aliases  */
  305. /*    loaded                                                          */
  306. /*--------------------------------------------------------------------*/
  307.  
  308. size_t LoadAliases(void)
  309. {
  310.    FILE *ff;
  311.    char buf[BUFSIZ];
  312.    char *token;
  313.    size_t   elements = 0;
  314.    size_t   max_elements = UserElements + 20;
  315.    size_t   subscript;
  316.    struct AliasTable *hit;           /* temporary pointer for searching */
  317.    struct AliasTable target;
  318.  
  319.  
  320.    checkuser( E_mailbox ); /* Force the table to be loaded            */
  321.    alias = calloc(max_elements, sizeof(*alias));
  322.    checkref(alias);
  323.  
  324. /*--------------------------------------------------------------------*/
  325. /*                   Actually load the alias table                    */
  326. /*--------------------------------------------------------------------*/
  327.  
  328.    if (E_nickname != NULL )   /* Did the user specify aliases file?   */
  329.    {
  330.       char fname[FILENAME_MAX];
  331.  
  332.       strcpy( fname, E_nickname);
  333.       expand_path( fname, E_homedir, E_homedir , NULL );
  334.       ff = FOPEN(fname , "r",TEXT_MODE);
  335.  
  336.       if (ff == NULL)
  337.       {
  338.          printerr(fname);
  339.          return elements;
  340.       } /* if */
  341.  
  342.       while (! feof(ff))
  343.       {
  344.          if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line     */
  345.             break;                  /* Exit if end of file             */
  346.          token = strtok(buf," \t\n");
  347.          if (token == NULL)         /* Any data?                       */
  348.             continue;               /* No --> read another line        */
  349.          if (token[0] == '#')
  350.             continue;                  /* Line is a comment; loop again */
  351.  
  352.          /* Add the alias to the table.  Note that we must add the nick */
  353.          /* to the table ourselves (rather than use lsearch) because   */
  354.          /* we must make a copy of the string; the *token we use for   */
  355.          /* the search is in the middle of our I/O buffer!             */
  356.          /*
  357.          /* I was burned, _you_ have been warned.                      */
  358.  
  359.          target.anick = token;
  360.  
  361.          hit = (void *) lfind(&target, alias, &elements , sizeof(alias[0]),
  362.              nickcmp);
  363.          if (hit == NULL)
  364.          {
  365.             char node[MAXADDR];
  366.             char user[MAXADDR];
  367.             char path[MAXADDR];
  368.             char addr[MAXADDR];
  369.             char *eos;
  370.  
  371.             if (elements == max_elements)
  372.             {
  373.                 max_elements = max_elements * 2;
  374.                 alias = realloc(alias, max_elements * sizeof(*alias));
  375.                 checkref(alias);
  376.             }
  377.  
  378.             alias[elements].anick = newstr(token);
  379.             token = strtok(NULL,"");    /* Get rest of string         */
  380.  
  381.             while ( strlen(token) && isspace(*token))
  382.                token++;
  383.             eos = token + strlen(token) - 1;
  384.             while ( strlen(token) && isspace(*eos))
  385.             {
  386.                *eos = '\0';
  387.                eos--;
  388.             }
  389.  
  390.             alias[elements].afull = newstr(token);
  391.             ExtractAddress(addr,alias[elements].afull,FALSE);
  392.             user_at_node(addr,path,node,user);
  393.             alias[elements].anode = newstr(node);
  394.             alias[elements].auser = newstr(user);
  395.             elements += 1;
  396.          }
  397.          else
  398.             printmsg(0,"LoadAliases: Duplicate alias '%s' in table",token);
  399.       }
  400.       fclose(ff);
  401.    } /* if (E_nickname != NULL ) */
  402.  
  403. /*--------------------------------------------------------------------*/
  404. /*           Add the local users as final aliases in table            */
  405. /*--------------------------------------------------------------------*/
  406.  
  407.    alias = realloc(alias, (elements + UserElements) * sizeof(*alias));
  408.                               /* Resize table to final known size     */
  409.    checkref(alias);
  410.  
  411.    for ( subscript = 0; subscript < UserElements;  subscript++)
  412.    {
  413.       if ( equal(users[subscript].realname,EMPTY_GCOS) )
  414.          continue;
  415.  
  416.       alias[elements].anick = "";   /* No nickname, only good for addr */
  417.       if (bflag[F_BANG])
  418.          sprintf(buf, "(%s) %s!%s",
  419.                users[subscript].realname, E_fdomain,
  420.                users[subscript].uid);
  421.       else
  422.          sprintf(buf, "\"%s\" <%s@%s>", users[subscript].realname,
  423.                users[subscript].uid, E_fdomain );
  424.       alias[elements].afull = newstr(buf);
  425.       alias[elements].anode = E_nodename;
  426.       alias[elements].auser = users[subscript].uid;
  427.  
  428.       elements++;
  429.    } /* for */
  430.  
  431. /*--------------------------------------------------------------------*/
  432. /*                         Now sort the table                         */
  433. /*--------------------------------------------------------------------*/
  434.  
  435.    qsort(alias, elements ,sizeof(alias[0]) , nickcmp);
  436.  
  437.    return (elements) ;
  438. } /*LoadAliases*/
  439.  
  440.  
  441. /*--------------------------------------------------------------------*/
  442. /*   n i c k c m p                                                    */
  443. /*                                                                    */
  444. /*   Accepts indirect pointers to two strings and compares them using */
  445. /*   stricmp (case insensitive string compare)                        */
  446. /*--------------------------------------------------------------------*/
  447.  
  448. int nickcmp( const void *a, const void *b )
  449. {
  450.    return stricmp(((struct AliasTable *)a)->anick,
  451.          ((struct AliasTable *)b)->anick);
  452. }  /*nickcmp*/
  453.