home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / elm.lzh / ELM / SRC / ALIASDB.C < prev    next >
C/C++ Source or Header  |  1991-01-11  |  10KB  |  398 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: aliasdb.c,v 4.1.1.1 90/06/21 23:21:47 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1.1.1 $   $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:    aliasdb.c,v $
  17.  * Revision 4.1.1.1  90/06/21  23:21:47  syd
  18.  * Add missing check for eof and for failure of scanf
  19.  * From: Ross Johnson
  20.  * 
  21.  * Revision 4.1  90/04/28  22:42:28  syd
  22.  * checkin of Elm 2.3 as of Release PL0
  23.  * 
  24.  *
  25.  ******************************************************************************/
  26.  
  27. /** Alias database files...
  28.  
  29. **/
  30.  
  31.  
  32. #include "headers.h"
  33.  
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include <errno.h>
  37.  
  38. extern int errno;
  39.  
  40. #ifdef USE_DBM
  41. # include <dbm.h>
  42. #endif
  43.  
  44. #define  absolute(x)        ((x) > 0 ? x : -(x))
  45.  
  46. char *find_path_to(), *strcat(), *strcpy();
  47. unsigned long sleep();
  48.  
  49. #ifndef DONT_TOUCH_ADDRESSES
  50. int  findnode_has_been_initialized = FALSE;
  51. #endif
  52.  
  53. findnode(name, display_error)
  54. char *name;
  55. int   display_error;
  56. {
  57.     /** break 'name' into machine!user or user@machine and then
  58.         see if you can find 'machine' in the path database..
  59.         If so, return name as the expanded address.  If not,
  60.         return what was given to us!   If display_error, then
  61.         do so...
  62.     **/
  63.  
  64. #ifndef DONT_TOUCH_ADDRESSES
  65.     
  66.     char   old_name[SLEN];
  67.     char   address[SLEN];
  68.  
  69.     if (strlen(name) == 0)
  70.       return;
  71.     
  72.     if (! findnode_has_been_initialized) {
  73.       if (warnings)
  74.         error("Initializing internal tables...");
  75. #ifndef USE_DBM
  76.       get_connections();
  77.       open_domain_file();
  78. #endif
  79.       init_findnode();
  80.       clear_error();
  81.           findnode_has_been_initialized = TRUE;
  82.     }
  83.  
  84.     strcpy(old_name, name);        /* save what we were given */
  85.  
  86.     if (expand_site(name, address) == -1) {
  87.           if (display_error && name[0] != '!') {
  88.         dprint(3, (debugfile, "Couldn't expand host %s in address.\n",
  89.                  name));
  90.         if (! check_only && warnings) {
  91.           error1("Couldn't expand system %s.", name);
  92.           sleep(1);
  93.         }
  94.       }
  95.       strcpy(name, old_name);    /* and restore... */
  96.     }
  97.     else
  98.       strcpy(name, address);
  99. #endif
  100.     return;
  101. }
  102.  
  103. #if defined(OPTIMIZE_RETURN) || !defined(DONT_TOUCH_ADDRESSES)
  104. int
  105. expand_site(cryptic, expanded)
  106. char *cryptic, *expanded;
  107. {
  108.  
  109.     /** Given an address of the form 'xyz@site' or 'site!xyz'
  110.         return an address of the form <expanded address for site>
  111.             with 'xyz' embedded according to the path database entry.
  112.         Note that 'xyz' can be eiher a simple address (as in "joe")
  113.         or a complex address (as in "joe%xerox.parc@Xerox.ARPA")!
  114.         0 = found, -1 return means unknown site code 
  115.     
  116.         Modified to strip out parenthetical comments...
  117.     **/
  118.  
  119. #ifdef ACSNET
  120.  
  121.     strcpy(expanded, cryptic);    /* fast and simple */
  122.     return(0);
  123.  
  124. #else
  125. # ifdef USE_DBM
  126.     datum  key, contents;
  127. # endif
  128.  
  129.     char   name[VERY_LONG_STRING], sitename[VERY_LONG_STRING], 
  130.                temp[VERY_LONG_STRING], old_name[VERY_LONG_STRING],
  131.            comment[LONG_STRING];
  132.     char   *expand_domain(), *addr;
  133.     register int i = 0, j = 0, in_parens = 0, domain_name;
  134.  
  135.     strcpy(old_name, cryptic);    /* remember what we were given */
  136.  
  137.     /** break down **/
  138.  
  139.     /** first, rip out the comment, if any, noting nested parens **/
  140.  
  141.     if ((i = chloc(cryptic, '(')) > -1) {
  142.       comment[j++] = ' ';            /* leading space */
  143.       do {
  144.           switch(comment[j++] = cryptic[i++]) {
  145.         case '(':    in_parens++;
  146.             break;
  147.         case ')':    in_parens--;
  148.             break;
  149.         }
  150.       } while(in_parens && cryptic[i] != '\0');
  151.       comment[j] = '\0';
  152.  
  153.       /* and remove this from cryptic string too... */
  154.       if (cryptic[(j = chloc(cryptic,'('))-1] == ' ')
  155.         cryptic[j-1] = '\0';
  156.       else
  157.         cryptic[j] = '\0';
  158.     }
  159.     else
  160.       comment[0] = '\0';
  161.  
  162.     i = j = 0;    /* reset */
  163.  
  164.     while (cryptic[i] != AT_SIGN && cryptic[i] != BANG && 
  165.            cryptic[i] != '\0' && cryptic[i] != '(')
  166.       sitename[j++] = cryptic[i++];
  167.  
  168.     sitename[j++] = '\0';
  169.  
  170.     j = 0;
  171.     
  172.     if (cryptic[i] == '\0') return(-1);    /* nothing to expand! */
  173.  
  174.     domain_name = (cryptic[i] == AT_SIGN);
  175.  
  176.     i++;
  177.  
  178.     while (cryptic[i] != '\0' && cryptic[i] != '(' && 
  179.                ! whitespace(cryptic[i]))
  180.       name[j++] = cryptic[i++];
  181.  
  182.     name[j] = '\0';
  183.  
  184.     if (domain_name) {
  185.       strcpy(temp, name);
  186.       strcpy(name, sitename);
  187.       strcpy(sitename, temp);
  188.     }
  189.  
  190.     dprint(5, (debugfile, "\nBroke address into '%s' @ '%s' '%s'\n\n",
  191.         name, sitename, comment));
  192.  
  193. #ifdef USE_DBM
  194.  
  195.     if (size_of_pathfd == 0)
  196.       return(-1);
  197.  
  198.     key.dptr  = sitename;
  199.     key.dsize = strlen(sitename) + 1;
  200.  
  201.     contents = fetch(key);
  202.  
  203.     if (contents.dptr == 0) 
  204.       return(-1);            /* can't find it! */
  205.  
  206.     sprintf(expanded, contents.dptr, name);
  207.     strcat(expanded, " ");            /* add a single space... */
  208.     strcat(expanded, comment);        /*    ...and add comment */
  209.     return(0);
  210. #else
  211.  
  212. #ifndef LOOK_CLOSE_AFTER_SEARCH
  213.  
  214.     if (talk_to(sitename)) {
  215.       strcpy(expanded, old_name);    /* restore! */
  216.       return(0);
  217.     }
  218. #endif
  219.  
  220.     if ((addr = find_path_to(sitename, TRUE)) == NULL) {
  221.  
  222. #ifdef LOOK_CLOSE_AFTER_SEARCH
  223.  
  224.         if (talk_to(sitename)) {
  225.           strcpy(expanded, old_name);    /* restore! */
  226.           return(0);
  227.         }
  228.         else
  229. #endif
  230.         if ((addr = expand_domain(cryptic)) != NULL) {
  231.            strcpy(expanded, addr);    /* into THIS buffer */
  232.            strcat(expanded, comment);    /* patch in comment */
  233.            return(0);
  234.         }
  235.         else  if (size_of_pathfd == 0) {    /* no path database! */
  236.           strcpy(expanded, old_name);    /* restore! */
  237.           return(0);
  238.         }
  239.         else {                 /* We just can't get there! */
  240.           strcpy(expanded, old_name);    /* restore! */
  241.           return(-1);
  242.         }
  243.     }
  244.     else {            /* search succeeded */
  245.        sprintf(expanded, addr, name);
  246.        strcat(expanded, comment);        /* add comment */
  247.        return(0);
  248.     }
  249. #endif
  250. #endif
  251. }
  252. #endif /* defined(OPTIMIZE_RETURN) || !defined(DONT_TOUCH_ADDRESSES) */
  253.  
  254. int
  255. binary_search(name, address)
  256. char *name, *address;
  257. {
  258.     /* binary search file for name.  Return 0 if found, -1 if not */
  259.  
  260.     char machine[40];
  261.     register long first = 0, last, middle;
  262.     register int  compare;
  263.  
  264.     address[0] = '\0';
  265.  
  266.     last = size_of_pathfd;
  267.  
  268.     do {
  269.  
  270.       middle = (long) ((first+last) / 2);
  271.  
  272.       get_entry(machine, address, pathfd, middle);
  273.  
  274.       compare = strcmp(name, machine);
  275.  
  276.       if (compare < 0) 
  277.         last = middle - 1;
  278.       else if (compare == 0)
  279.         return(0);
  280.       else  /* greater */
  281.         first = middle + 1; 
  282.     } while (absolute(last) - absolute(first) > FIND_DELTA);
  283.  
  284.     /* It could be that our target entry lies exactly at `first'.
  285.      * Since get_entry() compares at the entry beginning after
  286.      * the passed offset (unless it's 0), we need to decrement it
  287.      * (unless it's 0), and give it one more try.
  288.      */
  289.     get_entry(machine, address, pathfd, (first == 0L ? first : --first));
  290.     compare = strcmp(name, machine);
  291.     return(compare == 0 ? 0 : -1);
  292. }
  293.  
  294. get_entry(machine, address, fileid, offset)
  295. char *machine, *address;
  296. FILE *fileid;
  297. long offset;
  298. {
  299.     int    ch;
  300.  
  301.     /** get entry...return machine and address immediately
  302.         following given offset in fileid.  **/
  303.  
  304.     (void) fseek(fileid, offset, 0);
  305.  
  306.     /* To get to the beginning of a record, if we are not at offset 0,
  307.      * read until we hit an end-of-line */
  308.  
  309.     if(offset != 0L)
  310.       while ((ch = getc(fileid)) != EOF)
  311.         if (ch == '\n')
  312.           break;
  313.  
  314.     *machine = '\0';
  315.     *address = '\0';
  316.     fscanf(fileid, "%s\t%s", machine, address);
  317. }
  318.  
  319. #ifndef DONT_TOUCH_ADDRESSES
  320. init_findnode()
  321. {
  322.     /** Initialize the FILE and 'size_of_file' values for the 
  323.         findnode procedure **/
  324.  
  325.     struct stat buffer;
  326.     char   *path_filename;
  327.  
  328. #ifdef USE_DBM
  329.     char buf[BUFSIZ];
  330.  
  331.     sprintf(buf,"%s.pag", pathfile);
  332.     path_filename = buf;
  333. #else
  334.     path_filename = pathfile;
  335. #endif
  336.  
  337.     if (stat(path_filename, &buffer) == -1) {
  338.       dprint(2, (debugfile, 
  339.           "Warning: pathalias file \"%s\" wasn't found by %s\n", 
  340.           path_filename, "init_findnode"));
  341.       size_of_pathfd = 0;
  342.       return;
  343.     }
  344.  
  345.     size_of_pathfd = (long) buffer.st_size;
  346.  
  347. #ifdef USE_DBM
  348.     
  349.     if (dbminit(pathfile) != 0) {
  350.       dprint(2, (debugfile,
  351.          "Warning: couldn't initialize DBM database %s\n", 
  352.          pathfile));
  353.       dprint(2, (debugfile, "** %s - %s **\n\n", error_name(errno),
  354.              error_description(errno)));
  355.       size_of_pathfd = 0;    /* error flag, in this case */
  356.       return;
  357.     }
  358.      
  359.     return;
  360. #else
  361.  
  362.     if ((pathfd = fopen(pathfile,"r")) == NULL) {
  363.       dprint(2, (debugfile,
  364.         "Warning: Can't read pathalias file \"%s\" within %s\n", 
  365.            pathfile, "init_findnode"));
  366.       size_of_pathfd = 0;
  367.     }
  368.     else
  369.       dprint(3, (debugfile, "\nOpened '%s' as pathalias database.\n\n", 
  370.           pathfile));
  371. #endif
  372. }
  373. #endif /* DONT_TOUCH_ADDRESSES */
  374.  
  375. char *find_path_to(machine, printf_format)
  376. char *machine;
  377. int   printf_format;
  378. {
  379.     /** Returns either the path to the specified machine or NULL if
  380.         not found.  If "printf_format" is TRUE, then it leaves the
  381.         '%s' intact, otherwise it assumes that the address is a uucp
  382.         address for the domain expansion program and removes the
  383.         last three characters of the expanded name ("!%s") since
  384.         they're redundant with the expansion!
  385.         **/
  386.  
  387.     static char buffer[SLEN];    /* space for path */
  388.  
  389.     if (size_of_pathfd > 0)
  390.       if (binary_search(machine, buffer) != -1) {       /* found it! */
  391.         if (! printf_format && strlen(buffer) > 3)
  392.           buffer[strlen(buffer)-3] = '\0';
  393.         return( (char *) buffer);
  394.       }
  395.  
  396.     return(NULL);                        /* failed if it's here! */
  397. }
  398.