home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume16 / pcomm2 / part07 / x_ascii.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-09-14  |  6.9 KB  |  345 lines

  1. /*
  2.  * Transfer a file using just XON/XOFF flow control.  Currently limited to
  3.  * 7 bit ASCII codes.  (If this causes too much trouble, I'll change it).
  4.  */
  5.  
  6. #define CLIST    64
  7.  
  8. #include <stdio.h>
  9. #include <fcntl.h>
  10. #include <curses.h>
  11. #include <signal.h>
  12. #include "config.h"
  13. #include "misc.h"
  14. #include "param.h"
  15.  
  16. void
  17. xfer_ascii(list, up)
  18. char *list;
  19. int up;
  20. {
  21.     int cr_lf;
  22.     char *file, *strtok();
  23.     void send_ascii(), rcv_ascii(), line_set(), st_line(), suspend();
  24.     void load_vs(), ascii_mode();
  25.     unsigned int sleep();
  26.  
  27.     touchwin(stdscr);
  28.     refresh();
  29.                     /* only one file from list */
  30.     file = strtok(list, "     ");
  31.  
  32.     cr_lf = !strcmp(param->cr_out, "CR/LF");
  33.     ascii_mode(up);
  34.     if (up) {
  35.                     /* un-suspend the input routine */
  36.         suspend(0);
  37.  
  38.         send_ascii(file, cr_lf);
  39.                     /* re-suspend the input routine */
  40.         suspend(1);
  41.     }
  42.     else
  43.         rcv_ascii(file, cr_lf);
  44.  
  45.     /*
  46.      * Restoring the TTY modes is easier than setting them... The
  47.      * fixterm() and line_set() routines fix most of the damage.
  48.      */
  49.     fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY);
  50.     line_set();
  51.     fixterm();
  52.  
  53.     /*
  54.      * On downloading, the contents of the virtual screen won't contain
  55.      * the characters shown during the transfer.  Too bad...
  56.      */
  57.     load_vs();
  58.     beep();
  59.     st_line("xfer complete");
  60.  
  61.     sleep(2);
  62.     return;
  63. }
  64.  
  65. /*
  66.  * Put the TTY line in a mode suitable for the ASCII transfer.  Puts the
  67.  * terminal in the raw, non-blocking mode.
  68.  */
  69.  
  70. static void
  71. ascii_mode(up)
  72. int up;
  73. {
  74.     extern int fd;
  75.     struct termio tbuf;
  76.     void input_off(), term_mode();
  77.  
  78.     ioctl(fd, TCGETA, &tbuf);
  79.     tbuf.c_oflag = 0;
  80.                     /* flow control & 8th bit stripping */
  81.     if (up) {
  82.         tbuf.c_iflag = (ISTRIP|IXON);
  83.  
  84.                     /* use NL delays if no CR */
  85.         if (!strcmp(param->cr_up, "STRIP"))
  86.             tbuf.c_oflag = (OPOST|ONLRET);
  87.  
  88.                     /* CR delay times */
  89.         switch (param->cr_delay) {
  90.             case 0:
  91.                 tbuf.c_oflag = 0;
  92.                 break;
  93.             case 100:
  94.                 tbuf.c_oflag |= (OPOST|CR2);
  95.                 break;
  96.             case 150:
  97.                 tbuf.c_oflag |= (OPOST|CR3);
  98.                 break;
  99.         }
  100.     }
  101.                     /* if down loading */
  102.     else {
  103.         tbuf.c_iflag = (ISTRIP|IXOFF);
  104.                     /* kill the input routine */
  105.         input_off();
  106.     }
  107.  
  108.     ioctl(fd, TCSETA, &tbuf);
  109.     ioctl(fd, TCFLSH, 2);
  110.                     /* out of curses mode */
  111.     resetterm();
  112.     term_mode();
  113.                     /* non-blocking mode */
  114.     fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY);
  115.     return;
  116. }
  117.  
  118. /*
  119.  * Send a file.  The local echo option is independent of the duplex option,
  120.  * and would very rarely be used since the characters are most likely
  121.  * being echoed on the screen anyway.
  122.  */
  123.  
  124. static void
  125. send_ascii(file, cr_lf)
  126. char *file;
  127. int cr_lf;
  128. {
  129.     extern int fd;
  130.     FILE *fp;
  131.     int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, lecho, pace;
  132.     unsigned char c, last;
  133.     unsigned int sleep();
  134.                     /* permission already checked */
  135.     if (!(fp = fopen(file, "r")))
  136.         return;
  137.                     /* ASCII transfer options */
  138.     strip_cr = !strcmp(param->cr_up, "STRIP");
  139.     add_lf = !strcmp(param->cr_up, "ADD LF");
  140.     strip_lf = !strcmp(param->lf_up, "STRIP");
  141.     add_cr = !strcmp(param->lf_up, "ADD CR");
  142.     expand = !strcmp(param->expand, "YES");
  143.     lecho = !strcmp(param->lecho, "YES");
  144.     pace = !strcmp(param->pace, "YES");
  145.  
  146.     last = 0;
  147.     while ((i = fgetc(fp)) != EOF) {
  148.                     /* any keyboard activity? */
  149.         switch (j = getchar()) {
  150.             case -1:    /* no key was pressed */
  151.                 break;
  152.             case ESC:    /* <ESC> key for abort */
  153.                 fclose(fp);
  154.                 sleep(2);
  155.                 ioctl(fd, TCSBRK, 1);
  156.                 return;
  157.             default:    /* send the char */
  158.                 c = j & 0xff;
  159.                 putc_line(c);
  160.                 if (c == '\r' && cr_lf)
  161.                     putc_line('\n');
  162.                 break;
  163.         }
  164.         c = i & 0xff;
  165.                     /* expand blank lines */
  166.         if (expand && last == '\n' && c == '\n')
  167.             putc_line(' ');
  168.         last = c;
  169.  
  170.                     /* CR translations */
  171.         if (c == '\r' && strip_cr)
  172.             continue;
  173.         if (c == '\r' && add_lf) {
  174.             putc_line(c);
  175.             putc_line('\n');
  176.             continue;
  177.         }
  178.                     /* LF translations */
  179.         if (c == '\n' && strip_lf)
  180.             continue;
  181.         if (c == '\n' && add_cr) {
  182.             putc_line('\r');
  183.             putc_line(c);
  184.             continue;
  185.         }
  186.         putc_line(c);
  187.         /*
  188.          * There's really no mechanism for delaying characters
  189.          * going to the output, so we fake it by waiting for
  190.          * each character to clear the I/O buffer.
  191.          */
  192.         if (pace)
  193.             ioctl(fd, TCSBRK, 1);
  194.         if (lecho) {
  195.             putchar((char) c);
  196.             fflush(stdout);
  197.         }
  198.     }
  199.     fclose(fp);
  200.     sleep(2);
  201.     ioctl(fd, TCSBRK, 1);
  202.     return;
  203. }
  204.  
  205. /*
  206.  * Receive a file.  The timer is used to end the transfer.  This is not
  207.  * that much different from the data logging option.  The use of bgetc_line()
  208.  * and non-blocking input makes it seem like full duplex, but it's not.
  209.  * Be aware that while the timer is active the keyboard is deaf.  Input is
  210.  * NOT loaded into the virtual screen!!
  211.  */
  212.  
  213. static void
  214. rcv_ascii(file, cr_lf)
  215. char *file;
  216. int cr_lf;
  217. {
  218.     FILE *fp;
  219.     int i, strip_cr, strip_lf, add_cr, add_lf, got_first;
  220.     unsigned int delay;
  221.     char c;
  222.                     /* permission already checked */
  223.     if (!(fp = fopen(file, "w")))
  224.         return;
  225.                     /* ASCII transfer options */
  226.     strip_cr = !strcmp(param->cr_dn, "STRIP");
  227.     add_lf = !strcmp(param->cr_dn, "ADD LF");
  228.     strip_lf = !strcmp(param->lf_dn, "STRIP");
  229.     add_cr = !strcmp(param->lf_dn, "ADD CR");
  230.  
  231.     got_first = 0;
  232.     delay = 1;
  233.     while (1) {
  234.                     /* keyboard activity */
  235.         switch (i = getchar()) {
  236.             case -1:    /* no key was pressed */
  237.                 break;
  238.             case ESC:    /* <ESC> key */
  239.                 fclose(fp);
  240.                 return;
  241.             default:    /* send it */
  242.                 c = i & 0xff;
  243.                 putc_line((unsigned char) c);
  244.                 if (c == '\r' && cr_lf)
  245.                     putc_line('\n');
  246.                 break;
  247.         }
  248.                     /* read a character */
  249.         if ((i = bgetc_line(delay)) == -1) {
  250.             /*
  251.              * The transfer timeout is not activated until the
  252.              * first character is received.  Until then, it polls
  253.              * the line for one second and loops backs for
  254.              * keyboard input.
  255.              */
  256.             if (got_first) {
  257.                 fclose(fp);
  258.                 return;
  259.             }
  260.             continue;
  261.         }
  262.         got_first = 1;
  263.         delay = param->timer;
  264.         c = i & 0xff;
  265.                     /* display it on the screen */
  266.         putchar(c);
  267.         fflush(stdout);
  268.                     /* CR translations */
  269.         if (c == '\r' && strip_cr)
  270.             continue;
  271.         if (c == '\r' && add_lf) {
  272.             fputc(c, fp);
  273.             fputc('\n', fp);
  274.             continue;
  275.         }
  276.                     /* LF translations */
  277.         if (c == '\n' && strip_lf)
  278.             continue;
  279.         if (c == '\n' && add_cr) {
  280.             fputc('\r', fp);
  281.             fputc(c, fp);
  282.             continue;
  283.         }
  284.         fputc(c, fp);
  285.     }
  286. }
  287.  
  288. /*
  289.  * Get a character from the line (using buffered I/O) with a specified
  290.  * time-out period in seconds.  If the function times-out, it returns a -1.
  291.  */
  292.  
  293. static int bl_flag;
  294.  
  295. static int
  296. bgetc_line(sec)
  297. unsigned int sec;
  298. {
  299.     int bl_force();
  300.     char c;
  301.     unsigned int alarm();
  302.  
  303.     signal(SIGALRM, bl_force);
  304.     bl_flag = 0;
  305.  
  306.     alarm(sec);
  307.     if ((int) (c = buf_read()) < 0) {
  308.         alarm(0);
  309.         return(-1);
  310.     }
  311.     if (bl_flag)
  312.         return(-1);
  313.     alarm(0);
  314.     return(c & 0xff);
  315. }
  316. /*ARGSUSED*/
  317. static int
  318. bl_force(dummy)
  319. int dummy;
  320. {
  321.     bl_flag = 1;
  322. }
  323.  
  324. /*
  325.  * Do a single character buffered read from the serial port.
  326.  */
  327.  
  328. static int
  329. buf_read()
  330. {
  331.     extern int fd;
  332.     static char buf[CLIST];
  333.     static char *bufp = buf;
  334.     static int n = 0;
  335.  
  336.     if (n <= 0) {
  337.         if ((n = read(fd, buf, CLIST)) <= 0)
  338.             return(-1);
  339.         bufp = buf;
  340.     }
  341.     while (--n >= 0)
  342.         return(*bufp++ & 0xff);
  343.     return(-1);
  344. }
  345.