xtb+.c
上传用户:duobangkj
上传日期:2007-01-07
资源大小:70k
文件大小:25k
- /* xtb+.c -- CIS B+ Protocol module for XT
- This file uses 4-character tabstops
- */
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <ctype.h>
- #define NOREDEF 1 /* prevents xt.h from redefining fprint, fputc, fputs */
- #include "xt.h"
- #define min(x,y) ((int)(x)<(int)(y)?(x):(y))
- #define max(x,y) ((int)(x)>(int)(y)?(x):(y))
- #define MaskLowRange 0x01
- #define MaskHiRange 0x10
- #define Send_Ahead_Buffers 5
- #define ETX 0x3 /* ^C */
- #define DLE 0x10 /* ^P */
- #define XON 0x11 /* ^Q */
- #define XOFF 0x13 /* ^S */
- #define NAK 0x15 /* ^U */
- enum {
- Check_B,
- Check_CRC
- } ;
- enum {
- Quote_Default,
- Quote_Not_NULL,
- Quote_Extended,
- Quote_Full,
- Quote_Mask
- } ;
- enum {
- Overwrite,
- Resume
- } ;
- enum {
- Resume_Allowed,
- Resume_Not_Allowed,
- Resume_Failed,
- Resume_Denied
- } ;
- typedef enum {
- S_Get_DLE,
- S_DLE_Seen,
- S_DLE_B_Seen,
- S_Get_Data,
- S_Get_check,
- S_Get_CRC,
- S_Verify_CRC,
- S_Verify_CKS,
- S_Verify_Packet,
- S_Send_NAK,
- S_Send_ACK,
- S_Send_ENQ,
- S_Resend_Packets
- } Sender_Action;
- #define LOC_BUF 2064
- extern short cr_add;
- extern void cl_line();
- static char S_Buffer[LOC_BUF], R_Buffer[LOC_BUF], O_Buffer[2 * LOC_BUF],
- tdir[32];
- char Name[SM_BUFF];
- static unchar Mask[32];
- static unsigned Checksum;
- static int Ch, /* last char read from remote */
- Quoting, /* quoting level requested by the user */
- Window_Size, /* Send size of send ahead window */
- Packet_Size, /* Maximum block size. */
- R_Buffer_Len, O_Buffer_Len, Seq_Num, Pending_Count,
- Next_Packet, Packets_Btwn_ACKs, Last_ACK, textmode, Last_Chr,
- Send_Errors, Read_Errors;
- static short Max_Errors=10, Abort_Flag, Not_Masked, Sent_ENQ, Actual_Check,
- Valid_To_Resume_Download, Valid_To_Resume_Upload,
- Send_File_Information, Packet_Received, Result;
- static long already_have, data, total_read, total_sent,
- fsize, carriage_return;
- static time_t start;
- static FILE *Data_File;
- struct {
- int Seq;
- int Packet_Size;
- char *packet;
- } Pending[Send_Ahead_Buffers];
- /* crc_xmodem_tab calculated by Mark G. Mendel, Network Systems Corporation */
- ushort crc_xmodem_tab[256] = {
- 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
- 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
- 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
- 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
- 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
- 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
- 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
- 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
- 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
- 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
- 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
- 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
- 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
- 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
- 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
- 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
- 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
- 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
- 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
- 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
- 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
- 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
- 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
- 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
- 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
- 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
- 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
- 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
- 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
- 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
- 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
- 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
- };
- static void
- init_check()
- {
- Checksum=Actual_Check ? 0xffff : 0;
- }
- static void
- do_checksum(ch)
- unsigned ch;
- {
- if (Actual_Check==Check_B){
- Checksum<<=1;
- if (Checksum>255)
- Checksum=(Checksum&0xff)+1;
- Checksum+=ch&0xFF;
- if (Checksum>255)
- Checksum=(Checksum&0xff)+1;
- } else
- Checksum=(crc_xmodem_tab[((Checksum>>8)^ch)&0xff]^(Checksum<<8))&0xffff;
- }
- /* #define CIS_DEBUG*/ /* for B+ logging */
- #ifdef CIS_DEBUG
- static FILE *bfp;
- static void
- xtlog(dir, val)
- char dir;
- int val;
- {
- static int cnt, lastdir;
- if (!bfp)
- bfp=fopen("xtb+log","w"),
- cnt=0,
- lastdir=dir;
- if (++cnt>20||lastdir!=dir)
- fputc('n',bfp),
- cnt=1;
- if (lastdir!=dir)
- fputc('n',bfp);
- if (val>'~'||val<' ')
- fprintf(bfp,"%c%1x%1x ",dir,val/16,val%16);
- else
- fprintf(bfp,"%c%c ",dir,val);
- lastdir=dir;
- }
- static void
- Why_NAK(reason)
- char *reason;
- {
- sprintf(Msg,"Sending NAK, %s",reason);
- S0(Msg);
- }
- #else
- #define xtlog(dir,val)
- #define Why_NAK(reason)
- #endif
- static void
- stats(count)
- int count;
- {
- int rate, minutes, sec, data_percent;
- long chars, rem;
- time_t elapsed, now;
- data+=count;
- if (!fsize)
- data_percent=0;
- else
- data_percent=100*(data+carriage_return)/fsize;
- if (data_percent>100)
- data_percent=100;
- now=mtime();
- elapsed=now-start;
- chars=data+carriage_return-already_have-(tdir[0]=='T'?Packet_Size:0);
- if (elapsed<1000 || !chars)
- ttgoto(LI-6,26),
- fputs("estimating",tfp);
- else
- rate=100*chars/elapsed,
- rate*=10,
- rem=(fsize-(data+carriage_return-already_have))/rate,
- minutes=rem/60,
- sec=rem%60,
- ttgoto(LI-6,26),
- fprintf(tfp,"%8.1d:%2.2d",minutes,sec),
- elapsed/=1000,
- minutes=elapsed/60,
- sec=elapsed%60,
- ttgoto(LI-6,61),
- fprintf(tfp,"%8.1d:%2.2d",minutes,sec),
- ttgoto(LI-4,23),
- fprintf(tfp,"Rate: %d characters per second ", rate);
- ttgoto(LI-8,0),
- fprintf(tfp,"%8.1ld",total_sent),
- ttgoto(LI-8,20),
- fprintf(tfp,"%8.1ld",total_read),
- ttgoto(LI-8,40);
- if (!data_percent)
- fprintf(tfp,"%8.1ld",data);
- else
- fprintf(tfp,"%8.1ld %3.1u %%",data,data_percent);
- if (carriage_return)
- ttgoto(LI-8,60),
- fprintf(tfp,"%+7.1ld",carriage_return);
- }
- static void
- showmode()
- {
- int l;
- sprintf(Msg,"%s %s (%ld bytes) as %s",tdir,Name,fsize,
- textmode?"ASCII":"BINARY");
- ttgoto(LI-12,0);
- cl_line();
- if ((l=strlen(Msg)) < CO)
- ttgoto(LI-12,(CO-l)/2 -1);
- fputs(Msg,tfp);
- start=mtime();
- }
- static void
- Discard_ACKed_Packets()
- {
- int i, n;
- short Packet_Acked=FALSE;
- Last_ACK=Ch;
- n=(Next_Packet+Pending_Count)%Send_Ahead_Buffers;
- for (i=Pending_Count;i>0;i--){
- n--;
- if (n<0)
- n+=5;
- if (Pending[n].Seq==Ch-'0')
- Packet_Acked=TRUE,
- Next_Packet=(n+1)%Send_Ahead_Buffers;
- if (Packet_Acked==TRUE)
- free(Pending[n].packet),
- Pending[n].packet=NIL(char),
- Pending_Count--;
- }
- }
- static void
- Send_Byte(ch)
- int ch;
- {
- sendbyte(ch);
- total_sent++;
- xtlog('>',ch);
- }
- static void
- Add_Masked_Byte(ch)
- int ch;
- {
- if (ch<0x20 &&
- (Quoting==Quote_Full||(Mask[ch]&MaskLowRange)))
- O_Buffer[O_Buffer_Len++]=(char) DLE,
- ch+='@';
- else if (ch>=0x80 && ch<0xA0 &&
- (Quoting==Quote_Full||(Mask[ch-0x80]&MaskHiRange)))
- O_Buffer[O_Buffer_Len++]=(char) DLE,
- ch=ch+'`'-0x80;
- else if (ch==0xff)
- O_Buffer[O_Buffer_Len++]=(char) ch;
- O_Buffer[O_Buffer_Len++]=(char) ch;
- }
- static
- Read_Byte()
- {
- if ((Ch=readbyte(10))== -1)
- return FAILURE;
- total_read++;
- xtlog('<',Ch);
- return SUCCESS;
- }
- static
- Read_Masked_Byte()
- {
- Not_Masked=TRUE;
- if (!Read_Byte())
- return FAILURE;
- if (Ch==DLE){
- if (!Read_Byte())
- return FAILURE;
- Not_Masked=FALSE;
- if (Ch>='`')
- Ch+=0x80;
- Ch&=0x9F;
- }
- if (Ch==0xff)
- if (!Read_Byte())
- return FAILURE;
- return SUCCESS;
- }
- static void
- Send_ACK()
- {
- Send_Byte(DLE);
- Send_Byte(Seq_Num+'0');
- }
- static void
- Init()
- {
- int i;
- R_Buffer_Len=Window_Size=Pending_Count=Next_Packet=
- Seq_Num=Packets_Btwn_ACKs=Last_ACK=0;
- Packet_Size=LG_BUFF;
- Quoting=Quote_Mask;
- for (i=0;i<Send_Ahead_Buffers;i++)
- Pending[i].packet=NIL(char);
- Actual_Check=Check_B;
- Abort_Flag=Sent_ENQ=FALSE;
- memset(Mask,0,32);
- Mask[ETX]=Mask[ENQ]=Mask[DLE]=Mask[NAK]=Mask[XON]=Mask[XOFF]=MaskLowRange;
- total_sent=total_read=data=fsize=Read_Errors=Send_Errors=
- already_have=carriage_return=0;
- fputs("nnnnnnnnnnnnnnn",tfp);
- ttgoto(LI-14,25);
- S1("CIS B-Plus Protocol Transfer");
- ttgoto(LI-10,0);
- fputs("B+ Bytes Sent B+ Bytes Rcvd",tfp);
- ttgoto(LI-10,40);
- fputs("Data Bytes Carriage Returns",tfp);
- ttgoto(LI-6,10);
- fputs("Time Remaining:",tfp);
- ttgoto(LI-6,48);
- fputs("Elapsed Time:",tfp);
- }
- static void
- Xmit_Packet(Size, Seq, Packet)
- int Size, Seq;
- unchar *Packet;
- {
- register int I;
- init_check();
- O_Buffer_Len=0;
- O_Buffer[O_Buffer_Len++]=(char) DLE;
- O_Buffer[O_Buffer_Len++]=(char) 'B';
- O_Buffer[O_Buffer_Len++]=(char) Seq+'0';
- do_checksum(Seq+'0');
- for (I=0;I<Size;I++)
- Add_Masked_Byte(Packet[I]),
- do_checksum(Packet[I]);
- O_Buffer[O_Buffer_Len++]=(char) ETX;
- do_checksum(ETX);
- if (Actual_Check==Check_B)
- Add_Masked_Byte(Checksum);
- else
- Add_Masked_Byte(Checksum>>8),
- Add_Masked_Byte(Checksum&0xff);
- send_string(O_Buffer, O_Buffer_Len);
- total_sent += O_Buffer_Len;
- for (I=0;I<O_Buffer_Len;I++)
- xtlog('>',O_Buffer[I]&0xff);
- }
- static
- Wait_For_ACK(Have_DLE_B, Acknowledge, Resend)
- short Have_DLE_B, Acknowledge, Resend;
- {
- Sender_Action Action;
- int i=0, n, RCV_Num, Errors=0;
- R_Buffer_Len=0;
- Packet_Received=FALSE;
- if (Have_DLE_B)
- Action=S_DLE_B_Seen;
- else
- Action=S_Get_DLE;
- while (Errors<Max_Errors)
- switch (Action){
- case S_Get_Data:
- if (Read_Masked_Byte()==FAILURE){
- Action=S_Send_NAK;
- Why_NAK("couldn't read next data byte");
- } else if (Not_Masked && Ch==ETX)
- Action=S_Get_check;
- else if (Not_Masked && Ch==ENQ)
- Action=S_Send_ACK;
- else if (i>Packet_Size){
- Action=S_Send_NAK;
- Why_NAK("incoming buffer overflow");
- } else
- R_Buffer[i++]=Ch,
- do_checksum(Ch);
- break;
- case S_Get_DLE:
- if (Packets_Btwn_ACKs>Window_Size+2&&Pending_Count){
- Packets_Btwn_ACKs=0;
- Action=S_Send_ENQ;
- continue;
- }
- if (!Read_Byte())
- Action=S_Send_ENQ;
- else if (Ch==DLE)
- Action=S_DLE_Seen;
- else if (Ch==NAK)
- Action=S_Send_ENQ;
- else if (Ch==ENQ)
- Action=S_Send_ACK;
- else if (Ch==ETX){
- Action=S_Send_NAK;
- Why_NAK("awaiting DLE, got ETX");
- }
- break;
- case S_DLE_Seen:
- if (!Read_Byte())
- Action=S_Send_ENQ;
- else if (Ch>='0'&&Ch<='9')
- if (Sent_ENQ&&Ch==Last_ACK){
- Sent_ENQ=FALSE;
- if (!Pending_Count)
- return SUCCESS;
- else
- Action=S_Resend_Packets;
- } else {
- Discard_ACKed_Packets();
- if (Sent_ENQ)
- Action=S_Get_DLE;
- else
- return SUCCESS;
- }
- else if (Ch==';')
- Action=S_Get_DLE;
- else if (Ch=='B')
- Action=S_DLE_B_Seen;
- else if (Ch==ENQ)
- Action=S_Send_ACK;
- else
- Action=S_Get_DLE;
- break;
- case S_DLE_B_Seen:
- if (!Read_Byte()){
- Action=S_Send_NAK;
- Why_NAK("no data byte after DLE-B");
- } else if (Ch==ENQ)
- Action=S_Send_ACK;
- else {
- init_check();
- RCV_Num=Ch-'0';
- do_checksum(Ch);
- i=0;
- Action=S_Get_Data;
- }
- break;
- case S_Get_check:
- do_checksum(ETX);
- if (Read_Masked_Byte()==FAILURE){
- Action=S_Send_NAK;
- Why_NAK("no incoming checksum");
- } else if (Not_Masked&&Ch==ENQ)
- Action=S_Send_ACK;
- else if (Actual_Check==Check_CRC)
- Action=S_Get_CRC;
- else
- Action=S_Verify_CKS;
- break;
- case S_Get_CRC:
- do_checksum(Ch);
- if (Read_Masked_Byte()==FAILURE){
- Action=S_Send_NAK;
- Why_NAK("no incoming CRC value");
- } else if (Not_Masked&&Ch==ENQ)
- Action=S_Send_ACK;
- else
- Action=S_Verify_CRC;
- break;
- case S_Verify_CRC:
- do_checksum(Ch);
- if (!Checksum)
- Action=S_Verify_Packet;
- else {
- Action=S_Send_NAK;
- Why_NAK("CRC error");
- }
- break;
- case S_Verify_CKS:
- if (Checksum==Ch)
- Action=S_Verify_Packet;
- else {
- Action=S_Send_NAK;
- Why_NAK("Checksum error");
- }
- break;
- case S_Verify_Packet:
- if (RCV_Num==((Seq_Num+1)%10)||R_Buffer[0]=='F'){
- Packets_Btwn_ACKs++;
- Seq_Num=RCV_Num;
- if (Acknowledge)
- Send_ACK();
- R_Buffer_Len=i;
- Packet_Received=TRUE;
- return FAILURE;
- } else if (RCV_Num==Seq_Num)
- Action=S_Send_ACK;
- else {
- Action=S_Send_NAK;
- Why_NAK("packet out of sequence");
- }
- break;
- case S_Send_NAK:
- ttgoto(LI-2,20);
- sprintf(Msg,"Read Errors: %2.1d",++Read_Errors);
- S;
- Errors++;
- Send_Byte(NAK);
- Action=S_Get_DLE;
- break;
- case S_Send_ACK:
- Send_ACK();
- Action=S_Get_DLE;
- break;
- case S_Send_ENQ:
- ttgoto(LI-2,40);
- sprintf(Msg,"Send Errors: %2.1d",++Send_Errors);
- S;
- Errors++;
- Sent_ENQ=TRUE;
- Send_Byte(ENQ);
- Send_Byte(ENQ);
- Action=S_Get_DLE;
- break;
- case S_Resend_Packets:
- if (Resend)
- for (i=0;i<Pending_Count;i++)
- n=(Next_Packet+i)%Send_Ahead_Buffers,
- Xmit_Packet(
- Pending[n].Packet_Size,
- Pending[n].Seq,
- Pending[n].packet);
- else
- return FAILURE;
- Action=S_Get_DLE;
- break;
- }
- return FAILURE;
- }
- static void
- Send_Failure(Code, Text)
- char Code;
- char *Text;
- {
- int Len, Seq;
- S_Buffer[0]='F';
- S_Buffer[1]=Code;
- Len=2;
- while (*Text)
- S_Buffer[Len++]= *Text++;
- Seq=(Seq_Num+1)%10;
- while (Pending_Count&&Wait_For_ACK(FALSE,FALSE,FALSE))
- ;
- Xmit_Packet(Len,Seq,S_Buffer);
- do
- Wait_For_ACK(FALSE,FALSE,FALSE);
- while (Packet_Received);
- }
- static
- Flush_Pending()
- {
- while (Pending_Count)
- if (!Wait_For_ACK(FALSE,TRUE,TRUE))
- return FAILURE;
- return SUCCESS;
- }
- static void
- Send_Abort()
- {
- fclose(Data_File);
- sprintf(Msg,"Transfer abort requested");
- S0(Msg);
- Send_Failure('A',Msg);
- }
- static
- Send_Packet(Size)
- int Size;
- {
- int Next, Next_Seq;
- char *ptr = S_Buffer;
- while ((Pending_Count>Window_Size))
- if (!Wait_For_ACK(FALSE,TRUE,TRUE)){
- Send_Abort();
- return FAILURE;
- }
- Next=(Next_Packet+Pending_Count)%Send_Ahead_Buffers;
- Pending_Count++;
- Next_Seq=Seq_Num=(Seq_Num+1)%10;
- Pending[Next].Seq=Next_Seq;
- Pending[Next].packet=(char *) malloc(Size);
- memcpy(Pending[Next].packet,ptr,Size);
- Pending[Next].Packet_Size=Size;
- Packets_Btwn_ACKs=0;
- Xmit_Packet(Size,Next_Seq,S_Buffer);
- return SUCCESS;
- }
- static ulong
- cnvAtoL(ptr)
- char *ptr;
- {
- ushort sign=FALSE;
- char ch;
- ulong result=0;
- ch= *ptr++;
- if (ch=='-')
- sign=TRUE,
- ch= *ptr++;
- while (ch>='0'&&ch<='9')
- result=result*10+(ch-'0'),
- ch= *ptr++;
- return(sign?-result:result);
- }
- static
- char *cnvLtoA(ptr, n)
- char *ptr;
- ulong n;
- {
- char tmp1[11], *tmp2=tmp1;
- if (!n){
- *ptr++ ='0';
- return ptr;
- }
- *tmp2++ =0;
- do
- *tmp2++ =((char)(n%10))+'0',
- n/=10;
- while (n>0);
- tmp2--;
- while (*tmp2)
- *ptr++ = *tmp2--;
- return ptr;
- }
- static void
- Send_Unexpected_Packet()
- {
- sprintf(Msg,"Unexpected packet type");
- S0(Msg);
- Send_Failure('N',Msg);
- }
- FILE *
- QueryCreate(Offer_Resume)
- short Offer_Resume;
- {
- int key;
- short Condition;
- FILE *fileptr;
- Condition = isregfile(Name) ? Offer_Resume : Resume_Denied;
- if (access(Name,0)&&(fileptr=fopen(Name,"w"))){
- Result=Overwrite;
- return fileptr;
- } else if (access(Name,2))
- Condition = Resume_Denied;
- switch(Condition){
- case Resume_Allowed:
- sprintf(Msg,"'%s' exists; Overwrite, Resume, reName, or Abort?",Name);
- break;
- case Resume_Not_Allowed:
- sprintf(Msg,"'%s' exists; Overwrite, reName, or Abort?",Name);
- break;
- case Resume_Failed:
- sprintf(Msg,"'%s' CRC error; Overwrite, reName or Abort?",Name);
- break;
- case Resume_Denied:
- sprintf(Msg,"Permission denied for '%s'; reName, or Abort?",Name);
- break;
- }
- if (cismode)
- S0(Msg);
- else
- S2(Msg);
- for (;;){
- beep();
- key=toupper(fgetc(stdin));
- if (isupper(key)){
- fputc(key,tfp);
- switch(key){
- case 'O':
- if (Condition!=Resume_Denied){
- Result=Overwrite;
- return fopen(Name,"w");
- }
- break;
- case 'N':
- fputc('r',tfp);
- cl_line();
- show(-1,"Enter New Name:");
- getline();
- getword();
- strcpy(Name,word);
- return QueryCreate(Offer_Resume);
- case 'A':
- return NIL(FILE);
- case 'R':
- if (Condition==Resume_Allowed){
- Result=Resume;
- return fopen(Name,"r+");
- }
- break;
- }
- fputc('b',tfp);
- }
- }
- }
- static
- Read(fp, buf, want)
- FILE *fp;
- char *buf;
- register int want;
- {
- register int c;
- int read=0;
- while (want--)
- switch(c=getc(fp)){
- case EOF:
- return read;
- case 'n':
- if (cr_add&&textmode&&Last_Chr!='r')
- ungetc(c,fp),
- carriage_return++,
- c='r';
- default:
- Last_Chr= *buf++ =c;
- read++;
- }
- return read;
- }
- static
- Write(fp, buf, want)
- FILE *fp;
- char *buf;
- register int want;
- {
- int written=0;
- for (;want-->0;buf++){
- if (textmode){
- if (*buf=='r'){
- Last_Chr= *buf;
- continue;
- }
- if (Last_Chr=='r')
- if (*buf=='n')
- carriage_return--;
- else
- if (fputc('r',fp)== -1)
- return -1;
- else
- written++;
- Last_Chr= *buf;
- }
- if (fputc(*buf,fp)== -1)
- return -1;
- else
- written++;
- }
- return written;
- }
- static
- Receive_File()
- {
- char *ptr;
- int N, i;
- short Request_Resume;
- Result=Overwrite;
- if (Valid_To_Resume_Download==2)
- Request_Resume=Resume_Allowed;
- else
- Request_Resume=Resume_Not_Allowed;
- if (!(Data_File=QueryCreate(Request_Resume))){
- Send_Abort();
- return FAILURE;
- }
- if (Result==Resume){
- strcpy(tdir,"Attempting receive resume of");
- init_check();
- do {
- S_Buffer[0]='N';
- N=Read(Data_File,&S_Buffer[0],Packet_Size);
- if (N>0){
- for (i=0;i<N;i++)
- do_checksum(S_Buffer[i]);
- if (Abort_Flag){
- Send_Abort();
- return FAILURE;
- }
- already_have+=N;
- }
- } while (N>0);
- ptr= &S_Buffer[0];
- *ptr++ ='T';
- *ptr++ ='r';
- ptr=cnvLtoA(ptr,already_have);
- *ptr++ =' ';
- ptr=cnvLtoA(ptr,Checksum);
- if (!Send_Packet(ptr- &S_Buffer[0])||!Flush_Pending()){
- fclose(Data_File);
- S0("Can't resume transfer");
- return FAILURE;
- }
- fseek(Data_File,0L,2);
- strcpy(tdir,"Resuming receive of");
- data=already_have-carriage_return;
- carriage_return= -carriage_return;
- showmode();
- } else
- Send_ACK(),
- strcpy(tdir,"Receiving"),
- already_have=0;
- for (;;){
- if (Abort_Flag){
- Send_Abort();
- return FAILURE;
- }
- Wait_For_ACK(FALSE,TRUE,TRUE);
- if (Packet_Received)
- switch(R_Buffer[0]){
- case 'N':
- if ((N=Write(Data_File,&R_Buffer[1],R_Buffer_Len-1))== -1){
- sprintf(Msg,"Disk write error");
- S0(Msg);
- Send_Failure('I',Msg);
- fclose(Data_File);
- return FAILURE;
- }
- stats(N);
- break;
- case 'T':
- switch(R_Buffer[1]){
- case 'I':
- fsize=cnvAtoL(&R_Buffer[4]);
- showmode();
- break;
- case 'C':
- fclose(Data_File);
- return SUCCESS;
- case 'f':
- fclose(Data_File);
- if (!(Data_File=QueryCreate(Resume_Failed))){
- Send_Abort();
- return FAILURE;
- }
- strcpy(tdir,"Receiving");
- data=already_have=carriage_return=0;
- showmode();
- break;
- default:
- Send_Unexpected_Packet();
- fclose(Data_File);
- return FAILURE;
- }
- break;
- case 'F':
- fclose(Data_File);
- R_Buffer[R_Buffer_Len]=0;
- if (Result==Resume)
- sprintf(Msg,"Can't resume transfer: %s",&R_Buffer[3]);
- else
- sprintf(Msg,"B protocol Failure: %s",&R_Buffer[3]);
- S0(Msg);
- return FAILURE;
- default:
- Send_Unexpected_Packet();
- fclose(Data_File);
- return FAILURE;
- }
- else {
- fclose(Data_File);
- return FAILURE;
- }
- }
- }
- static char *
- Handle_Send_Failure()
- {
- if (!R_Buffer_Len)
- return("Remote is not responding");
- else {
- if (R_Buffer[0]=='F'){
- if (R_Buffer_Len>=2){
- R_Buffer[min(81,R_Buffer_Len)]=' ';
- return(&R_Buffer[1]);
- } else
- return("No reason given by remote");
- } else {
- Send_Failure('E',"Unexpected packet type");
- return("Unexpected packet type");
- }
- }
- }
- static
- Send_File()
- {
- int N;
- struct stat statbuf;
- if (!(Data_File=fopen(Name,"r"))){
- sprintf(Msg,"Can't access '%s'",Name);
- S0(Msg);
- Send_Failure('M',Msg);
- return FAILURE;
- }
- fstat(fileno(Data_File),&statbuf);
- fsize=statbuf.st_size;
- strcpy(tdir,"Transmitting");
- showmode();
- do {
- S_Buffer[0]='N';
- N=Read(Data_File,&S_Buffer[1],Packet_Size);
- if (N>0){
- if (!Send_Packet(N+1)){
- fclose(Data_File);
- S0(Handle_Send_Failure());
- return FAILURE;
- }
- if (Abort_Flag){
- Send_Abort();
- return FAILURE;
- }
- stats(N);
- }
- } while (N>0);
- if (!N){
- fclose(Data_File);
- S_Buffer[0]='T';
- S_Buffer[1]='C';
- if (!Send_Packet(2)){
- S0(Handle_Send_Failure());
- return FAILURE;
- }
- return Flush_Pending();
- } else {
- sprintf(Msg,"Disk read error");
- S0(Msg);
- Send_Failure('I',Msg);
- return FAILURE;
- }
- }
- #define Plus_Packet_Size 18
- #define LowRange 7
- #define HiRange 11
- #define My_Send_Window_Size 1
- #define My_Recv_Window_Size 1
- #define My_Buffer_Size 8
- #define My_Check_Method Check_CRC
- #define My_Download_Resume 2
- #define My_Upload_Resume 0
- #define My_File_Information 1
- static char Quote_Level_Select_Low[]={
- 1, 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 0, 0, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
- };
- static char QuotE_Level_select_Hi[]={
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
- };
- static char QUote_Level_Mapping[]={
- Quote_Not_NULL,
- Quote_Default,
- Quote_Extended,
- Quote_Full
- };
- static
- Plus_Respond()
- {
- int Status, temp_window_size, temp_method, temp_size, MaskByte, Bit, i;
- char Estimated_Quote_Level=0;
- S_Buffer[0]='+';
- S_Buffer[1]=My_Send_Window_Size;
- S_Buffer[2]=My_Recv_Window_Size;
- S_Buffer[3]=Packet_Size/128;
- S_Buffer[4]=My_Check_Method;
- S_Buffer[5]=Quote_Default;
- S_Buffer[6]=FALSE;
- S_Buffer[15]=My_Download_Resume;
- S_Buffer[16]=My_Upload_Resume;
- S_Buffer[17]=My_File_Information;
- for (i=0;i<8;i++)
- S_Buffer[i+LowRange]=0;
- for (MaskByte=0;MaskByte<4;MaskByte++)
- for (Bit=0;Bit<8;Bit++){
- if (Mask[MaskByte*8+Bit]&MaskLowRange)
- S_Buffer[MaskByte+LowRange]|=0x80>>Bit;
- if (Mask[MaskByte*8+Bit]&MaskHiRange)
- S_Buffer[MaskByte+HiRange]|=0x80>>Bit;
- }
- for (i=R_Buffer_Len;i<Plus_Packet_Size;i++)
- R_Buffer[i]=0;
- if (R_Buffer[3]<S_Buffer[3])
- temp_size=(R_Buffer[3]*128);
- else
- temp_size=(S_Buffer[3]*128);
- temp_window_size=min(R_Buffer[2],My_Send_Window_Size);
- temp_method=min(R_Buffer[4],My_Check_Method);
- Valid_To_Resume_Download=min(R_Buffer[15],My_Download_Resume);
- Valid_To_Resume_Upload=min(R_Buffer[16],My_Upload_Resume);
- Send_File_Information=min(R_Buffer[17],My_File_Information);
- if (R_Buffer_Len>=Plus_Packet_Size)
- for (MaskByte=0;MaskByte<4;MaskByte++)
- for (Bit=0;Bit<8;Bit++){
- if (R_Buffer[LowRange+MaskByte]&(0x80>>Bit))
- Mask[MaskByte*8+Bit]|=MaskLowRange;
- if (R_Buffer[HiRange+MaskByte]&(0x80>>Bit))
- Mask[MaskByte*8+Bit]|=MaskHiRange;
- }
- else {
- for (i=0;i<32&&Estimated_Quote_Level<3;i++){
- if (Mask[i]&MaskLowRange)
- Estimated_Quote_Level=
- max(Quote_Level_Select_Low[i],Estimated_Quote_Level);
- if (Mask[i]&MaskHiRange)
- Estimated_Quote_Level=
- max(QuotE_Level_select_Hi[i],Estimated_Quote_Level);
- }
- }
- Quoting=Quote_Full;
- S_Buffer[5]=QUote_Level_Mapping[Estimated_Quote_Level];
- if (Status=Send_Packet(Plus_Packet_Size))
- if (Status=Flush_Pending()){
- Actual_Check=temp_method;
- Packet_Size=temp_size;
- Window_Size=temp_window_size;
- }
- Quoting=Quote_Mask;
- return Status;
- }
- static
- Do_Transfer()
- {
- int I, N;
- short Have_DLE_B=TRUE;
- for (;;){
- Wait_For_ACK(Have_DLE_B,FALSE,TRUE);
- if (Packet_Received){
- if (R_Buffer[0]=='T'){
- if (R_Buffer[1]!='D'&&R_Buffer[1]!='U'){
- S0("Invalid transfer direction");
- Send_Failure('N',"Not implemented");
- return FAILURE;
- }
- if (R_Buffer[2]!='A'&&R_Buffer[2]!='B'){
- S0("Invalid transfer type");
- Send_Failure('N',"Not implemented");
- return FAILURE;
- }
- N=min(R_Buffer_Len-3,SM_BUFF-1);
- for (I=0;I<N;I++)
- Name[I]=R_Buffer[I+3];
- Name[I]=' ';
- textmode=(R_Buffer[2]=='A');
- if (R_Buffer[1]=='U'){
- Send_ACK();
- return Send_File();
- } else
- return Receive_File();
- } else if (R_Buffer[0]=='+'){
- if (Plus_Respond())
- Have_DLE_B=FALSE;
- else {
- S0("Could not negotiate B-Plus parameters");
- return FAILURE;
- }
- } else {
- Send_Unexpected_Packet();
- return FAILURE;
- }
- } else {
- S0("Remote is not responding");
- return FAILURE;
- }
- }
- }
- static
- RETSIGTYPE cisbsigint(junk)
- int junk;
- {
- signal(SIGINT,cisbsigint);
- Abort_Flag=TRUE;
- }
- void
- B_Transfer()
- {
- short Status=FALSE;
- RETSIGTYPE (*oldvec)();
- oldvec = signal(SIGINT,cisbsigint);
- cur_off();
- Init();
- while (readbyte(1) != -1)
- ;
- Send_Byte(DLE);
- Send_Byte('+');
- Send_Byte('+');
- Send_ACK();
- Read_Byte();
- switch(Ch){
- case DLE:
- Read_Byte();
- if (Ch=='B')
- Status=Do_Transfer();
- break;
- default:
- fputc(Ch,tfp);
- break;
- }
- sprintf(Msg,"File Transfer %s",Status?"Succeeded":"Failed");
- S0(Msg);
- beep();
- if (Abort_Flag){
- while (Read_Byte() && Ch==ENQ){
- Seq_Num=0;
- Send_Byte(DLE);
- Send_Byte('+');
- Send_Byte('+');
- Send_ACK();
- }
- }
- cur_on();
- signal(SIGINT,oldvec);
- }