home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume4 / xmodem / receive.c < prev    next >
C/C++ Source or Header  |  1986-11-30  |  5KB  |  256 lines

  1. /*
  2. **    receive filename
  3. */
  4. #
  5. # include <file.h>
  6. # include <curses.h>
  7. # include <signal.h>
  8. # include <time.h>
  9. # include <setjmp.h>
  10.  
  11. # define    SOH    0x1
  12. # define    NAK    0x15
  13. # define    ACK    0x6
  14. # define    EOT    0x4
  15. # define    CANCEL    0x18
  16.  
  17. char filename[64];
  18. int retries;        /* retries counter */
  19. int seq_num;        /* sequence number */
  20. int caught();        /* interrupt routine, called if haven't received a
  21.                block in 1 second */
  22. struct sigvec vec;
  23. jmp_buf env;
  24.  
  25. main(argc,argv)
  26. int argc;
  27. char *argv[]; {
  28.  
  29.     int fd;
  30.     char c;
  31.     register int i;
  32.  
  33.     if (!((argc == 2) || (argc == 3))) {
  34.         printf("ILLEGAL NUMBER OF ARGUMENTS.\n");
  35.         printf("SYNOPSIS: to_vax_x [-t] [-m] filename\n");
  36.         exit(-1);
  37.     }
  38.  
  39.     if (argc == 3) {
  40.         if (strcmp(argv[1],"-t") && strcmp(argv[1],"-m")) {
  41.             printf("bad argument `%s'\n",argv[1]);
  42.             printf("SYNOPSIS: to_vax_x [-t] [-m] filename\n");
  43.             exit(-1);
  44.         }
  45.     }
  46.  
  47.     strcpy(filename,argv[argc-1]);
  48.     if ((fd = open(filename,O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0) {
  49.         perror(filename);
  50.         exit(-1);
  51.     }
  52.  
  53.     initscr();
  54.     raw();            /* set terminal to 8-bit I/O */
  55.     noecho();
  56.  
  57. /*
  58. **    Ignore interrupts from the user.
  59. **    If the user could delete this program the terminal
  60. **    would be left in a undiserable state of mind.
  61. */
  62.  
  63.     vec.sv_handler = caught;
  64.     vec.sv_mask = vec.sv_onstack = 0;
  65.     sigvec(SIGALRM,&vec,(struct sigvec *)0);
  66.  
  67.     sigsetmask(-1 ^ (1 << (SIGALRM-1)));    /* enable alarm signal */
  68.  
  69.     c = NAK;
  70.     retries = 0;
  71.     if (setjmp(env)) {
  72.         write(1,&c,1);
  73.         if (retries++ > 10) {
  74.         reset(1);          /* restore terminal to normal state */
  75.         printf("Can not get reply from transmitter\n");
  76.         exit(0); 
  77.         }
  78.     }
  79.     
  80.     SET_TIMER(10);
  81.     read(0,&c,1);
  82.     DISABLE_TIMER();
  83.  
  84.     seq_num = 1; retries = 0;
  85.     for(;;) {
  86.  
  87.         if (retries == 10) {
  88.             c = CANCEL;
  89.             write(1,&c,1);
  90.             reset(1);
  91.             printf("Terminated after 10 retries\r\n");
  92.             exit(-1);
  93.         }
  94.  
  95.         switch( c & 0x7f ) {
  96.             case SOH:
  97.                 BLOCK(fd);
  98.                 break;
  99.             case CANCEL:
  100.                 printf("Received CANCEL signal\r\n");
  101.                 reset(1);
  102.                 exit(-1);
  103.             case EOT:
  104.                 c = ACK;
  105.                 write(1,&c,1);
  106.                 reset(0);
  107.                 goto END;
  108.             default:
  109.                 sleep(2);    /* wait for a bit */
  110.                 noraw();    /* flush input buffer */
  111.                 raw();
  112.                 c = NAK;
  113.                 write(1,&c,1);
  114.                 retries++;
  115.                 break;
  116.         }
  117.         c = NAK;
  118.         if (setjmp(env)) {
  119.             write(1,&c,1);
  120.             if (retries++ > 10) {
  121.             reset(1);          /* restore terminal to normal state */
  122.             printf("Can not get reply from transmitter\n");
  123.             exit(0); 
  124.             }
  125.         }
  126.     
  127.         SET_TIMER(10);
  128.         read(0,&c,1);
  129.             DISABLE_TIMER();
  130.         
  131.     }
  132. END:
  133.  
  134.     close(fd);
  135.     if (argc == 3) {
  136.         switch( argv[1][1] ) {
  137.             case 't':
  138.                 printf("Deleting carriage returns\n");
  139.                 DELCR(filename);
  140.                 break;
  141.             case 'm':
  142.                 printf("Changing cr's to lf's\n");
  143.                 CR2LF(filename);
  144.         }
  145.     }
  146. }
  147.  
  148. BLOCK(fd) 
  149. int fd; {
  150.     
  151.     register i;
  152.     register char *p;
  153.     char block[131];
  154.     char c;
  155.     int xsum;
  156.  
  157.     retries = 0;        /* start fresh */
  158.  
  159.     /* used to be 1 */
  160.     SET_TIMER(10);
  161.     if (setjmp(env)) {
  162.         noraw();
  163.         raw();
  164.         c = NAK;
  165.         write(1,&c,1);
  166.         retries++;
  167.         return;
  168.     } else {
  169.         i = read(0,block,131);
  170.         while( i < 131 ) {
  171.             i += read(0,&block[i],131-i);    /* data block */
  172.         }
  173.         DISABLE_TIMER();
  174.     }
  175.     
  176.     if ( (block[0] & 0xff) != seq_num ) {
  177.         i = (seq_num ? seq_num - 1 : 255);
  178.         if ((block[0] & 0xff) != i ) {
  179.             if ( (block[1] & 0xff) != (255 - seq_num) ) {
  180.                 i = 255 - i;
  181.                 if ((block[1] & 0xff) == i ) {
  182.                     c = NAK;
  183.                     write(1,&c,1);
  184.                     retries++;
  185.                     return;
  186.                 }
  187.                 c = CANCEL;     /* loss of synchronization */
  188.                 write(1,&c,1);
  189.                 reset(1);
  190.                 exit(-1);
  191.             }
  192.         }
  193.         retries++;
  194.         goto leave;
  195.     }
  196.  
  197.     if ( (block[1] & 0xff) != (255 - seq_num) ) {
  198.         c = NAK;
  199.         write(1,&c,1);
  200.         retries++;
  201.         return;
  202.     }
  203.     
  204.     xsum = 0;
  205.     for (i = 0, p = &block[2]; i < 128; i++) xsum += (*p++ & 0xff);
  206.     xsum &= 0xff;
  207.     if ( (block[130] & 0xff) != xsum ) {
  208.         c = NAK;
  209.         write(1,&c,1);
  210.         retries++;
  211.         return;
  212.     }
  213.  
  214.     write(fd,&block[2],128);
  215.     retries = 0;
  216.     seq_num = ++seq_num % 256;
  217. leave:
  218.     c = ACK;
  219.     write(1,&c,1);
  220. }
  221.  
  222. reset(remove) 
  223. int remove; {
  224.     
  225.     DISABLE_TIMER();
  226.     sigsetmask(0);
  227.     vec.sv_handler = SIG_DFL;
  228.     vec.sv_mask = vec.sv_onstack = 0;
  229.     sigvec(SIGALRM,&vec,(struct sigvec *)0);
  230.     noraw(); echo();
  231.     endwin();
  232.     if (remove) unlink(filename);
  233. }
  234.     
  235.  
  236. caught() {
  237.     longjmp(env,1);
  238. }
  239.  
  240. SET_TIMER(secs) 
  241. int secs; {
  242.     struct itimerval val;
  243.  
  244.     val.it_value.tv_sec = secs;
  245.     val.it_value.tv_usec = secs * 1000;
  246.     timerclear(&val.it_interval);
  247.     setitimer(ITIMER_REAL,&val,(struct itimerval *)0);
  248. }
  249.  
  250. DISABLE_TIMER() {
  251.     struct itimerval val;
  252.  
  253.     timerclear(&val.it_value);
  254.     setitimer(ITIMER_REAL,&val,(struct itimerval *)0);
  255. }
  256.