home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / BSRC_250.LZH / MDM_PROC.C < prev    next >
C/C++ Source or Header  |  1991-09-15  |  24KB  |  648 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-91, Bit Bucket Software Co., a Delaware Corporation. */
  11. /*                                                                          */
  12. /*                                                                          */
  13. /*               This module was written by Vince Perriello                 */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*                    BinkleyTerm Modem Handler 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.250.    */
  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:343/491             */
  37. /* P.O. Box 460398                AlterNet 7:491/0                          */
  38. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  39. /*                                Internet f491.n343.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 this file before any other includes or defines! */
  47.  
  48. #include "includes.h"
  49.  
  50. int dial_modem (char *);
  51. void phone_translate (char *, char *);
  52. char *get_response (long);
  53. int parse_response (char *);
  54. void empty_delay (void);
  55.  
  56. #define FAILURE   0
  57. #define IGNORE    1
  58. #define CONNECTED 2
  59. #define RINGING   3
  60. #define INCOMING  4
  61.  
  62. struct resp_str
  63. {
  64.    char *resp;
  65.    unsigned disp;
  66. };
  67.  
  68. static struct resp_str mdm_resps[] = {
  69.                                       {"RINGING", 1},
  70.                                       {"RING RESPONSE", 1},
  71.                                       {"RING", 3},
  72.                                       {"CONNECT", 2},
  73.                                       {"RRING", 1},
  74.                                       {"BUSY", 0},
  75.                                       {"VOICE", 0},
  76.                                       {"ERROR", 0},
  77.                                       {"OK", 0},
  78.                                       {"NO CARRIER", 0},
  79. /* "NO DIAL TONE" or "NO DIALTONE" */ {"NO DIAL", 4},
  80.                                       {"DIALING", 1},
  81.                                       {"NO ANSWER", 0},
  82.                                       {"DIAL TONE", 1},
  83.                                       {NULL, 0}
  84. };
  85.  
  86. static char *response_string = "                                                  ";
  87.  
  88. void do_dial_strings ()
  89. {
  90.    MDM_TRNS *m;
  91.  
  92.    predial = normprefix;
  93.    postdial = normsuffix;
  94.  
  95.    m = mm_head;
  96.    while (m != NULL)
  97.       {
  98.       if (m->mdm & newnodedes.ModemType)
  99.          {
  100.          predial = m->pre;
  101.          postdial = m->suf;
  102.          return;
  103.          }
  104.       m = m->next;
  105.       }
  106. }
  107.  
  108. void try_2_connect (char *phnum)
  109. {
  110.    long t1;
  111.    int j, k;
  112.  
  113.    for (j = 0; (j < poll_tries && !KEYPRESS ()); j++) /* do polltries or till keypress */
  114.       {
  115.       CLEAR_INBOUND ();
  116.       k = dial_modem (phnum);
  117.  
  118.       if ((un_attended || doing_poll) && fullscreen)
  119.          {
  120.          ++hist.calls_made;
  121.          (void) sprintf (junk, "%-4d", hist.calls_made);
  122.          sb_move (history_hWnd, HIST_ATT_ROW, HIST_COL);
  123.          sb_puts (history_Out, junk);
  124.          }
  125.  
  126.       if ((k > 0) || KEYPRESS ())
  127.          break;
  128.       t1 = timerset (200);
  129.       mdm_hangup ();
  130.       while (!timeup (t1) && !KEYPRESS ())
  131.          time_release ();                        /* pause for 2 seconds */
  132.       }
  133.    if (KEYPRESS ())                              /* If user's been busy */
  134.       {
  135.       (void) FOSSIL_CHAR ();                     /* Eat the character   */
  136.       if (!CARRIER)                              /* Abort if no carrier */
  137.          {
  138.          status_line (MSG_TXT(M_CONNECT_ABORTED));
  139.          mdm_hangup ();
  140.          }
  141.       }
  142.  
  143.    predial = normprefix;
  144.    postdial = normsuffix;
  145. }
  146.  
  147. int try_1_connect (char *phnum)
  148. {
  149.    int k;
  150.  
  151.    if ((k = dial_modem (phnum)) <= 0)
  152.       {
  153.       if (k != -2)            /* NO DIAL TONE needs express service */
  154.          mdm_hangup ();
  155.       }
  156.  
  157.    if ((un_attended || doing_poll) && fullscreen)
  158.       {
  159.       ++hist.calls_made;
  160.       (void) sprintf (junk, "%-4d", hist.calls_made);
  161.       sb_move (history_hWnd, HIST_ATT_ROW, HIST_COL);
  162.       sb_puts (history_Out, junk);
  163.       }
  164.  
  165.    predial = normprefix;
  166.    postdial = normsuffix;
  167.  
  168.    return (k);
  169. }
  170.  
  171. void phone_translate (char *number, char *translated)
  172. {
  173.    PN_TRNS *p;
  174.  
  175.    (void) strcpy (translated, number);
  176.    for (p = pn_head; p != NULL; p = p->next)
  177.       {
  178.       if (strncmp (p->num, number, (unsigned int) (p->len)) == 0)
  179.          {
  180.          (void) sprintf (translated, "%s%s%s", p->pre, &(number[p->len]), p->suf);
  181.          break;
  182.          }
  183.       }
  184. }
  185.  
  186. int dial_modem (char *number)
  187. {
  188.    int resp;
  189.    long t;
  190.    char translated[50];
  191.  
  192.    janus_OK = 0;
  193.    ARQ_lock = 0;
  194.  
  195.    phone_translate (number, translated);
  196.    if (translated[0] == '\"')                    /* If it's a script          */
  197.       {
  198.       resp = do_script (translated);             /* then do it that way       */
  199.       if (fullscreen)                            /* & clean up the bottom line*/
  200.          bottom_line ();
  201.       return (resp);
  202.       }
  203.  
  204.    status_line (MSG_TXT(M_DIALING_NUMBER), translated);
  205.    if (un_attended && fullscreen)
  206.       {
  207.       do_ready (MSG_TXT(M_READY_DIALING));
  208.       }
  209.  
  210.    /* First of all, if we have something, don't hang up on the guy! */
  211.    if (!no_collide && CHAR_AVAIL ())
  212.       return (-1);
  213.  
  214.    if (dial_setup != NULL)
  215.       {
  216.       mdm_cmd_string (dial_setup, 1);
  217.       }
  218.    else
  219.       {
  220.       LOWER_DTR ();                              /* drop DTR to reset modem   */
  221.       timer (20);                                /* leave it down 2 seconds   */
  222.       RAISE_DTR ();                              /* then raise DTR again      */
  223.       timer (5);                                 /* and wait .5 sec for modem */
  224.       }
  225.  
  226.    if (!no_collide && CHAR_AVAIL ())             /* If we have something
  227.                                                   * here, return */
  228.       return (-1);
  229.  
  230.    mdm_cmd_string (predial, 0);                  /* transmit the dial prefix  */
  231.    mdm_cmd_string (translated, 0);               /* then the phone number     */
  232.    mdm_cmd_string (postdial, 0);                 /* finally the dial suffix   */
  233.    if (no_collide)
  234.       CLEAR_INBOUND ();                          /* Throw out all echo to
  235.                                                   * this point  */
  236.    mdm_cmd_char (CR);                            /* terminate the string      */
  237.  
  238.    resp = modem_response (7500);
  239.    if (resp)                                     /* we got a good response,   */
  240.       {
  241.       if (resp == RINGING)                       /* Incoming ring to be
  242.                                                   * processed higher up */
  243.          return (-1);
  244.  
  245.       if (resp == INCOMING)                      /* No dial tone. That's */
  246.          {
  247.          return (-2);                            /* a potential remote. */
  248.          }
  249.  
  250.       t = timerset (200);                        /* Wait up to 2 seconds      */
  251.       while (!timeup (t))
  252.          {                                       /* If carrier detect, AND    */
  253.          if ((CHAR_AVAIL ()) && CARRIER)         /* some sign of life, */
  254.             break;                               /* leave early...            */
  255.          }
  256.       return ((int) CARRIER);                    /* Carrier should be on now  */
  257.       }
  258.    return (0);                                   /* no good */
  259. }
  260.  
  261. char *get_response (long end_time)
  262. {
  263.    char *p = response_string;                    /* points to character cell  */
  264.    char c;                                       /* current modem character   */
  265.    int count = 0;                                /* count of characters       */
  266.  
  267.    while ((count < 50)                           /* until we have 50 chars,   */
  268.           && (!timeup (end_time))                /* or out of time,           */
  269.           && (!KEYPRESS ()))                     /* or user gets impatient    */
  270.       {
  271.       if (!CHAR_AVAIL ())                        /* if nothing ready yet,     */
  272.          {
  273.          time_release ();
  274.          continue;                               /* just process timeouts     */
  275.          }
  276.       c = (char) (MODEM_IN () & 0xff);           /* get a character           */
  277.       if (c == '\r' || c == '\n')                /* if a line ending          */
  278.          {
  279.          if (count != 0)                         /* and we have something,    */
  280.             break;                               /* get out                   */
  281.          else continue;                          /* otherwise just keep going */
  282.          }
  283.       *p++ = c;                                  /* store the character       */
  284.       ++count;                                   /* increment the counter     */
  285.       }
  286.    *p = '\0';                                    /* terminate the new string  */
  287.  
  288.    if (count != 0 && strnicmp (response_string, "AT", 2))
  289.       {
  290.       (void) fancy_str (response_string);               /* make it pretty            */
  291.       status_line ("#%s", response_string);     /* pop it out on the screen  */
  292.       }
  293.  
  294.    return (response_string);                     /* return the pointer        */
  295. }
  296.  
  297. int parse_response (char *response)
  298. {
  299.    char *p;                                      /* temp character pointer    */
  300.    register int i;                               /* array pointer             */
  301.  
  302.    for (i = 0; mdm_resps[i].resp != NULL; i++)   /* scan through array        */
  303.       {
  304.       p = mdm_resps[i].resp;                     /* point at possible
  305.                                                   * response */
  306.       if (strnicmp (response, p, strlen (p)) == 0)      /* if a match,               */
  307.          return ((int) (mdm_resps[i].disp));             /* return disposition of it  */
  308.       }
  309.    return (1);                                   /* ignore all unknowns       */
  310. }
  311.  
  312.  
  313. int modem_response (int ths)
  314. {
  315.    unsigned int baudrate;
  316.    long end_time;                                /* holds time at end of 2min */
  317.    char *response;                               /* pointer to modem response */
  318.    char *c;                                      /* miscellaneous pointer     */
  319.    int result = IGNORE;                          /* result code               */
  320.    int i;
  321.    int ring_count = 0;                           /* # of RINGING responses    */
  322.  
  323.    /* If this modem doesn't differentiate between RING and RINGING */
  324.    if (modemring)
  325.       mdm_resps[2].disp = IGNORE;
  326.  
  327.    end_time = timerset ((unsigned int) ths);     /* arm the timeout           */
  328.    while ((result == IGNORE)                     /* until success or failure, */
  329.           && (!timeup (end_time))                /* or out of time,           */
  330.           && (!KEYPRESS ()))                     /* or user gets impatient    */
  331.       {
  332.   /*
  333.    *  See if we've been through this code enough times to reach
  334.    *  the user-defined failure threshold. For this purpose,
  335.    *  we crudely assume that all IGNORE cases are rings.
  336.    *
  337.    *  Henry Clark and Ron Bemis get credit for this one.
  338.    */
  339.       if (ring_count++ >= ring_tries)
  340.          {
  341.          response = "NO ANSWER";
  342.          (void) fancy_str (response);
  343.          status_line ("#%s", response);
  344.          result = parse_response(response);
  345.          break;
  346.          }
  347.   /*
  348.    *  We're still here. So get the next modem response 
  349.    *  (or time out trying).
  350.    */
  351.       response = get_response (end_time);        /* get a response            */
  352.       result = parse_response (response);        /* parse, determine status   */
  353.       time_release ();
  354.       }
  355.  
  356.    if (result == CONNECTED)                      /* Got to be a CONNECT msg   */
  357.       {
  358.       if (strnicmp (response, "connect", 7) == 0)/* if this is a CONNECT,     */
  359.          {
  360.          c = skip_blanks (&response[7]);         /* get past the blanks       */
  361.          mdm_reliable[0] = '\0';                 /* Start with nothing        */
  362.  
  363.          if (*c == '\0')                         /* if nothing there,         */
  364.             {
  365.             baudrate = (unsigned int) 300;       /* say that it's 300 baud    */
  366.             }
  367.          else
  368.             {
  369.             baudrate = (unsigned int) atoi (c);  /* else do baudrate fallback */
  370.  
  371.             /* For 1200/75 split speed modems and "Connect 212" */
  372.  
  373.             if ((baudrate == 1275) || (baudrate == 7512)
  374.             ||  (baudrate == 75) || (baudrate == 212) || (baudrate == 12))
  375.                baudrate = 1200;
  376.  
  377.             /* For "Connect 103" */
  378.             if (baudrate == 103)
  379.                baudrate = 300;
  380.             }
  381.  
  382.             ARQ_lock = 0;
  383.  
  384.             while (isdigit (*c))                 /* Get past digits           */
  385.                ++c;
  386.             c = skip_blanks (c);                 /* Get rid of blanks         */
  387.             if (*c != '\0')                      /* We have "reliable" info.  */
  388.                {
  389.                (void) strcpy (mdm_reliable, c);  /* Copy in the info          */
  390.                can_Janus (mdm_reliable);         /* Set the flag for Janus    */
  391.                for (i = 0; i < ARQs; i++)
  392.                   {
  393.                   if ((strnicmp (mdm_reliable, ARQ[i], strlen(ARQ[i]))) == 0)
  394.                      {
  395.                      ARQ_lock = 1;
  396.                      break;
  397.                      }
  398.                   }
  399.                }
  400.  
  401.          if (baudrate)
  402.             (void) set_baud (baudrate, 1);              
  403.          }
  404.  
  405.       MNP_Filter ();
  406.       }
  407.  
  408.    return (result);                              /* timeout or failure or OK  */
  409. }
  410.  
  411. void mdm_cmd_string (char *mdm_cmd, int dospace)
  412. {
  413.    register char *c;
  414.    register int escaped = 0;
  415.  
  416.    if (mdm_cmd == NULL)                          /* defense from shit         */
  417.       return;
  418.  
  419.    for (c = mdm_cmd; *c; c++)
  420.       {
  421.       if (escaped)
  422.          {
  423.          SENDBYTE (*c);
  424.          escaped = 0;
  425.          continue;
  426.          }
  427.  
  428.       if (*c == '\\')
  429.          {
  430.          escaped = 1;
  431.          continue;
  432.          }
  433.       
  434.       if (!isspace (*c) || dospace)              /* don't output spaces       */
  435.          mdm_cmd_char (*c);                      /* output the next character */
  436.       }
  437. }
  438.  
  439. void empty_delay ()
  440. {
  441.    long t;
  442.  
  443.    t = timerset (500);
  444.    while ((!OUT_EMPTY ()) && (!timeup (t)))
  445.       time_release ();                           /* wait for output to finish */
  446.  
  447.    if (!OUT_EMPTY ())
  448.       {
  449.       MDM_DISABLE ();
  450.       (void) Cominit (port_ptr, buftmo);
  451.       program_baud ();
  452.       RAISE_DTR ();
  453.       CLEAR_OUTBOUND ();
  454.       CLEAR_INBOUND ();
  455.       if (un_attended && fullscreen)
  456.          {
  457.          sb_dirty ();
  458.          sb_show ();
  459.          }
  460.       }
  461. }
  462.  
  463. void mdm_cmd_char (int outchr)
  464. {
  465.    switch (outchr)
  466.       {
  467.       case '-':                                /* if it's a dash (phone no) */
  468.          return;                                 /* ignore it                 */
  469.  
  470.       case '|':                                /* if the CR character,      */
  471.          outchr = CR;                            /* substitute a real CR here */
  472.          break;
  473.  
  474.       case '.':                                 /* Substitute ',' for '.'    */
  475.          outchr = ',';                           /* for compatibility         */
  476.          break;
  477.  
  478.       case '~':                                /* if the "delay" character, */
  479.          empty_delay ();                         /* wait for buffer to clear, */
  480.          timer (10);                             /* then wait 1 second        */
  481.          return;                                 /* and return                */
  482.  
  483.       case '^':                                 /* Raise DTR                 */
  484.          empty_delay ();                         /* wait for buffer to clear, */
  485.          RAISE_DTR ();                              /* Turn on DTR               */
  486.          return;                                 /* and return                */
  487.  
  488.       case 'v':                                 /* Lower DTR         */
  489.          empty_delay ();                         /* wait for buffer to clear, */
  490.          LOWER_DTR ();                             /* Turn off DTR              */
  491.          return;                                 /* and return                */
  492.  
  493.       case '`':                                 /* Short delay         */
  494.          timer (1);                              /* short pause, .1 second    */
  495.          return;                                 /* and return                */
  496.  
  497.       default:
  498.          break;
  499.       }
  500.  
  501.    SENDBYTE ((unsigned char) outchr);            /* then write the character  */
  502.  
  503.    if (outchr == CR)                             /* if it was a CR,           */
  504.       {
  505.       empty_delay ();
  506.       timer (1);                                 /* allow .1 sec line quiet   */
  507.       }
  508.    else if (slowmodem)
  509.       {
  510.       timer (1);                                 /* wait .1 sec for output    */
  511.       }
  512. }
  513.  
  514. void mdm_hangup ()
  515. {
  516.  
  517.    /*
  518.     * First, if a dial command is in progress, try to get the modem to abort
  519.     * it... 
  520.     */
  521.  
  522.    CLEAR_OUTBOUND ();
  523.    CLEAR_INBOUND ();
  524.  
  525.    if (un_attended && fullscreen)
  526.       {
  527.       do_ready (MSG_TXT(M_READY_HANGUP));
  528.       }
  529.    else
  530.       {
  531.       status_line (MSG_TXT(M_MODEM_HANGUP));      /* Tell what we are doing    */
  532.       }
  533.  
  534.    mdm_init (modem_init);                        /* re-initialize the modem   */
  535.    timer (5);                                    /* Wait another .5 sec       */
  536.  
  537.    ARQ_lock = 0;                                 /* Re-init lockbaud          */
  538.  
  539.    set_xy ("");
  540.    CLEAR_INBOUND ();                             /* then flush input and exit */
  541. }
  542.  
  543. void mdm_init (char *str)
  544. {
  545.    set_prior(4);                                           /* Always High    */
  546.  
  547.    CLEAR_OUTBOUND ();
  548.    CLEAR_INBOUND ();
  549.    if (init_setup != NULL)
  550.       {
  551.       (void) set_baud (max_baud.rate_value, 0);
  552.       mdm_cmd_string (init_setup, 1);
  553.       }
  554.    else
  555.       {
  556.       mdm_cmd_char (CR);                            /* output a CR, then         */
  557.       LOWER_DTR ();                                   /* Drop DTR to hangup        */
  558.       timer (10);                                   /* Hold it down for 1 sec    */
  559.  
  560.       RAISE_DTR ();                                    /* Raise DTR,                */
  561.       timer (5);                                    /* Then hold it up for .5
  562.                                                   * sec */
  563.       (void) set_baud (max_baud.rate_value, 0);
  564.  
  565.       mdm_cmd_char (' ');                           /* output a space            */
  566.       mdm_cmd_char (CR);                            /* then another CR           */
  567.       }
  568.    mdm_cmd_string (str, 0);                      /* then the modem init
  569.                                                   * string */
  570.  
  571.    set_prior(2);                                           /* Regular        */
  572.  
  573.    timer (5);                                    /* Hold DTR for .5 sec more  */
  574.    CLEAR_INBOUND ();                             /* then flush input and exit */
  575. }
  576.  
  577. void send_break (int t)
  578. {
  579.    long t1;
  580.  
  581.    t1 = timerset ((unsigned int) t);
  582.    do_break (1);
  583.    while (!timeup (t1))
  584.       time_release ();
  585.    do_break (0);
  586. }
  587.  
  588. void exit_DTR ()
  589. {
  590.    if (!leave_dtr_high)
  591.       LOWER_DTR ();
  592. }
  593.  
  594. /*
  595.  * We get here right after the CONNECT message. It could happen
  596.  * so quickly that we don't even have DCD set. (On a 33MHz 386
  597.  * and a T2500, that happens!)
  598.  *
  599.  * So: this routine waits up to 1 second for a carrier.
  600.  *
  601.  * It then eats anything that looks like an MNP string, with 
  602.  * a total time allowed of 10 seconds (for streaming garbage)
  603.  * and maximum inter-character delay of 3 seconds.
  604.  */
  605.  
  606.  
  607. void MNP_Filter ()
  608. {
  609.    long t, t1;
  610.    int c;
  611.    int logged = 0;
  612.  
  613.    t = timerset (100);      /* at most a one second delay  */
  614.  
  615.    while (!CARRIER && !timeup (t))
  616.       ;
  617.  
  618.    t1 = timerset (1000);   /* 10 second drop dead timer    */
  619.    t = timerset (300);     /* at most a three second delay */
  620.  
  621.    while (CARRIER && !timeup (t))
  622.       {
  623.       if (got_ESC ())
  624.          {                                       /* Manual abort?        */
  625.          LOWER_DTR ();                             /* Yes, drop carrier    */
  626.          return;
  627.          }
  628.  
  629.       if (timeup (t1))
  630.          break;
  631.  
  632.       if ((c = PEEKBYTE ()) != -1)
  633.          {
  634.          (void) TIMED_READ(0);
  635.  
  636.          /* If we get an MNP or v.42 character, eat it and wait for clear line */
  637.          if ((c != 0) && ((strchr (BadChars, (c | 0x80)) != NULL) || (strchr (BadChars, (c & 0x7f)) != NULL)))
  638.             {
  639.             t = timerset (300);
  640.             if ((logged++) == 0)
  641.                status_line (MSG_TXT(M_FILTER));
  642.             }
  643.          }
  644.       }
  645. }
  646.  
  647.  
  648.