home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / ELM23-2 / ELM23-2.ZIP / src / aliaslib.c < prev    next >
C/C++ Source or Header  |  1991-01-18  |  10KB  |  372 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: aliaslib.c,v 4.1.1.4 90/08/02 21:57:53 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1.1.4 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    aliaslib.c,v $
  17.  * Revision 4.1.1.4  90/08/02  21:57:53  syd
  18.  * The newly introduced function 'stricmp' has a name conflict with a libc
  19.  * function under SunOS 4.1.  Changed name to istrcmp.
  20.  * From: scs@lokkur.dexter.mi.us (Steve Simmons)
  21.  *
  22.  * Revision 4.1.1.3  90/07/12  23:18:17  syd
  23.  * Make domain name checking case independent
  24.  * From: Syd, reported by Steven Baur
  25.  *
  26.  * Revision 4.1.1.2  90/06/05  21:31:34  syd
  27.  * Fix now spurious error message for alias recursive expansion
  28.  * when alias lookup is on a string over 20 chars long.  If that
  29.  * long, its just not an alias, so just return.
  30.  * From: Syd
  31.  *
  32.  * Revision 4.1.1.1  90/06/05  20:41:25  syd
  33.  * Fix boundary condition in add_name_to_list() where it fails to
  34.  * print error message.
  35.  * From: Chip Rosenthal <chip@chinacat.Unicom.COM>
  36.  *
  37.  * Revision 4.1  90/04/28  22:42:29  syd
  38.  * checkin of Elm 2.3 as of Release PL0
  39.  *
  40.  *
  41.  ******************************************************************************/
  42.  
  43. /** Library of functions dealing with the alias system...
  44.  
  45.  **/
  46.  
  47. #include "headers.h"
  48. #include <ctype.h>
  49.  
  50. char *get_alias_address(), *get_token(), *strpbrk(), *index();
  51. long lseek();
  52.  
  53. #ifdef DONT_TOUCH_ADDRESSES
  54. char *expand_system();
  55. #endif
  56.  
  57. /*
  58.  * Expand "name" as an alias and return a pointer to static data containing
  59.  * the expansion.  If "name" is not an alias, then NULL is returned.
  60.  */
  61. char *get_alias_address(name, mailing)
  62. char *name;    /* name to expand as an alias                */
  63. int mailing;    /* TRUE to fully expand group names & recursive aliases    */
  64. {
  65.     static char buffer[VERY_LONG_STRING];
  66.     char *bufptr;
  67.     int bufsize;
  68.  
  69.     /* reads files iff changed since last read */
  70.     read_alias_files();
  71.  
  72.     /* if name is an alias then return its expansion */
  73.     bufptr = buffer;
  74.     bufsize = sizeof(buffer);
  75.     if ( do_get_alias(name, &bufptr, &bufsize, mailing, FALSE, 0) )
  76.       return buffer+2;    /* skip comma/space from add_name_to_list() */
  77.  
  78.     /* nope...not an alias */
  79.     return (char *) NULL;
  80. }
  81.  
  82.  
  83. /*
  84.  * Determine if "name" is an alias, and if so expand it and store the result in
  85.  * "*bufptr".  TRUE returned if any expansion occurs, else FALSE is returned.
  86.  */
  87. int do_get_alias(name, bufptr, bufsizep, mailing, sysalias, depth)
  88. char *name;    /* name to expand as an alias                */
  89. char **bufptr;    /* place to store result of expansion            */
  90. int *bufsizep;    /* available space in the buffer            */
  91. int mailing;    /* TRUE to fully expand group names & recursive aliases    */
  92. int sysalias;    /* TRUE to suppress checks of the user's aliases    */
  93. int depth;    /* recursion depth - initially call at depth=0        */
  94. {
  95.     char abuf[LONG_STRING];
  96.     int loc;
  97.  
  98.     /* update the recursion depth counter */
  99.     ++depth;
  100.  
  101.     dprint(6, (debugfile, "%*s->attempting alias expansion on \"%s\"\n",
  102.         (depth*2), "", name));
  103.  
  104.     /* strip out (comments) and leading/trailing whitespace */
  105.     remove_possible_trailing_spaces( name = strip_parens(name) );
  106.     for ( ; isspace(*name)  ; ++name ) ;
  107.  
  108.     /* throw back empty addresses */
  109.     if ( *name == '\0' )
  110.       return FALSE;
  111.  
  112.     /* check for a user alias, unless in the midst of sys alias expansion */
  113.     if ( !sysalias && user_data != -1 ) {
  114.       if ( (loc = find(name, user_hash_table, MAX_UALIASES)) >= 0 ) {
  115.         lseek(user_data, ntohl(user_hash_table[loc].byte), 0L);
  116.         get_line(user_data, abuf);
  117.         goto do_expand;
  118.       }
  119.     }
  120.  
  121.     /* check for a system alias */
  122.     if ( system_data != -1 ) {
  123.       if ( (loc = find(name, system_hash_table, MAX_SALIASES)) >= 0 ) {
  124.         lseek(system_data, ntohl(system_hash_table[loc].byte), 0L);
  125.         get_line(system_data, abuf);
  126.         sysalias = TRUE;
  127.         goto do_expand;
  128.       }
  129.     }
  130.  
  131.     /* nope...this name wasn't an alias */
  132.     return FALSE;
  133.  
  134. do_expand:
  135.  
  136.     /* at this point, alias is expanded into "abuf" - now what to do... */
  137.  
  138.     dprint(7, (debugfile, "%*s  ->expanded alias to \"%s\"\n",
  139.         (depth*2), "", abuf));
  140.  
  141.     /* check for an exact match */
  142.     loc = strlen(name);
  143.     if (strncmp(name, abuf, loc) == 0 && (abuf[loc] == ' ' || abuf[loc] == '\0'))
  144. #ifdef DONT_TOUCH_ADDRESSES
  145.       return add_name_to_list(abuf, bufptr, bufsizep);
  146. #else
  147.       return add_name_to_list(expand_system(abuf, TRUE), bufptr, bufsizep);
  148. #endif
  149.  
  150.     /* see if we are stuck in a loop */
  151.     if ( depth > 12 ) {
  152.       dprint(2, (debugfile,
  153.           "alias expansion loop detected at \"%s\" - bailing out\n", name));
  154.         error1("Error expanding \"%s\" - probable alias definition loop.",
  155.           name);
  156.         return FALSE;
  157.     }
  158.  
  159.     /* see if the alias equivalence is a group name */
  160.     if ( mailing && abuf[0] == '!' )
  161.       return do_expand_group(abuf+1, bufptr, bufsizep, sysalias, depth);
  162.  
  163.     /* see if the alias equivalence is an email address */
  164.     if ( strpbrk(abuf,"!@:") != NULL ) {
  165. #ifdef DONT_TOUCH_ADDRESSES
  166.       return add_name_to_list(abuf, bufptr, bufsizep);
  167. #else
  168.       return add_name_to_list(expand_system(abuf, TRUE), bufptr, bufsizep);
  169. #endif
  170.     }
  171.  
  172.     /* see if the alias equivalence is itself an alias */
  173.     if ( mailing && do_get_alias(abuf,bufptr,bufsizep,TRUE,sysalias,depth) )
  174.       return TRUE;
  175.  
  176.     /* the alias equivalence must just be a local address */
  177.     return add_name_to_list(abuf, bufptr, bufsizep);
  178. }
  179.  
  180.  
  181. /*
  182.  * Expand the comma-delimited group of names in "group", storing the result
  183.  * in "*bufptr".  Returns TRUE if expansion occurs OK, else FALSE in the
  184.  * event of errors.
  185.  */
  186. int do_expand_group(group, bufptr, bufsizep, sysalias, depth)
  187. char *group;    /* group list to expand                    */
  188. char **bufptr;    /* place to store result of expansion            */
  189. int *bufsizep;    /* available space in the buffer            */
  190. int sysalias;    /* TRUE to suppress checks of the user's aliases    */
  191. int depth;    /* nesting depth                    */
  192. {
  193.     char *name;
  194.  
  195.     /* go through each comma-delimited name in the group */
  196.     while ( group != NULL ) {
  197.  
  198.       /* extract the next name from the list */
  199.       for ( name = group ; isspace(*name) ; ++name ) ;
  200.       if ( (group = index(name,',')) != NULL )
  201.           *group++ = '\0';
  202.       remove_possible_trailing_spaces(name);
  203.       if ( *name == '\0' )
  204.         continue;
  205.  
  206.       /* see if this name is really an alias */
  207.       if ( do_get_alias(name, bufptr, bufsizep, TRUE, sysalias, depth) )
  208.         continue;
  209.  
  210.       /* verify it is a valid address */
  211.       if ( !valid_name(name) ) {
  212.         dprint(3, (debugfile,
  213.         "Illegal address %s during list expansion in %s\n",
  214.         name, "do_get_alias"));
  215.         error1("%s is an illegal address!", name);
  216.         return FALSE;
  217.       }
  218.  
  219.       /* add it to the list */
  220.       if ( !add_name_to_list(name, bufptr, bufsizep) )
  221.         return FALSE;
  222.  
  223.     }
  224.  
  225.     return TRUE;
  226. }
  227.  
  228.  
  229. /*
  230.  * Append "<comma><space>name" to the list, checking to ensure the buffer
  231.  * does not overflow.  Upon return, *bufptr and *bufsizep will be updated to
  232.  * reflect the stuff added to the buffer.  If a buffer overflow would occur,
  233.  * an error message is printed and FALSE is returned, else TRUE is returned.
  234.  */
  235. int add_name_to_list(name,bufptr,bufsizep)
  236. register char *name;    /* name to append to buffer            */
  237. register char **bufptr;    /* pointer to pointer to end of buffer        */
  238. register int *bufsizep;    /* pointer to space remaining in buffer        */
  239. {
  240.     if ( *bufsizep < 0 )
  241.         return FALSE;
  242.  
  243.     *bufsizep -= strlen(name)+2;
  244.     if ( *bufsizep <= 0 ) {
  245.         *bufsizep = -1;
  246.         error("Alias expansion is too long.");
  247.         return FALSE;
  248.     }
  249.  
  250.     *(*bufptr)++ = ',';
  251.     *(*bufptr)++ = ' ';
  252.     while ( *name != '\0' )
  253.       *(*bufptr)++ = *name++ ;
  254.     **bufptr = '\0';
  255.  
  256.     return TRUE;
  257. }
  258.  
  259.  
  260. #ifndef DONT_TOUCH_ADDRESSES
  261. char *expand_system(buffer, show_errors)
  262. char *buffer;
  263. int   show_errors;
  264. {
  265.     /** This routine will check the first machine name in the given path
  266.         (if any) and expand it out if it is an alias...if not, it will
  267.         return what it was given.  If show_errors is false, it won't
  268.         display errors encountered...
  269.     **/
  270.  
  271.     dprint(6, (debugfile, "expand_system(%s, show-errors=%s)\n", buffer,
  272.         onoff(show_errors)));
  273.     findnode(buffer, show_errors);
  274.  
  275.     return( (char *) buffer);
  276. }
  277. #endif
  278.  
  279. int
  280. find(word, table, size)
  281. char *word;
  282. struct alias_rec table[];
  283. int size;
  284. {
  285.     /** find word and return loc, or -1 **/
  286.     register int loc;
  287.  
  288.     /** cannot be an alias if its longer than 20 chars **/
  289.     if (strlen(word) > 20)
  290.       return(-1);
  291.  
  292.     loc = hash_it(word, size);
  293.  
  294.     while (istrcmp(word, table[loc].name) != 0) {
  295.       if (table[loc].name[0] == '\0')
  296.         return(-1);
  297.       loc = (loc + 1) % size;
  298.     }
  299.  
  300.     return(loc);
  301. }
  302.  
  303. int
  304. istrcmp(s1,s2)
  305. register char *s1, *s2;
  306. {
  307.     /* case insensitive comparison */
  308.     register int d;
  309.     for (;;) {
  310.       d = ( isupper(*s1) ? tolower(*s1) : *s1 )
  311.           - ( isupper(*s2) ? tolower(*s2) : *s2 ) ;
  312.       if ( d != 0 || *s1 == '\0' || *s2 == '\0' )
  313.         return d;
  314.       ++s1;
  315.       ++s2;
  316.     }
  317.     /*NOTREACHED*/
  318. }
  319.  
  320. int
  321. strincmp(s1,s2,n)
  322. register char *s1, *s2;
  323. register int n;
  324. {
  325.     /* case insensitive comparison */
  326.     register int d;
  327.     while (--n >= 0) {
  328.       d = ( isupper(*s1) ? tolower(*s1) : *s1 )
  329.           - ( isupper(*s2) ? tolower(*s2) : *s2 ) ;
  330.       if ( d != 0 || *s1 == '\0' || *s2 == '\0' )
  331.         return d;
  332.       ++s1;
  333.       ++s2;
  334.     }
  335.     return(0);
  336. }
  337.  
  338. int
  339. hash_it(string, table_size)
  340. register char *string;
  341. int   table_size;
  342. {
  343.     /** compute the hash function of the string, returning
  344.         it (mod table_size) **/
  345.  
  346.     register int sum = 0;
  347.     for ( ; *string != '\0' ; ++string )
  348.       sum += (int) ( isupper(*string) ? tolower(*string) : *string );
  349.  
  350.     return(sum % table_size);
  351. }
  352.  
  353. get_line(fd, buffer)
  354. int fd;
  355. char *buffer;
  356. {
  357.     /* Read from file fd.  End read upon reading either
  358.        EOF or '\n' character (this is where it differs
  359.        from a straight 'read' command!) */
  360.  
  361.     register int i= 0;
  362.     char     ch;
  363.  
  364.     while (read(fd, &ch, 1) > 0)
  365.       if (ch == '\n' || ch == '\r') {
  366.         buffer[i] = 0;
  367.         return;
  368.       }
  369.       else
  370.         buffer[i++] = ch;
  371. }
  372.