home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / OS2 / BSRCP240.ZIP / NODEPROC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-03  |  32.3 KB  |  1,054 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                            */
  3. /*                                                                            */
  4. /*        ------------         Bit-Bucket Software, Co.                        */
  5. /*        \ 10001101 /         Writers and Distributors of                    */
  6. /*         \ 011110 /          Freely Available<tm> Software.                 */
  7. /*          \ 1011 /                                                            */
  8. /*           ------                                                            */
  9. /*                                                                            */
  10. /*    (C) Copyright 1987-90, Bit Bucket Software Co., a Delaware Corporation. */
  11. /*                                                                            */
  12. /*                                                                            */
  13. /*                 This module was written by Vince Perriello                 */
  14. /*                                                                            */
  15. /*                                                                            */
  16. /*                   BinkleyTerm Nodelist processing module                    */
  17. /*                                                                            */
  18. /*                                                                            */
  19. /*      For complete    details  of the licensing restrictions, please refer    */
  20. /*      to the License  agreement,  which  is published in its entirety in    */
  21. /*      the MAKEFILE and BT.C, and also contained in the file LICENSE.240.    */
  22. /*                                                                            */
  23. /*      USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  24. /*      BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  25. /*      THIS    AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,    OR IF YOU DO    */
  26. /*      NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  27. /*      SOFTWARE CO.    AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  28. /*      SHOULD YOU  PROCEED TO USE THIS FILE    WITHOUT HAVING    ACCEPTED THE    */
  29. /*      TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  30. /*      AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.        */
  31. /*                                                                            */
  32. /*                                                                            */
  33. /* You can contact Bit Bucket Software Co. at any one of the following        */
  34. /* addresses:                                                                */
  35. /*                                                                            */
  36. /* Bit Bucket Software Co.          FidoNet  1:104/501, 1:132/491, 1:141/491    */
  37. /* P.O. Box 460398                  AlterNet 7:491/0                            */
  38. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  39. /*                                  Internet f491.n132.z1.fidonet.org         */
  40. /*                                                                            */
  41. /* Please feel free to contact us at any time to share your comments about    */
  42. /* our software and/or licensing policies.                                    */
  43. /*                                                                            */
  44. /*--------------------------------------------------------------------------*/
  45.  
  46. #include <sys\types.h>
  47. #include <sys\stat.h>
  48. #include <stdio.h>
  49. #include <fcntl.h>
  50. #include <signal.h>
  51. #include <ctype.h>
  52. #include <conio.h>
  53. #include <dos.h>
  54. #include <io.h>
  55. #include <string.h>
  56.  
  57. #ifdef OS_2
  58. #define  INCL_DOS
  59. #include <os2.h>
  60. #define _dos_read DosRead
  61. #endif
  62.  
  63. #ifdef __TURBOC__
  64. #include <alloc.h>
  65. #define _fmalloc(n) farmalloc (n)
  66. #define _ffree(n) farfree (n)
  67. #else
  68. #include <malloc.h>
  69. #endif
  70.  
  71. #include "com.h"
  72. #include "xfer.h"
  73. #include "zmodem.h"
  74. #include "keybd.h"
  75. #include "sbuf.h"
  76. #include "sched.h"
  77. #include "externs.h"
  78. #include "prototyp.h"
  79.  
  80. static char far *get_size (unsigned int);
  81. static int get_new_info (unsigned);
  82. static int get_old_info (unsigned);
  83. static int get_TBBS_info (unsigned, ADDR *);
  84. static int Quick_Next_Zone (void);
  85. static int opus_next_zone (void);
  86.  
  87. #ifdef __TURBOC__
  88. typedef long off_t;
  89. #endif
  90. static off_t  index_filesize = (off_t)    0L;
  91. static time_t index_filetime = (time_t) 0L;
  92. static char   index_filename[80];
  93.  
  94. static unsigned int idx_size = 0;                 /* number of entries in it   */
  95. static unsigned int zone_offset = 0;
  96. static int last_zone = -1;
  97. static int extra_bytes = 0;
  98. static char *curr_domain = NULL;
  99. static char *nodelist_name = "NODELIST";
  100. static char *nodelist_base = NULL;
  101.  
  102. static void get_nodelist_name (ADDR *);
  103.  
  104. static void get_nodelist_name (opus_addr)
  105. ADDR *opus_addr;
  106. {
  107.    int i;
  108.  
  109.    curr_domain = opus_addr->Domain;
  110.  
  111.    idx_size = 0;
  112.    zone_offset = 0;
  113.    last_zone = -1;
  114.    extra_bytes = 0;
  115.    nodelist_base = nodelist_name;
  116.    for (i = 0; domain_name[i] != NULL; i++)
  117.       {
  118.       if (domain_name[i] == opus_addr->Domain)
  119.          {
  120.          nodelist_base = domain_nodelist[i];
  121.          if (nodelist_base == NULL)
  122.             nodelist_base = nodelist_name;
  123.          }
  124.       }
  125. }
  126.  
  127. static char far *get_size (n)
  128. unsigned int n;
  129. {
  130.    /* If we get this far, then we have to use a straight far pointer */
  131.    return (_fmalloc (n));
  132. }
  133.  
  134. /*---------------------------------------------------------------------------*/
  135. /* CHECKLIST                                                                 */
  136. /* See if nodelist has changed since we first tried to use it and if so,     */
  137. /* dismiss old copy and get a new one                                         */
  138. /*---------------------------------------------------------------------------*/
  139. int checklist ()
  140. {
  141.    struct stat idxstat;
  142.    if (index_filesize == (off_t)0L)
  143.       return (0);
  144.    stat (index_filename, &idxstat);
  145.    if ((index_filesize == idxstat.st_size) && (index_filetime == idxstat.st_mtime))
  146.       return (0);
  147.    status_line (msgtxt[M_REFRESH_NODELIST]);
  148.    _ffree ((char far *) node_index);
  149.    node_index = (char far *) NULL;
  150.    index_filesize = (off_t)0L;
  151.    return (1);
  152. }
  153.  
  154.  
  155. /*---------------------------------------------------------------------------*/
  156. /* NODEPROC                                                                  */
  157. /* Find nodelist entry and set baud to nodelist baud for dialing out         */
  158. /*---------------------------------------------------------------------------*/
  159.  
  160. int nodeproc (nodeaddr)
  161. char *nodeaddr;
  162. {
  163.    ADDR opus_addr;
  164.    char *c, *skip_blanks ();
  165.  
  166.    c = skip_blanks (nodeaddr);                     /* get rid of the blanks      */
  167.    if (!find_address (c, &opus_addr))
  168.       {
  169.       return (0);
  170.       }
  171.    if (!nodefind (&opus_addr, 1))  /* if we can't find the node */
  172.       return (0);                                 /* go away now               */
  173.    status_line (msgtxt[M_PROCESSING_NODE], Full_Addr_Str (&opus_addr), newnodedes.SystemName);
  174.    if (!CARRIER)                                 /* if no carrier yet,          */
  175.       {
  176.       if (autobaud)
  177.          (void) set_baud (max_baud.rate_value, 1);
  178.                                                  /* Set to our highest baud rate */
  179.       else
  180.          (void) set_baud ((300 * newnodedes.BaudRate), 1);         /* set baud to nodelist
  181.                                                                  * baud */
  182.       }
  183.    return (1);                                     /* return success to caller  */
  184. }
  185.  
  186. /*---------------------------------------------------------------------------*/
  187. /* NODEFIND                                                                  */
  188. /* Find nodelist entry for use by other routines (password, nodeproc)         */
  189. /* If found, result will be in "newnodedes".                                 */
  190. /*---------------------------------------------------------------------------*/
  191.  
  192. int nodefind (bink_addr, prtflag)
  193. ADDR *bink_addr;                                 /* zone, net and node */
  194. int prtflag;
  195. {
  196.    int i, j, k;
  197.    int have_boss_data = 0;
  198.    int need_boss_data = 0;
  199.  
  200.    (void) checklist ();
  201.  
  202.    newnodedes.NetNumber = newnodedes.NodeNumber = found_zone = found_net = 0;
  203.  
  204.    CurrentOKFile = DEFAULT.rq_OKFile;     /* Set the default f.req paths */
  205.    CurrentFILES = DEFAULT.rq_FILES;
  206.    CurrentAbout = DEFAULT.rq_About;
  207.    CurrentReqTemplate = DEFAULT.rq_Template;
  208.    CurrentNetFiles = DEFAULT.sc_Inbound;
  209.    CurrentReqLim = DEFAULT.rq_Limit;
  210.    CurrentByteLim = DEFAULT.byte_Limit;
  211.  
  212.    if ((bink_addr->Net == boss_addr.Net) && (bink_addr->Node == boss_addr.Node) &&
  213.        (bink_addr->Zone == alias[0].Zone) && ((bink_addr->Domain == boss_addr.Domain) || (bink_addr->Domain == NULL)))
  214.       {
  215.       ++need_boss_data;
  216.       if (BOSSphone && strlen (BOSSphone) > 2)
  217.          ++have_boss_data;
  218.       if (BOSSpwd && strlen (BOSSpwd) > 2)
  219.          ++have_boss_data;
  220.       }
  221.  
  222.    if (!bink_addr->Zone)
  223.       {
  224.       bink_addr->Zone = alias[0].Zone;
  225.       i = (*nodefunc) (bink_addr, have_boss_data);
  226.       if (i) goto lookup_done;
  227.       }
  228.    i = (*nodefunc) (bink_addr, have_boss_data);
  229.  
  230. lookup_done:
  231.  
  232.    assumed = k = 0;                           /* Default to zone of first */
  233.    for (j = 0; j < num_addrs; j++)
  234.       {
  235.       if ((alias[j].Point != 0) &&
  236.           ((alias[j].Node != newnodedes.NodeNumber) ||
  237.            (alias[j].Net != found_net) ||
  238.            (alias[j].Zone != found_zone)))
  239.          {
  240.          /* Don't use our point address except to the boss! */
  241.          continue;
  242.          }
  243.  
  244.       if ((alias[j].Domain == curr_domain) ||
  245.           ((curr_domain == NULL) && (alias[j].Domain == my_addr.Domain)) ||
  246.           ((alias[j].Domain == NULL) && (curr_domain == my_addr.Domain)))
  247.          {
  248.          if (k == 0)
  249.             {
  250.             assumed = j;
  251.             ++k;
  252.             }
  253.  
  254.          if (alias[j].Zone == found_zone)
  255.             {
  256.             if (k == 1)
  257.                {
  258.                assumed = j;
  259.                ++k;
  260.                }
  261.  
  262.             if (alias[j].Net == found_net)
  263.                {
  264.                assumed = j;
  265.                break;
  266.                }
  267.             }
  268.          }
  269.       }
  270.  
  271.    if (!i && (have_boss_data != 2))
  272.       {
  273.       if (prtflag)
  274.          status_line (msgtxt[M_NO_ADDRESS], Full_Addr_Str (bink_addr));
  275.  
  276.       if (curmudgeon && CARRIER && (bink_addr->Net != -1) && (bink_addr->Node != -1) && (bink_addr->Node != 9999))
  277.          {
  278.          status_line (msgtxt[M_NUISANCE_CALLER]);
  279.          DTR_OFF ();                            /* Hang up right now      */
  280.          timer (2);                             /* Wait two secs          */
  281.          DTR_ON ();                             /* OK, turn modem back on */
  282.          }
  283.  
  284.       }
  285.  
  286.    if (bink_addr->Zone == (unsigned int) -1)
  287.       return i;
  288.  
  289.    /* If we found the entry, then we promote the file request
  290.     * to the "KNOWN" class. If the password field is non-zero,
  291.     * then promote to "PROT". It's OK to do that since the higher
  292.     * level code will hang up before f.req's if the password does
  293.     * not match.
  294.     *
  295.     */
  296.  
  297.    if (i)
  298.       {
  299.       if (newnodedes.Password[0])
  300.          {
  301.          CurrentOKFile = PROT.rq_OKFile;
  302.          CurrentFILES = PROT.rq_FILES;
  303.          CurrentAbout = PROT.rq_About;
  304.          CurrentReqTemplate = PROT.rq_Template;
  305.          CurrentNetFiles = PROT.sc_Inbound;
  306.          CurrentReqLim = PROT.rq_Limit;
  307.          CurrentByteLim = PROT.byte_Limit;
  308.          }
  309.       else
  310.          {
  311.          CurrentOKFile = KNOWN.rq_OKFile;
  312.          CurrentFILES = KNOWN.rq_FILES;
  313.          CurrentAbout = KNOWN.rq_About;
  314.          CurrentReqTemplate = KNOWN.rq_Template;
  315.          CurrentNetFiles = KNOWN.sc_Inbound;
  316.          CurrentReqLim = KNOWN.rq_Limit;
  317.          CurrentByteLim = KNOWN.byte_Limit;
  318.          }
  319.       }
  320.  
  321.    if (!need_boss_data)
  322.       return (i);
  323.  
  324. /*
  325.  *    We can get here one of two ways:
  326.  *
  327.  *    1) No nodelist data was found and this is the BOSS.
  328.  *
  329.  *    2) Nodelist lookup occurred, but this is the BOSS.
  330.  *
  331.  *    For case (1), have_boss_data MUST be 2 (meaning we have
  332.  *    both a phone number and a password entry). If that is the
  333.  *    case, fill in newnodedes with mostly zeroes, plugging in
  334.  *    the BOSS net, node, phone number and password.
  335.  *
  336.  *    For case (2), just see if there is any substitution for
  337.  *    BOSSphone and/or BOSSpwd, then exit.
  338.  *
  339.  */
  340.  
  341.    if (BOSSphone && strlen (BOSSphone) > 2)
  342.       {
  343.       (void) strncpy (newnodedes.PhoneNumber, BOSSphone, 40);
  344.       newnodedes.PhoneNumber[39] = '\0';
  345.       }
  346.  
  347.    if (BOSSpwd && strlen (BOSSpwd) > 2)
  348.       {
  349.       (void) memset (newnodedes.Password, 0, sizeof (newnodedes.Password));
  350.       (void) strncpy (newnodedes.Password, BOSSpwd, 8);
  351.       }
  352.  
  353.    if (i)
  354.       return (1);
  355.  
  356.    /* No BOSS in the nodelist */
  357.    if (have_boss_data != 2)
  358.       {
  359.       status_line (msgtxt[M_NO_BOSS]);
  360.       return (0);
  361.       }
  362.  
  363.    newnodedes.NodeNumber = bink_addr->Node;       /* Node Number */
  364.    newnodedes.NetNumber = bink_addr->Net;          /* Net Number  */
  365.    newnodedes.Cost = newnodedes.RealCost = 0;     /* Assume boss is free */
  366.    (void) strcpy (newnodedes.SystemName, "Binkley's Boss");    /* System Name defaults */
  367.    (void) strcpy (newnodedes.MiscInfo, "Somewhere out There"); /* As does City */
  368.    newnodedes.HubNode = 0;                         /* Don't know who is HUB */
  369.    newnodedes.BaudRate = (char) (max_baud.rate_value / 300);
  370.                                                  /* Assume boss speed = ours */
  371.    newnodedes.ModemType = 0;                     /* Or modem type */
  372.    newnodedes.NodeFlags = B_CM;                  /* Assume boss is CM */
  373.    newnodedes.NodeFiller = 0;                     /* Zero out filler */
  374.    return (1);
  375. }
  376.  
  377. static int Quick_Next_Zone ()
  378. {
  379.    register struct QuickNodeIdxRecord far *nodeidx;     /* index file          */
  380.    register unsigned int i;
  381.  
  382.    if (no_zones)
  383.       return (-1);
  384.  
  385.    nodeidx = (struct QuickNodeIdxRecord far *) (node_index + (zone_offset *
  386.               sizeof (struct QuickNodeIdxRecord)));
  387.    for (i = zone_offset; i < idx_size; ++nodeidx, i++)
  388.       {
  389.       if (nodeidx->QI_Zone != last_zone)
  390.          {
  391.          last_zone = nodeidx->QI_Zone;
  392.          zone_offset = i + 1;
  393.          return (last_zone);
  394.          }
  395.       }
  396.  
  397.    last_zone = -1;
  398.    zone_offset = 0;
  399.    return (-1);
  400. }
  401.  
  402.  
  403. int QuickLookup (Quick_addr, have_boss_data)
  404. ADDR *Quick_addr;                                 /* zone, net and node */
  405. int have_boss_data;                              /* BOSS data flag       */
  406. {
  407.    register struct QuickNodeIdxRecord far *nodeidx;     /* index file          */
  408.    struct QuickNodeListRecord nodedes;             /* desc. of node       */
  409.  
  410.    int foundnet = 0;                             /* 'found the net' flag      */
  411.    int found = 0;                                 /* 'found the node' flag     */
  412.    int idxrec = 0;                                 /* record in QNL_IDX.BBS      */
  413.    long nodeoff = 0L;                             /* offset into QNL_DAT.BBS   */
  414.    char temp[80];                                 /* where we build filenames  */
  415. #ifndef OS_2
  416.    int stream;
  417.    unsigned int i;
  418.    int got;
  419. #else
  420.    HFILE stream;
  421.    USHORT i;
  422.    USHORT got;
  423. #endif
  424.    FILE *stream1;
  425.    struct stat f;
  426.  
  427.    newnodedes.NetNumber = newnodedes.NodeNumber = 0;
  428.  
  429.    if (node_index == NULL)
  430.       {
  431.       index_filesize == (off_t) 0L;              /* Cover ourselves for error */
  432.       index_filename[0] = '\0';                  /* "null-terminated string"  */
  433.       (void) strcpy (index_filename, net_info);  /* take nodelist path          */
  434.       (void) strcat (index_filename, "QNL_IDX.BBS"); /* add in the file name  */
  435.       if ((stream = open(index_filename, O_RDONLY|O_BINARY)) == -1)
  436.          {
  437.          if (have_boss_data != 2)
  438.             status_line (msgtxt[M_UNABLE_TO_OPEN], index_filename);
  439.          return (0);                             /* no file, no work to do      */
  440.          }
  441.       (void) fstat (stream, &f);                 /* get file statistics       */
  442.       i = (unsigned int) f.st_size;              /* size of index file,       */
  443.       idx_size = i / sizeof (*nodeidx);          /* number of index entries   */
  444.       node_index = get_size (i);
  445.       if (node_index == NULL)
  446.          {
  447.          status_line (msgtxt[M_NODELIST_MEM]);
  448.          (void) close (stream);
  449.          return (0);
  450.          }
  451.       if (_dos_read (stream, node_index, i, &got) != 0)
  452.          {
  453.          status_line (msgtxt[M_NODELIST_READ_ERR]);
  454.          (void) close (stream);
  455.          return (0);
  456.          }
  457.       (void) close (stream);
  458.  
  459.       index_filesize = f.st_size;                 /* Save parameters for later */
  460.       index_filetime = f.st_mtime;
  461.       }
  462.  
  463.    nodeidx = (struct QuickNodeIdxRecord far *) node_index;
  464.  
  465.  
  466.    if (Quick_addr->Zone == (unsigned int) -1)
  467.       {
  468.       return (Quick_Next_Zone ());
  469.       }
  470.    else if (no_zones)
  471.       Quick_addr->Zone = 0;
  472.  
  473.    for (i = 1; i <= idx_size; idxrec++, nodeidx++, i++)
  474.       {
  475.       if (((Quick_addr->Zone == nodeidx->QI_Zone) || (Quick_addr->Zone == 0))
  476.           && (Quick_addr->Net == nodeidx->QI_Net))
  477.          {
  478.          foundnet = 1;                             /* say we found the net      */
  479.          if (((Quick_addr->Node == 0) && (nodeidx->QI_Node <= 0))
  480.              || (nodeidx->QI_Node == Quick_addr->Node)) /* see if we found the node  */
  481.             {
  482.             found = 1;                             /* say we found it           */
  483.             break;                                 /* get out                   */
  484.             }
  485.          }
  486.       else if (foundnet)                         /* already past the net?      */
  487.          break;                                  /* Yes, we failed...          */
  488.       }
  489.  
  490.    if (!found)
  491.       {
  492.       return (0);
  493.       }
  494.  
  495.  
  496.    nodeoff = (long) idxrec *(long) sizeof (nodedes);    /* actual file offset    */
  497.  
  498.    (void) strcpy (temp, net_info);                        /* take nodelist path         */
  499.    (void) strcat (temp, "QNL_DAT.BBS");                 /* add in the file name      */
  500.    if ((stream1 = fopen (temp, "rb")) == NULL)   /* OK, let's open the file   */
  501.       {
  502.       status_line (msgtxt[M_UNABLE_TO_OPEN], temp);
  503.       return (0);
  504.       }
  505.  
  506.    if (fseek (stream1, nodeoff, SEEK_SET))         /* try to point at record      */
  507.       {
  508.       status_line (msgtxt[M_NODELIST_SEEK_ERR], temp);
  509.       (void) fclose (stream1);
  510.       return (0);
  511.       }
  512.  
  513.    if (!fread (&nodedes, sizeof (nodedes), 1, stream1))
  514.       {
  515.       status_line (msgtxt[M_NODELIST_REC_ERR], temp);
  516.       (void) fclose (stream1);
  517.       return (0);
  518.       }
  519.    (void) fclose (stream1);
  520.  
  521.    /*
  522.     * Copy data from nodedes into newnodedes.
  523.     */
  524.  
  525.    newnodedes.NodeNumber = nodedes.QL_Node;      /* Node Number  */
  526.    newnodedes.NetNumber = nodedes.QL_Net;         /* Net Number     */
  527.    newnodedes.Cost = nodedes.QL_Cost;             /* Cost         */
  528.  
  529.    i = min (nodedes.QL_Name[0], 19);
  530.    (void) strncpy (&newnodedes.SystemName[0], &nodedes.QL_Name[1], i);
  531.    newnodedes.SystemName[i] = '\0';              /* System Name  */
  532.  
  533.    i = min (nodedes.QL_Phone[0], 39);
  534.    (void) strncpy (&newnodedes.PhoneNumber[0], &nodedes.QL_Phone[1], i);
  535.    newnodedes.PhoneNumber[i] = '\0';             /* Phone Number */
  536.  
  537.    i = min (nodedes.QL_City[0], 29);
  538.    (void) strncpy (&newnodedes.MiscInfo[0], &nodedes.QL_City[1], i);
  539.    newnodedes.MiscInfo[i] = '\0';
  540.  
  541.    /* This field is not necessarily null terminated */
  542.    i = min (nodedes.QL_Password[0], 8);
  543.    (void) strncpy (&newnodedes.Password[0], &nodedes.QL_Password[1], i);
  544.    if (i < 8)
  545.       newnodedes.Password[i] = '\0';
  546.  
  547.    /* Adam Hudson now gives us this, so we might as well use it */
  548.    newnodedes.NodeFlags = nodedes.QL_Flags;
  549.  
  550.    /* Since we have the stuff we need! */
  551.    newnodelist = 1;                              /* We have all the
  552.                                                   * information! */
  553.  
  554.    newnodedes.RealCost = nodedes.QL_Cost;         /* Cost                     */
  555.    newnodedes.HubNode = 0;                         /* Don't know who is Hub    */
  556.    newnodedes.BaudRate = (char) (nodedes.QL_BaudRate / 300);    /* Baud      */
  557.    newnodedes.ModemType = 0;                     /* Don't know modem type    */
  558.    newnodedes.NodeFiller = 0;                     /* Filler should be zero     */
  559.    found_zone = nodeidx -> QI_Zone;              /* Keep track of found zone */
  560.    found_net = nodeidx -> QI_Net;                 /* And of found net         */
  561.    return (1);
  562. }
  563.  
  564. static int opus_next_zone ()
  565. {
  566.    register struct _ndi far *nodeidx;             /* index file                  */
  567.    register unsigned int i;
  568.  
  569.    if (no_zones)
  570.       return (-1);
  571.  
  572.    if (zone_offset == 0)
  573.       zone_offset = 1;
  574.  
  575.    nodeidx = (struct _ndi far *) (node_index + (zone_offset *
  576.              sizeof (struct _ndi)));
  577.  
  578.    for (i = zone_offset; i < idx_size; ++nodeidx, i++)
  579.       {
  580.       if (nodeidx->node == -2)
  581.          {
  582.          last_zone = nodeidx->net;
  583.          zone_offset = i + 1;
  584.          return (last_zone);
  585.          }
  586.       }
  587.  
  588.    last_zone = -1;
  589.    zone_offset = 0;
  590.    return (-1);
  591. }
  592.  
  593. int opusfind (opus_addr, have_boss_data)
  594. ADDR *opus_addr;                                 /* zone, net and node */
  595. int have_boss_data;                              /* BOSS data flag       */
  596. {
  597.    register struct _ndi far *nodeidx;             /* index file                  */
  598. /* int foundnet = 0;   */                         /* 'found the net' flag      */
  599.    int found = 0;                                 /* 'found the node' flag     */
  600.    int nodeoff = 0;                              /* offset into nodelist.sys  */
  601.    char temp[80];                                 /* where we build filenames  */
  602. #ifndef OS_2
  603.    int stream;
  604.    unsigned int i;
  605.    int got;
  606. #else
  607.    HFILE stream;
  608.    USHORT i;
  609.    USHORT got;
  610. #endif
  611.    struct stat f;
  612.    int current_zone = 0;
  613.  
  614.    newnodedes.NetNumber = newnodedes.NodeNumber = 0;
  615.  
  616.    if (nodelist_base == NULL)
  617.       nodelist_base = nodelist_name;
  618.  
  619.    if ((node_index == NULL) || ((curr_domain != opus_addr->Domain) && ((opus_addr->Domain != NULL) || (curr_domain != my_addr.Domain))))
  620.       {
  621.       if (node_index != NULL)
  622.          {
  623.          _ffree (node_index);
  624.          }
  625.  
  626.       get_nodelist_name (opus_addr);
  627.       index_filesize == (off_t) 0L;              /* Cover ourselves for error */
  628.       index_filename[0] = '\0';                  /* "null-terminated string"  */
  629.       (void) strcpy (index_filename, net_info);  /* take nodelist path          */
  630.       (void) strcat (index_filename, nodelist_base); /* add in the file name  */
  631.       (void) strcat (index_filename, ".IDX");    /* add in the file ext       */
  632.       if ((stream = open(index_filename, O_RDONLY|O_BINARY)) == -1)
  633.          {
  634.          i = 0;                                  /* Need this later           */
  635.          if (have_boss_data != 2)
  636.             status_line (msgtxt[M_UNABLE_TO_OPEN], index_filename);
  637.          return (0);                             /* no file, no work to do      */
  638.          }
  639.       (void) fstat (stream, &f);                        /* get file statistics         */
  640.       i = (unsigned int) f.st_size;              /* size of index file,       */
  641.       idx_size = i / sizeof (struct _ndi);         /* number of index entries   */
  642.  
  643.       node_index = get_size (i);
  644.       if (node_index == NULL)
  645.          {
  646.          status_line (msgtxt[M_NODELIST_MEM]);
  647.          (void) close (stream);
  648.          return (0);
  649.          }
  650.       if (_dos_read (stream, node_index, i, &got) != 0)
  651.          {
  652.          status_line (msgtxt[M_NODELIST_READ_ERR]);
  653.          (void) close (stream);
  654.          return (0);
  655.          }
  656.       (void) close (stream);
  657.  
  658.       index_filesize = f.st_size;                 /* Save parameters for later */
  659.       index_filetime = f.st_mtime;
  660.  
  661.       /*
  662.        * Now take into account that the .DAT file can be bigger than we
  663.        * really expect it to be.  Just take the number of records, and
  664.        * divide into the size of the .DAT file to find the true record size
  665.        */
  666.       if (newnodelist)
  667.          {
  668.          temp[0] = '\0';                         /* "null-terminated string"  */
  669.          (void) strcpy (temp, net_info);         /* take nodelist path          */
  670.          (void) strcat (temp, nodelist_base);     /* add in the file name      */
  671.          (void) strcat (temp, ".DAT");           /* add in the file name      */
  672.          if (!stat (temp, &f))
  673.             {
  674.             extra_bytes = ((int) (f.st_size / idx_size)) - sizeof (newnodedes);
  675.             }
  676.          }
  677.  
  678.  
  679.       }
  680.  
  681.  
  682.    nodeidx = (struct _ndi far *) node_index;
  683.  
  684.    /* If using the old nodelist, bypass zone stuff - it isn't there */
  685.    if (opus_addr->Zone == (unsigned int) -1)
  686.       {
  687.       return (opus_next_zone ());
  688.       }
  689.    else if ((!newnodelist) || (alias[0].Zone == 0) || (no_zones))
  690.       {
  691.       opus_addr->Zone = 0;
  692.       }
  693.  
  694.    for (i = 1; i <= idx_size; nodeoff++, nodeidx++, i++)
  695.       {
  696.       if (nodeidx->node == -2)
  697.          current_zone = nodeidx->net;
  698.  
  699.       if (opus_addr->Zone > 0 && current_zone != opus_addr->Zone)
  700.          continue;
  701.  
  702.       if (nodeidx->net == opus_addr->Net)                /* if a match on net,         */
  703.          {
  704. /*         foundnet = 1;     */                      /* say we found the net      */
  705.          if (((opus_addr->Node == 0) && (nodeidx->node <= 0))
  706.              || (nodeidx->node == opus_addr->Node))     /* see if we found the node  */
  707.             {
  708.             found = 1;                             /* say we found it           */
  709.             break;                                 /* get out                   */
  710.             }
  711.          }
  712.  
  713.       /*
  714.        * This code is good, but many people complained about not being able
  715.        * to add nodes to nets by adding them at the end of the nodelist.  So,
  716.        * I commented this stuff out for now. - Bob
  717.        */
  718. /*        else*/
  719.       /*      if (foundnet)*//* already past the net?      */
  720.       /*         break;*//* Yes, we failed...          */
  721.       }
  722.  
  723.    if (!found)
  724.       return (0);
  725.  
  726.    found_zone = current_zone;                     /* Keep track of found zone */
  727.    found_net  = nodeidx->net;                     /* Keep track of found net  */
  728.  
  729.    if (newnodelist)
  730.       i = (get_new_info (nodeoff));
  731.    else i = (get_old_info (nodeoff));
  732.  
  733.    return (i);
  734. }
  735.  
  736.  
  737. static int get_old_info (recno)
  738. unsigned recno;
  739. {
  740.    struct _node nodedes;                         /* desc. of node              */
  741.    long nodeoff;                                 /* Offset into NODELIST.SYS  */
  742.    char temp[80];                                 /* where we build filenames  */
  743.    char *c, *ch;
  744.    int i;
  745.    FILE *stream;
  746.  
  747.    nodeoff = (long) recno *(long) sizeof (nodedes);     /* actual file offset         */
  748.  
  749.    (void) strcpy (temp, net_info);                        /* take nodelist path         */
  750.    (void) strcat (temp, nodelist_base);                /* add in the file name        */
  751.    (void) strcat (temp, ".SYS");                /* add in the file name      */
  752.    if ((stream = fopen (temp, "rb")) == NULL)    /* OK, let's open the file   */
  753.       {
  754.       status_line (msgtxt[M_UNABLE_TO_OPEN], temp);
  755.       return (0);
  756.       }
  757.  
  758.    if (fseek (stream, nodeoff, SEEK_SET))         /* try to point at record      */
  759.       {
  760.       status_line (msgtxt[M_NODELIST_SEEK_ERR], temp);
  761.       (void) fclose (stream);
  762.       return (0);
  763.       }
  764.  
  765.    if (!fread (&nodedes, sizeof (nodedes), 1, stream))
  766.       {
  767.       status_line (msgtxt[M_NODELIST_REC_ERR], temp);
  768.       (void) fclose (stream);
  769.       return (0);
  770.       }
  771.    (void) fclose (stream);
  772.  
  773.    /*
  774.     * Copy data from nodedes into newnodedes.
  775.     */
  776.  
  777.    newnodedes.NodeNumber = nodedes.number;         /* Node Number  */
  778.    newnodedes.NetNumber = nodedes.net;             /* Net Number     */
  779.    newnodedes.Cost = nodedes.cost;                 /* Cost         */
  780.  
  781.    (void) strncpy (&newnodedes.SystemName[0], &nodedes.name[0], 20);
  782.    newnodedes.SystemName[19] = '\0';             /* System Name  */
  783.  
  784.    (void) strncpy (&newnodedes.PhoneNumber[0], &nodedes.phone[0], 40);
  785.    newnodedes.PhoneNumber[39] = '\0';            /* Phone Number */
  786.  
  787.    (void) strncpy (&newnodedes.MiscInfo[0], &nodedes.city[0], 30);
  788.    newnodedes.MiscInfo[29] = '\0';
  789.  
  790.    ch = NULL;                                     /* Pointer to password      */
  791.    c = nodedes.city;                             /* Point to start of city     */
  792.    i = 37;                                         /* No password if this = 0  */
  793.    while (i--)                                     /* Enforce that limit         */
  794.       {
  795.       if (*c++ != '\0')                          /* If not at end of city,   */
  796.          continue;                                 /* go on to next character  */
  797.       if (*c++ != '!')                           /* End of city, got '!' ??  */
  798.          break;                                  /* No, treat like a failure */
  799.       ch = c;                                     /* Got it, point to it      */
  800.       break;                                     /* Exit with success code     */
  801.       }
  802.    if (ch != NULL)
  803.       {
  804.       (void) strncpy (&newnodedes.Password[0], ch, 8);    /* Copy the password        */
  805.       }
  806.    else newnodedes.Password[0] = '\0';           /* Else set zero length     */
  807.  
  808.    newnodedes.RealCost = nodedes.cost;             /* Cost                     */
  809.    newnodedes.HubNode = 0;                         /* Don't know who is Hub    */
  810.    newnodedes.BaudRate = (char) (nodedes.rate / 300);    /* Baud Rate                */
  811.    newnodedes.ModemType = 0;                     /* Don't know modem type    */
  812.    newnodedes.NodeFlags = 0;                     /* Don't know any flags     */
  813.    newnodedes.NodeFiller = 0;                     /* Filler should be zero     */
  814.    return (1);
  815. }
  816.  
  817. static int get_new_info (recno)
  818. unsigned recno;
  819. {
  820.    long nodeoff;                                 /* Offset into NODELIST.DAT  */
  821.    char temp[80];                                 /* where we build filenames  */
  822.    FILE *stream;
  823.  
  824.    /* actual file offset */
  825.    nodeoff = (long) recno * ((long) (sizeof (newnodedes) + extra_bytes));
  826.  
  827.    (void) strcpy (temp, net_info);                        /* take nodelist path         */
  828.    (void) strcat (temp, nodelist_base);                /* add in the file name        */
  829.    (void) strcat (temp, ".DAT");                /* add in the file name      */
  830.    if ((stream = fopen (temp, "rb")) == NULL)    /* OK, let's open the file   */
  831.       {
  832.       status_line (msgtxt[M_UNABLE_TO_OPEN], temp);
  833.       return (0);
  834.       }
  835.  
  836.    if (fseek (stream, nodeoff, SEEK_SET))         /* try to point at record      */
  837.       {
  838.       status_line (msgtxt[M_NODELIST_SEEK_ERR], temp);
  839.       (void) fclose (stream);
  840.       return (0);
  841.       }
  842.  
  843.    if (!fread (&newnodedes, sizeof (newnodedes), 1, stream))
  844.       {
  845.       status_line (msgtxt[M_NODELIST_REC_ERR], temp);
  846.       (void) fclose (stream);
  847.       return (0);
  848.       }
  849.    (void) fclose (stream);
  850.    return (1);
  851. }
  852.  
  853. static int get_TBBS_info (recno, TBBS_addr)
  854. unsigned recno;
  855. ADDR *TBBS_addr;
  856. {
  857.    struct nodels nodedes;                         /* desc. of node              */
  858.    struct extrastuff ext;                         /* Extra stuff for Binkley   */
  859.    long nodeoff;                                 /* Offset into NODELIST.DOG  */
  860.    char temp[80];                                 /* where we build filenames  */
  861.    FILE *stream;
  862.  
  863.    --recno;                                      /* TBBS list starts at first
  864.                                                   * record - no filler */
  865.  
  866.    nodeoff = (long) recno *(long) sizeof (nodedes);     /* actual file offset         */
  867.  
  868.    (void) strcpy (temp, net_info);                        /* take nodelist path         */
  869.    (void) strcat (temp, "NODELIST.DOG");                /* add in the file name      */
  870.    if ((stream = fopen (temp, "rb")) == NULL)    /* OK, let's open the file   */
  871.       {
  872.       status_line (msgtxt[M_UNABLE_TO_OPEN], temp);
  873.       return (0);
  874.       }
  875.  
  876.    if (fseek (stream, nodeoff, SEEK_SET))         /* try to point at record      */
  877.       {
  878.       status_line (msgtxt[M_NODELIST_SEEK_ERR], temp);
  879.       (void) fclose (stream);
  880.       return (0);
  881.       }
  882.  
  883.    if (!fread (&nodedes, sizeof (nodedes), 1, stream))
  884.       {
  885.       status_line (msgtxt[M_NODELIST_REC_ERR], temp);
  886.       (void) fclose (stream);
  887.       return (0);
  888.       }
  889.    (void) fclose (stream);
  890.  
  891.    /*
  892.     * Copy data from nodedes into newnodedes.
  893.     */
  894.  
  895.    newnodedes.NodeNumber = TBBS_addr->Node;             /* Node Number    */
  896.    newnodedes.NetNumber = TBBS_addr->Net;                /* Net Number    */
  897.    newnodedes.Cost = nodedes.nodecost;             /* Cost         */
  898.  
  899.    (void) strncpy (&newnodedes.SystemName[0], &nodedes.nodename[0], 14);
  900.    newnodedes.SystemName[19] = '\0';             /* System Name  */
  901.  
  902.    (void) strncpy (&newnodedes.PhoneNumber[0], &nodedes.nodephone[0], 40);
  903.    newnodedes.PhoneNumber[39] = '\0';            /* Phone Number */
  904.  
  905.    (void) strncpy (&newnodedes.MiscInfo[0], &nodedes.nodecity[0], 30);
  906.    newnodedes.MiscInfo[29] = '\0';
  907.  
  908.    newnodedes.Password[0] = '\0';                /* Else set zero length     */
  909.  
  910.    newnodedes.RealCost = nodedes.nodecost;         /* Cost                     */
  911.    newnodedes.HubNode = nodedes.nodehub;         /* Hub */
  912.    newnodedes.BaudRate = (char) (nodedes.nodebaud / 300);        /* Baud Rate                */
  913.    newnodedes.ModemType = 0;                     /* Don't know modem type    */
  914.    newnodedes.NodeFlags = 0;                     /* Don't know any flags     */
  915.    newnodedes.NodeFiller = 0;                     /* Filler should be zero     */
  916.  
  917.    /* Now get information from secondary file */
  918.    ++recno;
  919.    nodeoff = (long) recno *(long) sizeof (ext);  /* actual file offset          */
  920.  
  921.    (void) strcpy (temp, net_info);                        /* take nodelist path         */
  922.    (void) strcat (temp, "NODELIST.EXT");                /* add in the file name      */
  923.    newnodelist = 0;
  924.    if ((stream = fopen (temp, "rb")) == NULL)    /* OK, let's open the file   */
  925.       {
  926.       return (1);
  927.       }
  928.  
  929.    if (fseek (stream, nodeoff, SEEK_SET))         /* try to point at record      */
  930.       {
  931.       (void) fclose (stream);
  932.       return (1);
  933.       }
  934.  
  935.    if (!fread (&ext, sizeof (ext), 1, stream))
  936.       {
  937.       (void) fclose (stream);
  938.       return (1);
  939.       }
  940.    (void) fclose (stream);
  941.  
  942.    /*
  943.     * Copy data from ext into newnodedes.
  944.     */
  945.  
  946.    (void) strncpy (newnodedes.Password, ext.password, 8);       /* Password */
  947.  
  948.    newnodedes.NodeFlags = ext.flags1;             /* Nodelist flags */
  949.    newnodedes.ModemType = ext.modem;             /* Modem type */
  950.    newnodelist = 1;                              /* We have all the
  951.                                                   * information! */
  952.    return (1);
  953. }
  954.  
  955. int TBBSLookup (TBBS_addr, have_boss_data)
  956. ADDR *TBBS_addr;                                 /* zone, net and node */
  957. int have_boss_data;                              /* BOSS data flag       */
  958. {
  959.    register struct _ndi far *nodeidx;             /* index file                  */
  960. /* int foundnet = 0; */                          /* 'found the net' flag      */
  961.    int found = 0;                                 /* 'found the node' flag     */
  962.    int nodeoff = 0;                              /* offset into nodelist.sys  */
  963.    char temp[80];                                 /* where we build filenames  */
  964. #ifndef OS_2
  965.    int stream;
  966.    unsigned int i;
  967.    int got;
  968. #else
  969.    HFILE stream;
  970.    USHORT i;
  971.    USHORT got;
  972. #endif
  973.    struct stat f;
  974.    int current_zone = 0;
  975.  
  976.    newnodedes.NetNumber = newnodedes.NodeNumber = 0;
  977.  
  978.    if (node_index == NULL)
  979.       {
  980.       temp[0] = '\0';                            /* "null-terminated string"  */
  981.       (void) strcpy (temp, net_info);                    /* take nodelist path         */
  982.       (void) strcat (temp, "NODELIST.IDX");             /* add in the file name      */
  983.       if ((stream = open(temp, O_RDONLY|O_BINARY)) == -1)
  984.          {
  985.          i = 0;                                  /* Need this later           */
  986.          if (have_boss_data != 2)
  987.             status_line (msgtxt[M_UNABLE_TO_OPEN], temp);
  988.          return (0);                             /* no file, no work to do      */
  989.          }
  990.       (void) fstat (stream, &f);                        /* get file statistics         */
  991.       i = (unsigned int) f.st_size;              /* size of index file,       */
  992.       idx_size = i / sizeof (struct _ndi);         /* number of index entries   */
  993.       node_index = get_size (i);
  994.       if (node_index == NULL)
  995.          {
  996.          status_line (msgtxt[M_NODELIST_MEM]);
  997.          (void) close (stream);
  998.          return (0);
  999.          }
  1000.       if (_dos_read (stream, node_index, i, &got) != 0)
  1001.          {
  1002.          status_line (msgtxt[M_NODELIST_READ_ERR]);
  1003.          (void) close (stream);
  1004.          return (0);
  1005.          }
  1006.       (void) close (stream);
  1007.       }
  1008.    nodeidx = (struct _ndi far *) node_index;
  1009.  
  1010.    if (TBBS_addr->Zone == (unsigned int) -1)
  1011.       {
  1012.       return (opus_next_zone ());
  1013.       }
  1014.  
  1015.    for (i = 1; i <= idx_size; nodeoff++, nodeidx++, i++)
  1016.       {
  1017.       if (nodeidx->node == -2)
  1018.      current_zone = nodeidx->net;
  1019.  
  1020.       if (TBBS_addr->Zone > 0 && current_zone != TBBS_addr->Zone)
  1021.             continue;
  1022.  
  1023.       if (nodeidx->net == TBBS_addr->Net)                /* if a match on net,         */
  1024.          {
  1025. /*         foundnet = 1;    */                         /* say we found the net      */
  1026.          if (((TBBS_addr->Node == 0) && (nodeidx->node <= 0))
  1027.              || (nodeidx->node == TBBS_addr->Node))     /* see if we found the node  */
  1028.             {
  1029.             found = 1;                             /* say we found it           */
  1030.             break;                                 /* get out                   */
  1031.             }
  1032.          }
  1033.  
  1034.       /*
  1035.        * This code is good, but many people complained about not being able
  1036.        * to add nodes to nets by adding them at the end of the nodelist.  So,
  1037.        * I commented this stuff out for now. - Bob
  1038.        */
  1039. /*        else*/
  1040.       /*      if (foundnet)*//* already past the net?      */
  1041.       /*         break;*//* Yes, we failed...          */
  1042.       }
  1043.  
  1044.    if (!found)
  1045.       return (0);
  1046.  
  1047.    found_zone = current_zone;                     /* Keep track of found zone */
  1048.    found_net  = nodeidx->net;                     /* Keep track of found net  */
  1049.  
  1050.    i = get_TBBS_info (nodeoff, TBBS_addr);
  1051.  
  1052.    return (i);
  1053. }
  1054.