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