home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume15 / ultrix-modem / io.c next >
C/C++ Source or Header  |  1988-05-24  |  5KB  |  177 lines

  1. /*
  2.  * Copyright (c) Dave Settle, March 1987
  3.  * Permission is granted to do anything with this program, except remove
  4.  * this copyright notice, or sell it for profit.
  5.  *
  6.  *
  7.  * io.c: routines to talk to the device directly.
  8.  *
  9.  * dread and dwrite act like read(2) and write(2), execpt that they always
  10.  * either succeed or exit, so the caller doesn't have to check.
  11.  *
  12.  * hangup drops the DTR line to the modem, so that it will (hopefully) hang up
  13.  * the phone line. It keeps it this way for 5 seconds.
  14.  *
  15.  * findspeed takes an ascii speed, and returns the corresponing baud rate.
  16.  *
  17.  * uuexit is a dodgy routine to make UUCP happy.
  18.  */
  19.  
  20. #include <sys/errno.h>
  21. #include <termio.h>
  22. #include <fcntl.h>
  23.  
  24. #include "modem.h"
  25.  
  26. char *sys_errlist[];        /* error list        */
  27. #define RETRY 5            /* retry failed writes    */
  28. /*
  29.  * dwrite: write some characters to the modem. 
  30.  * If your modem likes characters to be written s-l-o-w-l-y, define 'SLOW'    
  31.  */
  32. dwrite(f, s, n)
  33. int f;
  34. unsigned n;
  35. char *s;
  36. {
  37.     struct termio termio;
  38.     int r, retry = 0, i = 0;
  39.     static int error = 0;        /* error occurred on last call */
  40.     while((i < n) && (retry < RETRY)) {
  41.         if(locked()) uuexit(0);
  42.         errno = 0;
  43.         if(r = write(f, s + i, 1) == 1) i++;    /* Success! */
  44.         else {
  45.             retry++;
  46.             fixline();
  47.         }
  48. #ifdef SLOW
  49.         sleep(1);        /* Let the modem deal with it */
  50. #endif
  51.     }
  52.     if(i != n) {
  53.         ioctl(dev, TCGETA, &termio);
  54.         printf("Tried %d times, still got %d/%d written. [error = %s]\n", 
  55.             retry, i, n, sys_errlist[errno]);
  56.         printf("FAIL: dev %d, iflag %x, oflag %x, cflag %x, lflag %x, line %d\n",
  57.             dev, termio.c_iflag,termio.c_oflag,termio.c_cflag,
  58.             termio.c_lflag, termio.c_line);
  59.         error = 1;
  60.     }
  61.     else if(retry > 1) printf("Write problem: fixed on retry %d\n", retry - 1);
  62.     if(error && i == n) {
  63.         ioctl(dev, TCGETA, &termio);
  64.         printf("OK: iflag %x, oflag %x, cflag %x, lflag %x, line %d\n",
  65.             termio.c_iflag,termio.c_oflag,termio.c_cflag,
  66.             termio.c_lflag, termio.c_line);
  67.     }
  68.     if(i == n) error = 0;
  69.     return(r);
  70. }
  71. /*
  72.  * read one character at a time, checking before (and after) each read for
  73.  * a lock file. If one exists, then exit.
  74.  */
  75. dread(f, s, n)
  76. int f, n;
  77. char *s;
  78. {
  79.     int i, w;
  80.     for(i=0;i<n;i++, s++) {
  81.         if(locked()) uuexit(0);
  82.         while((w = read(f, s, 1)) < 1) {
  83.             if(locked()) uuexit(0);
  84.             if(w == -1) switch(errno) {
  85.             case EINTR:
  86.                 break;
  87.             default:
  88.                 perror("dread");
  89.             }
  90.         }
  91.     }        
  92. }
  93. /*
  94.  * hangup(): hangup the phone, and close the device.
  95.  * I've had problems with indefinate echoes from the modem when a connection
  96.  * has closed - my modem transmits crap. This ought to hangup the phone and
  97.  * prevent this.
  98.  *
  99.  * Oct 87: This problem should now be fixed, with the introduction of the
  100.  * DCD control from the modem - we should now receive a hangup signal when
  101.  * the line drops.
  102.  */
  103. hangup(device) {
  104.     struct termio term;
  105.     if(ioctl(device, TCGETA, &term) == -1) perror("hangup: TCGETA");
  106.     term.c_lflag &= ~(ECHO | ECHOE | ECHOK);
  107.     term.c_cflag &= ~CBAUD;
  108.     term.c_cflag |= B0;        /* hangup */
  109.     if(ioctl(device, TCSETA, &term) == -1) perror("hangup: TCSETA");
  110.     if(ioctl(device, TCFLSH, 2) == -1) perror("hangup: TCFLSH");
  111.     sleep(5);        /* 5 seconds with DTR down */
  112.     return(0);
  113. }
  114. /*
  115.  * findspeed: convert ascii baud rate into termio parameter.
  116.  */
  117. findspeed(s)
  118. char *s;
  119. {
  120.     int baud = atoi(s);
  121.     switch(baud) {
  122.         case 110: baud = B110;
  123.             break;
  124.         case 300: baud = B300;
  125.             break;
  126.         case 1200: baud = B1200;
  127.             break;
  128.         case 2400: baud = B2400;
  129.             break;
  130.         default:
  131.             printf("findspeed: unknown baud rate %s\n", s);
  132.             baud = B1200;
  133.     }
  134.     return(baud);
  135. }
  136. /*
  137.  * uuexit: make line useable by UUCP.
  138.  * Because UUCP is pretty determined about using a "modem", it clears CLOCAL
  139.  * which means that it can't write any characters at this point (modem not
  140.  * online, so DCD not asserted). Not suprisingly, it doesn't work.
  141.  * Solution: turn it on again, while UUCP isn't looking; this seems to work
  142.  * fine, although I'm a little puzzled about the timing: this is a 
  143.  * definate "trial and error" solution.
  144.  * This unfortunately also means that UUCP won't detect a line hangup, 
  145.  * so we have to rely on it's timeout facilities ...
  146.  */
  147. #define DIALTIME 5        /* time to continue to assert CLOCAL */
  148. uuexit(code)
  149. {
  150.     struct termio term;
  151.     register int i;
  152.     for(i=0;i<DIALTIME;i++) {
  153.         close(open(dname, O_RDONLY | O_NDELAY)); /* vital magic */
  154.         if(ioctl(dev, TCGETA, &term) == -1) perror("qx TCGETA");
  155.         term.c_cflag |= CLOCAL;
  156.         if(ioctl(dev, TCSETA, &term) == -1) perror("qx TCSETA");
  157.         close(open(dname, O_RDONLY | O_NDELAY)); /* vital magic */
  158.         sleep(1);
  159.     }
  160.     exit(code);
  161. }
  162. /*
  163.  * extensions for send & expect
  164.  */
  165. myread()
  166. {
  167.     char c;
  168.     dread(dev, &c, 1);
  169.     return(c);
  170. }
  171. void mywrite(s)
  172. char *s;
  173. {
  174.     dwrite(dev, s, strlen(s));
  175. }
  176.  
  177.