home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / INTERNET / UPC2S1.ZIP / HOSTABLE.C < prev    next >
C/C++ Source or Header  |  1993-06-21  |  28KB  |  701 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       h o s t a b l e . c                                          */
  3. /*                                                                    */
  4. /*       Remote host table routines for UUPC/extended                 */
  5. /*--------------------------------------------------------------------*/
  6.  
  7. /*--------------------------------------------------------------------*/
  8. /*    Changes Copyright (c) 1990-1993 by Kendra Electronic            */
  9. /*    Wonderworks.                                                    */
  10. /*                                                                    */
  11. /*    All rights reserved except those explicitly granted by the      */
  12. /*    UUPC/extended license agreement.                                */
  13. /*--------------------------------------------------------------------*/
  14.  
  15. /*--------------------------------------------------------------------*/
  16. /*                          RCS Information                           */
  17. /*--------------------------------------------------------------------*/
  18.  
  19.  /*
  20.   *      $Id: hostable.c 1.7 1993/06/21 02:17:31 ahd Exp $
  21.   *
  22.   *      $Log: hostable.c $
  23.  *     Revision 1.7  1993/06/21  02:17:31  ahd
  24.  *     Correct errors in mail routing via HOSTPATH
  25.  *
  26.  *     Revision 1.6  1993/05/29  15:19:59  ahd
  27.  *     Allow configured systems, passwd files
  28.  *
  29.  *     Revision 1.5  1993/04/11  00:32:29  ahd
  30.  *     Global edits for year, TEXT, etc.
  31.  *
  32.  *     Revision 1.4  1993/04/04  04:57:01  ahd
  33.  *     Trap existence of local host name in SYSTEMS file
  34.  *
  35.  *     Revision 1.3  1992/12/18  12:05:57  ahd
  36.  *     Suppress duplicate machine state messages to improving OS/2 scrolling
  37.  *
  38.  *     Revision 1.3  1992/12/18  12:05:57  ahd
  39.  *     Suppress duplicate machine state messages to improving OS/2 scrolling
  40.  *
  41.  *    Revision 1.2  1992/11/22  20:58:55  ahd
  42.  *    Use strpool to allocate const strings
  43.  *
  44.  *    18 Mar 1990 Create hostable.c from router.c                    ahd
  45.  *                Move code to generate localdomain to here          ahd
  46.  *    22 Apr 90   Perform check for full host name before examining
  47.  *                name without domain.                               ahd
  48.  *    29 Jul 90   Only load host table based on first six characters
  49.  *                of host name.                                      ahd
  50.  *
  51.   */
  52.  
  53. #include <ctype.h>
  54. #include <limits.h>
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <string.h>
  58. #include <sys/types.h>
  59.  
  60. #include "lib.h"
  61. #include "hlib.h"
  62. #include "hostable.h"
  63. #include "security.h"
  64.  
  65. currentfile();
  66.  
  67. static struct HostTable *hosts = NULL;
  68.  
  69. static size_t  HostElements = 0;
  70.  
  71. static size_t loadhost( void );
  72.  
  73. static int hostcmp( const void *a , const void *b );
  74.  
  75. static size_t localdomainl;   /* Length of localdomain               */
  76.  
  77. /*--------------------------------------------------------------------*/
  78. /*    c h e c k n a m e                                               */
  79. /*                                                                    */
  80. /*    Perform a search for a single host name                         */
  81. /*                                                                    */
  82. /*    Rewritten for release 1.10a.  The old release had               */
  83. /*    most of the same logic, but nested it inside the search         */
  84. /*    loop; adding new cases (specifically, the wildcard domain       */
  85. /*    search) was difficult.  This version is slower because it       */
  86. /*    makes multiple passes through the host table, but this          */
  87. /*    isn't really performance code for a small (under 100 hosts)     */
  88. /*    table.                                 ahd 26 April 1991        */
  89. /*                                                                    */
  90. /*    Note because we save the arguments and use a static variable    */
  91. /*    to save the result of searches, this function is not            */
  92. /*    recursive!                                                      */
  93. /*--------------------------------------------------------------------*/
  94.  
  95. struct HostTable *checkname(const char *name)
  96. {
  97.    char  hostname[MAXADDR];   /* Local copy of name to process       */
  98.    char *period;              /* Pointer "." in hostname             */
  99.    size_t namel;              /* Length of the name input            */
  100.    size_t column;             /* Length of the name input            */
  101.  
  102.    static char savename[MAXADDR] = "";
  103.                               /* Saved copy of name to make function
  104.                                  reducible                           */
  105.    static struct HostTable *hostz;
  106.  
  107. /*--------------------------------------------------------------------*/
  108. /*                       Validate the argument                        */
  109. /*--------------------------------------------------------------------*/
  110.  
  111.    if ((name == NULL) || ((namel = strlen(name)) == 0))
  112.    {
  113.       printmsg(0,"checkname: Invalid (missing) hostname passed");
  114.       panic();
  115.       return NULL;           /* Never executed                      */
  116.    }
  117.  
  118. /*--------------------------------------------------------------------*/
  119. /*    If same argument as last time, return same result; otherwise    */
  120. /*    save input for next pass                                        */
  121. /*--------------------------------------------------------------------*/
  122.  
  123.    if (equali(name, savename))
  124.       return hostz;
  125.    strcpy( savename, name);   /* Save for next pass                  */
  126.  
  127. /*--------------------------------------------------------------------*/
  128. /*                      Search for the full name                      */
  129. /*--------------------------------------------------------------------*/
  130.  
  131.    if ((hostz = searchname(name, MAXADDR)) != BADHOST)
  132.       return hostz;
  133.  
  134. /*--------------------------------------------------------------------*/
  135. /*    If the name already has the local domain attached, search for   */
  136. /*    the host name without the domain.                               */
  137. /*--------------------------------------------------------------------*/
  138.  
  139.    column = namel - localdomainl;
  140.    if ((namel > localdomainl) && equali(E_localdomain, &name[column]) &&
  141.        (name[ column - 1] == '.'))
  142.    {
  143.       if ((hostz = searchname(name,column-1 )) != BADHOST)
  144.          return hostz;
  145.    } /* if */
  146.  
  147. /*--------------------------------------------------------------------*/
  148. /*    If the name already has the UUCP  domain attached, search for   */
  149. /*    the host name without the domain.                               */
  150. /*--------------------------------------------------------------------*/
  151.  
  152.    column = namel - 5;
  153.    if ((column > 0) && equali(".UUCP", &name[column]))
  154.    {
  155.       if ((hostz = searchname(name, column )) != BADHOST)
  156.          return hostz;
  157.    } /* if */
  158.  
  159. /*--------------------------------------------------------------------*/
  160. /*              Search for the name in the local domain               */
  161. /*--------------------------------------------------------------------*/
  162.  
  163.    if ((namel + localdomainl + 2) < MAXADDR)
  164.    {
  165.       sprintf(hostname,"%s.%s",name,E_localdomain);
  166.       if ((hostz = searchname(hostname, MAXADDR)) != BADHOST)
  167.          return hostz;
  168.    } /* if */
  169.  
  170. /*--------------------------------------------------------------------*/
  171. /*    If a simple name and not found, return search for truncated     */
  172. /*    UNIX name.                                                      */
  173. /*--------------------------------------------------------------------*/
  174.  
  175.    if ( strchr(name,'.') == NULL )
  176.       return checkreal( name );
  177.  
  178. /*--------------------------------------------------------------------*/
  179. /*               Perform a wildcard domain name search                */
  180. /*--------------------------------------------------------------------*/
  181.  
  182.    period = (char *) name;    /* Begin at front of name              */
  183.    while( period != NULL )
  184.    {
  185.       sprintf( hostname,(*period == '.') ? "*%s" : "*.%s",period);
  186.                               /* We add the missing period for the
  187.                                  first pass through the loop         */
  188.       if ((hostz = searchname(hostname, MAXADDR)) != BADHOST)
  189.          return hostz;
  190.       period = strchr(++period,'.');   /* Not found, search for next
  191.                                           higher domain              */
  192.    }
  193.  
  194. /*--------------------------------------------------------------------*/
  195. /*         We didn't find the host.  Return failure to caller         */
  196. /*--------------------------------------------------------------------*/
  197.  
  198.    return BADHOST;
  199.  
  200. }  /* checkname */
  201.  
  202. /*--------------------------------------------------------------------*/
  203. /*    c h e c k r e a l                                               */
  204. /*                                                                    */
  205. /*    Perform a search for a real (connected) simple host name        */
  206. /*--------------------------------------------------------------------*/
  207.  
  208. struct HostTable *checkreal(const char *name)
  209. {
  210.    size_t  namel = max( strlen(name), HOSTLEN);
  211.    struct HostTable *hostp = searchname( name, namel );
  212.  
  213. /*--------------------------------------------------------------------*/
  214. /*             If we didn't find the host, return failure             */
  215. /*--------------------------------------------------------------------*/
  216.  
  217.    if ((hostp == BADHOST) || (hostp->hstatus >= nocall))
  218.       return hostp;           /* Return raw information              */
  219.    else
  220.       return BADHOST;         /* Not a real host, invalid for our
  221.                                  purposes                            */
  222.  
  223. } /* searchreal */
  224.  
  225. /*--------------------------------------------------------------------*/
  226. /*    s e a r c h n a m e                                             */
  227. /*                                                                    */
  228. /*    Look up a system name in our systems (L.sys) file.              */
  229. /*    Only the first 7 characters of a system name is significant.    */
  230. /*--------------------------------------------------------------------*/
  231.  
  232. struct HostTable *searchname(const char *name, const size_t namel)
  233. {
  234.    int   lower;
  235.    int   upper;
  236.  
  237.  /*------------------------------------------------------------------*/
  238.  /*             Initialize the host name table if needed             */
  239.  /*------------------------------------------------------------------*/
  240.  
  241.    if (HostElements == 0)           /* host table initialized yet?   */
  242.       HostElements = loadhost();        /* No --> load it            */
  243.  
  244.    lower = 0;
  245.    upper = HostElements - 1;
  246.    while ( lower <= upper )
  247.    {
  248.       int midpoint = (lower + upper) / 2;
  249.       int hit;
  250.  
  251. /*--------------------------------------------------------------------*/
  252. /*    Compare for up to the specified length of the host name, but    */
  253. /*    never less than the length of the item we are comparing it      */
  254. /*    to.  In other words, the search key can be shorter than the     */
  255. /*    table entry for a simple host name.                             */
  256. /*                                                                    */
  257. /*    This mostly affects simple host names, as domain names          */
  258. /*    have a Very Large Number (VLN) passed into to insure we         */
  259. /*    compare the entire length of the name.                          */
  260. /*--------------------------------------------------------------------*/
  261.  
  262.       hit = strnicmp(name,hosts[midpoint].hostname,namel);
  263.       if (hit > 0)
  264.          lower = midpoint + 1;
  265.       else if ((hit < 0) || (strlen(hosts[midpoint].hostname) > namel))
  266.          upper = midpoint - 1;
  267.       else {
  268.             printmsg(8,"searchname: Looking for \"%s\" of length %d,\
  269.  found \"%s\"",
  270.             name, namel, hosts[midpoint].hostname);
  271.          return &hosts[midpoint];
  272.       }
  273.    }
  274.  
  275. /*--------------------------------------------------------------------*/
  276. /*         We didn't find the host.  Return failure to caller         */
  277. /*--------------------------------------------------------------------*/
  278.  
  279.    printmsg(8,"searchname: Looking for \"%s\", did not find it",
  280.             name);
  281.    return BADHOST;
  282.  
  283. }  /* searchname */
  284.  
  285.  
  286. /*--------------------------------------------------------------------*/
  287. /*    n e x t h o s t                                                 */
  288. /*                                                                    */
  289. /*    Returns next host in table with requested attribute             */
  290. /*--------------------------------------------------------------------*/
  291.  
  292. struct HostTable *nexthost( const boolean start )
  293. {
  294.    static size_t current = 0;
  295.  
  296.    if (HostElements == 0)     /* host table initialized yet?         */
  297.       HostElements = loadhost(); /* No --> load it                   */
  298.  
  299.    if (start)
  300.       current = 0;
  301.    else
  302.       current ++;
  303.  
  304.    while ( current < HostElements )
  305.    {
  306.       if (hosts[current].hstatus >= nocall)
  307.          return &hosts[current];
  308.       else
  309.          current++;
  310.    }
  311.  
  312.    return BADHOST;
  313.  
  314. }  /* nexthost */
  315.  
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*    i n i t h o s t                                                 */
  319. /*                                                                    */
  320. /*    Intializes a host table entry for for loadhost                  */
  321. /*--------------------------------------------------------------------*/
  322.  
  323. struct HostTable *inithost(char *name)
  324. {
  325.  
  326.    size_t hit = HostElements;
  327.    size_t element = 0;
  328.    static size_t max_elements = 32; /* This is automatically
  329.                                        raised if we run out of room  */
  330.  
  331.    if (hosts == NULL)
  332.    {
  333.       hosts = calloc(max_elements, sizeof(*hosts));
  334.       printmsg(5,"inithost: Allocated room for %d host entries",
  335.                max_elements);
  336.    }
  337.    else if ( max_elements == HostElements )
  338.    {
  339.       max_elements = max_elements * 2;
  340.       hosts = realloc(hosts , max_elements * sizeof(*hosts));
  341.       printmsg(5,"inithost: reallocated room for %d host entries",
  342.                max_elements);
  343.    }
  344.    checkref(hosts);
  345.  
  346. /*--------------------------------------------------------------------*/
  347. /*    Add the host to the table.  Note that we must add the host      */
  348. /*    to the table ourselves (rather than use lsearch) because we     */
  349. /*    must make a copy of the string; the *token we use for the       */
  350. /*    search is in the middle of our I/O buffer!                      */
  351. /*--------------------------------------------------------------------*/
  352.  
  353.    while ( element < hit )
  354.    {
  355.       if (equali( hosts[element].hostname , name ))
  356.          hit = element;
  357.       else
  358.          element++;
  359.    }
  360.  
  361. /*--------------------------------------------------------------------*/
  362. /*               If a new element, initialize the block               */
  363. /*--------------------------------------------------------------------*/
  364.  
  365.    if (hit == HostElements)
  366.    {
  367.       memset( &hosts[hit] , 0, sizeof hosts[hit] );
  368.       hosts[hit].hostname = newstr(name);
  369.       checkref( hosts[hit].hostname );
  370.       hosts[hit].anylogin = TRUE;   /* Allow generic login by default   */
  371.       HostElements ++ ;
  372.    } /* if */
  373.  
  374.    return &hosts[hit];
  375.  
  376. } /* inithost */
  377.  
  378. /*--------------------------------------------------------------------*/
  379. /*    l o a d h o s t                                                 */
  380. /*                                                                    */
  381. /*    Initializes table of known host names for checkname             */
  382. /*--------------------------------------------------------------------*/
  383.  
  384. static size_t loadhost()
  385. {
  386.    FILE *ff;
  387.    char buf[BUFSIZ];
  388.    char *token;
  389.    char s_hostable[FILENAME_MAX]; /* full-name of hostable file        */
  390.    size_t hit;
  391.  
  392.    struct HostTable *hostp;
  393.  
  394. /*--------------------------------------------------------------------*/
  395. /*                      Validate the domain name                      */
  396. /*--------------------------------------------------------------------*/
  397.  
  398.    token = strrchr(E_domain,'.');
  399.  
  400.    if (token == NULL)
  401.    {
  402.       printmsg(0,"Domain name \"%s\" is invalid, missing period",E_domain);
  403.       panic();
  404.    }
  405.  
  406. /*--------------------------------------------------------------------*/
  407. /*                  Load the local host information                   */
  408. /*--------------------------------------------------------------------*/
  409.  
  410.    hostp = inithost(E_nodename);
  411.    hostp->hstatus  = localhost;
  412.    hostp->realname = E_nodename; /* Don't let user alias our system
  413.                                     name                             */
  414.  
  415. /*--------------------------------------------------------------------*/
  416. /*                Now do the local domain information                 */
  417. /*--------------------------------------------------------------------*/
  418.  
  419.    hostp = inithost(E_domain);
  420.  
  421.    if (hostp->via == NULL )   /* Not initialized?                    */
  422.       hostp->via      = E_nodename;  /* Correct --> Route via local  */
  423.    else
  424.       panic();                /* "Houston, we a have problem" -
  425.                                  Apollo 13                           */
  426.  
  427.    hostp->realname = E_nodename;
  428.  
  429. /*--------------------------------------------------------------------*/
  430. /*    If we allow anonymous UUCP, load the dummy host we use for      */
  431. /*    connections to such hosts                                       */
  432. /*--------------------------------------------------------------------*/
  433.  
  434.    if ( E_anonymous != NULL )
  435.    {
  436.       hostp = inithost( ANONYMOUS_HOST );
  437.       hostp->hstatus = nocall;
  438.       hostp->via     = E_nodename;
  439.       hostp->hstats  = malloc( sizeof *(hostp->hstats) );
  440.       checkref( hostp->hstats );
  441.       memset( hostp->hstats, 0, sizeof *(hostp->hstats) );
  442.    } /* if */
  443.  
  444. /*--------------------------------------------------------------------*/
  445. /*                  Load names from the systems file                  */
  446. /*--------------------------------------------------------------------*/
  447.  
  448.  
  449.    ff = FOPEN(E_systems, "r",TEXT_MODE);
  450.    if (ff == NULL)
  451.    {
  452.       printerr(E_systems);
  453.       panic();
  454.    }
  455.  
  456.    while (! feof(ff))
  457.    {
  458.       if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line      */
  459.          break;                  /* Exit if end of file              */
  460.       token = strtok(buf,WHITESPACE);
  461.       if (token == NULL)         /* Any data?                        */
  462.          continue;               /* No --> read another line         */
  463.       if (token[0] == '#')
  464.          continue;                  /* Line is a comment; loop again */
  465.  
  466.       if ( equali( token, E_nodename ))
  467.       {
  468.          printmsg(0,"Error: Local host %s must not be in SYSTEMS file",
  469.                     E_nodename );
  470.          panic();
  471.       }
  472.  
  473.       hostp = inithost(token);
  474.  
  475.       if (hostp->hstatus == phantom)
  476.       {
  477.          hostp->hstatus = nocall;
  478.          hostp->hstats  = malloc( sizeof *(hostp->hstats) );
  479.          checkref( hostp->hstats );
  480.          memset( hostp->hstats, 0, sizeof *(hostp->hstats) );
  481.       }
  482.    } /* while */
  483.  
  484.    fclose(ff);
  485.  
  486. /*--------------------------------------------------------------------*/
  487. /*               Now the load the routing file, if any.               */
  488. /*--------------------------------------------------------------------*/
  489.  
  490.    mkfilename(s_hostable, E_confdir, PATHS);
  491.  
  492.    if ((ff = FOPEN(s_hostable, "r",TEXT_MODE)) != NULL)
  493.    {
  494.  
  495.       while (! feof(ff))
  496.       {
  497.          boolean freeit = FALSE;
  498.  
  499.          if (fgets(buf,BUFSIZ,ff) == NULL)   /* Try to read a line      */
  500.             break;                  /* Exit if end of file              */
  501.          token = strtok(buf,WHITESPACE);
  502.  
  503.          if (token == NULL)         /* Any data?                        */
  504.             continue;               /* No --> read another line         */
  505.  
  506.          if (*token == '#')
  507.             continue;               /* Line is a comment; loop again    */
  508.  
  509.          hostp = inithost(token);
  510.          token = strtok(NULL,WHITESPACE);
  511.  
  512.          if ( token == NULL )
  513.          {
  514.             printmsg(0,"loadhost: Missing path name for host \"%s\"",
  515.                         hostp->hostname);
  516.             freeit = TRUE;
  517.          }
  518. /*--------------------------------------------------------------------*/
  519. /*                              Gate way                              */
  520. /*--------------------------------------------------------------------*/
  521.          else if (equal(token,"|"))
  522.          {
  523.             token = strtok(NULL,"\n");
  524.  
  525.             if (( hostp->via != NULL ) || ( token == NULL ))
  526.                freeit = TRUE;
  527.             else {
  528.                hostp->hstatus = gatewayed;
  529.  
  530.                while(isspace( *token ))   /* Drop leading white space only */
  531.                   token++;
  532.  
  533.                if (*token == '\0')        /* Empty string?           */
  534.                   freeit = TRUE;          /* Yes --> Flag for error  */
  535.                else
  536.                   hostp->via = token = newstr(token);
  537.             } /* else if */
  538.  
  539.             if ( freeit )
  540.                printmsg(0,"loadhost: Invalid/duplicate gateway for \"%s\"",
  541.                      hostp->hostname );
  542.  
  543.          } /* else if */
  544. /*--------------------------------------------------------------------*/
  545. /*                               Alias                                */
  546. /*--------------------------------------------------------------------*/
  547.          else if (equal(token,"="))
  548.          {
  549.             token = strtok(NULL,WHITESPACE);
  550.  
  551.             if (( hostp->realname == NULL ) && (token != NULL))
  552.                hostp->realname = token = newstr( token );
  553.             else {
  554.                printmsg(0,"loadhost: Invalid/duplicate alias of \"%s\"",
  555.                      hostp->hostname );
  556.                freeit = TRUE;
  557.             } /* else */
  558.          } /* else if (equal(token,"=")) */
  559. /*--------------------------------------------------------------------*/
  560. /*                           Routing entry                            */
  561. /*--------------------------------------------------------------------*/
  562.          else {
  563.  
  564.             if ( hostp->via == NULL )
  565.                hostp->via = token = newstr( token );
  566.             else {
  567.                printmsg(0,"loadhost: Invalid/duplicate route for \"%s\"",
  568.                      hostp->hostname );
  569.                freeit = TRUE;
  570.             } /* else */
  571.  
  572.          } /* else */
  573.  
  574.  
  575.          if ( ! freeit )
  576.          {
  577.             checkref( token );
  578.  
  579.             if (*token == '*')       /* Wildcard on right side?    */
  580.             {
  581.                printmsg(0,
  582.      "loadhost: Wildcard \"%s\" not allowed for real name of host \"%s\"",
  583.          token, hostp->hostname);
  584.                freeit = TRUE;
  585.             } /* if (*token == '*') */
  586.          } /* if ( ! freeit ) */
  587.  
  588.          if ( freeit )
  589.          {
  590.             if ( hostp->hstatus == phantom )
  591.                HostElements--;            /* Ignore the routing entry   */
  592.          }
  593.       }  /* end while */
  594.  
  595.       fclose(ff);
  596.    }
  597.    else {
  598.       if ( debuglevel > 2 )
  599.          perror( s_hostable );
  600.    }
  601.  
  602. /*--------------------------------------------------------------------*/
  603. /*                   Provide default for fromdomain                   */
  604. /*--------------------------------------------------------------------*/
  605.  
  606.    if (E_fdomain != NULL)     /* If fromdomain provided ...          */
  607.    {
  608.       hostp = inithost(E_fdomain);
  609.  
  610.       if (hostp->via == NULL)    /* Uninitialized?                   */
  611.          hostp->via = E_mailserv;   /* Yes --> Use default route     */
  612.    }
  613.    else
  614.       E_fdomain = E_domain;   /* Use domain as fromdomain            */
  615.  
  616. /*--------------------------------------------------------------------*/
  617. /*    Shrink the table to whatever we actually need, then sort it     */
  618. /*--------------------------------------------------------------------*/
  619.  
  620.    hosts = realloc(hosts, HostElements *  sizeof(*hosts));
  621.    checkref(hosts);
  622.  
  623.    qsort(hosts, HostElements ,sizeof(hosts[0]) , hostcmp);
  624.  
  625. /*--------------------------------------------------------------------*/
  626. /*    If the user did not define a local domain, then generate one    */
  627. /*    based on our own domain name; the generated name will either    */
  628. /*    be of the format ".a.b.c" (incuding the trailing period) or     */
  629. /*    a null string.                                                  */
  630. /*--------------------------------------------------------------------*/
  631.  
  632.    if ( E_localdomain == NULL )
  633.    {
  634.       E_localdomain = strchr(E_domain,'.');
  635.  
  636.       if (E_localdomain == NULL)
  637.          E_localdomain = "UUCP";
  638.       else {
  639.          E_localdomain ++;    /* Step past the period                */
  640.  
  641.          if ( !equali(E_localdomain, "UUCP" ) &&
  642.               (strchr( E_localdomain, '.' ) == NULL ))
  643.                               /* Implied single level domain name?   */
  644.             E_localdomain = E_domain;
  645.                               /* Impossible, use both parts of name  */
  646.       } /* else */
  647.  
  648.       printmsg(3,"loadhost: local domain defined as \"%s\"",
  649.                  E_localdomain);
  650.  
  651.    } /* if */
  652.  
  653.    localdomainl = strlen(E_localdomain);
  654.  
  655. /*--------------------------------------------------------------------*/
  656. /*    Amend for the sin of typing the domain wrong in the sample      */
  657. /*    files for the old releases of UUPC/extended.                    */
  658. /*--------------------------------------------------------------------*/
  659.  
  660.    if (equali(E_localdomain,"UUPC"))
  661.    {
  662.       printmsg(0,"inithost: UUPC is an invalid domain name! "
  663.                  "Change it to UUCP");
  664.       panic();
  665.    }
  666.  
  667. /*--------------------------------------------------------------------*/
  668. /*                      Display the final table                       */
  669. /*--------------------------------------------------------------------*/
  670.  
  671.    for (hit = 0; hit < HostElements; hit++)
  672.    {
  673.       printmsg(8,"loadhost: entry[%02d] %-20s\tvia %s\talias %s",
  674.                   hit,
  675.                   hosts[hit].hostname,
  676.                   (hosts[hit].via == NULL) ? "(self)" : hosts[hit].via,
  677.                   (hosts[hit].realname == NULL)
  678.                                     ? "(self)" : hosts[hit].realname);
  679.    } /* for */
  680.  
  681. /*--------------------------------------------------------------------*/
  682. /*                          Return to caller                          */
  683. /*--------------------------------------------------------------------*/
  684.  
  685.    return (HostElements) ;
  686. } /*loadhost*/
  687.  
  688.  
  689. /*--------------------------------------------------------------------*/
  690. /*    h o s t c m p                                                   */
  691. /*                                                                    */
  692. /*    Accepts indirect pointers to two strings and compares           */
  693. /*    them using stricmp (case insensitive string compare)            */
  694. /*--------------------------------------------------------------------*/
  695.  
  696. int hostcmp( const void *a , const void *b )
  697. {
  698.    return stricmp(((struct HostTable*) a)->hostname,
  699.         ((struct HostTable*) b)->hostname);
  700. }  /*hostcmp*/
  701.