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