home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / bts314b4 / misc.bak < prev    next >
Text File  |  1994-09-18  |  61KB  |  2,815 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. /*                     with code from several authors                       */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*                Miscellaneous routines used by BinkleyTerm                */
  18. /*                                                                          */
  19. /*                                                                          */
  20. /*    For complete  details  of the licensing restrictions, please refer    */
  21. /*    to the License  agreement,  which  is published in its entirety in    */
  22. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.240.    */
  23. /*                                                                          */
  24. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  25. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  26. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  27. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  28. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  29. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  30. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  31. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  32. /*                                                                          */
  33. /*                                                                          */
  34. /* You can contact Bit Bucket Software Co. at any one of the following      */
  35. /* addresses:                                                               */
  36. /*                                                                          */
  37. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:132/491, 1:141/491  */
  38. /* P.O. Box 460398                AlterNet 7:491/0                          */
  39. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  40. /*                                Internet f491.n132.z1.fidonet.org         */
  41. /*                                                                          */
  42. /* Please feel free to contact us at any time to share your comments about  */
  43. /* our software and/or licensing policies.                                  */
  44. /*                                                                          */
  45. /*--------------------------------------------------------------------------*/
  46.  
  47. /*
  48.  * Note that for the ATARIST most of the screen functions are simplified
  49.  * by using the ST's inbuilt VT52 escape codes, thereby eliminating
  50.  * the need for the OS/2 video fossil.
  51.  * - STeVeN
  52.  */
  53.  
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #include <time.h>
  57. #include <ctype.h>
  58. #include <stdarg.h>
  59. #include <string.h>
  60.  
  61. #ifdef __TOS__
  62. #pragma warn -sus
  63. #include <ext.h>
  64. #else
  65. #include <dos.h>
  66. #include <fcntl.h>
  67. #endif
  68. #ifdef __TOS__
  69. #include <conio.h>
  70. #endif
  71.  
  72. #ifdef LATTICE
  73. #include <errno.h>
  74. #include <osbind.h>
  75. #else
  76. #include <process.h>
  77. #include <io.h>
  78. #endif
  79.  
  80. #ifdef OS_2
  81. #define  INCL_DOSPROCESS
  82. #endif
  83.  
  84. #ifdef __TURBOC__
  85. #include "tc_utime.h"
  86. #ifndef __TOS__
  87. #include <mem.h>
  88. #endif
  89. #else
  90. #ifndef LATTICE
  91. #include <sys/utime.h>
  92. #include <memory.h>
  93. #endif
  94. #endif
  95.  
  96. #include "bink.h"
  97. #include "msgs.h"
  98. #include "com.h"
  99. #include "sbuf.h"
  100. #include "vfossil.h"
  101. #include "sched.h"
  102. #include "defines.h"
  103. #include "zmodem.h"
  104.  
  105. #ifdef OS_2
  106. #ifdef Snoop
  107. #include "snserver.h"
  108. static HSNOOP hsnoop=(HSNOOP)NULL;
  109. #endif /* Snoop */
  110. #endif /* OS_2  */
  111.  
  112.  
  113. static char newstring[200];
  114.  
  115. static int find_addr( char *s, ADDR *addr, char *d );
  116.  
  117.  
  118. int dexists( char *filename )
  119. {
  120.    struct FILEINFO dta;
  121.  
  122.    return (!dfind (&dta, filename, 0));
  123. }
  124.  
  125.  
  126. #ifdef LATTICE
  127. /* #include <dos.h> */
  128. #else
  129.  
  130. int dfind( struct FILEINFO *dta, char *name, int times )
  131. {
  132. #if !defined(OS_2) && !defined(__TOS__)
  133.    union REGS r;
  134.  
  135.    r.x.dx = (unsigned int) dta;
  136.    r.h.ah = 0x1a;
  137.    (void) intdos (&r, &r);
  138.    r.x.bx = 0;
  139.    r.x.cx = ~0x08;
  140.    r.x.dx = (unsigned int) name;
  141.    r.x.si = 0;
  142.    r.x.di = 0;
  143.    if (times == 0)
  144.       {
  145.       r.h.ah = 0x4e;
  146.       (void) intdos (&r, &r);
  147.       dta->nill = '\0';
  148.       if (r.x.cflag != 0)
  149.          {
  150.          dta->name[0] = '\0';
  151.          return (1);
  152.          }
  153.       return (0);
  154.       }
  155.    else
  156.       {
  157.       r.h.ah = 0x4f;
  158.       (void) intdos (&r, &r);
  159.       dta->nill = '\0';
  160.       if (r.x.cflag != 0)
  161.          {
  162.          dta->name[0] = '\0';
  163.          return (1);
  164.          }
  165.       return (0);
  166.       }
  167. #else
  168.    int retval;
  169.  
  170.    if (times == 0)
  171.    {
  172.       retval = dir_findfirst(name, 0x37, dta);
  173. /*    dta->nill = '\0'; */
  174.       if (retval)
  175.       {
  176. /*       dta->name[0] = '\0'; */
  177.          return (1);
  178.       }
  179.       else
  180.          return (0);
  181.    }
  182.    else
  183.    {
  184.       retval = dir_findnext(dta);
  185. /*    dta->nill = '\0'; */
  186.       if (retval)
  187.       {
  188. /*       dta->name[0] = '\0'; */
  189.          return (1);
  190.       }
  191.       else
  192.          return (0);
  193.    }
  194. #endif
  195. }
  196.  
  197. #endif /* ATARIST */
  198.  
  199. int set_baud( unsigned int baudrate, BOOLEAN log )
  200. {
  201.    register int i;
  202.  
  203.    if (baudrate > max_baud.rate_value)
  204.       baudrate = max_baud.rate_value;
  205.  
  206.    for (i = 0; btypes[i].rate_value; i++)
  207.    {
  208.       if (btypes[i].rate_value == baudrate)
  209.       {
  210.          if (baud != i)                          /* same as what we have?     */
  211.          {
  212.             if(!batch_mode)
  213.             {
  214.                 if (log && !un_attended)
  215.                    status_line (msgtxt[M_SETTING_BAUD], baudrate);
  216.                 baud = i;                            /* need this for ALT-B       */
  217.                 MDM_ENABLE (lock_baud && (btypes[baud].rate_value >= lock_baud) ? max_baud.rate_mask : btypes[baud].rate_mask);
  218.             }
  219.               cur_baud = baudrate;
  220.          }
  221.  
  222.  
  223.          if (un_attended && fullscreen)
  224.          {
  225.             sb_move (settingswin, SET_PORT_ROW, SET_COL);
  226.             sprintf (junk, "%-5u Com%d", baudrate, port_ptr + 1);
  227.             sb_puts (settingswin, (unsigned char *) junk);
  228.             sb_show ();
  229.          }
  230.          return (1);
  231.       }
  232.    }
  233.    return (0);
  234. }
  235.  
  236. /*--------------------------------------------------------------------------*/
  237. /* THROUGHPUT                                                               */
  238. /* Print throughput message at end of transfer                              */
  239. /*--------------------------------------------------------------------------*/
  240. void throughput( int opt, size_t bytes )
  241. {
  242.    static time_t started = 0L;
  243.    static time_t elapsed;
  244.    static long cps;
  245.  
  246. #ifdef ATARIST
  247.     if(ikbdclock)
  248.         update_time();
  249. #endif
  250.  
  251.    if (!opt)
  252.       started = time (NULL);
  253.    else if (started)
  254.       {
  255.       elapsed = time (NULL);
  256.       /* The next line tests for day wrap without the date rolling over */
  257.       if (elapsed < started)
  258.          elapsed += 86400L;        /* 24*60*60 = 1 day */
  259.       elapsed -= started;
  260.       if (elapsed == 0L)
  261.          elapsed = 1L;
  262.       cps = (long) bytes / (unsigned long) elapsed;
  263.       started = (cps * 1000L) / ((long) cur_baud);
  264.       status_line ((char *) msgtxt[M_CPS_MESSAGE], cps, bytes, started);
  265.       }
  266. }                                                /* throughput */
  267.  
  268. int got_error( char *string1, char *string2 )
  269. {
  270.  
  271. #ifdef __TURBOC__
  272. /*    Since TurboC doesn't handle errno correctly, zero it and ignore. */
  273.     errno = 0;
  274.    status_line ("%s, %s %s %s", msgtxt[M_ERROR], msgtxt[M_CANT], string1, string2);
  275. #else
  276.    if (errno == 0x18)
  277.       errno = 0;
  278.    if (errno != 0)
  279.       {
  280.       status_line ("%s %d, %s %s %s", msgtxt[M_ERROR], errno, msgtxt[M_CANT], string1, string2);
  281.       errno = 0;
  282.       return (1);
  283.       }
  284. #endif
  285.    return (0);
  286. }
  287.  
  288. void set_xy( char *string )
  289. {
  290.    WRITE_ANSI ('\r');
  291.    WRITE_ANSI ('\n');
  292.    scr_printf (string);
  293.    locate_x = wherex ();
  294.    locate_y = wherey ();
  295. }
  296.  
  297. void message( char *string )
  298. {
  299.    if (string != NULL)
  300.       {
  301.       status_line (" %s", string);
  302.       }
  303. }
  304.  
  305. void time_release(void)
  306. {
  307.     update_log();
  308.  
  309. #if defined(ATARIST)
  310.  
  311.     /* What shall we do? */
  312.  
  313. #elif defined(OS_2)
  314.  
  315.    DosSleep (1L);
  316.  
  317. #else
  318.  
  319.    dos_break_off ();                            /* Turn off ^C trapping */
  320.  
  321.    if (have_dv)
  322.       {
  323.       dv_pause ();
  324.       }
  325.     else if (have_mos)
  326.         {
  327.         mos_pause ();
  328.         }
  329.    else if (have_ddos)
  330.       {
  331.       ddos_pause ();
  332.       }
  333.    else if (have_tv)
  334.       {
  335.       tv_pause ();
  336.       }
  337.    else if (have_ml)
  338.       {
  339.       ml_pause ();
  340.       }
  341.     else
  342.         {
  343.         /* The idea for this code came from Holger Schurig */
  344.         msdos_pause ();
  345.         }
  346.  
  347. #endif /* OS_2 */
  348. }
  349.  
  350. char *strToAscii(char *s)
  351. {
  352.     if(s)
  353.         return s;
  354.     else
  355.         return "<NULL>";
  356. }
  357.  
  358. char *fancy_str( char *string )
  359. {
  360.    register int flag = 0;
  361.    char *s;
  362.  
  363.    s = string;
  364.  
  365.    while (*string)
  366.       {
  367.       if (isalpha (*string))                     /* If alphabetic,     */
  368.          {
  369.          if (flag)                               /* already saw one?   */
  370.             *string = tolower (*string);         /* Yes, lowercase it  */
  371.          else
  372.             {
  373.             flag = 1;                            /* first one, flag it */
  374.             *string = toupper (*string);         /* Uppercase it       */
  375.             }
  376.          }
  377.       else /* if not alphabetic  */ flag = 0;    /* reset alpha flag   */
  378.       string++;
  379.       }
  380.  
  381.    return (s);
  382. }
  383. void timer( int interval )
  384. {
  385.    long timeout;
  386.  
  387.    timeout = timerset ((long)interval * 10);
  388.    while (!timeup (timeout))
  389.       time_release ();
  390. }
  391.  
  392. void big_pause( int secs )
  393. {
  394.    long timeout;
  395.  
  396.    timeout = timerset ((long)secs * 100);
  397.    while (!timeup (timeout))
  398.       {
  399.       if (CHAR_AVAIL ())
  400.          break;
  401.       time_release ();
  402.       }
  403. }
  404.  
  405. int com_getc( int t )
  406. {
  407.    long t1;
  408.  
  409.    if (!CHAR_AVAIL ())
  410.       {
  411.       t1 = timerset ((long)t * 100);
  412.       while (!CHAR_AVAIL ())
  413.          {
  414.          if (timeup (t1))
  415.             {
  416.             return (EOF);
  417.             }
  418.  
  419.          /*
  420.           * This should work because we only do TIMED_READ when we have
  421.           * carrier
  422.           */
  423.          if (!CARRIER)
  424.             {
  425.             return (EOF);
  426.             }
  427.          time_release ();
  428.          }
  429.       }
  430.    return (int)(((unsigned int)MODEM_IN ()) & 0x00ff);
  431. }
  432.  
  433. /* Z F R E E -- Return total number of free bytes on drive specified */
  434. #if defined(OS_2)
  435. long zfree ( char *path )
  436. {
  437.    int drive;
  438.    FSALLOCATE dt;
  439.  
  440.    if (!path || !*path)
  441.       drive = 0;
  442.    else
  443.       drive = tolower (*path) - 'a' + 1;
  444.    DosQFSInfo (drive, 1, (char far *) &dt, sizeof (FSALLOCATE));
  445.    return ( dt.cSectorUnit * dt.cUnitAvail * dt.cbSector);
  446. }
  447.  
  448. #elif defined ( ATARIST ) && ( __TOS__ ) 
  449.  
  450. unsigned long zfree( char *path )
  451. {
  452.  
  453.     DISKINFO             *info;
  454.     unsigned long         free_bytes;
  455.     
  456.     int    drive;
  457.     
  458.     if (( info = ( DISKINFO *)calloc( 1, sizeof( DISKINFO ))) == NULL )
  459.         return 0; 
  460.  
  461.     if (( path[0] != '\0' ) && ( path[1] == ':' ))
  462.         drive = toupper( path[0] ) - 'A' + 1 ;
  463.     else
  464.         drive = 0;
  465.  
  466.     if ( Dfree( info, drive ) != 0 )
  467.     {
  468.         free( info );        
  469.         return 0;
  470.     }
  471.  
  472.     free_bytes = ( info-> b_free * info-> b_secsiz * info-> b_clsiz );
  473.     free( info );
  474.     return( free_bytes );
  475. }
  476.  
  477. #else
  478.  
  479. /* Default PC version */
  480.  
  481. long zfree (char *drive)
  482. {
  483.    union REGS r;
  484.  
  485.    unsigned char driveno;
  486.    long stat;
  487.  
  488.    if (drive[0] != '\0' && drive[1] == ':')
  489.       {
  490.       driveno = (unsigned char) (islower (*drive) ? toupper (*drive) : *drive);
  491.       driveno = (unsigned char) (driveno - 'A' + 1);
  492.       }
  493.    else driveno = 0;                             /* Default drive    */
  494.  
  495.    r.x.ax = 0x3600;                              /* get free space   */
  496.    r.h.dl = driveno;                             /* on this drive    */
  497.    (void) int86 (0x21, &r, &r);                         /* go do it      */
  498.  
  499.    if (r.x.ax == 0xffff)                         /* error return??   */
  500.       return (0);
  501.  
  502.    stat = (long) r.x.bx                          /* bx = clusters avail  */
  503.       * (long) r.x.ax                            /* ax = sectors/clust   */
  504.       * (long) r.x.cx;                           /* cx = bytes/sector    */
  505.  
  506.    return (stat);
  507.  
  508. }
  509.  
  510. #endif /* OS_2 */
  511.  
  512. void scr_printf (char *string)
  513. {
  514.  
  515.    if (string != NULL)
  516. #ifdef OS_2
  517.       VioWrtTTY (string, (USHORT) strlen (string), (HVIO) 0L);
  518. #else
  519.       while (*string != 0)
  520.          WRITE_ANSI (*string++);
  521. #endif
  522. }
  523.  
  524. void send_can( void )
  525. {
  526.    int i;
  527.  
  528.    CLEAR_OUTBOUND ();
  529.    CLEAR_INBOUND ();
  530.  
  531.    for (i = 0; i < 10; i++)
  532.       SENDBYTE (CAN);
  533.    for (i = 0; i < 10; i++)
  534.       SENDBYTE (BS);
  535. }
  536.  
  537. void invent_pkt_name( char *string )
  538. {
  539.    struct tm *tp;
  540.    time_t ltime;
  541.  
  542.    (void) time (<ime);
  543.    tp = localtime (<ime);
  544.    (void) sprintf (string, "%02i%02i%02i%02i.pkt",
  545.             tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec);
  546. }
  547.  
  548.  
  549.  
  550. int get_number( char *target )
  551. {
  552.    ADDR gaddr;
  553.    int k;
  554.  
  555.    (void) fgets (target, 100, stdin);
  556.    k = (int) strlen (target);
  557.    if (k == 1)
  558.       return (0);
  559.    target[--k] = '\0';                           /* no '\n' */
  560.    if (!isdigit(target[0]) && (target[0] != '\"') && (target[0] != '.'))
  561.       {
  562.       fidouser (target, &gaddr);
  563.       if ((gaddr.Net != -1U) && (gaddr.Node != -1U) && (gaddr.Zone != -1U))
  564.          {
  565.          sprintf (target, "%s", Pretty_Addr_Str (&gaddr));
  566.          }
  567.       else return (0);                           /* Gotta have addr */
  568.       }
  569.    return (1);
  570. }
  571.  
  572. void gong( void )
  573. {
  574.    long t;
  575.    int i;
  576.  
  577.    if (!gong_allowed)
  578.       return;
  579.  
  580.    for (i = 0; i < 15; i++)
  581.       {
  582.       WRITE_ANSI ('\07');                        /* Bell code       */
  583.       t = timerset (100);                        /* 1 second        */
  584.       while (!timeup (t))
  585.          {
  586.          if (KEYPRESS ())                        /* If key pressed, */
  587.             {
  588.             (void) READKB ();                           /* Throw it away   */
  589.             return;                              /* And get out     */
  590.             }
  591.          }
  592.       }
  593. }
  594.  
  595. char *skip_blanks( char *string )
  596. {
  597.    while (*string && isspace (*string))
  598.       ++string;
  599.    return (string);
  600. }
  601.  
  602. char *skip_to_blank( char *string )
  603. {
  604.    while (*string && (!isspace (*string)))
  605.       ++string;
  606.    return (string);
  607. }
  608.  
  609.  
  610. /*
  611.  * Compare 1st word of input with the parse_list list
  612.  * Returns:
  613.  *  -1 : Not found
  614.  *  +ve: list element number
  615.  *
  616.  * Updated 10th July 1992: SWG :
  617.  *    Distinguish between words beginning the same
  618.  *  e.g. "Hold" and "HoldOnUs".
  619.  *  The terminator is any character not in a..z,A..Z,0..9
  620.  *
  621.  */
  622.  
  623. int parse( char *input, struct parse_list list[] )
  624. {
  625.     int i;
  626.  
  627.     size_t wordlen;
  628.     char *s;
  629.  
  630.     /* Advance to White space */
  631.     
  632.     s = input;
  633.     wordlen = 0;
  634.     while(isalnum(*s) || (*s == '_'))
  635.     {
  636.         wordlen++;
  637.         s++;
  638.     }
  639.  
  640.     for(i = 0; list->p_length; i++, list++)
  641.     {
  642.         if( (list->p_length == wordlen) &&
  643.             (strnicmp(input, list->p_string, wordlen) == 0) )
  644.                 return i+1;
  645.     }
  646.  
  647.        return -1;
  648. }
  649.  
  650. void change_prompt( void )
  651. {
  652.    char *s;
  653.  
  654.    if (newstring[0])
  655.       {
  656.       (void) putenv (newstring);
  657.       return;
  658.       }
  659.  
  660.    (void) strcpy (newstring, "PROMPT=[");
  661.    (void) strcat (newstring, xfer_id);
  662. #ifdef OVERLAYS
  663.    (void) strcat (newstring, "-Overlay");
  664. #endif
  665.    (void) strcat (newstring, " Shell]$_");
  666.    s = getenv ("PROMPT");
  667.    if (s)
  668.       {
  669.       (void) strcat (newstring, s);
  670.       }
  671.    else
  672.       {
  673.       (void) strcat (newstring, "$P$G");
  674.       }
  675.  
  676.    (void) putenv (newstring);
  677. }
  678.  
  679. void update_files( int t )
  680. {
  681.    char s[10];
  682.  
  683.    if (un_attended && fullscreen)
  684.       {
  685.       if (t)
  686.          {
  687.          ++hist.files_out;
  688.          }
  689.       else
  690.          {
  691.          ++hist.files_in;
  692.          }
  693.  
  694.       sb_move (historywin, HIST_FILE_ROW, HIST_COL);
  695.       (void) sprintf (s, "%d/%d", hist.files_in, hist.files_out);
  696.       sb_puts (historywin, (unsigned char *) s);
  697.       sb_show ();
  698.       }
  699. }
  700.  
  701. static char *last_str[] = {
  702.                            "     None    ",
  703.                            "     WaZOO   ",
  704.                            "     FTS-0001",
  705.                            "     BBS     ",
  706.                            "     Ext Mail"
  707. };
  708.  
  709. void last_type( int n, ADDR *taddr )
  710. {
  711.     int i;
  712.        char *p;
  713.     char j[40];    /* Space for domain! "zzz:nnnnn/nnnnn.nnnnn @ dddddddd.ddd" */
  714.  
  715.        if (fullscreen)
  716.         sb_move (historywin, HIST_LAST_ROW, HIST_COL2);
  717.  
  718.        if ((n == 1) || (n == 2))
  719.     {
  720.           if ((taddr->Zone != -1000U) && (taddr->Net > 0))
  721.         {
  722.             (void) sprintf (j, "%s", Pretty_Addr_Str (taddr));
  723.             j[13] = 0;
  724.             if ((p = strchr (j, '@')) != NULL)
  725.                 *p = '\0';
  726.              for (i = (int) strlen (j); i < 13; i++)
  727.                 j[i] = ' ';
  728.              j[i] = '\0';
  729.              hist.last_zone = taddr->Zone;
  730.              hist.last_net = taddr->Net;
  731.              hist.last_node = taddr->Node;
  732.             hist.last_point = taddr->Point;
  733.             memset(hist.last_Domain, 0, sizeof(hist.last_Domain));
  734.             if(taddr->Domain)
  735.                 strcpy(hist.last_Domain, taddr->Domain);
  736.         }
  737.           else
  738.         {
  739.             (void) strcpy (j, "     FTS-0001");
  740.         }
  741.           if (fullscreen)
  742.           {
  743.             sb_puts (historywin, (unsigned char *) j);
  744.             last_assumed = assumed;
  745.             top_line();
  746.         }
  747.      }
  748.       else
  749.     {
  750.         if ((n < 0) || (n > 4))
  751.             n = 0;
  752.  
  753.           if (fullscreen)
  754.             sb_puts (historywin, (unsigned char *) last_str[n]);
  755.       }
  756.  
  757.        hist.last_caller = n;
  758. }
  759.  
  760.  
  761.  
  762. /*--------------------------------------------------------------------------*/
  763. /* UNIQUE_NAME                                                              */
  764. /* Increments the suffix of a filename as necessary to make the name unique */
  765. /*--------------------------------------------------------------------------*/
  766. void unique_name( char *fname )
  767. {
  768.    static char suffix[] = ".001";
  769.    register char *p;
  770.    register int n;
  771.  
  772.    if (dexists (fname))
  773.       {                                          /* If file already exists...      */
  774.       p = fname;
  775.       while (*p && *p != '.')
  776.          p++;                                    /* ...find the extension, if
  777.                                                   * any  */
  778.       for (n = 0; n < 4; n++)                    /* ...fill it out if
  779.                                                   * neccessary   */
  780.          if (!*p)
  781.             {
  782.             *p = suffix[n];
  783.             *(++p) = '\0';
  784.             }
  785.          else p++;
  786.  
  787.       while (dexists (fname))                    /* ...If 'file.ext' exists
  788.                                                   * suffix++ */
  789.          {
  790.          p = fname + strlen (fname) - 1;
  791.          for (n = 3; n--;)
  792.             {
  793.             if (!isdigit (*p))
  794.                *p = '0';
  795.             if (++(*p) <= '9')
  796.                break;
  797.             else *p-- = '0';
  798.             }                                    /* for */
  799.          }                                       /* while */
  800.       }                                          /* if exist */
  801. }                                                /* unique_name */
  802.  
  803. int got_ESC( void )
  804. {
  805.    while (KEYPRESS ())
  806.       {
  807.       screen_blank = 0;
  808.       if (fullscreen && un_attended)
  809.          sb_show ();
  810.       if (READKB () == 27)     /* ESC pressed?        */
  811.          {
  812.          while (KEYPRESS ())
  813.             (void) READKB ();
  814.          return (1);
  815.          }
  816.       }
  817.    return (0);
  818. }
  819.  
  820.  
  821. #if !defined(ATARIST)
  822. /* These are in stvfosil.c on Atari ST */
  823.  
  824. void screen_clear ()
  825. {
  826.  
  827.    register int r;
  828.    unsigned int far *q;
  829.  
  830.    if (!vfossil_installed)
  831.       scr_printf ("\033[H\033[2J");
  832.    else
  833.       {
  834.       for (r = 0; r <= SB_ROWS; r++)
  835.          {
  836.          q = (unsigned int far *) blanks;
  837. #if !defined(OS_2)
  838.          (void) VioWrtCellStr (q, SB_COLS * 2, r, 0, 0);
  839. #else
  840.          (void) VioWrtCellStr ((PCH) q, (USHORT) (SB_COLS * 2), (USHORT) r, (USHORT) 0, (HVIO) 0L);
  841. #endif
  842.          }
  843.  
  844.       gotoxy (0, 0);
  845.       }
  846. }
  847.  
  848. void clear_eol( void )
  849. {
  850.    int x, y;
  851.    unsigned int far *q;
  852.    if (!vfossil_installed)
  853.       (void) printf ("\033[K");
  854.    else
  855.       {
  856.       x = wherex();
  857.       y = wherey();
  858.  
  859.       q = (unsigned int far *) blanks;
  860. #ifndef OS_2
  861.       (void) VioWrtCellStr (q, (SB_COLS - (unsigned) x) * 2, y, x, 0);
  862. #else
  863.       (void) VioWrtCellStr ((PCH) q, (USHORT) ((SB_COLS - x) * 2), (USHORT) y, (USHORT) x, (HVIO) 0L);
  864. #endif
  865.       }
  866. }
  867.  
  868. #endif /* ATARIST */
  869.  
  870.  
  871. void log_product( int product, int version, int subversion )
  872. {
  873.    switch (product)
  874.       {
  875.       case isBITBRAIN :
  876.       case isFIDO     :
  877.       case isSPARK    :
  878.       case isSEA      :
  879.       case isSlick    :
  880.       case isHENK     :
  881.       case isTABBIE   :
  882.       case isWOLF     :
  883.       case isQMM      :
  884.       case isFD       :
  885.       case isGSPOINT  :
  886.       case isBGMAIL   :
  887.       case isCROSSBOW :
  888.       case isDBRIDGE  :
  889.       case isDAISY    :
  890.       case isPOLAR    :
  891.       case isTHEBOX   :
  892.       case isWARLOCK  :
  893.       case isTCOMM    :
  894.       case isBANANNA  :
  895.       case isAPPLE    :
  896.       case isCHAMELEON:
  897.       case isMAJIK    :
  898.       case isDOMAIN   :
  899.       case isLESROBOT :
  900.       case isROSE     :
  901.       case isPARAGON  :
  902.       case isBINKST   :
  903.       case isSTARNET  :
  904.       case isQUICKBBS :
  905.       case isPBBS     :
  906.       case isTRAPDOOR :
  907.       case isWELMAT   :
  908.       case isTIMS     :
  909.       case isISIS     :
  910.          status_line ("%s %s %s %d.%02d", msgtxt[M_REMOTE_USES],
  911.              prodcode[product], msgtxt[M_VERSION], version, subversion);
  912.          break;
  913.  
  914.       case isOPUS:
  915.          status_line ("%s Opus %s %d.%02d", msgtxt[M_REMOTE_USES],
  916.                       msgtxt[M_VERSION], version,
  917.                       (subversion == 48) ? 0 : subversion);
  918.          break;
  919.  
  920.       default:
  921.          status_line ("%s %s '%02x' %s %d.%02d", msgtxt[M_REMOTE_USES],
  922.                       msgtxt[M_PROGRAM], product,
  923.                       msgtxt[M_VERSION], version, subversion);
  924.          break;
  925.       }
  926. return;
  927. }
  928.  
  929. int next_minute( void )
  930. {
  931.    int hours, mins, secs, ths;
  932.  
  933.    /* Get the DOS time */
  934.    dostime (&hours, &mins, &secs, &ths);
  935.  
  936.    return ((60 - (secs % 60)) * 100 + 1);
  937. }
  938.  
  939. void can_Janus( char *p )
  940. {
  941.    J_TYPESP j;
  942.  
  943.    janus_OK = 0;
  944.    for (j = j_top; j != NULL; j = j->next)
  945.       {
  946.       if (strnicmp (p, j->j_match, strlen (j->j_match)) == 0)
  947.          {
  948.          janus_OK = 1;
  949.          break;
  950.          }
  951.       }
  952.    janus_OK = janus_OK && !no_Janus_Session;
  953. }
  954.  
  955. int check_failed( char *fname, char *theirname, char *info, char *ourname )
  956. {
  957.    FILE *abortlog;
  958.    char linebuf[64];
  959.     char *p, *badname;
  960.     int ret;
  961.  
  962.     ret = 0;
  963.    if ((abortlog = fopen (fname, read_ascii)) == NULL)
  964.       {
  965.       (void) got_error (msgtxt[M_OPEN_MSG], fname);
  966.       }
  967.    else
  968.       {
  969.       while (!feof (abortlog))
  970.          {
  971.          linebuf[0] = '\0';
  972.          if (!fgets ((p = linebuf), 64, abortlog))
  973.             break;
  974.          while (*p >= ' ')
  975.             ++p;
  976.          *p = '\0';
  977.          p = strchr (linebuf, ' ');
  978.          *p = '\0';
  979.          if (!stricmp (linebuf, theirname))
  980.             {
  981.             p = strchr ((badname = ++p), ' ');
  982.             *p = '\0';
  983.             if (!stricmp (++p, info))
  984.                {
  985.                strcpy (ourname, badname);
  986.                     ret = 1;
  987.                break;
  988.                }
  989.             }
  990.          }
  991.       fclose (abortlog);
  992.       }
  993.  
  994.     return (ret);
  995. }
  996.  
  997. void add_abort( char *fname, char *rname, char *cname, char *cpath, char *info )
  998. {
  999.     FILE *abortlog;
  1000.     char namebuf[100];
  1001.  
  1002.    strcpy (namebuf, cpath);
  1003.    strcat (namebuf, "BadWaZOO.001");
  1004.    unique_name (namebuf);
  1005.    rename (cname, namebuf);
  1006.    if ((abortlog = fopen (fname, append_ascii)) == NULL)
  1007.       {
  1008.       (void) got_error (msgtxt[M_OPEN_MSG], fname);
  1009.       unlink (namebuf);
  1010.       }
  1011.    else
  1012.       {
  1013.       fprintf (abortlog, "%s %s %s\n", rname, namebuf + strlen (cpath), info);
  1014.       fclose (abortlog);
  1015.       }
  1016. }
  1017.  
  1018. void remove_abort( char *fname, char *rname )
  1019. {
  1020.     FILE *abortlog, *newlog;
  1021.     char namebuf[100];
  1022.     char linebuf[100];
  1023.     char *p;
  1024.     int c;
  1025.  
  1026.     if (!dexists (fname))
  1027.         return;
  1028.  
  1029.    if ((abortlog = fopen (fname, read_ascii)) == NULL)
  1030.       {
  1031.       (void) got_error (msgtxt[M_OPEN_MSG], fname);
  1032.       }
  1033.    else
  1034.       {
  1035.       strcpy (namebuf, fname);
  1036.       strcpy (namebuf + strlen (namebuf) - 1, "TMP");
  1037.       c = 0;
  1038.       if ((newlog = fopen (namebuf, write_ascii)) == NULL)
  1039.          {
  1040.          (void) got_error (msgtxt[M_OPEN_MSG], namebuf);
  1041.          fclose (abortlog);
  1042.          }
  1043.       else
  1044.          {
  1045.          while (!feof (abortlog))
  1046.             {
  1047.             linebuf[0] = '\0';
  1048.             if (!fgets (linebuf, 64, abortlog))
  1049.                break;
  1050.             p = linebuf;
  1051.             while (*p > ' ')
  1052.                ++p;
  1053.             *p = '\0';
  1054.             if (stricmp (linebuf, rname))
  1055.                {
  1056.                *p = ' ';
  1057.                fputs (linebuf, newlog);
  1058.                ++c;
  1059.                }
  1060.             }
  1061.          fclose (abortlog);
  1062.          fclose (newlog);
  1063.          unlink (fname);
  1064.          if (c)
  1065.             rename (namebuf, fname);
  1066.          else unlink (namebuf);
  1067.          }
  1068.       }
  1069. }
  1070.  
  1071. /*
  1072.  * The next routine is used in the count down timer during file
  1073.  * transfers, and were provided by Jon Sabol, along with the other code that
  1074.  * calls these routines.
  1075.  */
  1076.  
  1077. void elapse_time( void )
  1078. {
  1079.    time_t ltime;
  1080.    long eh;
  1081.    long em;
  1082.    long es;
  1083.  
  1084.  
  1085. #ifdef ATARIST
  1086.     if(ikbdclock)
  1087.         update_time();
  1088. #endif
  1089.  
  1090.    if (fullscreen && (un_attended || doing_poll))
  1091.       {
  1092.       time (<ime);
  1093.  
  1094.       if (ltime < etm)
  1095.          ltime += 86400L;
  1096.  
  1097.       eh = (ltime - etm) / 3600L;
  1098.       em = ((ltime - etm) / 60L) - (eh * 60L);
  1099.       es = (ltime - etm) - (eh * 3600L) - (em * 60L);
  1100.  
  1101.       sb_move (settingswin, SET_TASK_ROW, SET_TIME_COL);
  1102.       sprintf (junk, "%s:  %02ld:%02ld:%02ld", msgtxt[M_ELAPSED], eh, em, es);
  1103.       sb_puts (settingswin, junk);
  1104.       sb_show ();
  1105.       }
  1106. }
  1107.  
  1108. /*
  1109.  * Parse a string for a fidonet address
  1110.  * d is space for a domain string.
  1111.  *
  1112.  * (A better method)
  1113.  */
  1114.  
  1115. static int find_addr( char *s, ADDR *addr, char *d )
  1116. {
  1117.     int ret = 0;
  1118.     register char *s1, *s2;
  1119.  
  1120.     d[0] = 0;               /* Null the domain */
  1121.     addr->Domain = NULL;
  1122.  
  1123.     /* Find Zone */
  1124.  
  1125.     s1 = strchr(s, ':');
  1126.     if(s1)
  1127.     {
  1128.         addr->Zone = atoi(s);
  1129.         s = s1+1;
  1130.         ret++;
  1131.     }
  1132.     else
  1133.         addr->Zone = 0;
  1134.  
  1135.     /* Find Net */
  1136.  
  1137.     s1 = strchr(s, '/');
  1138.     if(s1)
  1139.     {
  1140.         addr->Net = atoi(s);
  1141.         s = s1+1;
  1142.         ret++;
  1143.     }
  1144.     else
  1145.         addr->Net = 0;
  1146.  
  1147.     /* Find Node */
  1148.  
  1149.     if(isdigit(*s))
  1150.     {
  1151.         addr->Node = atoi(s);
  1152.         ret++;
  1153.     }
  1154.     else
  1155.         addr->Node = alias[0].ad.Node;
  1156.  
  1157.     /* Find point & domain */
  1158.  
  1159.     s1 = strchr(s, '.');   
  1160.     s2 = strchr(s, '@');
  1161.     if(s1 && !(s2 && (s1 > s2)))        /* check if it's a real point*/
  1162.     {
  1163.         s = s1+1;
  1164.         addr->Point = atoi(s);
  1165.         ret++;
  1166.     }
  1167.     else
  1168.         addr->Point = 0;
  1169.    
  1170.     if(s2)
  1171.     {
  1172.         s = skip_blanks(s2+1);        /* Polling causes "address @ domain" to be parsed! */
  1173.         while(*s && !isspace(*s))
  1174.             *d++ = *s++;
  1175.         *d = 0;
  1176.         ret++;
  1177.     }
  1178.  
  1179.     return ret;
  1180. }
  1181.  
  1182. /*
  1183.  * Read in an address with wildcards
  1184.  *
  1185.  * Similar to find_addr but accepts ALL as a field
  1186.  * returns number of fields (0=none)
  1187.  *
  1188.  * There must be a neater way to do this!
  1189.  *
  1190.  * Format is:
  1191.  *
  1192.  *  [[[z:]net/]node][.point][@domain[.ext]]
  1193.  *  ALL
  1194.  *  z:ALL
  1195.  *  z:net/ALL
  1196.  *  z:net/node.ALL 
  1197.  *
  1198.  * Any field may be ALL or if ALL is the end of the address all other fields
  1199.  * default to ALL.
  1200.  */
  1201.  
  1202. int read_wild_ad( char *node, ADKEY *dest )
  1203. {
  1204.     int ret = 0;
  1205.     register char *s1, *s2, *s;
  1206.     s = node;
  1207.  
  1208.     /* Check for ALL */
  1209.     
  1210.     if( (strcmp(s, "ALL") == 0) || (strcmp(s, "*") == 0))
  1211.     {
  1212.         dest->wild.zone = TRUE;        
  1213.         dest->wild.net = TRUE;        
  1214.         dest->wild.node = TRUE;        
  1215.         dest->wild.point = TRUE;        
  1216.         dest->wild.domain = TRUE;        
  1217.         return 1;
  1218.     }
  1219.  
  1220.  
  1221.     /* Find Zone */
  1222.  
  1223.     s1 = strchr(s, ':');
  1224.     if(s1)
  1225.     {
  1226.         *s1 = 0;
  1227.         if(strcmp(s, "ALL") && (*s != '*'))
  1228.             dest->ad.Zone = atoi(s);
  1229.         else
  1230.             dest->wild.zone = TRUE;
  1231.         s = s1+1;
  1232.         ret++;
  1233.     }
  1234.     else
  1235.         dest->ad.Zone = 0;
  1236.     
  1237.  
  1238.     if( (strcmp(s, "ALL") == 0) || (*s == '*'))
  1239.     {
  1240.         dest->wild.net = TRUE;        
  1241.         dest->wild.node = TRUE;        
  1242.         dest->wild.point = TRUE;        
  1243.         dest->wild.domain = TRUE;        
  1244.         return 1;
  1245.     }
  1246.  
  1247.     /* Find Net */
  1248.  
  1249.     s1 = strchr(s, '/');
  1250.     if(s1)
  1251.     {
  1252.         *s1 = 0;
  1253.         if(strcmp(s, "ALL") && (*s != '*'))
  1254.             dest->ad.Net = atoi(s);
  1255.         else
  1256.             dest->wild.net = TRUE;
  1257.         s = s1+1;
  1258.         ret++;
  1259.     }
  1260.     else
  1261.         dest->ad.Net = 0;
  1262.  
  1263.     if( (strcmp(s, "ALL") == 0) || (*s == '*'))
  1264.     {
  1265.         dest->wild.node = TRUE;        
  1266.         dest->wild.point = TRUE;        
  1267.         dest->wild.domain = TRUE;        
  1268.         return 1;
  1269.     }
  1270.  
  1271.     /* Find Node */
  1272.  
  1273.     if(strncmp(s, "ALL", 3) && (*s != '*'))
  1274.     {
  1275.         if(isdigit(*s))
  1276.         {
  1277.             dest->ad.Node = atoi(s);
  1278.             ret++;
  1279.         }
  1280.         else
  1281.             dest->ad.Node = alias[0].ad.Node;
  1282.     }
  1283.     else
  1284.     {
  1285.         dest->wild.node = TRUE;
  1286.         ret++;
  1287.     }
  1288.  
  1289.     if( (strcmp(s, "ALL") == 0) || (*s == '*'))
  1290.     {
  1291.         dest->wild.point = TRUE;        
  1292.         dest->wild.domain = TRUE;        
  1293.         return 1;
  1294.     }
  1295.  
  1296.     /* Find point & domain */
  1297.  
  1298.     s1 = strchr(s, '.');   
  1299.     s2 = strchr(s, '@');
  1300.     if(s1 && !(s2 && (s1 > s2)))        /* check if it's a real point*/
  1301.     {
  1302.         s = s1+1;
  1303.         if(strncmp(s, "ALL", 3) && (*s != '*'))
  1304.             dest->ad.Point = atoi(s);
  1305.         else
  1306.         {
  1307.             dest->wild.point = TRUE;
  1308.             if(!s2)
  1309.                 dest->wild.domain = TRUE;
  1310.         }
  1311.         ret++;
  1312.     }
  1313.     else
  1314.         dest->ad.Point = 0;
  1315.    
  1316.     if(s2)
  1317.     {
  1318.         s = s2+1;
  1319.  
  1320.         if(strncmp(s, "ALL", 3) && (*s != '*'))
  1321.         {
  1322.             while(*s2 && !isspace(*s2))
  1323.                 s2++;
  1324.             *s2 = 0;
  1325.             
  1326.             dest->ad.Domain = find_domain(s);
  1327.         }
  1328.         else
  1329.             dest->wild.domain = TRUE;
  1330.         ret++;
  1331.     }
  1332.     else
  1333.         dest->ad.Domain = NULL;
  1334.  
  1335.     /*
  1336.      * Make intelligent guess at address zone and domain if missing
  1337.      *
  1338.      * e.g. 1004/0 should expand to 90:1004/0@nest
  1339.      *       25@n ==> 90:1004/25@nest
  1340.      *       25   ==>  2:25/25@fidonet
  1341.      */
  1342.     
  1343.     if(!(dest->ad.Domain || dest->wild.domain) ||
  1344.        !(dest->ad.Zone || dest->wild.zone) ||
  1345.        !(dest->ad.Net || dest->wild.net) )
  1346.     {
  1347.         int count = num_addrs;
  1348.         ADDRESS *ad = alias;
  1349.  
  1350.         
  1351.         while(count--)
  1352.         {
  1353.             if( (!dest->ad.Zone || dest->wild.zone || (ad->ad.Zone == dest->ad.Zone)) &&
  1354.                 (!dest->ad.Domain || dest->wild.domain || (ad->ad.Domain == dest->ad.Domain)) &&
  1355.                 (dest->wild.domain ||dest->ad.Domain ||
  1356.                  dest->wild.zone || dest->ad.Zone ||
  1357.                  dest->wild.net || !dest->ad.Net || (ad->ad.Net == dest->ad.Net)) )
  1358.             {
  1359.                 dest->ad.Zone = ad->ad.Zone;
  1360.                 dest->ad.Domain = ad->ad.Domain;
  1361.                 if(!dest->ad.Net)
  1362.                     dest->ad.Net = ad->ad.Net;
  1363.                 break;
  1364.             }
  1365.             ad++;
  1366.         }
  1367.         if(!dest->ad.Domain)
  1368.             dest->ad.Domain = alias[0].ad.Domain;
  1369.         if(!dest->ad.Zone)
  1370.             dest->ad.Zone = alias[0].ad.Zone;
  1371.         if(!dest->ad.Net)
  1372.             dest->ad.Net = alias[0].ad.Net;
  1373. #ifdef DEBUG
  1374.         status_line("#expanded %s to %s", node, Pretty_Addr_Str(&dest->ad));
  1375. #endif
  1376.     }
  1377.  
  1378.     return ret;
  1379. }
  1380.  
  1381. /*
  1382.  * Parse an address in text form and put it into the address structure
  1383.  */
  1384.  
  1385. int parse_address( char *node, ADDR *addr )
  1386. {
  1387.     int ret;
  1388.        char d[100];
  1389.  
  1390.        ret = find_addr (node, addr, d);
  1391.  
  1392.        if (d[0] != '\0')
  1393.        {
  1394.           addr->Domain = add_domain (d);
  1395.        }
  1396.     return (ret);
  1397. }
  1398.  
  1399.  
  1400. int find_address( char *node, ADDR *addr )
  1401. {
  1402.        int ret;
  1403.        char d[100];
  1404.        char *p;
  1405.  
  1406.        d[0] = '\0';
  1407.        p = skip_blanks (node);
  1408.        if (!isdigit (*p) && (*p != '.'))
  1409.     {
  1410.         fidouser (p, addr);
  1411.           if ((addr->Net == -1U) || (addr->Node == -1U) || (addr->Zone == -1U))
  1412.         {
  1413.             ret = 0;
  1414.         }
  1415.           else
  1416.         {
  1417.             ret = 1;
  1418.         }
  1419.       }
  1420.        else
  1421.     {
  1422.         ret = find_addr (p, addr, d);
  1423.     }
  1424.  
  1425. /*       if (d[0] != '\0')
  1426.     { */
  1427. #ifdef DEBUG
  1428.         status_line("# b4 find domain %s", Pretty_Addr_Str(addr));
  1429. #endif
  1430.         addr->Domain = find_domain (d);
  1431.         if (!addr->Domain)
  1432.             addr->Domain = "unknown.ftn";
  1433. #ifdef DEBUG
  1434.         status_line("#after find domain %s", Pretty_Addr_Str(addr));
  1435. #endif
  1436. /*    } */
  1437.  
  1438.     /*
  1439.      * Make intelligent guess at address zone and domain if missing
  1440.      *
  1441.      * e.g. 1004/0 should expand to 90:1004/0@nest
  1442.      *       25@n ==> 90:1004/25@nest
  1443.      *       25   ==>  2:25/25@fidonet
  1444.      */
  1445.     
  1446.     if(!addr->Domain || !addr->Zone || !addr->Net)
  1447.     {
  1448.         int count = num_addrs;
  1449.         ADDRESS *ad = alias;
  1450.  
  1451.         status_line("#addr is %s", Pretty_Addr_Str(addr));
  1452.                 
  1453.         while(count--)
  1454.         {
  1455.             if( (!addr->Zone || (ad->ad.Zone == addr->Zone)) &&
  1456.                 (!addr->Domain || (ad->ad.Domain == addr->Domain)) &&
  1457.                 (addr->Domain || addr->Zone || !addr->Net || (ad->ad.Net == addr->Net)) )
  1458.             {
  1459.                 addr->Zone = ad->ad.Zone;
  1460.                 addr->Domain = ad->ad.Domain;
  1461. #ifdef DEBUG
  1462.                 status_line("#address now is %s", Pretty_Addr_Str(addr));
  1463. #endif
  1464.                 if(!addr->Net)
  1465.                     addr->Net = ad->ad.Net;
  1466.                 break;
  1467.             }
  1468.             ad++;
  1469.         }
  1470.         if(!addr->Domain)
  1471.             addr->Domain = alias[0].ad.Domain;
  1472.         if(!addr->Zone)
  1473.             addr->Zone = alias[0].ad.Zone;
  1474.         if(!addr->Net)
  1475.             addr->Net = alias[0].ad.Net;
  1476. /* #ifdef DEBUG BS */
  1477.         status_line("#expanded1 %s to %s", node, Pretty_Addr_Str(addr));
  1478. /* #endif */
  1479.     }
  1480.  
  1481.        return (ret);
  1482. }
  1483.  
  1484. /*
  1485.  * Add to the domain list
  1486.  */
  1487.  
  1488. char *add_domain( char *d )
  1489. {
  1490.    char *p;
  1491.    int i;
  1492.  
  1493.     /* SWG: 10th July 1991 : Domains case insensitive and pretty */
  1494.     strlwr(d);
  1495.  
  1496.     p = find_domain(d);        /* If we already have this domain */
  1497.     if(p)
  1498.         return p;
  1499.     
  1500.     /* Otherwise make a new entry */
  1501.  
  1502.     for(i = 0; domain_name[i]; i++)
  1503.         ;
  1504.  
  1505.     if(i >= (MAXDOMAIN-1))
  1506.         return NULL;
  1507.     
  1508.    domain_name[i] = strdup (d);
  1509.    return (domain_name[i]);
  1510. }
  1511.  
  1512. /*
  1513.  * Find domain in domain list
  1514.  */
  1515.  
  1516. char *find_domain( char *d )
  1517. {
  1518.    char *p, *q, *s;
  1519.    char c;
  1520.    int i;
  1521.    size_t j,k;    
  1522.  
  1523.     /* SWG: 10th July 1991 : Domains case insensitive */
  1524.     strlwr(d);
  1525.    j = strlen (d);
  1526.    /* First see if we can find the whole domain name at the right */
  1527.    for (i = 0; (p = domain_name[i]) != NULL; i++)
  1528.       {
  1529.       k = strlen (p);
  1530.       if (k > j)
  1531.          continue;
  1532.  
  1533.       q = &(d[j - k]);
  1534.       if (strnicmp (q, p, k) == 0)
  1535.          {
  1536.          return (p);
  1537.          }
  1538.       }
  1539.  
  1540.    /* Ok, now see if we can find the abbreviated name at the right */
  1541.    for (i = 0; (p = domain_abbrev[i]) != NULL; i++)
  1542.       {
  1543.       k = strlen (p);
  1544.       if (k > j)
  1545.          continue;
  1546.  
  1547.       q = &(d[j - k]);
  1548.       if (strnicmp (q, p, k) == 0)
  1549.          {
  1550.          return (domain_name[i]);
  1551.          }
  1552.       }
  1553.  
  1554.    /* If there is a period in it, see if we can match the abbreviated name
  1555.       just before the period */
  1556.    if ((s = strrchr (d, '.')) != NULL)
  1557.       {
  1558.       c = *s;
  1559.       *s = '\0';
  1560.       j = strlen (d);
  1561.       for (i = 0; (p = domain_abbrev[i]) != NULL; i++)
  1562.          {
  1563.          k = strlen (p);
  1564.          if (k > j)
  1565.             continue;
  1566.  
  1567.          q = &(d[j - k]);
  1568.          if (strnicmp (q, p, k) == 0)
  1569.             {
  1570.             *s = c;
  1571.             return (domain_name[i]);
  1572.             }
  1573.          }
  1574.       *s = c;
  1575.       }
  1576.  
  1577.     /* Pick first domain that matches from left, e.g. @l make pick @lifenet */
  1578.        for (i = 0; (p = domain_abbrev[i]) != NULL; i++)
  1579.     {
  1580.         s = d;
  1581.         q = p;
  1582.         
  1583.         do
  1584.             if(!*s)
  1585.                 return domain_name[i];
  1586.         while(*s++ == *q++);
  1587.     }
  1588.  
  1589.    return (NULL);
  1590. }
  1591.  
  1592. /*
  1593.  * Find out if we should ignore this address or not as it belongs to an
  1594.  * unknown domain
  1595.  *
  1596.  * Returns:
  1597.  *   TRUE: Known
  1598.  *  FALSE: Unknown
  1599.  *
  1600.  * Ignore address if it belongs to a domain that we have never heard of
  1601.  * If we only have one domain set up then assume we are one of those
  1602.  * people who set up as ...@fidonet.org even for their aka's.
  1603.  */
  1604.  
  1605. BOOLEAN isKnownDomain(ADDR *ad)
  1606. {
  1607.  
  1608.     /* If we are both using Domains */
  1609.     
  1610.     if(ad->Domain && domain_name[0] && domain_name[1])
  1611.     {
  1612.         char **domain = domain_name;
  1613.  
  1614.         while(*domain)
  1615.         {
  1616.             if(*domain == ad->Domain)
  1617.                 return TRUE;
  1618.             domain++;
  1619.         }
  1620. #ifdef DEBUG
  1621.         status_line("#Ignoring unknown Domain %s", ad->Domain);
  1622. #endif
  1623.         return FALSE;
  1624.     }
  1625.     else
  1626.         return TRUE;
  1627. }
  1628.  
  1629. /*
  1630.  * Find the assumed address for a given address
  1631.  */
  1632.  
  1633. static ADDRESS *get_assumed(ADDR *ad)
  1634. {
  1635.     int i;                /* Alias counter */
  1636.     int k;                /* How many fields have been matched */
  1637.     ADDRESS *a;            /* Current alias */
  1638.     ADDRESS *best;        /* Best alias */
  1639.     ADKEY *key;
  1640.     
  1641.     a = best = alias;
  1642.     i = k = 0;
  1643.     while(i < num_addrs)
  1644.     {
  1645.         if( (a->ad.Domain == ad->Domain) ||
  1646.             (!ad->Domain && (a->ad.Domain == alias[0].ad.Domain)) )
  1647.         {
  1648.             if(k == 0)
  1649.             {
  1650.                 k++;
  1651.                 best = a;
  1652.             }
  1653.             if(a->ad.Zone == ad->Zone)
  1654.             {
  1655.                 if(k == 1)
  1656.                 {
  1657.                     k++;
  1658.                     best = a;
  1659.                 }
  1660.                 if(a->ad.Net == ad->Net)
  1661.                 {
  1662.                     if(k == 2)
  1663.                     {
  1664.                         k++;
  1665.                         best = a;
  1666.                     }
  1667.                     if(a->ad.Node == ad->Node)
  1668.                     {
  1669.                         best = a;
  1670.                         break;
  1671.                     }
  1672.                 }
  1673.             }
  1674.         }
  1675.         a++;
  1676.         i++;
  1677.     }
  1678.  
  1679.     /* Now go through the KEYs in case one overides it */
  1680.     
  1681.     key = adkeys;
  1682.     while(key)
  1683.     {
  1684.         if( (key->wild.net || (key->ad.Net == ad->Net)) &&
  1685.             (key->wild.node || (key->ad.Node == ad->Node)) &&
  1686.             (key->wild.zone || (key->ad.Zone == ad->Zone)) &&
  1687.             (key->wild.domain || (key->ad.Domain == ad->Domain)) &&
  1688.             (key->wild.point || (key->ad.Point == ad->Point)) )
  1689.         {
  1690.             /* We have a match */
  1691.             
  1692.             if(key->alias)
  1693.             {
  1694.                 best = key->alias;
  1695.                 break;
  1696.             }
  1697.         }
  1698.  
  1699.         key = key->next;
  1700.     }
  1701.     return best;
  1702. }
  1703.  
  1704. /*
  1705.  * Set the current assumed variable to match a given address
  1706.  */
  1707.  
  1708. int make_assumed(ADDR *ad)
  1709. {
  1710.     ADDRESS *bestAlias = get_assumed(ad);
  1711.     ADDRESS *tmp;
  1712.         
  1713.     /* Convert alias to assumed */
  1714.  
  1715.     assumed = 0;
  1716.     if(bestAlias != NULL)
  1717.     {
  1718.         int j = 0;
  1719.         tmp = alias;
  1720.         while(j < num_addrs)
  1721.         {
  1722.             if(bestAlias == tmp)
  1723.             {
  1724.                 assumed = j;
  1725.                 break;
  1726.             }
  1727.             j++;
  1728.             tmp++;
  1729.         }
  1730.     }
  1731.     return assumed;
  1732. }
  1733.  
  1734. /*
  1735.  * Convert a 3D address into a real 4D address
  1736.  *
  1737.  * e.g. 2:fakenet/7 ===> 2:ourad/ournode.7
  1738.  */
  1739.  
  1740. void make4d( ADDR *destad )
  1741. {
  1742.     /* Convert 2D to 4D if in one of our fakenets */
  1743.             
  1744.  
  1745.     if(destad->Point == 0)
  1746.     {
  1747.         ADDRESS *ad = alias;
  1748.         int i = 0;
  1749.     
  1750.         while(i < num_addrs)
  1751.         {
  1752.             if( (destad->Zone == ad->ad.Zone) &&
  1753.                 (destad->Domain == ad->ad.Domain) &&
  1754.                 (destad->Net == ad->fakenet) )
  1755.             {
  1756.                 destad->Point = destad->Node;
  1757.                 destad->Node = ad->ad.Node;
  1758.                 destad->Net = ad->ad.Net;
  1759.                 return;
  1760.             }
  1761.             ad++;
  1762.             i++;
  1763.         }
  1764.     }
  1765. }
  1766.  
  1767.  
  1768. /*
  1769.  * Make up the 8 digit packet name for an address
  1770.  *
  1771.  * Updated 7th July 1991 SWG to use 4D addresses
  1772.  * Updated 23rd July 1991 SWG to stop it sending mail for our points
  1773.  *   to points from other networks!!!
  1774.  * Updated 28th Sept 1991 SWG: Use -1/point if its a point that isnt yours!
  1775.  *
  1776.  */
  1777.  
  1778. char addr_str[100];
  1779.  
  1780. char *Hex_Addr_Str( ADDR *a )
  1781. {
  1782.     if(a->Point)
  1783.     {
  1784.         ADDRESS *assume = get_assumed(a);
  1785.         if( (assume->ad.Zone   == a->Zone  )
  1786.           &&(assume->ad.Net    == a->Net   )
  1787.           &&(assume->ad.Node   == a->Node  )
  1788.           &&(!assume->ad.Domain || !a->Domain || (assume->ad.Domain == a->Domain)) )
  1789.         {
  1790.             sprintf(addr_str, "%04x%04x", assume->fakenet, a->Point);
  1791.             return addr_str;
  1792.         }
  1793.         else
  1794.         {
  1795.             sprintf(addr_str, "%04x%04x", -1, a->Point);
  1796.             return addr_str;
  1797.         }
  1798.     }
  1799.    sprintf (addr_str, "%04x%04x", a->Net, a->Node);
  1800.    return (addr_str);
  1801. }
  1802.  
  1803. char *Pretty_Addr_Str( ADDR *a )
  1804. {
  1805.    char t1[10];
  1806.    char t2[30];
  1807.    char t3[10];
  1808.    char t4[50];
  1809.  
  1810.    if (a->Zone && !no_zones)
  1811.       sprintf (t1, "%hu:", a->Zone);
  1812.    else
  1813.       t1[0] = '\0';
  1814.  
  1815.    sprintf (t2, "%hu/%hu", a->Net, a->Node);
  1816.  
  1817.    if (a->Point)
  1818.       sprintf (t3, ".%hu", a->Point);
  1819.    else
  1820.       t3[0] = '\0';
  1821.  
  1822.    if (a->Domain != NULL)
  1823.     /* PRETTYDOMAIN  26.08.1990 */
  1824.     {
  1825.       sprintf (t4, " @ %s", a->Domain);
  1826.       fancy_str(t4);
  1827.     }
  1828.    else
  1829.       t4[0] = '\0';
  1830.  
  1831.    strcpy (addr_str, t1);
  1832.    strcat (addr_str, t2);
  1833.    strcat (addr_str, t3);
  1834.    strcat (addr_str, t4);
  1835.    return (addr_str);
  1836. }
  1837.  
  1838. char *Full_Addr_Str( ADDR *a)
  1839. {
  1840.    char t1[10];
  1841.    char t2[30];
  1842.    char t3[10];
  1843.    char t4[50];
  1844.  
  1845.    if (a->Zone && !no_zones)
  1846.       sprintf (t1, "%hu:", a->Zone);
  1847.    else
  1848.       t1[0] = '\0';
  1849.  
  1850.    sprintf (t2, "%hu/%hu", a->Net, a->Node);
  1851.  
  1852.    if (a->Point)
  1853.       sprintf (t3, ".%hu", a->Point);
  1854.    else
  1855.       t3[0] = '\0';
  1856.  
  1857.    if (a->Domain != NULL)
  1858.       sprintf (t4, "@%s", a->Domain);
  1859.    else
  1860.       t4[0] = '\0';
  1861.  
  1862.    strcpy (addr_str, t1);
  1863.    strcat (addr_str, t2);
  1864.    strcat (addr_str, t3);
  1865.    strcat (addr_str, t4);
  1866.    return (addr_str);
  1867. }
  1868.  
  1869. /*
  1870.  * Convert the Hex 2D string into an address
  1871.  * (Domain and Zone are not changed) and are assumed to be predefined
  1872.  */
  1873.  
  1874. BOOLEAN get2daddress(char *name, ADDR *destad)
  1875. {
  1876.     if (sscanf (name, "%04x%04x.", &destad->Net, &destad->Node) != 2)
  1877.         return FALSE;
  1878.  
  1879.     /* Convert 2D to 4D if in one of our fakenets */
  1880.             
  1881.     destad->Point = 0;
  1882.     {
  1883.         ADDRESS *ad = alias;
  1884.         int i = 0;
  1885.     
  1886.         while(i < num_addrs)
  1887.         {
  1888.             if( (destad->Zone == ad->ad.Zone) &&
  1889.                 (destad->Domain == ad->ad.Domain) &&
  1890.                 (destad->Net == ad->fakenet) )
  1891.             {
  1892.                 destad->Point = destad->Node;
  1893.                 destad->Node = ad->ad.Node;
  1894.                 destad->Net = ad->ad.Net;
  1895.                 return TRUE;
  1896.             }
  1897.             ad++;
  1898.             i++;
  1899.         }
  1900.     }
  1901.     return TRUE;
  1902. }
  1903.  
  1904. #ifdef IOS
  1905. /*
  1906.  * IOS support... convert filename into net/node.point
  1907.  *
  1908.  * Code provided by Rinaldo Visscher 90:4000/103
  1909.  */
  1910.  
  1911. unsigned int ztoi(char *str, int len)
  1912. {
  1913.     unsigned int temp;
  1914.     
  1915.     temp = 0;
  1916.     while(*str && len-- && isalnum(*str))
  1917.     {
  1918.         temp *= 36;
  1919.         temp += isdigit(*str) ? *str-'0' : toupper(*str)-'A'+10;
  1920.         str++;
  1921.     }
  1922.     return temp;
  1923. }
  1924.  
  1925. void getaddress(char *str, unsigned int *net, unsigned int *node, unsigned int *point)
  1926. {
  1927.     *net = ztoi(str, 3);
  1928.     *node = ztoi(str+3, 3);
  1929.     *point = ztoi(str+6, 2);
  1930. }
  1931.  
  1932. void put36(char *s, unsigned int n, int len)
  1933. {
  1934.     s += len;    /* Get to end of string! */
  1935.     *s-- = 0;    /* Null terminate */
  1936.     while(len--)
  1937.     {
  1938.         int d = n % 36;                /* Remainder */
  1939.         n /= 36;
  1940.         if(d < 10)
  1941.             *s-- = d + '0';
  1942.         else
  1943.             *s-- = d - 10 + 'A';
  1944.     }
  1945. }
  1946.  
  1947. char *Addr36(ADDR *ad)
  1948. {
  1949.     put36(addr_str, ad->Net, 3);
  1950.     put36(addr_str+3, ad->Node, 3);
  1951.     put36(addr_str+6, ad->Point, 2);
  1952.     return addr_str;
  1953. }
  1954.  
  1955. /*
  1956.  * Make up the name for an ArcMail packet (names are SU? MO?..etc
  1957.  */
  1958.  
  1959. void make_dummy_arcmail(char *s, ADDR *from, ADDR *to)
  1960. {
  1961.     static char suffixes[7][3] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA" };
  1962.     char *day;
  1963.     time_t thetime;
  1964.     struct tm *t;
  1965.     static int digit = 0;    
  1966.     
  1967.     time(&thetime);
  1968.     t = localtime(&thetime);
  1969.     day = suffixes[t->tm_wday];
  1970.  
  1971.     /* Make a dummy *.su0 name */
  1972.  
  1973.     if(to->Point || from->Point)
  1974.     {
  1975.         ADDRESS *assume1 = get_assumed(to);
  1976.         ADDRESS *assume2 = get_assumed(from);
  1977.         
  1978.         sprintf(s, "%04x%04x.%s%c",
  1979.             assume2->fakenet - assume1->fakenet,
  1980.             from->Point - to->Point,
  1981.             day, digit+'0');
  1982.     }
  1983.     else
  1984.     {
  1985.         sprintf(s, "%04x%04x.%s%c",
  1986.             from->Net - to->Net,
  1987.             from->Node - to->Node,
  1988.             day, digit+'0');
  1989.     }
  1990. #if 0
  1991.     if(++digit > 9)
  1992.         digit = 0;
  1993. #endif
  1994. }
  1995.  
  1996. #endif
  1997.  
  1998. unsigned int crc_block( unsigned char *ptr, size_t count )
  1999. {
  2000.     unsigned int crc;
  2001.     int i;
  2002.  
  2003.        for (crc = 0, i = 0; i < count; i++, ptr++)
  2004.        {    
  2005.         crc = xcrc (crc, (byte) *ptr);
  2006.     }
  2007.     return (crc & 0xFFFF);
  2008. }
  2009.  
  2010. void Data_Check( XMDATAP xtmp, int mode )
  2011. {
  2012.     int i;
  2013.     unsigned char cs;
  2014.     unsigned char *cp;
  2015.     unsigned int cs1;
  2016.  
  2017.     /* If we are in checksum mode, just do it */
  2018.     if (mode == CHECKSUM)
  2019.         {
  2020.         cp = xtmp->data_bytes;
  2021.         cs = 0;
  2022.         for (i = 0; i < 128; i++)
  2023.             {
  2024.             cs += *cp++;
  2025.             }
  2026.         xtmp->data_check[0] = cs;
  2027.         }
  2028.     /* If we are in CRC mode, run the characters through the CRC calculator */
  2029.     else
  2030.         {
  2031.         cs1 = crc_block (xtmp->data_bytes, 128);
  2032.         xtmp->data_check[0] = (unsigned char) (cs1 >> 8);
  2033.         xtmp->data_check[1] = (unsigned char) (cs1 & 0xff);
  2034.         }
  2035.     }
  2036.  
  2037. static size_t buff_bytes = 0;
  2038.  
  2039. FILE *buff_fopen( char *fname, char *fmode )
  2040. {
  2041.     buff_bytes = 0;
  2042.     return (fopen (fname, fmode));
  2043. }
  2044.  
  2045. size_t buff_fwrite(char *buff, size_t size1, size_t size2, FILE *fp)
  2046. {
  2047.     if ((buff_bytes + (size1 * size2)) > WAZOOMAX)
  2048.         {
  2049.         (void) fwrite (Secbuf, 1, buff_bytes, fp);
  2050.         buff_bytes = 0;
  2051.         }
  2052.  
  2053.     memcpy (Secbuf + buff_bytes, buff, size1 * size2);
  2054.     buff_bytes += size1 * size2;
  2055.     return (size1 * size2);
  2056. }
  2057.  
  2058. int buff_fclose( FILE *fp )
  2059. {
  2060.     (void) fwrite (Secbuf, 1, buff_bytes, fp);
  2061.     buff_bytes = 0;
  2062.     return (fclose (fp));
  2063. }
  2064.  
  2065. int buff_fseek( FILE *fp, long a, int b )
  2066. {
  2067.     (void) fwrite (Secbuf, 1, buff_bytes, fp);
  2068.     buff_bytes = 0;
  2069.     return (fseek (fp, a, b));
  2070. }
  2071.  
  2072. #ifdef OS_2
  2073. void set_prior (int pclass)
  2074. {
  2075.     char *s;
  2076.     static USHORT regular = 0;
  2077.     static USHORT janus = 0;
  2078.     static USHORT modem = 0;
  2079.     USHORT priority;
  2080.  
  2081.     switch (pclass)
  2082.         {
  2083.         case 2:
  2084.             if (regular)
  2085.                priority = regular;
  2086.             else
  2087.                {
  2088.                s = getenv("REGULARPRIORITY");
  2089.                if (s)
  2090.                   priority = regular = atoi(s);
  2091.                else
  2092.                   priority = regular = 2;
  2093.                }
  2094.            break;
  2095.  
  2096.         case 3:
  2097.             if (janus)
  2098.                priority = janus;
  2099.             else
  2100.                {
  2101.                s = getenv("JANUSPRIORITY");
  2102.                if (s)
  2103.                   priority = janus = atoi(s);
  2104.                else
  2105.                   priority = janus = 3;
  2106.                }
  2107.            break;
  2108.  
  2109.         case 4:
  2110.             if (modem)
  2111.                priority = modem;
  2112.             else
  2113.                {
  2114.                s = getenv("MODEMPRIORITY");
  2115.                if (s)
  2116.                   priority = modem = atoi(s);
  2117.                else
  2118.                   priority = modem = 4;
  2119.                }
  2120.             break;
  2121.  
  2122.         default:
  2123.             priority = 2;
  2124.             break;
  2125.         }
  2126.  
  2127.    (void) DosSetPrty ((USHORT) 1, priority, (SHORT) 31, (USHORT) 0);
  2128. }
  2129.  
  2130. #ifdef Snoop
  2131. #pragma check_stack(off)
  2132. static int far pascal _loadds mesgfunc(int error, char far *mesg)
  2133. {
  2134.     if(!error)
  2135.         status_line(":%Fs", mesg);
  2136.     else
  2137.         status_line("!SYS%04u : %Fs", error, mesg);
  2138.     return(0);
  2139. }
  2140. #pragma check_stack()
  2141.  
  2142. void snoop_open(char *pipename)
  2143. {
  2144.    static char *pipe = NULL;
  2145.    if(pipe)
  2146.       free(pipe);
  2147.    if(pipename)
  2148.       pipe = strdup(pipename);
  2149.    SnoopOpen(pipe, &hsnoop, xfer_id, (PFNSN)mesgfunc);
  2150. }
  2151.  
  2152. void snoop_close(void)
  2153. {
  2154.     if(hsnoop)
  2155.         SnoopClose(hsnoop);
  2156.     hsnoop = (HSNOOP)NULL;
  2157. }
  2158. #endif /* Snoop */
  2159. #else /* OS_2 */
  2160. void set_prior (int pclass)
  2161. {
  2162.     if ( pclass )
  2163.     {
  2164.     }
  2165.  
  2166.    return;
  2167.    /* pclass = 5; */
  2168. }
  2169. #endif /* OS_2 */
  2170.  
  2171.  
  2172. /*
  2173.  * Implement file locking
  2174.  */
  2175.  
  2176. int flag_file (int function, ADDR *address, int do_stat)
  2177. {
  2178.  
  2179.     FILE *fptr;
  2180.     char *HoldName;
  2181.     static ADDR last_set[3];    /* Need two of them during EMSI Janus */
  2182.     static int counts[3];        /* How many times they are locked! */
  2183.     char flagname[128];
  2184.     char tmpname[128];
  2185.     int set;
  2186.  
  2187.     if (!TaskNumber)
  2188.         return (FALSE);
  2189.  
  2190.     HoldName = HoldAreaNameMunge (address);
  2191.  
  2192.     switch (function)
  2193.     {
  2194.     case INITIALIZE:
  2195.         last_set[0].Zone = -1;
  2196.         last_set[1].Zone = -1;
  2197.         last_set[2].Zone = -1;
  2198.         counts[0] = counts[1] = counts[2] = 0;
  2199.         break;
  2200.  
  2201.     case SET_SESSION_FLAG:
  2202.         /* At the start of a session, set up the task number */
  2203.         if (flag_dir)
  2204.         {
  2205.             sprintf (flagname, "%sTask.%d",
  2206.             flag_dir, TaskNumber);
  2207.             fptr = fopen (flagname, write_binary);
  2208.             fclose (fptr);
  2209.         }
  2210.         return (FALSE);
  2211.  
  2212.     case CLEAR_SESSION_FLAG:
  2213.         /* At the end of a session, delete the task file */
  2214.         if (flag_dir)
  2215.         {
  2216.             sprintf (flagname, "%sTask.%d",
  2217.             flag_dir, TaskNumber);
  2218.             unlink (flagname);
  2219.         }
  2220.         return (FALSE);
  2221.  
  2222.     case TEST_AND_SET:
  2223.  
  2224.     /*
  2225.      * First see if we already HAVE this lock! If so, return now.
  2226.      *
  2227.      */
  2228.  
  2229.         if (memcmp (&last_set[0], address, sizeof (ADDR)) == 0)
  2230.         {
  2231.             counts[0]++;
  2232. #ifdef DEBUG
  2233.             status_line(">Incremented flagfile for %s", Pretty_Addr_Str(address));
  2234.             status_line(">flag0=%s[%d]", Pretty_Addr_Str(&last_set[0]), counts[0]);
  2235.             status_line(">flag1=%s[%d]", Pretty_Addr_Str(&last_set[1]), counts[1]);
  2236.             status_line(">flag2=%s[%d]", Pretty_Addr_Str(&last_set[2]), counts[2]);
  2237. #endif
  2238.             return (FALSE);
  2239.         }
  2240.         if (memcmp (&last_set[1], address, sizeof (ADDR)) == 0)
  2241.         {
  2242.             counts[1]++;
  2243. #ifdef DEBUG
  2244.             status_line(">Incremented flagfile for %s", Pretty_Addr_Str(address));
  2245.             status_line(">flag0=%s[%d]", Pretty_Addr_Str(&last_set[0]), counts[0]);
  2246.             status_line(">flag1=%s[%d]", Pretty_Addr_Str(&last_set[1]), counts[1]);
  2247.             status_line(">flag2=%s[%d]", Pretty_Addr_Str(&last_set[2]), counts[2]);
  2248. #endif
  2249.             return (FALSE);
  2250.         }
  2251.         if (memcmp (&last_set[2], address, sizeof (ADDR)) == 0)
  2252.         {
  2253.             counts[2]++;
  2254. #ifdef DEBUG
  2255.             status_line(">Incremented flagfile for %s", Pretty_Addr_Str(address));
  2256.             status_line(">flag0=%s[%d]", Pretty_Addr_Str(&last_set[0]), counts[0]);
  2257.             status_line(">flag1=%s[%d]", Pretty_Addr_Str(&last_set[1]), counts[1]);
  2258.             status_line(">flag2=%s[%d]", Pretty_Addr_Str(&last_set[2]), counts[2]);
  2259. #endif
  2260.             return (FALSE);
  2261.         }
  2262.  
  2263.     /*
  2264.      * Check for the INMAIL.$$$ file.
  2265.      *
  2266.      */
  2267.  
  2268.         if (flag_dir != NULL)
  2269.         {
  2270.             sprintf (tmpname, "%sINMAIL.$$$",flag_dir);
  2271.  
  2272.             if ((fptr = fopen (tmpname, read_binary)) != NULL)
  2273.             {
  2274.                 fclose (fptr);
  2275.                 if (!CARRIER)
  2276.                     if (do_stat)
  2277.                         status_line (msgtxt[M_OTHERPROC]);
  2278.                 return (TRUE);
  2279.             }
  2280.         }
  2281.  
  2282.     /*
  2283.      * Next create a file using a temporary name.
  2284.      *
  2285.      */
  2286.  
  2287.         sprintf (tmpname, "%sBINK%04x.BSY",HoldName,TaskNumber);
  2288.         fptr = fopen (tmpname, write_binary);
  2289.         if (fptr == NULL)
  2290.         {
  2291.             if (do_stat)
  2292.                 status_line (msgtxt[M_FAILED_CREATE_FLAG],tmpname);
  2293.             return (TRUE);
  2294.         }
  2295.         fclose (fptr);
  2296.  
  2297.     /*
  2298.      * Now the test&set. Attempt to rename the file.
  2299.      * If we succeed, we have the lock. If we do not,
  2300.      * delete the temp file.
  2301.      *
  2302.      */
  2303.  
  2304. #ifdef IOS
  2305.         if(iosmode)
  2306.             sprintf (flagname, "%s%s.BSY", HoldName, Addr36(address));
  2307.         else
  2308. #endif
  2309.             sprintf (flagname, "%s%s.BSY", HoldName, Hex_Addr_Str(address));
  2310.  
  2311.         if (!rename (tmpname, flagname))
  2312.         {
  2313.             if (do_stat)
  2314.                 status_line (msgtxt[M_CREATED_FLAGFILE],flagname);
  2315.             if(last_set[0].Zone == -1U)
  2316.             {
  2317.                 memcpy (&last_set[0], address, sizeof (ADDR));
  2318.                 counts[0] = 1;
  2319.             }
  2320.             else if(last_set[1].Zone == -1U)
  2321.             {
  2322.                 memcpy (&last_set[1], address, sizeof (ADDR));
  2323.                 counts[1] = 1;
  2324.             }
  2325.             else
  2326.             {
  2327.                 memcpy (&last_set[2], address, sizeof (ADDR));
  2328.                 counts[2] = 1;
  2329.             }
  2330. #ifdef DEBUG
  2331.             status_line(">flag0=%s[%d]", Pretty_Addr_Str(&last_set[0]), counts[0]);
  2332.             status_line(">flag1=%s[%d]", Pretty_Addr_Str(&last_set[1]), counts[1]);
  2333.             status_line(">flag2=%s[%d]", Pretty_Addr_Str(&last_set[2]), counts[2]);
  2334. #endif
  2335.             return (FALSE);
  2336.         }
  2337.         if (do_stat)
  2338.             status_line (msgtxt[M_THIS_ADDRESS_LOCKED], Pretty_Addr_Str (address));
  2339.         unlink (tmpname);
  2340.         return (TRUE);
  2341.  
  2342.     case CLEAR_FLAG:
  2343.  
  2344.     /*
  2345.      * Make sure we need to clear something.
  2346.      * Zone should be something other than -1 if that's the case.
  2347.      *
  2348.      */
  2349.         if ( (last_set[0].Zone == -1U) && (last_set[1].Zone == -1U) && (last_set[2].Zone == -1U))
  2350.             return (TRUE);
  2351.  
  2352.         /*
  2353.          * Next compare what we want to clear with what we think we have.
  2354.          *
  2355.          */
  2356.  
  2357.         if (memcmp (&last_set[0], address, sizeof (ADDR)) == 0)
  2358.             set = 0;
  2359.         else if (memcmp (&last_set[1], address, sizeof (ADDR)) == 0)
  2360.             set = 1;
  2361.         else if (memcmp (&last_set[2], address, sizeof (ADDR)) == 0)
  2362.             set = 2;
  2363.         else
  2364.         {
  2365.             if (do_stat)
  2366.                 status_line (msgtxt[M_BAD_CLEAR_FLAGFILE],
  2367.                 Pretty_Addr_Str (address));
  2368.             return (TRUE);
  2369.         }
  2370.  
  2371.         /*
  2372.          * Decrement counter and clear the file if zero
  2373.          */
  2374.  
  2375.         if(--counts[set])
  2376.         {
  2377. #ifdef DEBUG
  2378.             status_line(">Decremented flagfile for %s", Pretty_Addr_Str(address));
  2379.             status_line(">flag0=%s[%d]", Pretty_Addr_Str(&last_set[0]), counts[0]);
  2380.             status_line(">flag1=%s[%d]", Pretty_Addr_Str(&last_set[1]), counts[1]);
  2381.             status_line(">flag2=%s[%d]", Pretty_Addr_Str(&last_set[2]), counts[2]);
  2382. #endif
  2383.             return TRUE;
  2384.         }
  2385.  
  2386.         /*
  2387.          * We match. Unlink the flag file. If we're successful, jam a -1
  2388.          * into our saved Zone.
  2389.          *
  2390.          */
  2391.  
  2392. #ifdef IOS
  2393.         if(iosmode)
  2394.             sprintf (flagname, "%s%s.BSY", HoldName, Addr36(address));
  2395.         else
  2396. #endif
  2397.             sprintf (flagname, "%s%s.BSY", HoldName, Hex_Addr_Str(address));
  2398.         if (!unlink (flagname))
  2399.         {
  2400.             if (do_stat)
  2401.                 status_line (msgtxt[M_CLEARED_FLAGFILE], flagname);
  2402.             last_set[set].Zone = -1;
  2403. #ifdef DEBUG
  2404.             status_line(">flag0=%s[%d]", Pretty_Addr_Str(&last_set[0]), counts[0]);
  2405.             status_line(">flag1=%s[%d]", Pretty_Addr_Str(&last_set[1]), counts[1]);
  2406.             status_line(">flag2=%s[%d]", Pretty_Addr_Str(&last_set[2]), counts[2]);
  2407. #endif
  2408.             return (TRUE);
  2409.         }
  2410.  
  2411.         if (do_stat)
  2412.             status_line (msgtxt[M_FAILED_CLEAR_FLAG],flagname);
  2413.         return (FALSE);
  2414.  
  2415.     default:
  2416.         break;
  2417.     }
  2418.  
  2419.     return (TRUE);
  2420. }
  2421.  
  2422. #ifdef GENERIC
  2423.  
  2424. /*
  2425.  * Portability functions
  2426.  */
  2427.  
  2428. /* Both these functions actually do the same! */
  2429.  
  2430. /*
  2431.  * Converts from generic word to MSDOS word
  2432.  */
  2433.  
  2434. word PUTWORD( register word val )
  2435. {
  2436.     MWORD temp;
  2437.     
  2438.     temp.lohi.lo = val & 0xff;
  2439.     temp.lohi.hi = (val >> 8) & 0xff;
  2440.  
  2441.     return temp.w;
  2442. }
  2443.  
  2444. /*
  2445.  * This returns a normal word from an MSDOS format word
  2446.  */
  2447.  
  2448. word GETWORD( register word val )
  2449. {
  2450.     MWORD temp;
  2451.     temp.w = val;
  2452.  
  2453.     return ((word)(temp.lohi.lo + (temp.lohi.hi << 8)));
  2454. }
  2455.  
  2456. #endif
  2457.  
  2458. /* GENERALEXEC  24.09.1989 */
  2459.  
  2460. void exec_shell( int j )
  2461. {
  2462.     status_line (msgtxt[M_EXECSHELL], j);
  2463.     mdm_init (modem_busy);
  2464.     exit_DTR ();
  2465.     close_up ();
  2466.     vfossil_cursor (1);
  2467.     b_spawn (shells[j-1]);
  2468.     come_back ();
  2469.     set_up_outbound ();
  2470.     DTR_ON ();
  2471.     mdm_init (modem_init);
  2472.     status_line (msgtxt[M_RETSHELL]);
  2473. }
  2474.  
  2475. /* STR_LIST manipulation */
  2476.  
  2477. /*
  2478.  * Add the white space seperated text (s) to the end of STR_LIST
  2479.  */
  2480.  
  2481. void add_to_strlist(STR_LIST **list, char *s)
  2482. {
  2483.     char *p;
  2484.     STR_LIST *l;
  2485.     STR_LIST *lst;
  2486.     
  2487.     /* Get to end of list ready to add new data */
  2488.     
  2489.     lst = (STR_LIST *)list;
  2490.     if(lst->next)
  2491.         while(lst->next)
  2492.             lst = lst->next;
  2493.  
  2494.     p = strtok(s, seperators);
  2495.     while(p)
  2496.     {
  2497.         l = calloc(sizeof(STR_LIST), 1);
  2498.         if(l)
  2499.         {
  2500.             l->str = strdup(p);
  2501.  
  2502.             if(l->str)
  2503.             {
  2504.                 l->next = NULL;
  2505.                 lst->next = l;
  2506.                 lst = l;
  2507.             }
  2508.             else
  2509.                 free(l);
  2510.         }
  2511.         p =strtok(NULL, seperators);
  2512.     }
  2513. }
  2514.  
  2515. /*
  2516.  * match a string with a a sequence of a wildcard string
  2517.  * ? = any one character
  2518.  * * = remainder of field matches
  2519.  *
  2520.  * TRUE: Matches
  2521.  * FALSE: no match
  2522.  */
  2523.  
  2524. static BOOLEAN match_wild(char *text, char *pattern)
  2525. {
  2526.  
  2527.     while(*text)
  2528.     {
  2529.         char c = *pattern++;
  2530.         char c1 = *text++;
  2531.         
  2532.         if(c == '*')
  2533.             return TRUE;
  2534.         if( (c != '?') && (c != c1))
  2535.             return FALSE;
  2536.     }
  2537.     if(*pattern && (isdigit(*pattern) || (*pattern == '*') || (*pattern == '?')))
  2538.         return FALSE;
  2539.  
  2540.     return TRUE;
  2541. }
  2542.  
  2543. /*
  2544.  * Find entry for address in a string list
  2545.  *
  2546.  * The 1st character if not a digit (or wildcard) is assumed to be a special
  2547.  * character, e.g. '-' to disable a node.
  2548.  *
  2549.  * Returns the str field or NULL if not found
  2550.  */
  2551.  
  2552. char *find_strlist(STR_LIST *list, ADDR *ad, char **spec_field)
  2553. {
  2554.     char zone[6];
  2555.     char net[6];
  2556.     char node[6];
  2557.     char point[6];
  2558.     static char extra[40];        /* special field in listentry    */
  2559.     
  2560.     /* Convert Address fields to ascii */
  2561.  
  2562.     sprintf(zone, "%d", ad->Zone);
  2563.     sprintf(net, "%d", ad->Net);
  2564.     sprintf(node, "%d", ad->Node);
  2565.     sprintf(point, "%d", ad->Point);
  2566.  
  2567.     for(; list; list = list->next)
  2568.     {
  2569.         char *s = list->str, *tmp;
  2570.         char *s1, *s2;
  2571.         
  2572.         /*
  2573.         ** if spec_field is not null, extract first entry from s
  2574.         ** (separeted by ! from the rest) and copy it to extra
  2575.         */
  2576.         
  2577.         tmp = s;        
  2578.         if (spec_field != NULL)
  2579.         {
  2580.             memset (extra, 0, sizeof (extra));
  2581.             if ((*spec_field = strchr (s, '!')) != NULL )
  2582.             {
  2583.                 strncpy (extra, s, *spec_field - s);
  2584.                 s = *spec_field + 1;
  2585.                 tmp = s;
  2586.                 *spec_field = extra;
  2587.             }
  2588.             else
  2589.             {
  2590.                 *spec_field = NULL;
  2591.             }
  2592.         }
  2593.         
  2594.         /* 1st check the zone */
  2595.  
  2596.         if(*s && !isdigit(*s) && (*s != '*') && (*s != '?'))    /* Skip initial character */
  2597.             s++;
  2598.  
  2599.         s1 = strchr(s, ':');    /* Look for zone end */
  2600.         if(s1)
  2601.         {
  2602.             if(!match_wild(zone, s))
  2603.                 continue;
  2604.             s = s1 + 1;
  2605.         }
  2606.         s1 = strchr(s, '/');    /* net marker */
  2607.         if(s1)
  2608.         {
  2609.             if(!match_wild(net, s))
  2610.                 continue;
  2611.             s = s1 + 1;
  2612.         }
  2613.         s1 = strchr(s, '.');    /* Point */
  2614.         s2 = strchr(s, '@');    /* Domain */
  2615.  
  2616.         if(s1 && s2 && (s2 < s1))    /* Ignore point if part of domain */
  2617.             s1 = NULL;
  2618.  
  2619.         if(*s && !match_wild(node, s))
  2620.             continue;
  2621.  
  2622.         if(s1)
  2623.         {
  2624.             s1++;
  2625.             if(!match_wild(point, s1))
  2626.                 continue;
  2627.         }
  2628.         if(s2 && ad->Domain)
  2629.         {
  2630.             s2++;
  2631.             if(!match_wild(ad->Domain, s2))
  2632.                 continue;
  2633.         }
  2634.         return tmp;
  2635.     }
  2636.     return NULL;
  2637. }
  2638.  
  2639. /*
  2640.  * Finds an address in string list
  2641.  *
  2642.  * returns TRUE if enabled, FALSE if not.
  2643.  *
  2644.  * An address that begins with a '-' stops the search and returns FALSE.
  2645.  */
  2646.  
  2647. BOOLEAN find_ad_strlist(STR_LIST *list, ADDR *ad, char **spec_field)
  2648. {
  2649.     char *s;
  2650.     
  2651.     if(list == NULL)
  2652.         return TRUE;
  2653.  
  2654. #ifdef DEBUG
  2655.     status_line(">find_ad_strlist(%s)", Pretty_Addr_Str(ad));
  2656. #endif
  2657.  
  2658.     s = find_strlist(list, ad, spec_field);
  2659.     if(s && (*s != '-'))
  2660.         return TRUE;
  2661.     else
  2662.         return FALSE;
  2663. }
  2664.  
  2665.  
  2666. BOOLEAN check_holdonus( ADDR *ad, char **spec_field )
  2667. {
  2668.     BOOLEAN flag = HoldsOnUs;
  2669.     
  2670.     if(flag)
  2671.     {
  2672.         if(ad)
  2673.             flag = find_ad_strlist(hold_list, ad, spec_field);
  2674.         else
  2675.             flag = !hold_list;
  2676.     }
  2677.  
  2678. #ifdef DEBUG
  2679.     status_line(">HoldOnUs %sabled for %s",
  2680.         flag ? "en" : "dis",
  2681.         ad ? Pretty_Addr_Str(ad) : "all nodes");
  2682. #endif
  2683.     return flag;
  2684. }
  2685.  
  2686. /*
  2687.  * Returns:
  2688.  *   TRUE: If EMSI disabled for this node
  2689.  */
  2690.  
  2691. BOOLEAN check_noemsi( ADDR *ad, char **spec_field )
  2692. {
  2693.     BOOLEAN flag = no_EMSI;
  2694.     
  2695.     if(flag)
  2696.     {
  2697.         if(ad)
  2698.             flag = find_ad_strlist(emsi_list, ad, spec_field);
  2699.         else
  2700.             flag = !emsi_list;
  2701.     }
  2702.  
  2703. #ifdef DEBUG
  2704.     status_line(">EMSI %sabled for %s",
  2705.         flag ? "dis" : "en",
  2706.         ad ? Pretty_Addr_Str(ad) : "Inbound");
  2707. #endif
  2708.  
  2709.     return flag;
  2710. }
  2711.  
  2712. BOOLEAN check_nojanus( ADDR *ad, char **spec_field )
  2713. {
  2714.     BOOLEAN flag = no_JANUS;
  2715.     
  2716.     if(flag)
  2717.     {
  2718.         if(ad)
  2719.             flag = find_ad_strlist(janus_list, ad, spec_field);
  2720.         else
  2721.             flag = !janus_list;
  2722.     }
  2723.  
  2724. #ifdef DEBUG
  2725.     status_line(">JANUS %sabled for %s",
  2726.         flag ? "dis" : "en",
  2727.         ad ? Pretty_Addr_Str(ad) : "Inbound");
  2728. #endif
  2729.  
  2730.     return flag;
  2731. }
  2732.  
  2733. BOOLEAN check_reqonus(ADDR *ad, char **spec_field )
  2734. {
  2735.     BOOLEAN flag = on_our_nickel;
  2736.     
  2737.     if(flag)
  2738.     {
  2739.         if(ad)
  2740.             flag = find_ad_strlist(reqonus_list, ad, spec_field);
  2741.         else
  2742.             flag = !reqonus_list;
  2743.     }
  2744.  
  2745. #ifdef DEBUG
  2746.     status_line(">ReqOnUs %sabled for %s",
  2747.         flag ? "en" : "dis",
  2748.         ad ? Pretty_Addr_Str(ad) : "all");
  2749. #endif
  2750.  
  2751.     return flag;
  2752. }
  2753.  
  2754. BOOLEAN check_norequest(ADDR *ad, char **spec_field )
  2755. {
  2756.     BOOLEAN flag = no_REQUEST;
  2757.     
  2758.     if(flag)
  2759.     {
  2760.         if(ad)
  2761.             flag = find_ad_strlist(request_list, ad, spec_field);
  2762.         else
  2763.             flag = !request_list;
  2764.     }
  2765.  
  2766. #ifdef DEBUG
  2767.     status_line(">Requests %sabled for %s",
  2768.         flag ? "en" : "dis",
  2769.         ad ? Pretty_Addr_Str(ad) : "all");
  2770. #endif
  2771.  
  2772.     return flag;
  2773. }
  2774.  
  2775. void call_fax( void )
  2776. {
  2777.     long ret;
  2778.     
  2779.     if (!fax_prg)
  2780.     {
  2781.         fax_recieve();
  2782.         return;
  2783.     }
  2784.  
  2785.     status_line (msgtxt[M_FAX_RECIEVER], fax_prg);
  2786.     
  2787.     ret = b_spawn(fax_prg);
  2788.  
  2789.     if (ret < 0)
  2790.     {
  2791.         status_line (msgtxt[M_FAX_EXEC], errno);
  2792.     }
  2793.     else
  2794.     {
  2795.         if (ret != 0) status_line (msgtxt[M_FAX_RETURN], ret);
  2796.     }
  2797.  
  2798.     if (afterfax_prg)
  2799.         b_spawn (afterfax_prg);
  2800.             
  2801.     return;
  2802. }
  2803.  
  2804. char *DirName( const char *fullname )
  2805. {
  2806.     static char    str[64];
  2807.     
  2808.     if (!fullname) return(NULL);
  2809.     
  2810.     strcpy(str, fullname);
  2811.     *(strrchr(str, '\\')+1) = '\0';
  2812.     
  2813.     return(str);
  2814. }
  2815.