NODEPROC.C

35.2 KB 185665c3447c69a3…
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         Bit-Bucket Software, Co.                       */
/*      \ 10001101 /         Writers and Distributors of                    */
/*       \ 011110 /          Freely Available<tm> Software.                 */
/*        \ 1011 /                                                          */
/*         ------                                                           */
/*                                                                          */
/*  (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
/*                                                                          */
/*                                                                          */
/*               This module was written by Vince Perriello                 */
/*                                                                          */
/*                                                                          */
/*                 BinkleyTerm Nodelist processing module                   */
/*                                                                          */
/*                                                                          */
/*    For complete  details  of the licensing restrictions, please refer    */
/*    to the License  agreement,  which  is published in its entirety in    */
/*    the MAKEFILE and BT.C, and also contained in the file LICENSE.250.    */
/*                                                                          */
/*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
/*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
/*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
/*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
/*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
/*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
/*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
/*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
/*                                                                          */
/*                                                                          */
/* You can contact Bit Bucket Software Co. at any one of the following      */
/* addresses:                                                               */
/*                                                                          */
/* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
/* P.O. Box 460398                AlterNet 7:491/0                          */
/* Aurora, CO 80046               BBS-Net  86:2030/1                        */
/*                                Internet f491.n343.z1.fidonet.org         */
/*                                                                          */
/* Please feel free to contact us at any time to share your comments about  */
/* our software and/or licensing policies.                                  */
/*                                                                          */
/*--------------------------------------------------------------------------*/

/* Include this file before any other includes or defines! */

#include "includes.h"

char far *get_size (unsigned int);
int get_new_info (unsigned);

#ifdef OLDTBBSLIST
int get_TBBS_info (unsigned, ADDR *);
#endif

#ifdef V5_LIST
int get_old_info (unsigned);
#endif

static off_t  index_filesize = (off_t)  0L;
static time_t index_filetime = (time_t) 0L;
static char   index_filename[80];

static unsigned int idx_size = 0;                       /* number of entries  */
static int extra_bytes = 0;
static char *curr_domain = NULL;

void get_nodelist_name (ADDR *);

void get_nodelist_name (ADDRP opus_addr)
{
    int i;

    curr_domain = opus_addr->Domain;

    idx_size = 0;
    extra_bytes = 0;
    nodelist_base = nodelist_name;
    for (i = 0; domain_name[i] != NULL; i++)
        {
        if (domain_name[i] == opus_addr->Domain)
            {
            nodelist_base = domain_nodelist[i];
            if (nodelist_base == NULL)
                nodelist_base = nodelist_name;
            }
        }
}

char far *get_size (unsigned int n)
{
    /* If we get this far, then we have to use a straight far pointer */
    return (_fmalloc(n));
}

/*---------------------------------------------------------------------------*/
/* CHECKLIST                                                                 */
/* See if nodelist has changed since we first tried to use it and if so,     */
/* dismiss old copy and get a new one                                        */
/*---------------------------------------------------------------------------*/

int checklist ()
{
    struct stat idxstat;
    if (index_filesize == (off_t)0L)
        return (0);
    (void) stat (index_filename, &idxstat);    
    if ((index_filesize == idxstat.st_size) && (index_filetime == idxstat.st_mtime)) 
        return (0);
    status_line (MSG_TXT(M_REFRESH_NODELIST));
    _ffree( node_index );
    node_index = (char far *) NULL;
    index_filesize = (off_t)0L;
    return (1);
}


/*---------------------------------------------------------------------------*/
/* NODEPROC                                                                  */
/* Find nodelist entry and set baud to nodelist baud for dialing out         */
/*---------------------------------------------------------------------------*/

