home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / zmodem / rbsb.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  10KB  |  473 lines

  1. /*
  2.  *
  3.  *  Rev 5-15-91
  4.  *  This file contains Unix specific code for setting terminal modes,
  5.  *  very little is specific to ZMODEM or YMODEM per se (that code is in
  6.  *  sz.c and rz.c).  The CRC-16 routines used by XMODEM, YMODEM, and ZMODEM
  7.  *  are also in this file, a fast table driven macro version
  8.  *
  9.  *    V7/BSD HACKERS:  SEE NOTES UNDER mode(2) !!!
  10.  *
  11.  *   This file is #included so the main file can set parameters such as HOWMANY.
  12.  *   See the main files (rz.c/sz.c) for compile instructions.
  13.  */
  14.  
  15. #ifdef V7
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #define STAT
  19. #include <sgtty.h>
  20. #define OS "V7/BSD"
  21. #define ROPMODE "r"
  22. #ifdef LLITOUT
  23. long Locmode;        /* Saved "local mode" for 4.x BSD "new driver" */
  24. long Locbit = LLITOUT;    /* Bit SUPPOSED to disable output translations */
  25. #include <strings.h>
  26. #endif
  27. #endif
  28.  
  29. #ifndef OS
  30. #ifndef USG
  31. #define USG
  32. #endif
  33. #endif
  34.  
  35. #ifdef USG
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #define STAT
  39. #include <termio.h>
  40. #define OS "SYS III/V"
  41. #define ROPMODE "r"
  42. #define MODE2OK
  43. #include <string.h>
  44. #endif
  45.  
  46. #ifdef T6K
  47. #include <sys/ioctl.h>        /* JPRadley: for the Tandy 6000 */
  48. #endif
  49.  
  50. #include <setjmp.h>
  51.  
  52. #if HOWMANY  > 255
  53. Howmany must be 255 or less
  54. #endif
  55.  
  56.  /*
  57.  *  Some systems (Venix, Coherent, Regulus) may not support tty raw mode
  58.  *  read(2) the same way as Unix. ONEREAD must be defined to force one
  59.  *  character reads for these systems. Added 7-01-84 CAF
  60.  */
  61.  
  62. #define sendline(c) putc(c & 0377, Ttystream)
  63. #define xsendline(c) putc(c, Ttystream)
  64.  
  65. FILE *Ttystream;
  66. int Tty;
  67. char linbuf[HOWMANY];
  68. char xXbuf[BUFSIZ];
  69. int Lleft=0;        /* number of characters in linbuf */
  70. jmp_buf tohere;        /* For the interrupt on RX timeout */
  71. #ifdef ONEREAD
  72. /* Sorry, Regulus and some others don't work right in raw mode! */
  73. int Readnum = 1;    /* Number of bytes to ask for in read() from modem */
  74. #else
  75. int Readnum = HOWMANY;    /* Number of bytes to ask for in read() from modem */
  76. #endif
  77. int Verbose=0;
  78.  
  79.  
  80. struct {
  81.     unsigned baudr;
  82.     int speedcode;
  83. } speeds[] = {
  84.     110,    B110,
  85.     300,    B300,
  86.     600,    B600,
  87.     1200,    B1200,
  88.     2400,    B2400,
  89.     4800,    B4800,
  90.     9600,    B9600,
  91.     19200,    EXTA,
  92.     38400,    EXTB,
  93.     0,
  94. };
  95.  
  96. int Twostop;        /* Use two stop bits */
  97.  
  98.  
  99. /*
  100.  *  The following uses an external rdchk() routine if available,
  101.  *  otherwise defines the function for BSD or fakes it for SYSV.
  102.  */
  103.  
  104. #ifndef READCHECK
  105. #ifdef FIONREAD
  106. #define READCHECK
  107. /*
  108.  *  Return non 0 iff something to read from io descriptor f
  109.  */
  110. rdchk(f)
  111. {
  112.     static long lf;
  113.  
  114.     ioctl(f, FIONREAD, &lf);
  115.     return ((int) lf);
  116. }
  117.  
  118. #else        /* FIONREAD */
  119.  
  120. #ifdef SV
  121. #define READCHECK
  122. #include <fcntl.h>
  123.  
  124. int checked = 0;
  125. /*
  126.  * Nonblocking I/O is a bit different in System V, Release 2
  127.  *  Note: this rdchk vsn throws away a byte, OK for ZMODEM
  128.  *  sender because protocol design anticipates this problem.
  129.  */
  130. #define EATSIT
  131. rdchk(f)
  132. {
  133.     int lf, savestat;
  134.     static char bchecked;
  135.  
  136.     savestat = fcntl(f, F_GETFL) ;
  137.     fcntl(f, F_SETFL, savestat | O_NDELAY) ;
  138.     lf = read(f, &bchecked, 1) ;
  139.     fcntl(f, F_SETFL, savestat) ;
  140.     checked = bchecked & 0377;    /* force unsigned byte */
  141.     return(lf) ;
  142. }
  143. #endif
  144. #endif
  145. #endif
  146.  
  147.  
  148. static unsigned
  149. getspeed(code)
  150. {
  151.     register n;
  152.  
  153.     for (n=0; speeds[n].baudr; ++n)
  154.         if (speeds[n].speedcode == code)
  155.             return speeds[n].baudr;
  156.     return 38400;    /* Assume fifo if ioctl failed */
  157. }
  158.  
  159.  
  160.  
  161. #ifdef ICANON
  162. struct termio oldtty, tty;
  163. #else
  164. struct sgttyb oldtty, tty;
  165. struct tchars oldtch, tch;
  166. #endif
  167.  
  168. /*
  169.  * mode(n)
  170.  *  3: save old tty stat, set raw mode with flow control
  171.  *  2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g
  172.  *  1: save old tty stat, set raw mode 
  173.  *  0: restore original tty mode
  174.  */
  175. mode(n)
  176. {
  177.     static did0 = FALSE;
  178.  
  179.     vfile("mode:%d", n);
  180.     switch(n) {
  181. #ifdef USG
  182.     case 2:        /* Un-raw mode used by sz, sb when -g detected */
  183.         if(!did0)
  184.             (void) ioctl(Tty, TCGETA, &oldtty);
  185.         tty = oldtty;
  186.  
  187.         tty.c_iflag = BRKINT|IXON;
  188.  
  189.         tty.c_oflag = 0;    /* Transparent output */
  190.  
  191.         tty.c_cflag &= ~(PARENB|HUPCL);        /* Disable parity */
  192.         tty.c_cflag |= (CREAD|CS8);    /* Set character size = 8 */
  193.         if (Twostop)
  194.             tty.c_cflag |= CSTOPB;    /* Set two stop bits */
  195.  
  196.  
  197. #ifdef READCHECK
  198.         tty.c_lflag = Zmodem ? 0 : ISIG;
  199.         tty.c_cc[VINTR] = Zmodem ? -1:030;    /* Interrupt char */
  200. #else
  201.         tty.c_lflag = ISIG;
  202.         tty.c_cc[VINTR] = Zmodem ? 03:030;    /* Interrupt char */
  203. #endif
  204.         tty.c_cc[VQUIT] = -1;            /* Quit char */
  205. #ifdef NFGVMIN
  206.         tty.c_cc[VMIN] = 1;
  207. #else
  208.         tty.c_cc[VMIN] = 3;     /* This many chars satisfies reads */
  209. #endif
  210.         tty.c_cc[VTIME] = 1;    /* or in this many tenths of seconds */
  211.  
  212.         (void) ioctl(Tty, TCSETAW, &tty);
  213.         did0 = TRUE;
  214.         return OK;
  215.     case 1:
  216.     case 3:
  217.         if(!did0)
  218.             (void) ioctl(Tty, TCGETA, &oldtty);
  219.         tty = oldtty;
  220.  
  221.         tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
  222.  
  223.          /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
  224.         tty.c_lflag &= ~(ECHO | ICANON | ISIG);
  225.  
  226.         tty.c_oflag = 0;    /* Transparent output */
  227.  
  228.         tty.c_cflag &= ~PARENB;    /* Same baud rate, disable parity */
  229.         tty.c_cflag |= CS8;    /* Set character size = 8 */
  230.         if (Twostop)
  231.             tty.c_cflag |= CSTOPB;    /* Set two stop bits */
  232. #ifdef NFGVMIN
  233.         tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
  234. #else
  235.         tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
  236. #endif
  237.         tty.c_cc[VTIME] = 1;    /* or in this many tenths of seconds */
  238.         (void) ioctl(Tty, TCSETAW, &tty);
  239.         did0 = TRUE;
  240.         Effbaud = Baudrate = getspeed(tty.c_cflag & CBAUD);
  241.         return OK;
  242. #endif
  243. #ifdef V7
  244.     /*
  245.      *  NOTE: this should transmit all 8 bits and at the same time
  246.      *   respond to XOFF/XON flow control.  If no FIONREAD or other
  247.      *   rdchk() alternative, also must respond to INTRRUPT char
  248.      *   This doesn't work with V7.  It should work with LLITOUT,
  249.      *   but LLITOUT was broken on the machine I tried it on.
  250.      */
  251.     case 2:        /* Un-raw mode used by sz, sb when -g detected */
  252.         if(!did0) {
  253.             ioctl(Tty, TIOCEXCL, 0);
  254.             ioctl(Tty, TIOCGETP, &oldtty);
  255.             ioctl(Tty, TIOCGETC, &oldtch);
  256. #ifdef LLITOUT
  257.             ioctl(Tty, TIOCLGET, &Locmode);
  258. #endif
  259.         }
  260.         tty = oldtty;
  261.         tch = oldtch;
  262. #ifdef READCHECK
  263.         tch.t_intrc = Zmodem ? -1:030;    /* Interrupt char */
  264. #else
  265.         tch.t_intrc = Zmodem ? 03:030;    /* Interrupt char */
  266. #endif
  267.         tty.sg_flags |= (ODDP|EVENP|CBREAK);
  268.         tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE);
  269.         ioctl(Tty, TIOCSETP, &tty);
  270.         ioctl(Tty, TIOCSETC, &tch);
  271. #ifdef LLITOUT
  272.         ioctl(Tty, TIOCLBIS, &Locbit);
  273. #endif
  274.         bibi(99);    /* un-raw doesn't work w/o lit out */
  275.         did0 = TRUE;
  276.         return OK;
  277.     case 1:
  278.     case 3:
  279.         if(!did0) {
  280.             ioctl(Tty, TIOCEXCL, 0);
  281.             ioctl(Tty, TIOCGETP, &oldtty);
  282.             ioctl(Tty, TIOCGETC, &oldtch);
  283. #ifdef LLITOUT
  284.             ioctl(Tty, TIOCLGET, &Locmode);
  285. #endif
  286.         }
  287.         tty = oldtty;
  288.         tty.sg_flags |= (RAW|TANDEM);
  289.         tty.sg_flags &= ~ECHO;
  290.         ioctl(Tty, TIOCSETP, &tty);
  291.         did0 = TRUE;
  292.         Effbaud = Baudrate = getspeed(tty.sg_ospeed);
  293.         return OK;
  294. #endif
  295.     case 0:
  296.         if(!did0)
  297.             return ERROR;
  298. #ifdef USG
  299.         (void) ioctl(Tty, TCSBRK, 1);    /* Wait for output to drain */
  300.         (void) ioctl(Tty, TCFLSH, 1);    /* Flush input queue */
  301.         (void) ioctl(Tty, TCSETAW, &oldtty);    /* Restore modes */
  302.         (void) ioctl(Tty, TCXONC,1);    /* Restart output */
  303. #endif
  304. #ifdef V7
  305.         ioctl(Tty, TIOCSETP, &oldtty);
  306.         ioctl(Tty, TIOCSETC, &oldtch);
  307.         ioctl(Tty, TIOCNXCL, 0);
  308. #ifdef LLITOUT
  309.         ioctl(Tty, TIOCLSET, &Locmode);
  310. #endif
  311. #endif
  312.  
  313.         return OK;
  314.     default:
  315.         return ERROR;
  316.     }
  317. }
  318.  
  319. sendbrk()
  320. {
  321. #ifdef V7
  322. #ifdef TIOCSBRK
  323. #define CANBREAK
  324.     sleep(1);
  325.     ioctl(Tty, TIOCSBRK, 0);
  326.     sleep(1);
  327.     ioctl(Tty, TIOCCBRK, 0);
  328. #endif
  329. #endif
  330. #ifdef USG
  331. #define CANBREAK
  332.     ioctl(Tty, TCSBRK, 0);
  333. #endif
  334. }
  335.  
  336. /* Initialize tty device for serial file xfer */
  337. inittty()
  338. {
  339.     Tty = open("/dev/tty", 2);
  340.     if (Tty < 0) {
  341.         perror("/dev/tty");  exit(2);
  342.     }
  343.     Ttystream = fdopen(Tty, "w");
  344.     setbuf(Ttystream, xXbuf);        
  345. }
  346.  
  347. flushmoc()
  348. {
  349.     fflush(Ttystream);
  350. }
  351. flushmo()
  352. {
  353.     fflush(Ttystream);
  354. }
  355.  
  356. /*
  357.  * This version of readline is reasoably well suited for
  358.  * reading many characters.
  359.  *
  360.  * timeout is in tenths of seconds
  361.  */
  362. alrm()
  363. {
  364.     longjmp(tohere, -1);
  365. }
  366. readline(timeout)
  367. int timeout;
  368. {
  369.     register n;
  370.     static char *cdq;    /* pointer for removing chars from linbuf */
  371.  
  372.     if (--Lleft >= 0) {
  373.         if (Verbose > 8) {
  374.             fprintf(stderr, "%02x ", *cdq&0377);
  375.         }
  376.         return (*cdq++ & 0377);
  377.     }
  378.     n = timeout/10;
  379.     if (n < 2)
  380.         n = 3;
  381.     if (Verbose > 5)
  382.         fprintf(stderr, "Calling read: alarm=%d  Readnum=%d ",
  383.           n, Readnum);
  384.     if (setjmp(tohere)) {
  385. #ifdef TIOCFLUSH
  386. /*        ioctl(Tty, TIOCFLUSH, 0); */
  387. #endif
  388.         Lleft = 0;
  389.         if (Verbose>1)
  390.             fprintf(stderr, "Readline:TIMEOUT\n");
  391.         return TIMEOUT;
  392.     }
  393.     signal(SIGALRM, alrm); alarm(n);
  394.     errno = 0;
  395.     Lleft=read(0, cdq=linbuf, Readnum);
  396.     alarm(0);
  397.     if (Verbose > 5) {
  398.         fprintf(stderr, "Read returned %d bytes errno=%d\n",
  399.           Lleft, errno);
  400.     }
  401.     if (Lleft < 1)
  402.         return TIMEOUT;
  403.     --Lleft;
  404.     if (Verbose > 8) {
  405.         fprintf(stderr, "%02x ", *cdq&0377);
  406.     }
  407.     return (*cdq++ & 0377);
  408. }
  409.  
  410.  
  411.  
  412. /*
  413.  * Purge the modem input queue of all characters
  414.  */
  415. purgeline()
  416. {
  417.     Lleft = 0;
  418. #ifdef USG
  419.     ioctl(Tty, TCFLSH, 0);
  420. #else
  421.     lseek(Tty, 0L, 2);
  422. #endif
  423. }
  424.  
  425.  
  426. /* send cancel string to get the other end to shut up */
  427. canit()
  428. {
  429.     static char canistr[] = {
  430.      24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  431.     };
  432.  
  433.     zmputs(canistr);
  434.     Lleft=0;    /* Do read next time ... */
  435. }
  436.  
  437. /*
  438.  * Send a string to the modem, processing for \336 (sleep 1 sec)
  439.  *   and \335 (break signal)
  440.  */
  441. zmputs(s)
  442. char *s;
  443. {
  444.     register c;
  445.  
  446.     while (*s) {
  447.         switch (c = *s++) {
  448.         case '\336':
  449.             sleep(1); continue;
  450.         case '\335':
  451.             sendbrk(); continue;
  452.         default:
  453.             sendline(c);
  454.         }
  455.     }
  456.     flushmo();
  457. }
  458.  
  459.  
  460. /* VARARGS1 */
  461. vfile(f, a, b, c, d)
  462. char *f;
  463. long a, b, c, d;
  464. {
  465.     if (Verbose > 2) {
  466.         fprintf(stderr, f, a, b, c, d);
  467.         fprintf(stderr, "\n");
  468.     }
  469. }
  470.  
  471.  
  472. /* End of rbsb.c */
  473.