⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gethost.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  BSD-like host-entry functions
 *
 *  G. Vanem  <giva@bgnett.no>
 *
 *  18.aug 1996 (GV)  - Created
 *  02.dec 1997 (GV)  - Integrated with resolve()
 *  05.jan 1998 (GV)  - Added host cache functionality
 *  18.may 1999 (GV)  - Added timeout of cached values
 *  02.may 2000 (GV)  - Added function reverse_lookup_myip()
 *
 *  todo: support real host aliases as they come from the name server
 *  todo: accept "rooted FQDN" strings as normal FQDN strings.
 *        Note: "domain_name.com" and "domain_name.com." are equivalent
 *        (both are valid forms of fully qualified domain names (FQDNs);
 *        with the period, it is referred to as a rooted FQDN). Both forms
 *        should work with all mail clients and servers.  However, using the
 *        trailing "." is rarely used (except in DNS maintenance).
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <netdb.h>

#include "wattcp.h"
#include "strings.h"
#include "misc.h"
#include "language.h"
#include "pcconfig.h"
#include "pc_cbrk.h"
#include "pcbsd.h"
#include "pctcp.h"
#include "bsdname.h"
#include "udp_dom.h"

typedef struct {
        struct dhead h;
        char   x[50];
      } question_t;

typedef struct {
        struct dhead  h;
        char   x[500];
      } answer_t;


#if defined(USE_BSD_FUNC)

typedef struct _hostent {            /* internal hostent structure  */
        char            *h_name;     /* official name of host       */
        char           **h_aliases;  /* hostname alias list         */
        u_long           h_address;  /* IP address (network order)  */
        time_t           h_timeout;  /* cached entry expiry time    */
        struct _hostent *h_next;     /* ptr to next entry (or NULL) */
      } _hostent;


#define MAX_HOST_ALIASES  5
#define MAX_CACHE_LIFE    (15*60)

int h_errno = 0;

int netdbCacheLife = MAX_CACHE_LIFE;

static char *hostFname = NULL;
static FILE *hostFile  = NULL;
static BOOL  hostClose = 0;
static _hostent *host0 = NULL;

/*
 *
 */
static __inline struct hostent *FillHostEnt (const _hostent *h)
{
  static struct in_addr adr;
  static struct hostent ret;
  static char  *list[2];

  if (!h->h_name)
     return (NULL);

  adr.s_addr      = h->h_address;
  list[0]         = (char*) &adr;
  list[1]         = NULL;
  ret.h_name      = h->h_name;
  ret.h_aliases   = h->h_aliases;
  ret.h_addrtype  = AF_INET;
  ret.h_length    = sizeof (adr.s_addr);
  ret.h_addr_list = list;
  h_errno         = NETDB_SUCCESS;
  return (&ret);
}                          

/*
 * Modify an expired cached entry or create a new node to
 * the linked list.
 */
static __inline void AddHostEnt (struct _hostent *h,
                                 const char *name,
                                 u_long      addr,
                                 BOOL        expires)
{
  if (h)         /* reuse expired entry */
  {
    if (h->h_name)
       free (h->h_name);
  }
  else           /* create a new node */
  {
    h = calloc (sizeof(*h),1);
    if (h)
    {
      h->h_next = host0;
      host0 = h;
    }
  }

  if (h)
  {
    h->h_name    = strdup (name);
    h->h_address = addr;
    if (netdbCacheLife && expires)
         h->h_timeout = time (NULL) + netdbCacheLife;
    else h->h_timeout = 0;
  }

#ifdef TEST_PROG  /* test updated cache */
  if (h)
       printf ("new entry: h->h_address = %-17.17s h->h_name = %s\n",
               inet_ntoa(*(struct in_addr*)&h->h_address), h->h_name);
  else printf ("new entry: no mem\n");
#endif
}

/*------------------------------------------------------------------*/

void ReadHostFile (const char *fname)
{
  static int been_here = 0;

  if (!fname || !*fname)
     return;

  if (been_here)  /* loading multiple hosts files */
  {
    free (hostFname);
    fclose (hostFile);
    hostFile = NULL;
  }
  been_here = 1;

  hostFname = strdup (fname);
  if (!hostFname)
     return;

  sethostent (1);
  if (!hostFile)
     return;

  while (1)
  {
    struct  hostent *h = gethostent();
    struct _hostent *h2;

    if (!h)
       break;

    h2 = calloc (sizeof(*h2),1);
    if (!h2)
    {
      outsnl (_LANG("Hostfile too big!\7"));
      break;
    }
    h2->h_name    = h->h_name;
    h2->h_aliases = h->h_aliases;
    h2->h_address = *(u_long*) h->h_addr_list[0];
    h2->h_timeout = 0;      /* don't expire */
    h2->h_next = host0;
    host0      = h2;
  }
  rewind (hostFile);
  atexit (endhostent);

}

const char *GetHostsFile (void)
{
  return (hostFname);
}

/*
 * To prevent running out of file-handles, one should close the
 * 'hosts' file before spawning a new shell.
 */
void CloseHostFile (void)
{
  fclose (hostFile);
  hostFile = NULL;
}

void ReopenHostFile (void)
{
  ReadHostFile (hostFname);
}

