home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / pcomm / part05 / x_ascii.c < prev   
Encoding:
C/C++ Source or Header  |  1988-05-17  |  5.8 KB  |  273 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. #include <stdio.h>
  7. #include <fcntl.h>
  8. #include <curses.h>
  9. #include <signal.h>
  10. #include "param.h"
  11. #include "status.h"
  12.  
  13. void
  14. xfer_ascii(list, up)
  15. char *list;
  16. int up;
  17. {
  18.     int cr_lf;
  19.     char *file, *strtok();
  20.     void send_ascii(), rcv_ascii(), line_set(), status_line();
  21.     unsigned int sleep();
  22.  
  23.                     /* only one file from list */
  24.     file = strtok(list, "     ");
  25.  
  26.     cr_lf = ascii_mode(up);
  27.     if (up) {
  28.                     /* un-suspend the input routine */
  29.         if (status->pid != -1)
  30.             kill(status->pid, SIGINT);
  31.  
  32.         send_ascii(file, cr_lf);
  33.                     /* re-suspend the input routine */
  34.         if (status->pid != -1)
  35.             kill(status->pid, SIGINT);
  36.     }
  37.     else
  38.         rcv_ascii(file, cr_lf);
  39.  
  40.     /*
  41.      * Restoring the tty modes is easier than setting them... The
  42.      * fixterm() and line_set() routines fix most of the damage.
  43.      */
  44.     fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY);
  45.     fixterm();
  46.     line_set();
  47.     sleep(1);
  48.  
  49.     status_line("xfer complete");
  50.     sleep(2);
  51.     return;
  52. }
  53.  
  54. /*
  55.  * Put the tty line in a mode suitable for the ASCII transfer.  Puts the
  56.  * terminal in the raw, non-blocking mode.  Returns the status of the
  57.  * cr_lf parameter flag.
  58.  */
  59.  
  60. int
  61. ascii_mode(up)
  62. int up;
  63. {
  64.     int cr_lf;
  65.     struct termio tbuf;
  66.     void input_off();
  67.  
  68.     ioctl(status->fd, TCGETA, &tbuf);
  69.     tbuf.c_oflag = 0;
  70.                     /* flow control & 8th bit stripping */
  71.     if (up) {
  72.         tbuf.c_iflag = (ISTRIP|IXON|IXANY);
  73.  
  74.                     /* use NL delays if no CR */
  75.         if (!strcmp(param->cr_up, "STRIP"))
  76.             tbuf.c_oflag = (OPOST|ONLRET);
  77.  
  78.                     /* CR delay times */
  79.         switch (param->cr_delay) {
  80.             case 0:
  81.                 tbuf.c_oflag = 0;
  82.                 break;
  83.             case 100:
  84.                 tbuf.c_oflag |= (OPOST|CR2);
  85.                 break;
  86.             case 150:
  87.                 tbuf.c_oflag |= (OPOST|CR3);
  88.                 break;
  89.         }
  90.     }
  91.                     /* if down loading */
  92.     else {
  93.         tbuf.c_iflag = (ISTRIP|IXOFF);
  94.                     /* kill the input routine */
  95.         input_off();
  96.     }
  97.  
  98.     ioctl(status->fd, TCSETA, &tbuf);
  99.     ioctl(status->fd, TCFLSH, 2);
  100.                     /* out of curses mode */
  101.     resetterm();
  102.     cr_lf = raw_mode();
  103.                     /* non-blocking mode */
  104.     fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NDELAY);
  105.     return(cr_lf);
  106. }
  107.     
  108. /*
  109.  * Send a file.  The local echo option is independent of the duplex option,
  110.  * and would very rarely be used since the characters are most likely
  111.  * being echoed on the screen anyway.
  112.  */
  113.  
  114. void
  115. send_ascii(file, cr_lf)
  116. char *file;
  117. int cr_lf;
  118. {
  119.     FILE *fp;
  120.     int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, last;
  121.     int lecho, pace;
  122.     unsigned int sleep();
  123.     unsigned char c;
  124.                     /* permission already checked */
  125.     if (!(fp = fopen(file, "r")))
  126.         return;
  127.                     /* ASCII transfer options */
  128.     strip_cr = !strcmp(param->cr_up, "STRIP");
  129.     add_lf = !strcmp(param->cr_up, "ADD LF");
  130.     strip_lf = !strcmp(param->lf_up, "STRIP");
  131.     add_cr = !strcmp(param->lf_up, "ADD CR");
  132.     expand = !strcmp(param->expand, "YES");
  133.     lecho = !strcmp(param->lecho, "YES");
  134.     pace = !strcmp(param->pace, "YES");
  135.  
  136.     last = 0;
  137.     while ((i = fgetc(fp)) != EOF) {
  138.                     /* any keyboard activity? */
  139.         switch(j = getchar()) {
  140.             case -1:    /* no key was pressed */
  141.                 break;
  142.             case 27:    /* ESC key for abort */
  143.                 fclose(fp);
  144.                 ioctl(status->fd, TCFLSH, 2);
  145.                 return;
  146.             default:    /* send the char */
  147.                 c = j;
  148.                 putc_line(c);
  149.                 if (c == 13 && cr_lf)
  150.                     putc_line(10);
  151.                 break;
  152.         }
  153.         c = i;
  154.                     /* expand blank lines */
  155.         if (expand && last == 10 && c == 10)
  156.             putc_line(' ');
  157.         last = c;
  158.  
  159.                     /* CR translations */
  160.         if (c == 13 && strip_cr)
  161.             continue;
  162.         if (c == 13 && add_lf) {
  163.             putc_line(c);
  164.             putc_line(10);
  165.             continue;
  166.         }
  167.                     /* LF translations */
  168.         if (c == 10 && strip_lf)
  169.             continue;
  170.         if (c == 10 && add_cr) {
  171.             putc_line(13);
  172.             putc_line(c);
  173.             continue;
  174.         }
  175.         putc_line(c);
  176.         /*
  177.          * There's really no mechanism for delaying characters
  178.          * going to the output, so we fake it by waiting for
  179.          * each character to clear the I/O buffer.
  180.          */
  181.         if (pace)
  182.             ioctl(status->fd, TCSBRK, 1);
  183.         if (lecho)
  184.             write(1, (char *) &c, 1);
  185.     }
  186.     sleep(1);
  187.     ioctl(status->fd, TCSBRK, 1);
  188.     fclose(fp);
  189.     return;
  190. }
  191.  
  192. /*
  193.  * Receive a file.  The timer is used to end the transfer.  This is not
  194.  * that much different from the data logging option.  The use of getc_line()
  195.  * and non-blocking input makes it seem like full duplex, but it's not.
  196.  * Beware that while the timer is active the keyboard is deaf.  Input is
  197.  * NOT loaded into the virtual screen!!
  198.  */
  199.  
  200. void
  201. rcv_ascii(file, cr_lf)
  202. char *file;
  203. int cr_lf;
  204. {
  205.     FILE *fp;
  206.     int i, strip_cr, strip_lf, add_cr, add_lf, got_first;
  207.     unsigned int delay;
  208.     unsigned char c;
  209.                     /* permission already checked */
  210.     if (!(fp = fopen(file, "w")))
  211.         return;
  212.                     /* ASCII transfer options */
  213.     strip_cr = !strcmp(param->cr_dn, "STRIP");
  214.     add_lf = !strcmp(param->cr_dn, "ADD LF");
  215.     strip_lf = !strcmp(param->lf_dn, "STRIP");
  216.     add_cr = !strcmp(param->lf_dn, "ADD CR");
  217.  
  218.     got_first = 0;
  219.     delay = 1;
  220.     while (1) {
  221.                     /* keyboard activity */
  222.         switch (i = getchar()) {
  223.             case -1:    /* no key was pressed */
  224.                 break;
  225.             case 27:    /* ESC key */
  226.                 fclose(fp);
  227.                 return;
  228.             default:    /* send it */
  229.                 c = i;
  230.                 putc_line(c);
  231.                 if (c == 13 && cr_lf)
  232.                     putc_line(10);
  233.                 break;
  234.         }
  235.                     /* read a character */
  236.         if ((i = getc_line(delay)) == -1) {
  237.             /*
  238.              * The transfer timeout is not activated until the
  239.              * first character is received.  Until then, it polls
  240.              * the line for one second and loops backs for
  241.              * keyboard input.
  242.              */
  243.             if (got_first) {
  244.                 fclose(fp);
  245.                 return;
  246.             }
  247.             continue;
  248.         }
  249.         got_first = 1;
  250.         delay = param->timer;
  251.         c = i & 0177;
  252.                     /* display it on the screen */
  253.         write(1, (char *) &c, 1);
  254.                     /* CR translations */
  255.         if (c == 13 && strip_cr)
  256.             continue;
  257.         if (c == 13 && add_lf) {
  258.             fputc((char) c, fp);
  259.             fputc(10, fp);
  260.             continue;
  261.         }
  262.                     /* LF translations */
  263.         if (c == 10 && strip_lf)
  264.             continue;
  265.         if (c == 10 && add_cr) {
  266.             fputc(13, fp);
  267.             fputc((char) c, fp);
  268.             continue;
  269.         }
  270.         fputc((char) c, fp);
  271.     }
  272. }
  273.