int nodeproc (char *nodeaddr)
{
    ADDR opus_addr;
    char *c;

    c = skip_blanks (nodeaddr);                     /* get rid of the blanks  */
    if (!find_address (c, &opus_addr))
        {
        return (0);
        }
    if (!nodefind (&opus_addr, 1))              /* if we can't find the node  */
        return (0);                             /* go away now                */
    status_line (MSG_TXT(M_PROCESSING_NODE), Full_Addr_Str (&opus_addr), newnodedes.SystemName);
    if (!CARRIER)                               /* if no carrier yet,         */
        {
        if (autobaud)
            (void) set_baud (max_baud.rate_value, 1);   /* Set to highest rate*/
        else
            (void) set_baud ((300 * newnodedes.BaudRate), 1);/* nodelist baud */
        }
    return (1);                                 /* return success to caller   */
}

/*---------------------------------------------------------------------------*/
/* NODEFIND                                                                  */
/* Find nodelist entry for use by other routines (password, nodeproc)        */
/* If found, result will be in "newnodedes".                                 */
/*---------------------------------------------------------------------------*/

int nodefind (ADDRP bink_addr, int prtflag)
{
    int i, j, k;
    int have_boss_data = 0;
    int need_boss_data = 0;

    (void) checklist ();

    newnodedes.NetNumber = newnodedes.NodeNumber = found_zone = found_net = 0;

    CURRENT = DEFAULT;                          /* Set default paths, quotas  */

    if ((bink_addr->Net == boss_addr.Net) 
    &&  (bink_addr->Node == boss_addr.Node) 
    &&  (bink_addr->Zone == alias[0].Zone) 
    &&  ((bink_addr->Domain == boss_addr.Domain) || (bink_addr->Domain == NULL)))
        {
        ++need_boss_data;
        if (BOSSphone && strlen (BOSSphone) > 2)
            ++have_boss_data;
        if (BOSSpwd && strlen (BOSSpwd) > 2)
            ++have_boss_data;
        }

    if (!bink_addr->Zone)
        {
        bink_addr->Zone = alias[0].Zone;
        i = (*nodefunc) (bink_addr, have_boss_data);
        if (i) goto lookup_done;
        }
    i = (*nodefunc) (bink_addr, have_boss_data);

lookup_done:

    assumed = k = 0;                            /* Default to zone of first   */
    for (j = 0; j < num_addrs; j++)
        {
        if ((alias[j].Point != 0) 
        &&  ((alias[j].Node != newnodedes.NodeNumber) 
          || (alias[j].Net != found_net) 
          || (alias[j].Zone != found_zone)))
            {
            /* Don't use our point address except to the boss! */
            continue;
            }

        if ((alias[j].Domain == curr_domain)
        ||  ((curr_domain == NULL) && (alias[j].Domain == my_addr.Domain)) 
        ||  ((alias[j].Domain == NULL) && (curr_domain == my_addr.Domain)))
            {
            if (k == 0)
                {
                assumed = j;
                ++k;
                }

            if (alias[j].Zone == found_zone)
                {
                if (k == 1)
                    {
                    assumed = j;
                    ++k;
                    }

                if (alias[j].Net == found_net)         
                    {
                    assumed = j;
                    break;
                    }
                }
            }
        }

    if (!i && (have_boss_data != 2))
        {
        if (prtflag)
            status_line (MSG_TXT(M_NO_ADDRESS), Full_Addr_Str (bink_addr));

        if (curmudgeon && CARRIER && (bink_addr->Net != 0xffff) && (bink_addr->Node != 0xffff) && (bink_addr->Node != 9999)
                                          && ((bink_addr->Zone != alias[0].Zone) || (bink_addr->Net != alias[0].Net)))
            {
            status_line (MSG_TXT(M_NUISANCE_CALLER));
            LOWER_DTR ();                             /* Hang up right now      */
            timer (2);                              /* Wait two secs          */
            RAISE_DTR ();                              /* OK, turn modem back on */
            }

        }

    if (bink_addr->Zone == (unsigned int) -1)
        return i;

    /* If we found the entry, then we promote the file request
     * to the "KNOWN" class. If the password field is non-zero,
     * then promote to "PROT". It's OK to do that since the higher
     * level code will hang up before f.req's if the password does
     * not match.
     *
     */

    if (i)
        {
        if (newnodedes.Password[0])
            {
            CURRENT = PROT;         /* Structure assignment */
            }
        else
            {
            CURRENT = KNOWN;
            }
        }

    if (!need_boss_data)
        return (i);

/*
 *    We can get here one of two ways:
 *
 *    1) No nodelist data was found and this is the BOSS.
 *
 *    2) Nodelist lookup occurred, but this is the BOSS.
 *
 *    For case (1), have_boss_data MUST be 2 (meaning we have
 *    both a phone number and a password entry). If that is the
 *    case, fill in newnodedes with mostly zeroes, plugging in
 *    the BOSS net, node, phone number and password.
 *
 *    For case (2), just see if there is any substitution for
 *    BOSSphone and/or BOSSpwd, then exit.
 *
 */

    if (BOSSphone && strlen (BOSSphone) > 2)
        {
        (void) strncpy (newnodedes.PhoneNumber, BOSSphone, 40);
        newnodedes.PhoneNumber[39] = '\0';
        }

    if (BOSSpwd && strlen (BOSSpwd) > 2)
        {
        (void) memset (newnodedes.Password, 0, sizeof (newnodedes.Password));
        (void) strncpy (newnodedes.Password, BOSSpwd, 8);
        }

    if (i)
        return (1);

    /* No BOSS in the nodelist */
    if (have_boss_data != 2)
        {
        status_line (MSG_TXT(M_NO_BOSS));
        return (0);
        }

    newnodedes.NodeNumber = bink_addr->Node;                /* Node Number */
    newnodedes.NetNumber = bink_addr->Net;                  /* Net Number  */
    newnodedes.Cost = newnodedes.RealCost = 0;              /* Assume boss is free  */
    (void) strcpy (newnodedes.SystemName, PRDCT_PRTY "'s Boss");/* System Name defaults */
    (void) strcpy (newnodedes.MiscInfo, "Somewhere out There"); /* As does City     */
    newnodedes.HubNode = 0;                                 /* Don't know who's HUB */
    newnodedes.BaudRate = (char) (max_baud.rate_value / 300);
                                                            /* Assume boss speed = ours */
    newnodedes.ModemType = 0;                               /* Or modem type        */
    newnodedes.NodeFlags = B_CM;                            /* Assume boss is CM    */
    newnodedes.NodeFiller = 0;                              /* Zero out filler      */
    return (1);
}

#ifdef QUICK_LIST

int QuickLookup (ADDRP Quick_addr, int have_boss_data)
{
    register struct QuickNodeIdxRecord far *nodeidx;/* index file             */
    struct QuickNodeListRecord nodedes;             /* desc. of node          */

    int foundnet = 0;                               /* 'found the net' flag   */
    int found = 0;                                  /* 'found the node' flag  */
    int idxrec = 0;                                 /* record in QNL_IDX.BBS  */
    long nodeoff = 0L;                              /* offset into QNL_DAT.BBS*/
    char temp[80];                                  /* we build filenames here*/

    HFILE stream;
    USHORT i;
    USHORT got;

    FILE *stream1;
    struct stat f;

    newnodedes.NetNumber = newnodedes.NodeNumber = 0;

    if (node_index == NULL)
        {
        index_filesize = (off_t) 0L;                /* Cover error condition  */
        index_filename[0] = '\0';                   /* "null-terminated string*/
        (void) strcpy (index_filename, net_info);   /* take nodelist path     */
        (void) strcat (index_filename, "QNL_IDX.BBS"); /* add in the file name*/
        if ((stream = share_open (index_filename, O_RDONLY|O_BINARY, DENY_WRITE)) == -1)
            {
            if (have_boss_data != 2)
                status_line (MSG_TXT(M_UNABLE_TO_OPEN), index_filename);
            return (0);                             /* no file, no work to do */
            }
        (void) fstat (stream, &f);                  /* get file statistics    */
        i = (unsigned int) f.st_size;               /* size of index file,    */
        idx_size = i / sizeof (*nodeidx);           /* number of index entries*/
        node_index = get_size (i);
        if (node_index == NULL)
            {
            status_line (MSG_TXT(M_NODELIST_MEM));
            (void) close (stream);
            return (0);
            }

        if (_dos_read (stream, node_index, i, &got) != 0)
            {
            status_line (MSG_TXT(M_NODELIST_READ_ERR));
            (void) close (stream);
            return (0);
            }
        (void) close (stream);

        index_filesize = f.st_size;                 /* Save params for later  */
        index_filetime = f.st_mtime;
        }

    nodeidx = (struct QuickNodeIdxRecord far *) node_index;


    if (no_zones)
        Quick_addr->Zone = 0;

    for (i = 1; i <= idx_size; idxrec++, nodeidx++, i++)
        {
        if (((Quick_addr->Zone == nodeidx->QI_Zone) || (Quick_addr->Zone == 0))
             && (Quick_addr->Net == nodeidx->QI_Net))
            {
            foundnet = 1;                           /* say we found the net   */
            if (((Quick_addr->Node == 0) && (nodeidx->QI_Node <= 0))
                 || (nodeidx->QI_Node == Quick_addr->Node)) /* is it the node?*/
                {
                found = 1;                          /* say we found it        */
                break;                              /* get out                */
                }
            }
        else if (foundnet)                          /* already past the net?  */
            break;                                  /* Yes, we failed...      */
        }

    if (!found)
        {
        return (0);
        }


    nodeoff = (long) idxrec *(long) sizeof (nodedes);   /* actual file offset */

    (void) strcpy (temp, net_info);                 /* take nodelist path     */
    (void) strcat (temp, "QNL_DAT.BBS");            /* add in the file name   */
    if ((stream1 = share_fopen (temp, "rb", DENY_WRITE)) == NULL)   /* open it*/
        {
        status_line (MSG_TXT(M_UNABLE_TO_OPEN), temp);
        return (0);
        }

    if (fseek (stream1, nodeoff, SEEK_SET))         /* try to point at record */
        {
        status_line (MSG_TXT(M_NODELIST_SEEK_ERR), temp);
        (void) fclose (stream1);
        return (0);
        }

    if (!fread (&nodedes, sizeof (nodedes), 1, stream1))
        {
        status_line (MSG_TXT(M_NODELIST_REC_ERR), temp);
        (void) fclose (stream1);
        return (0);
        }
    (void) fclose (stream1);

    /*
     * Copy data from nodedes into newnodedes. 
     */

    newnodedes.NodeNumber = nodedes.QL_Node;        /* Node Number  */
    newnodedes.NetNumber = nodedes.QL_Net;          /* Net Number    */
    newnodedes.Cost = nodedes.QL_Cost;              /* Cost            */

    i = min (nodedes.QL_Name[0], 19);
    (void) strncpy (&newnodedes.SystemName[0], &nodedes.QL_Name[1], i);
    newnodedes.SystemName[i] = '\0';                /* System Name  */

    i = min (nodedes.QL_Phone[0], 39);
    (void) strncpy (&newnodedes.PhoneNumber[0], &nodedes.QL_Phone[1], i);
    newnodedes.PhoneNumber[i] = '\0';               /* Phone Number */

    i = min (nodedes.QL_City[0], 29);
    (void) strncpy (&newnodedes.MiscInfo[0], &nodedes.QL_City[1], i);
    newnodedes.MiscInfo[i] = '\0';

    /* This field is not necessarily null terminated */
    i = min (nodedes.QL_Password[0], 8);
    (void) strncpy (&newnodedes.Password[0], &nodedes.QL_Password[1], i);
    if (i < 8)
        newnodedes.Password[i] = '\0';

    /* Adam Hudson now gives us this, so we might as well use it */
    newnodedes.NodeFlags = nodedes.QL_Flags;

    /* Since we have the stuff we need! */
    newnodelist = 1;                                /* We have all the info   */

    newnodedes.RealCost = nodedes.QL_Cost;          /* Cost                   */
    newnodedes.HubNode = 0;                         /* Don't know who is Hub  */
    newnodedes.BaudRate = (char) (nodedes.QL_BaudRate / 300);   /* Baud       */
    newnodedes.ModemType = 0;                       /* Don't know modem type  */
    newnodedes.NodeFiller = 0;                      /* Filler should be zero  */
    found_zone = nodeidx -> QI_Zone;                /* Retain the found zone  */
    found_net = nodeidx -> QI_Net;                  /* And the found net      */
    return (1);
}

#endif /* QUICK_LIST */

int opusfind (ADDRP opus_addr, int have_boss_data)
{
    register struct _ndi far *nodeidx;              /* index file             */
    int found = 0;                                  /* 'found the node' flag  */
    int found_boss = 0;                             /* 'found the boss' flag  */
    int nodeoff = 0;                                /* offset in nodelist.sys */
    char temp[80];                                  /* we build filenames here*/

    HFILE stream;
    USHORT i;
    USHORT got;

    struct stat f;
    unsigned int current_zone = 0;

    newnodedes.NetNumber = newnodedes.NodeNumber = 0;

    if (nodelist_base == NULL)
        nodelist_base = nodelist_name;

    if  ((node_index == NULLGLOBALPTR)
    ||   ((curr_domain != opus_addr->Domain) && ((opus_addr->Domain != NULL) || (curr_domain != my_addr.Domain))))
        {
        if (node_index != NULL)
            {
            _ffree (node_index);
            }

        get_nodelist_name (opus_addr);
        index_filesize = (off_t) 0L;                /* Cover the error case   */
        index_filename[0] = '\0';                   /* "null-terminated string*/
        (void) strcpy (index_filename, net_info);   /* take nodelist path     */
        (void) strcat (index_filename, nodelist_base); /* add in the file name*/
        (void) strcat (index_filename, ".IDX");     /* add in the file ext    */
        if ((stream = share_open(index_filename, O_RDONLY|O_BINARY, DENY_WRITE)) == -1)
            {
            i = 0;                                  /* Need this later        */
            if (have_boss_data != 2)
                status_line (MSG_TXT(M_UNABLE_TO_OPEN), index_filename);
            return (0);                             /* no file, no work to do */
            }
        (void) fstat (stream, &f);                  /* get file statistics    */
        i = (unsigned int) f.st_size;               /* size of index file,    */
        idx_size = i / sizeof (struct _ndi);        /* number of index entries*/

        node_index = get_size (i);
        if (node_index == NULL)
            {
            status_line (MSG_TXT(M_NODELIST_MEM));
            (void) close (stream);
            return (0);
            }

        if (_dos_read (stream, node_index, i, &got) != 0)
            {
            status_line (MSG_TXT(M_NODELIST_READ_ERR));
            (void) close (stream);
            return (0);
            }
        (void) close (stream);

        index_filesize = f.st_size;                 /* Save params for later  */
        index_filetime = f.st_mtime;

        /*
         * Now take into account that the .DAT file can be bigger than we
         * really expect it to be.  Just take the number of records, and
         * divide into the size of the .DAT file to find the true record size
         */
        if (newnodelist)
            {
            temp[0] = '\0';                         /* "null-terminated string*/
            (void) strcpy (temp, net_info);         /* take nodelist path     */
            (void) strcat (temp, nodelist_base);    /* add in the file name   */
            (void) strcat (temp, ".DAT");           /* add in the file name   */
            if (!stat (temp, &f))
                {
                extra_bytes = ((int) (f.st_size / idx_size)) - sizeof (newnodedes);
                }
            }


        }


    nodeidx = (struct _ndi far *) node_index;

    if ((!newnodelist) || (alias[0].Zone == 0) || (no_zones))
        {
        opus_addr->Zone = 0;
        }

    for (i = 1; i <= idx_size; nodeoff++, nodeidx++, i++)
        {
        if (nodeidx->node == -2)
            current_zone = nodeidx->net;
     
        if (opus_addr->Zone > 0 && current_zone != opus_addr->Zone)
            continue;

        if ((unsigned)nodeidx->net == opus_addr->Net)   /* if a match on net, */
            {
            if (((opus_addr->Node == 0) && (nodeidx->node <= 0))
            || ((unsigned)nodeidx->node == opus_addr->Node))      
                {
                if (opus_addr->Point == 0)
                   {
                   found = 1;                           /* Say we found Node  */
                   break;
                   }
                found_boss = 1;                         /* say we found Boss  */
                continue;
                }
            }

        if (nodeidx->net != -1)
           {
           found_boss = 0;
           continue;
           }

        if ((found_boss == 1) 
        && ((unsigned)nodeidx->node == opus_addr->Point))
           {
           found = 1;
           break;
           }

        }

    if (!found)
        return (0);

    found_zone = current_zone;                      /* Retain the found zone  */
    found_net  = nodeidx->net;                      /* Keep track of found net*/

    if (newnodelist)
        i = (get_new_info (nodeoff));
#ifdef V5_LIST
    else i = (get_old_info (nodeoff));
#endif

    return (i);
}

#ifdef V5_LIST

int get_old_info (unsigned recno)
{
    struct _node nodedes;                           /* desc. of node          */
    long nodeoff;                                   /* Offset in NODELIST.SYS */
    char temp[80];                                  /* we build filenames here*/
    char *c, *ch;
    int i;
    FILE *stream;

    nodeoff = (long) recno *(long) sizeof (nodedes); /* actual file offset    */

    (void) strcpy (temp, net_info);                  /* take nodelist path    */
    (void) strcat (temp, nodelist_base);             /* add in the file name  */
    (void) strcat (temp, ".SYS");                    /* add in the file name  */
    if ((stream = share_fopen (temp, "rb", DENY_WRITE)) == NULL)/* open it    */
        {
        status_line (MSG_TXT(M_UNABLE_TO_OPEN), temp);
        return (0);
        }

    if (fseek (stream, nodeoff, SEEK_SET))           /* try to point at record*/
        {
        status_line (MSG_TXT(M_NODELIST_SEEK_ERR), temp);
        (void) fclose (stream);
        return (0);
        }

    if (!fread (&nodedes, sizeof (nodedes), 1, stream))
        {
        status_line (MSG_TXT(M_NODELIST_REC_ERR), temp);
        (void) fclose (stream);
        return (0);
        }
    (void) fclose (stream);

    /*
     * Copy data from nodedes into newnodedes. 
     */

    newnodedes.NodeNumber = (word) nodedes.number;      /* Node Number  */
    newnodedes.NetNumber = (word) nodedes.net;          /* Net Number    */
    newnodedes.Cost = (word) nodedes.cost;              /* Cost            */

    (void) strncpy (&newnodedes.SystemName[0], &nodedes.name[0], 20);
    newnodedes.SystemName[19] = '\0';                   /* System Name  */

    (void) strncpy (&newnodedes.PhoneNumber[0], &nodedes.phone[0], 40);
    newnodedes.PhoneNumber[39] = '\0';                  /* Phone Number */

    (void) strncpy (&newnodedes.MiscInfo[0], &nodedes.city[0], 30);
    newnodedes.MiscInfo[29] = '\0';

    ch = NULL;                                          /* password           */
    c = nodedes.city;                                   /* start of city      */
    i = 37;                                             /* No password if =0  */
    while (i--)                                         /* Enforce that limit */
        {
        if (*c++ != '\0')                               /* If not end of city,*/
            continue;                                   /* go on to next char */
        if (*c++ != '!')                                /* End city, got '!' ?*/
            break;                                      /* No, failure        */
        ch = c;                                         /* Got it, point to it*/
        break;                                          /* Exit with success  */
        }
    if (ch != NULL)
        {
        (void) strncpy (&newnodedes.Password[0], ch, 8);/* Copy the password  */
        }
    else newnodedes.Password[0] = '\0';                 /* Else none          */

    newnodedes.RealCost = nodedes.cost;                 /* Cost               */
    newnodedes.HubNode = 0;                             /* Don't know Hub     */
    newnodedes.BaudRate = (char) (nodedes.rate / 300);  /* Baud Rate          */
    newnodedes.ModemType = 0;                           /* Don't know modem   */
    newnodedes.NodeFlags = 0;                           /* Don't know flags   */
    newnodedes.NodeFiller = 0;                          /* Filler must be zero*/
    return (1);
}

#endif /* V5_LIST */

int get_new_info (unsigned recno)
{
    long nodeoff;                                   /* Offset in NODELIST.DAT */
    char temp[80];                                  /* we build filenames here*/
    FILE *stream;

    /* actual file offset */
    nodeoff = (long) recno * ((long) (sizeof (newnodedes) + extra_bytes));

    (void) strcpy (temp, net_info);                     /* take nodelist path */
    (void) strcat (temp, nodelist_base);                /* add in the filename*/
    (void) strcat (temp, ".DAT");                       /* then the extension */
    if ((stream = share_fopen (temp, "rb", DENY_WRITE)) == NULL)    /* open it*/
        {
        status_line (MSG_TXT(M_UNABLE_TO_OPEN), temp);
        return (0);
        }

    if (fseek (stream, nodeoff, SEEK_SET))              /* point at record    */
        {
        status_line (MSG_TXT(M_NODELIST_SEEK_ERR), temp);
        (void) fclose (stream);
        return (0);
        }

    if (!fread (&newnodedes, sizeof (newnodedes), 1, stream))
        {
        status_line (MSG_TXT(M_NODELIST_REC_ERR), temp);
        (void) fclose (stream);
        return (0);
        }
    (void) fclose (stream);
    return (1);
}

#ifdef OLDTBBSLIST
int get_TBBS_info (unsigned recno, ADDRP TBBS_addr)
{
    struct nodels nodedes;                          /* desc. of node          */
    struct extrastuff ext;                          /* Extra stuff for Binkley*/
    long nodeoff;                                   /* Offset in NODELIST.DOG */
    char temp[80];                                  /* we build filenames here*/
    FILE *stream;

    --recno;                                            /* TBBS starts at 1st *
                                                         * record - no filler */

    nodeoff = (long) recno *(long) sizeof (nodedes);    /* actual file offset */

    (void) strcpy (temp, net_info);                     /* take nodelist path */
    (void) strcat (temp, "NODELIST.DOG");               /* add in the filename*/
    if ((stream = share_fopen (temp, "rb", DENY_WRITE)) == NULL)    /* open it*/
        {
        status_line (MSG_TXT(M_UNABLE_TO_OPEN), temp);
        return (0);
        }

    if (fseek (stream, nodeoff, SEEK_SET))              /* point at record    */
        {
        status_line (MSG_TXT(M_NODELIST_SEEK_ERR), temp);
        (void) fclose (stream);
        return (0);
        }

    if (!fread (&nodedes, sizeof (nodedes), 1, stream))
        {
        status_line (MSG_TXT(M_NODELIST_REC_ERR), temp);
        (void) fclose (stream);
        return (0);
        }
    (void) fclose (stream);

    /*
     * Copy data from nodedes into newnodedes. 
     */

    newnodedes.NodeNumber = TBBS_addr->Node;            /* Node Number        */
    newnodedes.NetNumber = TBBS_addr->Net;              /* Net Number         */
    newnodedes.Cost = nodedes.nodecost;                 /* Cost               */

    (void) strncpy (&newnodedes.SystemName[0], &nodedes.nodename[0], 14);
    newnodedes.SystemName[19] = '\0';                   /* System Name        */

    (void) strncpy (&newnodedes.PhoneNumber[0], &nodedes.nodephone[0], 40);
    newnodedes.PhoneNumber[39] = '\0';                  /* Phone Number       */

    (void) strncpy (&newnodedes.MiscInfo[0], &nodedes.nodecity[0], 30);
    newnodedes.MiscInfo[29] = '\0';

    newnodedes.Password[0] = '\0';                      /* Else set zero length*/

    newnodedes.RealCost = nodedes.nodecost;             /* Cost               */
    newnodedes.HubNode = nodedes.nodehub;               /* Hub                */
    newnodedes.BaudRate = (char) (nodedes.nodebaud / 300);  /* Baud Rate      */
    newnodedes.ModemType = 0;                           /* Don't know modem   */
    newnodedes.NodeFlags = 0;                           /* Don't know flags   */
    newnodedes.NodeFiller = 0;                          /* Filler must be zero*/

    /* Now get information from secondary file */
    ++recno;
    nodeoff = (long) recno *(long) sizeof (ext);        /* actual file offset */

    (void) strcpy (temp, net_info);                     /* take nodelist path */
    (void) strcat (temp, "NODELIST.EXT");               /* add in the filename*/
    newnodelist = 0;
    if ((stream = share_fopen (temp, "rb", DENY_WRITE)) == NULL)    /* open it*/
        {
        return (1);
        }

    if (fseek (stream, nodeoff, SEEK_SET))          /* try to point at record */
        {
        (void) fclose (stream);
        return (1);
        }

    if (!fread (&ext, sizeof (ext), 1, stream))
        {
        (void) fclose (stream);
        return (1);
        }
    (void) fclose (stream);

    /*
     * Copy data from ext into newnodedes. 
     */

    (void) strncpy (newnodedes.Password, ext.password, 8);  /* Password       */

    newnodedes.NodeFlags = ext.flags1;                  /* Nodelist flags     */
    newnodedes.ModemType = ext.modem;                   /* Modem type         */
    newnodelist = 1;                                    /* We've all the info */
    return (1);
}

int TBBSLookup (ADDRP TBBS_addr, int have_boss_data)
{
    register struct _ndi far *nodeidx;              /* index file             */
    int found = 0;                                  /* 'found the node' flag  */
    int nodeoff = 0;                                /* offset in nodelist.sys */
    char temp[80];                                  /* we build filenames here*/

    HFILE stream;
    USHORT i;
    USHORT got;

    struct stat f;
    unsigned int current_zone = 0;

    newnodedes.NetNumber = newnodedes.NodeNumber = 0;

    if (node_index == NULL)
        {
        temp[0] = '\0';                             /* "null-terminated string*/
        (void) strcpy (temp, net_info);             /* take nodelist path     */
        (void) strcat (temp, "NODELIST.IDX");       /* add in the file name   */
        if ((stream = share_open(temp, O_RDONLY|O_BINARY, DENY_WRITE)) == -1)
            {
            i = 0;                                  /* Need this later        */
            if (have_boss_data != 2)
                status_line (MSG_TXT(M_UNABLE_TO_OPEN), temp);
            return (0);                             /* no file, no work to do */
            }
        (void) fstat (stream, &f);                  /* get file statistics    */
        i = (unsigned int) f.st_size;               /* size of index file,    */
        idx_size = i / sizeof (struct _ndi);        /* number of index entries*/
        node_index = get_size (i);
        if (node_index == NULL)
            {
            status_line (MSG_TXT(M_NODELIST_MEM));
            (void) close (stream);
            return (0);
            }

        if (_dos_read (stream, node_index, i, &got) != 0)
            {
            status_line (MSG_TXT(M_NODELIST_READ_ERR));
            (void) close (stream);
            return (0);
            }
        (void) close (stream);
        }
    nodeidx = (struct _ndi far *) node_index;

    if (TBBS_addr->Zone == (unsigned int) -1)
        {
        return (opus_next_zone ());
        }

    for (i = 1; i <= idx_size; nodeoff++, nodeidx++, i++)
        {
        if (nodeidx->node == -2)
        current_zone = nodeidx->net;
     
        if (TBBS_addr->Zone > 0 && current_zone != TBBS_addr->Zone)
                continue;

        if ((unsigned)nodeidx->net == TBBS_addr->Net)   /* if a match on net, */
            {
            if (((TBBS_addr->Node == 0) && (nodeidx->node <= 0))
                 || ((unsigned)nodeidx->node == TBBS_addr->Node))
                                                        /* is this the node?  */
                {
                found = 1;                              /* say we found it    */
                break;                                  /* get out            */
                }
            }
        }

    if (!found)
        return (0);

    found_zone = current_zone;                      /* Retain the found zone  */
    found_net  = nodeidx->net;                      /* Keep track of found net*/

    i = get_TBBS_info (nodeoff, TBBS_addr);

    return (i);
}

#endif /* defined OLDTBBSLIST */