/*
 * Return the next (non-commented) line from the host-file
 * Format is:
 *  ip-address [=] host-name [alias..] {\n | # ..}
 */
struct hostent * gethostent (void)
{
  static _hostent h;
  char   *ip, *name, *alias;
  char    buf[100];

  if (!netdb_init() || !hostFile)
     return (NULL);

  do
  {
    if (!fgets(buf,sizeof(buf)-1,hostFile))
       return (NULL);
  }
  while (buf[0] == '#' || buf[0] == ';' || buf[0] == '\n');

  if (hostClose)
     endhostent();

  ip   = strtok (buf, " \t");
  name = strtok (NULL, " \t\n");

  if (!strcmp(ip,"0.0.0.0"))  /* inet_addr() maps 0 -> INADDR_NONE */
       h.h_address = 0;
  else h.h_address = inet_addr (ip);

  h.h_name = strdup (name);
  if (!h.h_name)
     return (NULL);

  h.h_aliases = NULL;
  alias       = strtok (NULL, " \t\n");

  if (alias && *alias != '#' && *alias != ';')
  {
    char **alist = calloc ((1+MAX_HOST_ALIASES) * sizeof(char*), 1);
    int  i = 0;
    do
    {
      if (*alias == '#' || *alias == ';')
         break;
      if (!alist || (i == MAX_HOST_ALIASES) ||
          (alist[i++] = strdup(alias)) == NULL)
         break;
      alias = strtok (NULL, " \t\n");
    }
    while (alias);
    h.h_aliases = alist;
  }
  return FillHostEnt (&h);
}

/*------------------------------------------------------------------*/

struct hostent *gethostbyname (const char *name)
{
  struct _hostent *h, ret;
  struct  in_addr  addr;
  u_long  ip;
  static  char fqdn[MAX_HOSTLEN];

  h_errno = HOST_NOT_FOUND;

  if (!netdb_init())
     return (NULL);

  if (inet_aton(name,&addr))
  {
    ret.h_name    = (char*) name; /* !!to-do: should be canonical name */
    ret.h_aliases = NULL;
    ret.h_address = addr.s_addr;
    return FillHostEnt (&ret);
  }

  for (h = host0; h; h = h->h_next)
  {
    char **alias;

    if (h->h_name && !stricmp(h->h_name,name))
    {
      /* if cached entry expired, do DNS lookup
       */
      if (h->h_timeout && time(NULL) >= h->h_timeout)
         goto expired;

      if (h->h_address)
         return FillHostEnt (h);
      return (NULL);
    }
    for (alias = h->h_aliases; alias && *alias; alias++)
        if (!stricmp(name,*alias))
        {
          if (h->h_timeout && time(NULL) >= h->h_timeout)
             goto expired;

          if (h->h_address)
             return FillHostEnt (h);
          return (NULL);
        }
  }

  if (!h)
  {
    /* Not found in linked list (hosts file or cache). Check name
     * against our own host-name (short-name or FQDN)
     */
    if (hostname[0] && !stricmp(name,hostname))
    {
      ret.h_address = gethostid();
      ret.h_name    = hostname;
      return FillHostEnt (&ret);
    }

    if (!gethostname(fqdn,sizeof(fqdn)) && !stricmp(name,fqdn))
    {
      ret.h_address = gethostid();
      ret.h_name    = fqdn;
      return FillHostEnt (&ret);
    }
  }

expired:

  if (called_from_resolve) /* prevent recursion */
     return (NULL);

 /* Not our own host-name; do a full DNS lookup
  */

  called_from_ghbn = 1;
  ip = htonl (resolve((char*)name)); /* do a normal lookup */
  called_from_ghbn = 0;

 /* Add the IP to the list even if DNS failed (but not interrupted by
  * _resolve_hook() or timedout). Thus the next call to gethostbyxx()
  * will return immediately.
  */
  if (_resolve_exit ||   /* interrupted by _resolve_hook() */
      _resolve_timeout)  /* timed out resolving */
     return (NULL);

  if (ip)                /* successfully resolved */
  {
    AddHostEnt (h, name, ip, TRUE);
    ret.h_address = ip;
    ret.h_name    = (char*) name;  /* !!to-do: should be canonical name */
    ret.h_aliases = h ? h->h_aliases : NULL;
    return FillHostEnt (&ret);
  }

  AddHostEnt (h, name, INADDR_ANY, TRUE);  /* or INADDR_NONE ? */
  return (NULL);
}

/*------------------------------------------------------------------*/

struct hostent *gethostbyaddr (const char *adr_name, int len, int type)
{
  _hostent *h, ret;
  u_long   addr;
  static   char name [MAX_HOSTLEN];
  int      rc;

  h_errno = HOST_NOT_FOUND;

  if (!netdb_init())
     return (NULL);

  if (type != AF_INET || len < sizeof(addr))
     return (NULL);

  addr = *(u_long*) adr_name;

  if ((addr == INADDR_ANY ||           /* 0.0.0.0 -> my_ip_addr */
       addr == gethostid()) &&
      !gethostname(name,sizeof(name)))
  {
    ret.h_address = gethostid();
    ret.h_name    = name;
    return FillHostEnt (&ret);
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -