home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1992,1993 Peter Edward Cann, all rights reserved.
- */
-
- #include<stdio.h>
- #include<bios.h>
- #include<dos.h>
- #include<fcntl.h>
- #include<sys\types.h>
- #include<sys\stat.h>
- #include<signal.h>
- #include"port.h"
-
- #define NAK 21
- #define ACK 6
- #define SOH 1
- #define STX 2
- #define HI6 0xb6 /* 0x80 + '6'; the dreaded 16k packet introducer */
- #define EOT 4
- #define CAN 24
-
- unsigned long tick;
-
- void (interrupt far *oldtick)();
-
- void interrupt far tickhndl()
- {
- tick++;
- }
-
- sendchar(c)
- unsigned char c;
- {
- while(!((inp(basereg+STATREG)&TXMTMASK)&&(inp(basereg+MSTATREG)&CTSMASK)))
- if(_bios_keybrd(_KEYBRD_READY))
- if((_bios_keybrd(_KEYBRD_READ)&0xff)==0x03)
- quit();
- outp(basereg, c);
- }
-
- int follow;
-
- int rcharto(ticks)
- int ticks;
- {
- int c;
- tick=0L;
- while(1)
- {
- if(_bios_keybrd(_KEYBRD_READY))
- if((_bios_keybrd(_KEYBRD_READ)&0xff)==0x03)
- quit();
- if(tick>ticks)
- return(-1); /* NOTE: This is an INT!!! */
- if(follow!=index)
- {
- c=buf[follow++];
- if(follow>=TBUFSIZ)
- follow=0;
- return(c);
- }
- }
- }
-
- int calccrc(ptr, count)
- char *ptr;
- int count;
- {
- int crc, i;
- crc = 0;
- while(--count >= 0)
- {
- crc = crc ^ (int)*ptr++ << 8;
- for(i = 0; i < 8; ++i)
- if(crc & 0x8000)
- crc = crc << 1 ^ 0x1021;
- else
- crc = crc << 1;
- }
- return (crc & 0xFFFF);
- }
-
- unsigned char block[16384];
-
- rblock(size)
- int size;
- {
- unsigned long crc;
- unsigned long rcrc;
- int c, i, j, blockn, invblockn;
- crc=0;
- if((blockn=rcharto(20))==-1)
- return(-1);
- printf("Block %d: ", blockn);
- if((invblockn=rcharto(20))==-1)
- return(-1);
- for(i=0;i<size;++i)
- if((c=rcharto(60))==-1)
- {
- printf("Timeout in data phase after %d bytes.", i);
- return(-1);
- }
- else
- block[i]=c;
- if((c=rcharto(20))==-1)
- {
- printf("Timeout waiting for CRC MSB.\n");
- return(-1);
- }
- rcrc=c<<8;
- if((c=rcharto(20))==-1)
- {
- printf("Timeout waiting for CRC LSB.\n");
- return(-1);
- }
- rcrc|=c;
- crc=calccrc(block, size);
- if(((invblockn^0xff)&0xff)!=blockn)
- {
- printf("Bad complement block number.\n");
- return(-1);
- }
- if(crc!=rcrc)
- {
- printf("CRC mismatch. Here=%04x There=%04x\n", crc, rcrc);
- return(-1);
- }
- return(blockn);
- }
-
- quit()
- {
- cleanup(0);
- _dos_setvect(0x1c, oldtick);
- exit(99);
- }
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int i, j, outfd, ok, c;
- unsigned char blocknum;
- long nbytes;
- int bsize;
- index=follow=0;
- printf("Copyright (C) 1992,1993 Peter Edward Cann, all rights reserved.\n");
- printf("xmodem crc 128/1k/16k receive of %s.\n", argv[4]);
- if(argc!=5)
- {
- printf("USAGE: xmodemr <comnum> <bps> <stopbits> <file pathname>\n");
- exit(1);
- }
- if((outfd=open(argv[4], O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, S_IWRITE))==-1)
- {
- printf("Error opening file %s.\n", argv[4]);
- exit(2);
- }
- comnum=atoi(argv[1])-1;
- speed=atoi(argv[2]);
- databits='8';
- parity='n';
- stopbits=argv[3][0];
- setport();
- readset();
- oldtick=_dos_getvect(0x1c);
- signal(SIGINT, quit);
- _dos_setvect(0x1c, tickhndl);
- setup();
- ok=nbytes=0;
- for(i=0;i<10;++i)
- {
- sendchar('C');
- c=rcharto(200);
- if(c==SOH)
- {
- bsize=128;
- ok=1;
- break;
- }
- else if(c==STX)
- {
- bsize=1024;
- ok=1;
- break;
- }
- else if(c==HI6)
- {
- bsize=16384;
- ok=1;
- break;
- }
- }
- if(!ok)
- {
- printf("No SOH, STX or HI6 after 10 10-second-spaced Cs.\n");
- cleanup(0);
- _dos_setvect(0x1c, oldtick);
- exit(10);
- }
- blocknum=1;
- for(i=0;i<10;++i)
- {
- printf("\nSeeking block %d: ", blocknum);
- if((c=rblock(bsize))==blocknum)
- {
- i=0;
- if(write(outfd, block, bsize)!=bsize)
- {
- printf("Write error.\n");
- cleanup(0);
- _dos_setvect(0x1c, oldtick);
- exit(13);
- }
- nbytes+=bsize;
- printf("Successful. Bytes so far: %ld", nbytes);
- blocknum=(blocknum+1)&0xff;
- sendchar(ACK);
- }
- else if(c==-1)
- {
- while(rcharto(20)!=-1);
- sendchar(NAK);
- }
- else if(c<blocknum)
- sendchar(ACK);
- else
- {
- printf("\nSender skipped a block; cancelling transfer.\n");
- for(j=0;j<10;++j)
- sendchar(CAN);
- while(!(inp(basereg+STATREG)&TXSHMTMASK));
- cleanup(0);
- _dos_setvect(0x1c, oldtick);
- exit(14);
- }
- do
- {
- c=rcharto(200);
- if(c==CAN)
- c=rcharto(200);
- }
- while((c!=SOH)&&(c!=STX)&&(c!=HI6)&&(c!=EOT)&&(c!=CAN)&&(c!=-1));
- if(c==EOT)
- {
- sendchar(ACK);
- printf("\nTransfer successful.\n");
- close(outfd);
- while(!(inp(basereg+STATREG)&TXSHMTMASK));
- cleanup(0);
- _dos_setvect(0x1c, oldtick);
- exit(0);
- }
- if(c==SOH)
- bsize=128;
- else if(c==STX)
- bsize=1024;
- else if(c==HI6)
- bsize=16384;
- else
- {
- if(c==-1)
- printf("Timeout waiting for SOH, STX, HI6 or EOT.\n");
- else
- printf("\nReceived two consecutive CANcel codes (^X).\n");
- cleanup(0);
- _dos_setvect(0x1c, oldtick);
- exit(11);
- }
- }
- printf("Retry limit exceeded.\n");
- cleanup(0);
- _dos_setvect(0x1c, oldtick);
- exit(12);
- }
-