home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / UUCP_Blars.lzh / dial.c < prev    next >
C/C++ Source or Header  |  1991-03-09  |  15KB  |  680 lines

  1. /*
  2.  *    @(#) dialHA12.c 1.5 86/12/18 
  3.  *
  4.  *  Copyright (C) The Santa Cruz Operation, Inc. 1986
  5.  *
  6.  *  Function:    dialer program for the Hayes Smartmodem 1200/1200b
  7.  *
  8.  *  Usage:    dial ttyname telnumber speed 
  9.  *        dial -h ttyname speed
  10.  *
  11.  *  Returns:    0x80    bit = 1 if connection failed
  12.  *        0x10    bit = 1 if line is also used for dialin
  13.  *        0x0f    if msb=1: error code
  14.  *            if msb=0: connected baud rate (0=same as dialed baud)
  15.  *
  16.  *        Note: cu and uucp only call the dialer with -h when they are
  17.  *        done if the return code from the first dialer call has the
  18.  *        0x10 bit set.
  19.  *
  20.  *        Error codes are split into two catagories: 1) (codes 0-11)
  21.  *        Local problems are defined as tty port, or modem problems:
  22.  *        problems that can be worked around by using a different device.
  23.  *        2) (codes 12-15) Remote problems are phone busy, no answer, etc.
  24.  *        : attempts to connect to this remote system should be stopped.
  25.  *
  26.  *  Documents:    Smartmodem 1200/1200b manual
  27.  *
  28.  *  Recommended switch settings for the Hayes Smartmodem 1200
  29.  *
  30.  *        1   2   3   4   5   6   7   8
  31.  *        up  up down up  up  up  up down
  32.  */
  33.  
  34. #include <stdio.h>
  35. #include <signal.h>
  36. #include <fcntl.h>
  37. #include <sys/types.h>
  38. #include <sys/ioctl.h>
  39. #include <termio.h>
  40. #include <pwd.h>
  41. #include <errno.h>
  42.  
  43. static char Sccsid[] = "@(#) dialHA12.c 1.5 86/12/18 ";
  44.  
  45. /* return codes: these are set up so that an abort signal at any time can */
  46. /* set the fail bit and return to the caller with the correct status */
  47. #define    RC_BAUD        0x0f    /* CBAUD connected at (0=same as dialed speed)*/
  48. #define    RC_ENABLED    0x10    /* enabled flag: 1 = ungetty -r required to */
  49.                 /* restore the line */
  50. #define    RC_FAIL        0x80    /* 1 = failed to connect */
  51.  
  52. /* return code error codes */
  53. #define    RCE_NULL    0    /* general purpose or unknown error code */
  54. #define    RCE_INUSE    1    /* line in use */
  55. #define    RCE_SIG        2    /* signal aborted dialer */
  56. #define    RCE_ARGS    3    /* invalid arguments */
  57. #define    RCE_PHNO    4    /* invalid phone number */
  58. #define    RCE_SPEED    5    /* invalid baud rate -or- bad connect baud */
  59. #define    RCE_OPEN    6    /* can't open line */
  60. #define    RCE_IOCTL    7    /* ioctl error */
  61. #define    RCE_TIMOUT    8    /* timeout */
  62. #define    RCE_NOTONE    9    /* no dial tone */
  63. #define    RCE_BUSY    13    /* phone is busy */
  64. #define    RCE_NOCARR    14    /* no carrier */
  65. #define    RCE_ANSWER    15    /* no answer */
  66.  
  67. #define    SUCCESS    0
  68.  
  69. /* ungetty return codes */
  70. #define    UG_NOTENAB    0
  71. #define    UG_ENAB        1
  72. #define    UG_RESTART    1
  73. #define    UG_FAIL        2
  74.  
  75. #define SAME        0
  76. #define MAXLINE        80
  77. #define    UNGETTY        "/usr/lib/uucp/ungetty"
  78.  
  79. #define DEBUG(l, f, s)    if (Debug >= l) fprintf(stderr, f, s)
  80. #ifndef    DBG
  81. #define    DBG    0
  82. #endif
  83.  
  84. /*
  85.  *  MDSETUP - No echo, enable result codes, tone dial, set escape to +++.
  86.  */
  87. #define    MDSETUP        "ATX3E0V1S2=043\r"
  88.  
  89. /*
  90.  *  MDVALID - Allow only these characters to reach the modem.
  91.  */
  92. #define MDVALID        "0123456789TPW/,*#()-"
  93.  
  94. /*
  95.  *  MDESCAPE - Takes modem out of online state to accept commands.
  96.  */
  97. #define    MDESCAPE    "+++"
  98.  
  99. /*
  100.  *  MDHANGUP - Force modem to drop carrier.
  101.  */
  102. #define    MDHANGUP    "ATH\r"
  103.  
  104. /*
  105.  *  MDRESET - Reset modem to default power-up state.
  106.  */
  107. #define    MDRESET        "ATQ0Z\r" 
  108.  
  109. /*
  110.  *  MDDIALIN - Setup modem for dial in
  111.  */
  112. #define    MDDIALIN    "ATS0=1Q1\r"
  113.  
  114. /*
  115.  *  MDDSBLESC - Disable escape sequence
  116.  */
  117. #define    MDDSBLESC    "ATS2=128\r"
  118.  
  119. /*
  120.  *  These defines are used to determine how long the dialer timeout
  121.  *  should be.  MDPULSDLY can be changed, but MDPAUSDLY requires
  122.  *  reprogramming modem register S8 to be effective.
  123.  */
  124. #define    MDPULSCHR    'P'
  125. #define    MDPULSDLY    15
  126.  
  127. #define    MDPAUSCHR    ','
  128. #define    MDPAUSDLY    2
  129.  
  130. #define    DIAL_RETRY    4
  131. /*
  132.  *  Possible messages produced by modem.
  133.  *  We ignore RING since the HAYES only produces it when answering.
  134.  */
  135. #define    OK        0
  136. #define    NOCARRIER    1
  137. #define    ERROR        2
  138. #define    BUSY        3
  139. #define    NOANSWER    4
  140. #define    NODIALTONE    5
  141. #define    CONNECT1200    6
  142. #define    CONNECT        7
  143.  
  144. char *mdmsgs[] = {
  145. /* 0 */    "OK",
  146. /* 1 */    "NO CARRIER",
  147. /* 2 */    "ERROR",
  148. /* 3 */ "BUSY",
  149. /* 4 */ "NO ANSWER",
  150. /* 5 */ "NO DIALTONE",
  151. /* 6 */ "CONNECT 1200",
  152. /* 7 */    "CONNECT",
  153.     0
  154. };
  155.  
  156. char *strchr();
  157. int alrmint();
  158. struct termio term;
  159. int Debug = DBG;            /* set when debug flag is given    */
  160. int dialing;                /* set while modem is dialing    */
  161. int fd = -1;                /* file descriptor for acu    */
  162. int retcode = RC_FAIL;            /* return code            */
  163. char User[10] = "unknown";        /* user id for logfile entries    */
  164. char Rmtname[] = "unknown";        /* remote system for logfile    */
  165.  
  166.  
  167. abort(sig)
  168. int sig;
  169. {
  170.     signal(SIGINT, SIG_IGN);
  171.     if (fd != -1) {
  172.         ioctl(fd, TCGETA, &term);
  173.         term.c_cflag |= HUPCL;        /* make sure modem hangs up */
  174.         ioctl(fd, TCSETA, &term);
  175.         close(fd);
  176.     }
  177.     if (sig)  retcode |= (RC_FAIL | RCE_SIG);
  178.     exit(retcode);
  179. }
  180.  
  181.  
  182. main(argc,argv)
  183.     int argc;
  184.     char *argv[];
  185. {
  186.     char *acu;            /* device to dial through    */
  187.     char *phone;            /* phone number to dial        */
  188.     char command[MAXLINE];        /* modem command buffer        */
  189.     int errflag = 0;        /* set on errors        */
  190.     int hflag = 0;            /* set to hangup modem        */
  191.     int timeout;            /* how long to wait for alarm    */
  192.     int dial_retry = DIAL_RETRY;    /* dial retry count        */
  193.     int highbaud, lowbaud;        /* baud rate limits        */
  194.     extern int optind;
  195.     extern char *optarg;
  196.     int c, pid;
  197.     char *p;
  198.     struct passwd *pwd, *getpwuid();
  199.  
  200.     /*
  201.      *  Reenable all those signals we want to know about
  202.      */
  203.  
  204.     signal(SIGILL, SIG_DFL);
  205.     signal(SIGIOT, SIG_DFL);
  206.     signal(SIGEMT, SIG_DFL);
  207.     signal(SIGFPE, SIG_DFL);
  208.     signal(SIGBUS, SIG_DFL);
  209.     signal(SIGSEGV, SIG_DFL);
  210.     signal(SIGSYS, SIG_DFL);
  211.     signal(SIGTERM, SIG_DFL);
  212.  
  213.     while ((c = getopt(argc, argv, "hx:")) != EOF)
  214.         switch(c) {
  215.             case 'h':
  216.                 hflag++;
  217.                 break;
  218.             case 'x':
  219.                 Debug = atoi(optarg);
  220.                 break;
  221.             case '?':
  222.                 errflag++;
  223.                 break;
  224.         }
  225.  
  226.     if (Debug) {
  227.         fprintf(stderr, "dialer args ");
  228.         for (c=0; c<argc; c++)  fprintf(stderr, ":%s", argv[c]);
  229.         fprintf(stderr, "\n");
  230.     }
  231.  
  232.     if (hflag) {
  233.         if (argc - optind != 2)  errflag++ ;
  234.     } else {
  235.         if (argc - optind != 3)  errflag++ ;
  236.     }
  237.  
  238.     if (errflag) {
  239.         if (hflag)
  240.             fprintf(stderr,"Usage: %s -h devicename speed\n",
  241.                                 argv[0]);
  242.         else
  243.             fprintf(stderr,"Usage: %s devicename number speed\n",
  244.                                 argv[0]);
  245.         exit(RC_FAIL | RCE_ARGS);
  246.     }
  247.  
  248.     acu = argv[optind++];
  249.  
  250.     if (!hflag) {
  251.         phone = argv[optind++];
  252.         if (strlen(phone) != strspn(phone, MDVALID)) {
  253.             fprintf(stderr, "dial: Bad phone number %s\n", phone);
  254.             exit(RC_FAIL | RCE_PHNO);
  255.         }
  256.     }
  257.  
  258.     lowbaud = highbaud = checkbaud(atoi(argv[optind]));
  259.  
  260.     /* test for a range of baudrates */
  261.  
  262.     if ((p = strchr(argv[optind], '-')) != NULL) {
  263.         *p++ = '\0';
  264.         highbaud = checkbaud(atoi(p));
  265.     }
  266.  
  267.     if (!hflag) {
  268.         if ((pid = fork()) == 0) {
  269.             DEBUG(6, "dialer: %s called\n", UNGETTY);
  270.             execl(UNGETTY, "ungetty", acu, NULL);
  271.             fprintf(stderr, "ungetty exec error\n");
  272.             exit(-1);
  273.         }
  274.         while (((c = wait(&errflag)) != pid) && c != -1);
  275.         switch ((errflag>>8) & 0xff) {
  276.         case UG_NOTENAB:    /* line acquired: not enabled */
  277.             retcode = SUCCESS;
  278.             break;
  279.         case UG_ENAB:    /* line acquired: need ungetty -r when done */
  280.             retcode = RC_ENABLED;
  281.             break;
  282.         case UG_FAIL:        /* could not acquire line */
  283.             exit(RC_FAIL | RCE_INUSE);
  284.         case 255:
  285.             exit(RC_FAIL);
  286.         }
  287.     }
  288.  
  289.     /*
  290.      *  Must open with O_NDELAY set or the open may hang.
  291.      */
  292.     if ((fd = open(acu, O_RDWR | O_NDELAY)) < 0) {
  293.         fprintf(stderr, "dial: Can't open device: %s\n", acu);
  294.         exit(RC_FAIL | RCE_OPEN | retcode);
  295.     }
  296.     /*
  297.      * set line for no echo and correct speed.
  298.      * We will issue commands to the Hayes 1200 at the highest possible
  299.      * baud rate to encourage connection at the highest baud rate.
  300.      * If hanging up, issue commands at 1200 to enable auto answer
  301.      * at 1200.
  302.      */
  303.     signal(SIGINT, abort);
  304.     errflag = ioctl(fd, TCGETA, &term);
  305.     term.c_cflag &= ~(CBAUD | HUPCL);
  306.     term.c_cflag |= CLOCAL | (hflag ? (B1200|HUPCL) : highbaud);
  307.     term.c_lflag &= ~ECHO;
  308.     term.c_cc[VMIN] = '\1';
  309.     term.c_cc[VTIME] = '\0';
  310.     errflag = ioctl(fd, TCSETA, &term);
  311.     if (errflag) {
  312.         char buf[16];
  313.         DEBUG(1, "dial: ioctl error on %s", acu);
  314.         DEBUG(1, " errno=%d\n", errno);
  315.         cleanup(RC_FAIL | RCE_IOCTL | retcode);
  316.     }
  317.     /*
  318.      *  Reopen line with clocal so we can talk without carrier present
  319.      */
  320.     c = fd;
  321.     if ((fd = open(acu, O_RDWR)) < 0) {
  322.         fprintf(stderr, "dial: Can't open device local: %s\n", acu);
  323.         exit(RC_FAIL | RCE_OPEN | retcode);
  324.     }
  325.     close(c);
  326.  
  327.     /*
  328.      *  Timeout after 10 seconds if no response
  329.      */
  330.     timeout = 10;
  331.     signal(SIGALRM, alrmint);
  332.  
  333.     /*
  334.      * Hangup and exit if requested
  335.      */
  336.     if (hflag) {
  337.         hangup(timeout);
  338.         mdwrite(MDDSBLESC);        /* disable escape */
  339.  
  340.         /* call ungetty to see if we need to switch to dialin */
  341.  
  342.         if ((pid = fork()) == 0) {
  343.             execl(UNGETTY, "ungetty", "-t", acu, NULL);
  344.             exit(-1);
  345.         }
  346.         while (((c = wait(&errflag)) != pid) && c != -1) ;
  347.         if (((errflag>>8) & 0xff) != UG_RESTART)  cleanup(SUCCESS);
  348.  
  349.         /* setup modem for dialin */
  350.         /* note: mdwrite(MDDIALIN) will never work because */
  351.         /* the last modem command disables "OK" */
  352.         mdwrite(MDDIALIN);    /* return to dial in mode */
  353.         if ((pid = fork()) == 0) {
  354.             execl(UNGETTY, "ungetty", "-r", acu, NULL);
  355.             exit(-1);
  356.         }
  357.         while (((c = wait(&errflag)) != pid) && c != -1) ;
  358.         cleanup( ((errflag>>8) & 0xff) ? RC_FAIL : SUCCESS ) ;
  359.     }
  360.  
  361.     /*
  362.      *  Reset and put modem into command mode
  363.      */
  364. reset:
  365.     if (mdwrite(MDRESET) == -1)
  366.         cleanup(RC_FAIL | retcode);
  367.     if (mdread(timeout) != OK) {
  368.         if (hangup(timeout) == -1)
  369.             cleanup(RC_FAIL | retcode);
  370.         goto reset;
  371.     }
  372.  
  373.     /*
  374.      *  Must wait at least 0.5 seconds after reset
  375.      *  for HAYES to recover and receive commands.
  376.      */
  377.     sleep(1);
  378.  
  379.     /*
  380.      *  Initialize the modem
  381.      */
  382.     if (mdwrite(MDSETUP) == -1)
  383.         cleanup(RC_FAIL | retcode);
  384.     if (mdread(timeout) != OK) {
  385.         if (hangup(timeout) == -1)
  386.             cleanup(RC_FAIL | retcode);
  387.         goto reset;
  388.     }
  389.  
  390.     /*
  391.      *  Build up the phone number
  392.      */
  393.     sprintf(command, "ATD%s\r", phone);
  394.  
  395.     /*
  396.      *  Set up a timeout for the connect.
  397.      *    Add in MDPAUSDLY seconds more for each pause character
  398.      *    Pulse dialing takes MDPULSDLY seconds longer too
  399.      */
  400.     timeout = 6 * strlen(phone) + 15;
  401.     for (p = phone; (p = strchr(p, MDPAUSCHR)) != NULL; p++)
  402.         timeout += MDPAUSDLY;
  403.     if (strchr(phone, MDPULSCHR) != NULL)
  404.         timeout += MDPULSDLY;
  405.     if (timeout < 30)
  406.         timeout = 30;
  407.  
  408.     /* command string can only be 40 characters excluding "AT" */
  409.     if (strlen(command) > 42)
  410.         cleanup(RC_FAIL | RCE_PHNO | retcode);
  411.  
  412. redial:
  413.     if (mdwrite(command) == -1)
  414.         cleanup(RC_FAIL | retcode);
  415.  
  416.     dialing = 1;
  417.     DEBUG(6, "wait for connect - timeout %d\n", timeout);
  418.  
  419.     switch (mdread(timeout)) {
  420.         case OK:
  421.         case ERROR:
  422.             if (dial_retry--) goto redial;
  423.             cleanup(RC_FAIL | RCE_NULL | retcode);
  424.         case CONNECT:
  425.             cleanup(retcode);
  426.         case CONNECT1200:
  427.             c = matchbaud(B1200, lowbaud, highbaud);
  428.             cleanup(retcode | c);
  429.         case NOANSWER:
  430.             cleanup(RC_FAIL | RCE_ANSWER | retcode);
  431.         case NODIALTONE:
  432.             cleanup(RC_FAIL | RCE_NOTONE | retcode);
  433.         case NOCARRIER:
  434.             cleanup(RC_FAIL | RCE_NOCARR | retcode);
  435.         case BUSY:
  436.             cleanup(RC_FAIL | RCE_BUSY | retcode);
  437.         default:
  438.             cleanup(RC_FAIL | retcode);
  439.     }
  440. }
  441.  
  442.  
  443. /*
  444.  *  hangup(htime)
  445.  *
  446.  *  Function:    Forces the modem to drop carrier and hang up the phone.
  447.  *        Reads are allowed htime seconds before timeout.
  448.  *
  449.  *  Returns:    0 if disconnect completed.
  450.  *        -1 on failure, phone may still be connected.
  451.  *
  452.  */
  453. nil() {}
  454.  
  455. hangup(htime)
  456.     int htime;
  457. {
  458.     int retry = 4, rcode;
  459.     int (*s)();
  460.  
  461.     DEBUG(4, "hangup - timeout %d\n", htime);
  462.     sleep(1);
  463.     rcode = -1;
  464.     s = signal(SIGALRM, nil);    /* alarms are non-fatal here */
  465.     while (retry--  &&  rcode == -1) {
  466.         if (mdwrite(MDESCAPE) == -1)
  467.             return(-1);
  468.         sleep(1);
  469.         /*
  470.          * MDESCAPE will return OK only if online, so ignore error return
  471.          */
  472.         mdflush() ;        /* waste "OK" if we were on line */
  473.         if (mdwrite(MDHANGUP) == -1)
  474.             return(-1);
  475.         if (mdread(htime) == OK)
  476.             rcode = 0;
  477.     }
  478.     signal(SIGALRM, s);
  479.     return(-1);
  480. }
  481.     
  482. /*
  483.  *  mdread(rtime)
  484.  *
  485.  *  Function:    Reads from the ACU until it finds a valid response (found
  486.  *        in mdmsgs) or times out after rtime seconds.
  487.  *
  488.  *  Returns:    The index in mdmsgs of the modem response found.
  489.  *        -1 on timeout.
  490.  *
  491.  */
  492. mdread(rtime)
  493.     int rtime;
  494. {
  495.     char c, **mp;
  496.     register char *bp;
  497.     char buf[MAXLINE];
  498.  
  499.     bp = buf;
  500.     alarm(rtime);
  501.     DEBUG(6, "MODEM returned %s", "<<");
  502.     while (read(fd, &c, 1) == 1) {
  503.         if ((*bp = c) != '\0')
  504.             *++bp = '\0';
  505.         DEBUG(6, (c >= 040 ? "%c" : "^%c"), (c >= 040 ? c : c+0100));
  506.         if (bp >= buf + MAXLINE) {
  507.             alarm(0);
  508.             DEBUG(4,">>-%s\n","FAIL");
  509.             return(-1);
  510.         }
  511.         if (c == '\r')
  512.             for (mp = mdmsgs; *mp; ++mp)
  513.                 if (substr(*mp, buf) == 0) {
  514.                     alarm(0);
  515.                     DEBUG(6,">>-%s\n", "OK");
  516.                     DEBUG(4,"got %s\n",mdmsgs[mp - mdmsgs]);
  517.                     return(mp - mdmsgs);
  518.                 }
  519.     }
  520.     alarm(0);
  521.     DEBUG(6,">>-%s","FAIL");
  522.     DEBUG(4, " no responce\n", 0);
  523.     return(-1);
  524. }
  525.  
  526.  
  527. /*  mdflush()
  528.  *
  529.  *  Function:    Flushes input clists for modem
  530.  */
  531. mdflush()
  532. {
  533.     ioctl(fd, TCFLSH, 0) ;
  534. }
  535.  
  536.  
  537. /*
  538.  *  mdwrite(c)
  539.  *
  540.  *  Function:    Outputs the string pointed to by c to the ACU device.
  541.  *
  542.  *  Returns:    0 on completion.
  543.  *        -1 on write errors.
  544.  *
  545.  */
  546. mdwrite(c)
  547.     register char *c;
  548. {
  549.     int err;
  550.     /*
  551.      *  Give modem a chance to recover before writing.
  552.      */
  553.     sleep(1);
  554.     DEBUG(6, "Sent MODEM %s", "<<");
  555.     while (*c) {
  556.         if ((err = write(fd, c, 1)) != 1) {
  557.             char buf[16];
  558.             DEBUG(6, ">>-%s\n", "FAIL");
  559.             DEBUG(1, "ACU write error (errno=%d)\n", errno);
  560.             return(-1);
  561.         }
  562.         DEBUG(6, (*c >= 040 ? "%c" : "^%c"),(*c >= 040 ? *c : *c+0100));
  563.         c++;
  564.     }
  565.     DEBUG(6, ">>-%s\n", "OK");
  566.     return(0);
  567. }
  568.  
  569.  
  570. /*
  571.  *  substr(s, l)
  572.  *
  573.  *  Function:    Checks for the presence of the string pointed to by s
  574.  *        somewhere within the string pointed to by l.
  575.  *
  576.  *  Returns:    0 if found.
  577.  *        -1 if not found.
  578.  */
  579. substr(s, l)
  580.     char *s;
  581.     register char *l;
  582. {
  583.     int len;
  584.  
  585.     len = strlen(s);
  586.     while ((l = strchr(l, *s)) != NULL) {
  587.         if (strncmp(s, l, len) == SAME)
  588.             return(0);
  589.         l++;
  590.     }
  591.     return(-1);
  592. }
  593.  
  594.  
  595. /*
  596.  *  alrmint()
  597.  *
  598.  *  Function:    Catches alarm calls (signal 14) and exits.
  599.  *
  600.  *  Returns:    No return.  Exits with status RC_FAIL.
  601.  */
  602. alrmint()
  603. {
  604.     DEBUG(4, "\nTimeout waiting for %s\n", dialing ? "carrier" : "acu");
  605.     cleanup(RC_FAIL | RCE_TIMOUT | retcode);
  606. }
  607.  
  608.  
  609. /*
  610.  *  cleanup(stat)
  611.  *
  612.  *  Function:    Closes device file and exits.
  613.  *
  614.  *  Returns:    No return.  Exits with status stat.
  615.  */
  616. cleanup(stat)
  617.     int stat;
  618. {
  619.     if (stat & RC_FAIL) {    /* if we failed, drop DTR (in abort) */
  620.         retcode = stat;
  621.         abort(0);
  622.     } else {        /* else, return */
  623.         exit(stat);
  624.     }
  625. }
  626.  
  627.  
  628. /*
  629.  *  checkbaud(n)
  630.  *
  631.  *  Function:    Check for valid baud rates
  632.  *
  633.  *  Returns:    The baud rate in struct termio c_cflag fashion
  634.  *
  635.  */
  636.  
  637. checkbaud(n)
  638. int n;
  639. {
  640.     int baudrate;
  641.  
  642.     switch(n) {
  643.         case 300:
  644.             baudrate = B300;
  645.             break;
  646.         case 1200:
  647.             baudrate = B1200;
  648.             break;
  649.         default:
  650.             fprintf(stderr, "dial: Bad speed: %d\n", n);
  651.             exit(RC_FAIL | RCE_SPEED);
  652.     }        
  653.     return(baudrate);
  654. }
  655.  
  656. /*
  657.  *  matchbaud(connect, high, low)
  658.  *
  659.  *  Function:    determine dialer return code based on connect, high, and low
  660.  *        baud rates
  661.  *
  662.  *  Returns:    0        if connected baud == high baud
  663.  *        Bxxxx        if low baud <= connected baud <= high baud
  664.  *        RCE_NOCARR    if connected baud rate is out of range
  665.  *                (actually, bad carrier not 'no carrier'
  666.  *                 but its a remote problem so RCE_SPEED
  667.  *                 is clearly wrong)
  668.  */
  669.  
  670. matchbaud(cbaud, low, high)
  671. int cbaud, low, high;
  672. {
  673.  
  674.     if (cbaud == high)  return(0);          /* uucp/cu assume highest baud */
  675.     if (low <= cbaud  &&  cbaud <= high)  return(cbaud);
  676.     return(RC_FAIL | RCE_SPEED);
  677. }
  678.  
  679.  
  680.