home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / tip / aculib / courier.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  8.3 KB  |  379 lines

  1. /*
  2.  * Copyright (c) 1986 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)courier.c    5.7 (Berkeley) 3/2/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * Routines for calling up on a Courier modem.
  40.  * Derived from Hayes driver.
  41.  */
  42. #include "tip.h"
  43. #include <stdio.h>
  44.  
  45. #define    MAXRETRY    5
  46.  
  47. static    void sigALRM();
  48. static    int timeout = 0;
  49. static    int connected = 0;
  50. static    jmp_buf timeoutbuf, intbuf;
  51. static    int coursync();
  52.  
  53. cour_dialer(num, acu)
  54.     register char *num;
  55.     char *acu;
  56. {
  57.     register char *cp;
  58. #ifdef ACULOG
  59.     char line[80];
  60. #endif
  61.     static int cour_connect(), cour_swallow();
  62.  
  63.     if (boolean(value(VERBOSE)))
  64.         printf("Using \"%s\"\n", acu);
  65.  
  66.     ioctl(FD, TIOCHPCL, 0);
  67.     /*
  68.      * Get in synch.
  69.      */
  70.     if (!coursync()) {
  71. badsynch:
  72.         printf("can't synchronize with courier\n");
  73. #ifdef ACULOG
  74.         logent(value(HOST), num, "courier", "can't synch up");
  75. #endif
  76.         return (0);
  77.     }
  78.     cour_write(FD, "AT E0\r", 6);    /* turn off echoing */
  79.     sleep(1);
  80. #ifdef DEBUG
  81.     if (boolean(value(VERBOSE)))
  82.         verbose_read();
  83. #endif
  84.     ioctl(FD, TIOCFLUSH, 0);    /* flush any clutter */
  85.     cour_write(FD, "AT C1 E0 H0 Q0 X6 V1\r", 21);
  86.     if (!cour_swallow("\r\nOK\r\n"))
  87.         goto badsynch;
  88.     fflush(stdout);
  89.     cour_write(FD, "AT D", 4);
  90.     for (cp = num; *cp; cp++)
  91.         if (*cp == '=')
  92.             *cp = ',';
  93.     cour_write(FD, num, strlen(num));
  94.     cour_write(FD, "\r", 1);
  95.     connected = cour_connect();
  96. #ifdef ACULOG
  97.     if (timeout) {
  98.         sprintf(line, "%d second dial timeout",
  99.             number(value(DIALTIMEOUT)));
  100.         logent(value(HOST), num, "cour", line);
  101.     }
  102. #endif
  103.     if (timeout)
  104.         cour_disconnect();
  105.     return (connected);
  106. }
  107.  
  108. cour_disconnect()
  109. {
  110.      /* first hang up the modem*/
  111.     ioctl(FD, TIOCCDTR, 0);
  112.     sleep(1);
  113.     ioctl(FD, TIOCSDTR, 0);
  114.     coursync();                /* reset */
  115.     close(FD);
  116. }
  117.  
  118. cour_abort()
  119. {
  120.     cour_write(FD, "\r", 1);    /* send anything to abort the call */
  121.     cour_disconnect();
  122. }
  123.  
  124. static void
  125. sigALRM()
  126. {
  127.     printf("\07timeout waiting for reply\n");
  128.     timeout = 1;
  129.     longjmp(timeoutbuf, 1);
  130. }
  131.  
  132. static int
  133. cour_swallow(match)
  134.   register char *match;
  135.   {
  136.     sig_t f;
  137.     char c;
  138.  
  139.     f = signal(SIGALRM, sigALRM);
  140.     timeout = 0;
  141.     do {
  142.         if (*match =='\0') {
  143.             signal(SIGALRM, f);
  144.             return (1);
  145.         }
  146.         if (setjmp(timeoutbuf)) {
  147.             signal(SIGALRM, f);
  148.             return (0);
  149.         }
  150.         alarm(number(value(DIALTIMEOUT)));
  151.         read(FD, &c, 1);
  152.         alarm(0);
  153.         c &= 0177;
  154. #ifdef DEBUG
  155.         if (boolean(value(VERBOSE)))
  156.             putchar(c);
  157. #endif
  158.     } while (c == *match++);
  159. #ifdef DEBUG
  160.     if (boolean(value(VERBOSE)))
  161.         fflush(stdout);
  162. #endif
  163.     signal(SIGALRM, SIG_DFL);
  164.     return (0);
  165. }
  166.  
  167. struct baud_msg {
  168.     char *msg;
  169.     int baud;
  170. } baud_msg[] = {
  171.     "",        B300,
  172.     " 1200",    B1200,
  173.     " 2400",    B2400,
  174.     0,        0,
  175. };
  176.  
  177. static int
  178. cour_connect()
  179. {
  180.     char c;
  181.     int nc, nl, n;
  182.     struct sgttyb sb;
  183.     char dialer_buf[64];
  184.     struct baud_msg *bm;
  185.     sig_t f;
  186.  
  187.     if (cour_swallow("\r\n") == 0)
  188.         return (0);
  189.     f = signal(SIGALRM, sigALRM);
  190. again:
  191.     nc = 0; nl = sizeof(dialer_buf)-1;
  192.     bzero(dialer_buf, sizeof(dialer_buf));
  193.     timeout = 0;
  194.     for (nc = 0, nl = sizeof(dialer_buf)-1 ; nl > 0 ; nc++, nl--) {
  195.         if (setjmp(timeoutbuf))
  196.             break;
  197.         alarm(number(value(DIALTIMEOUT)));
  198.         n = read(FD, &c, 1);
  199.         alarm(0);
  200.         if (n <= 0)
  201.             break;
  202.         c &= 0x7f;
  203.         if (c == '\r') {
  204.             if (cour_swallow("\n") == 0)
  205.                 break;
  206.             if (!dialer_buf[0])
  207.                 goto again;
  208.             if (strcmp(dialer_buf, "RINGING") == 0 &&
  209.                 boolean(value(VERBOSE))) {
  210. #ifdef DEBUG
  211.                 printf("%s\r\n", dialer_buf);
  212. #endif
  213.                 goto again;
  214.             }
  215.             if (strncmp(dialer_buf, "CONNECT",
  216.                     sizeof("CONNECT")-1) != 0)
  217.                 break;
  218.             for (bm = baud_msg ; bm ; bm++)
  219.                 if (strcmp(bm->msg,
  220.                     dialer_buf+sizeof("CONNECT")-1) == 0) {
  221.                     if (ioctl(FD, TIOCGETP, &sb) < 0) {
  222.                         perror("TIOCGETP");
  223.                         goto error;
  224.                     }
  225.                     sb.sg_ispeed = sb.sg_ospeed = bm->baud;
  226.                     if (ioctl(FD, TIOCSETP, &sb) < 0) {
  227.                         perror("TIOCSETP");
  228.                         goto error;
  229.                     }
  230.                     signal(SIGALRM, f);
  231. #ifdef DEBUG
  232.                     if (boolean(value(VERBOSE)))
  233.                         printf("%s\r\n", dialer_buf);
  234. #endif
  235.                     return (1);
  236.                 }
  237.             break;
  238.         }
  239.         dialer_buf[nc] = c;
  240. #ifdef notdef
  241.         if (boolean(value(VERBOSE)))
  242.             putchar(c);
  243. #endif
  244.     }
  245. error1:
  246.     printf("%s\r\n", dialer_buf);
  247. error:
  248.     signal(SIGALRM, f);
  249.     return (0);
  250. }
  251.  
  252. /*
  253.  * This convoluted piece of code attempts to get
  254.  * the courier in sync.
  255.  */
  256. static int
  257. coursync()
  258. {
  259.     int already = 0;
  260.     int len;
  261.     char buf[40];
  262.  
  263.     while (already++ < MAXRETRY) {
  264.         ioctl(FD, TIOCFLUSH, 0);    /* flush any clutter */
  265.         cour_write(FD, "\rAT Z\r", 6);    /* reset modem */
  266.         bzero(buf, sizeof(buf));
  267.         sleep(1);
  268.         ioctl(FD, FIONREAD, &len);
  269.         if (len) {
  270.             len = read(FD, buf, sizeof(buf));
  271. #ifdef DEBUG
  272.             buf[len] = '\0';
  273.             printf("coursync: (\"%s\")\n\r", buf);
  274. #endif
  275.             if (index(buf, '0') || 
  276.                   (index(buf, 'O') && index(buf, 'K')))
  277.                 return(1);
  278.         }
  279.         /*
  280.          * If not strapped for DTR control,
  281.          * try to get command mode.
  282.          */
  283.         sleep(1);
  284.         cour_write(FD, "+++", 3);
  285.         sleep(1);
  286.         /*
  287.          * Toggle DTR to force anyone off that might have left
  288.          * the modem connected.
  289.          */
  290.         ioctl(FD, TIOCCDTR, 0);
  291.         sleep(1);
  292.         ioctl(FD, TIOCSDTR, 0);
  293.     }
  294.     cour_write(FD, "\rAT Z\r", 6);
  295.     return (0);
  296. }
  297.  
  298. cour_write(fd, cp, n)
  299. int fd;
  300. char *cp;
  301. int n;
  302. {
  303.     struct sgttyb sb;
  304. #ifdef notdef
  305.     if (boolean(value(VERBOSE)))
  306.         write(1, cp, n);
  307. #endif
  308.     ioctl(fd, TIOCGETP, &sb);
  309.     ioctl(fd, TIOCSETP, &sb);
  310.     cour_nap();
  311.     for ( ; n-- ; cp++) {
  312.         write(fd, cp, 1);
  313.         ioctl(fd, TIOCGETP, &sb);
  314.         ioctl(fd, TIOCSETP, &sb);
  315.         cour_nap();
  316.     }
  317. }
  318.  
  319. #ifdef DEBUG
  320. verbose_read()
  321. {
  322.     int n = 0;
  323.     char buf[BUFSIZ];
  324.  
  325.     if (ioctl(FD, FIONREAD, &n) < 0)
  326.         return;
  327.     if (n <= 0)
  328.         return;
  329.     if (read(FD, buf, n) != n)
  330.         return;
  331.     write(1, buf, n);
  332. }
  333. #endif
  334.  
  335. /*
  336.  * Code stolen from /usr/src/lib/libc/gen/sleep.c
  337.  */
  338. #define mask(s) (1<<((s)-1))
  339. #define setvec(vec, a) \
  340.         vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
  341.  
  342. static napms = 50; /* Give the courier 50 milliseconds between characters */
  343.  
  344. static int ringring;
  345.  
  346. cour_nap()
  347. {
  348.     
  349.         static void cour_napx();
  350.     int omask;
  351.         struct itimerval itv, oitv;
  352.         register struct itimerval *itp = &itv;
  353.         struct sigvec vec, ovec;
  354.  
  355.         timerclear(&itp->it_interval);
  356.         timerclear(&itp->it_value);
  357.         if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
  358.                 return;
  359.         setvec(ovec, SIG_DFL);
  360.         omask = sigblock(mask(SIGALRM));
  361.         itp->it_value.tv_sec = napms/1000;
  362.     itp->it_value.tv_usec = ((napms%1000)*1000);
  363.         setvec(vec, cour_napx);
  364.         ringring = 0;
  365.         (void) sigvec(SIGALRM, &vec, &ovec);
  366.         (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
  367.         while (!ringring)
  368.                 sigpause(omask &~ mask(SIGALRM));
  369.         (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
  370.         (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
  371.     (void) sigsetmask(omask);
  372. }
  373.  
  374. static void
  375. cour_napx()
  376. {
  377.         ringring = 1;
  378. }
  379.