home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / xc-4.1 / part02 / xcb+.c next >
Encoding:
C/C++ Source or Header  |  1993-04-13  |  22.2 KB  |  1,287 lines

  1. /*    xcb+.c -- CIS B+ Protocol module for XC
  2.     This file uses 4-character tabstops
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <signal.h>
  10. #include <time.h>
  11. #include <fcntl.h>
  12. #include <ctype.h>
  13. #define NODEBUG 1    /* prevents xc.h from defining DEBUG */
  14. #include "xc.h"
  15.  
  16. #define min(x,y)    ((int)(x)<(int)(y)?(x):(y))
  17. #define max(x,y)    ((int)(x)>(int)(y)?(x):(y))
  18. #define MaskLowRange 0x01
  19. #define MaskHiRange 0x10
  20. #define Send_Ahead_Buffers    5
  21.  
  22. enum {
  23.     Check_B,
  24.     Check_CRC
  25.     } ;
  26.  
  27. enum {
  28.     Quote_Default,
  29.     Quote_Not_NULL,
  30.     Quote_Extended,
  31.     Quote_Full,
  32.     Quote_Mask
  33.     } ;
  34.  
  35. enum {
  36.     Overwrite,
  37.     Resume
  38.     } ;
  39.  
  40. enum {
  41.     Resume_Allowed,
  42.     Resume_Not_Allowed,
  43.     Resume_Failed,
  44.     Resume_Denied
  45.     } ;
  46.  
  47. typedef enum {
  48.     S_Get_DLE,
  49.     S_DLE_Seen,
  50.     S_DLE_B_Seen,
  51.     S_Get_Data,
  52.     S_Get_check,
  53.     S_Get_CRC,
  54.     S_Verify_CRC,
  55.     S_VErify_CKS,
  56.     S_VerIfy_Packet,
  57.     S_Send_NAK,
  58.     S_SenD_ACK,
  59.     S_SEnd_ENQ,
  60.     S_Resend_Packets,
  61. } Sender_Action;
  62.  
  63. extern short cr_add;
  64. extern void cl_line();
  65. static char S_Buffer[1033], R_Buffer[1033], tdir[32];
  66. char    Name[SM_BUFF];
  67. static unchar Mask[32];
  68. static unsigned Checksum;
  69. static    Ch,                /* last char read from remote */
  70.         Quoting,        /* quoting level requested by the user */
  71.         Window_Size,    /* Send size of send ahead window */
  72.         PackeT_Size,    /* Maximum block size. */
  73.         R_BUffer_Len, S_Bytes, R_Bytes, Seq_Num, PendinG_Count,
  74.         Next_Packet, Packets_Btwn_ACKs, Last_ACK, textmode, Last_Chr,
  75.         Send_Errors, Read_Errors;
  76. static short Max_Errors=10, Abort_Flag, Not_Masked, Sent_ENQ, Actual_Check,
  77.             Valid_To_Resume_Download, ValiD_To_Resume_Upload,
  78.             Send_FIle_Information, Packet_Received, Result;
  79. static FILE *Data_File;
  80. static long    already_have, data, total_read, total_sent,
  81.             fsize, start, carriage_return;
  82.  
  83. struct {
  84.     int Seq;
  85.     int PackeT_Size;
  86.     char *packet;
  87. } Pending[Send_Ahead_Buffers];
  88.  
  89. extern ushort crc_xmodem_tab[256];
  90.  
  91. static void
  92. init_check()
  93. {
  94.     Checksum=Actual_Check ? 0xffff : 0;
  95. }
  96.  
  97. static void
  98. do_checksum(ch)
  99. unsigned ch;
  100. {
  101.     if (Actual_Check==Check_B){
  102.         Checksum<<=1;
  103.         if (Checksum>255)
  104.             Checksum=(Checksum&0xFF)+1;
  105.         Checksum+=ch&0xFF;
  106.         if (Checksum>255)
  107.             Checksum=(Checksum&0xFF)+1;
  108.     } else
  109.     Checksum=(crc_xmodem_tab[((Checksum>>8)^ch)&0xff]^(Checksum<<8))&0xffff;
  110. }
  111.  
  112. /* #define CIS_DEBUG /* for B+ logging */
  113.  
  114. #ifdef CIS_DEBUG
  115. static FILE *bfp = NIL(FILE);
  116. static void
  117. xclog(dir, val)
  118. char dir;
  119. int val;
  120. {
  121.     static int cnt, lastdir;
  122.  
  123.     if (!bfp)
  124.         bfp=fopen("xc.log","w"),
  125.         cnt=0,
  126.         lastdir=dir;
  127.  
  128.     if (++cnt>20||lastdir!=dir)
  129.         fputc('\n',bfp),
  130.         cnt=1;
  131.  
  132.     if (lastdir!=dir)
  133.         fputc('\n',bfp);
  134.  
  135.     if (val>'~'||val<' ')
  136.         fprintf(bfp,"%c%1x%1x ",dir,val/16,val%16);
  137.     else
  138.         fprintf(bfp,"%c%c  ",dir,val);
  139.  
  140.     lastdir=dir;
  141. }
  142.  
  143. static void
  144. Why_NAK(reason)
  145. char *reason;
  146. {
  147.     sprintf(Msg,"Sending NAK, %s",reason);
  148.     S0(Msg);
  149. }
  150.  
  151. #else
  152. #define xclog(dir,val)
  153. #define Why_NAK(reason)
  154. #endif
  155.  
  156. static void
  157. stats(count)
  158. int count;
  159. {
  160.     int rate, minutes, sec, data_percent, rate_percent;
  161.     long chars, elapsed, now, rem;
  162.  
  163.     data+=count;
  164.  
  165.     if (!fsize)
  166.         data_percent=0;
  167.     else
  168.         data_percent=100*(data+carriage_return)/fsize;
  169.  
  170.     if (data_percent>100)
  171.         data_percent=100;
  172.  
  173.     time(&now);
  174.  
  175.     elapsed=now-start;
  176.     chars=data+carriage_return-already_have-(tdir[0]=='T'?PackeT_Size-1:0);
  177.     if (elapsed<5 || !chars)
  178.         ttgoto(LI-6,26),
  179.         fputs("estimating",tfp);
  180.     else
  181.         rate=chars/elapsed,
  182.         rem=(fsize-(data+carriage_return-already_have))/rate,
  183.         minutes=rem/60,
  184.         sec=rem%60,
  185.         rate_percent=1000*rate/mrate(NIL(char)),
  186.  
  187.         ttgoto(LI-6,26),
  188.         fprintf(tfp,"%8.1d:%2.2d",minutes,sec),
  189.  
  190.         minutes=elapsed/60,
  191.         sec=elapsed%60,
  192.         ttgoto(LI-6,61),
  193.         fprintf(tfp,"%8.1d:%2.2d",minutes,sec),
  194.  
  195.         ttgoto(LI-4,23),
  196.         fprintf(tfp,"Rate: %d characters per second ", rate,rate_percent);
  197.  
  198.     ttgoto(LI-8,0),
  199.     fprintf(tfp,"%8.1ld",total_sent),
  200.     ttgoto(LI-8,20),
  201.     fprintf(tfp,"%8.1ld",total_read),
  202.     ttgoto(LI-8,40);
  203.     if (!data_percent)
  204.         fprintf(tfp,"%8.1ld",data);
  205.     else
  206.         fprintf(tfp,"%8.1ld %3.1u %%",data,data_percent);
  207.     if (carriage_return)
  208.         ttgoto(LI-8,60),
  209.         fprintf(tfp,"%+7.1ld",carriage_return);
  210. }
  211.  
  212. static void
  213. showmode()
  214. {
  215.     int l;
  216.     sprintf(Msg,"%s %s (%ld bytes) as %s",tdir,Name,fsize,
  217.         textmode?"ASCII":"BINARY");
  218.  
  219.     ttgoto(LI-12,0);
  220.     cl_line();
  221.     if ((l=strlen(Msg)) < CO)
  222.         ttgoto(LI-12,(CO-l)/2 -1);
  223.     fputs(Msg,tfp);
  224.  
  225.     time(&start);
  226. }
  227.  
  228. static void
  229. Discard_ACKed_Packets()
  230. {
  231.     int i, n;
  232.     short Packet_Acked=FALSE;
  233.  
  234.     Last_ACK=Ch;
  235.     n=(Next_Packet+PendinG_Count)%Send_Ahead_Buffers;
  236.  
  237.     for (i=PendinG_Count;i>0;i--){
  238.         n--;
  239.         if (n<0)
  240.             n+=5;
  241.  
  242.         if (Pending[n].Seq==Ch-'0')
  243.             Packet_Acked=TRUE,
  244.             Next_Packet=(n+1)%Send_Ahead_Buffers;
  245.  
  246.         if (Packet_Acked==TRUE)
  247.             free(Pending[n].packet),
  248.             Pending[n].packet=NIL(char),
  249.             PendinG_Count--;
  250.     }
  251. }
  252.  
  253. static void
  254. Send_Byte(ch)
  255. int ch;
  256. {
  257.     sendbyte(ch);
  258.     total_sent++;
  259.     xclog('>',ch);
  260. }
  261.  
  262. static void
  263. Send_Masked_Byte(ch)
  264. int ch;
  265. {
  266.     if (ch<0x20){
  267.         if (Quoting==Quote_Full||(Mask[ch]&MaskLowRange))
  268.             Send_Byte(DLE),
  269.             ch+='@';
  270.     } else if (ch>=0x80&&ch<0xA0&&
  271.         (Quoting==Quote_Full||(Mask[ch-0x80]&MaskHiRange)))
  272.             Send_Byte(DLE),
  273.             ch=ch+'`'-0x80;
  274.  
  275.     Send_Byte(ch);
  276. }
  277.  
  278. static
  279. Read_Byte()
  280. {
  281.     if ((Ch=readbyte(10))== -1)
  282.         return FAILURE;
  283.     total_read++;
  284.     xclog('<',Ch);
  285.     return SUCCESS;
  286. }
  287.  
  288. static
  289. Read_Masked_Byte()
  290. {
  291.     Not_Masked=TRUE;
  292.  
  293.     if (!Read_Byte())
  294.         return FAILURE;
  295.  
  296.     if (Ch==DLE){
  297.         if (!Read_Byte())
  298.             return FAILURE;
  299.  
  300.         Not_Masked=FALSE;
  301.  
  302.         if (Ch>='`')
  303.             Ch+=0x80;
  304.  
  305.         Ch&=0x9F;
  306.     }
  307.     return SUCCESS;
  308. }
  309.  
  310. static void
  311. Send_ACK()
  312. {
  313.     Send_Byte(DLE);
  314.     Send_Byte(Seq_Num+'0');
  315. }
  316.  
  317. static void
  318. Init()
  319. {
  320.     int i;
  321.  
  322.     R_BUffer_Len=Window_Size=PendinG_Count=Next_Packet=
  323.         R_Bytes=S_Bytes=Seq_Num=Packets_Btwn_ACKs=Last_ACK=0;
  324.  
  325. /*    PackeT_Size=(mrate(NIL(char))) > 1200 ? 1025 : 513; */
  326.     i=mrate(NIL(char));
  327.     PackeT_Size=(i>2400) ? 2049 : (i>1200) ? 1025 : 513;
  328.  
  329.     Quoting=Quote_Mask;
  330.  
  331.     for (i=0;i<Send_Ahead_Buffers;i++)
  332.         Pending[i].packet=NIL(char);
  333.  
  334.     Actual_Check=Check_B;
  335.     Abort_Flag=Sent_ENQ=FALSE;
  336.  
  337.     memset(Mask,0,32);
  338.  
  339.     Mask[ETX]=Mask[ENQ]=Mask[DLE]=Mask[NAK]=Mask[XON]=Mask[XOFF]=MaskLowRange;
  340.  
  341.     total_sent=total_read=data=fsize=Read_Errors=Send_Errors=
  342.         already_have=carriage_return=0;
  343.     fputs("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",tfp);
  344.     ttgoto(LI-14,25);
  345.     S1("CIS B-Plus Protocol Transfer");
  346.  
  347.     ttgoto(LI-10,0);
  348.     fputs("B+ Bytes Sent       B+ Bytes Rcvd",tfp);
  349.     ttgoto(LI-10,40);
  350.     fputs("Data Bytes          Carriage Returns",tfp);
  351.     ttgoto(LI-6,10);
  352.     fputs("Time Remaining:",tfp);
  353.     ttgoto(LI-6,48);
  354.     fputs("Elapsed Time:",tfp);
  355. }
  356.  
  357. static void
  358. Xmit_Packet(Size, Seq, Packet)
  359. int Size, Seq;
  360. unchar *Packet;
  361. {
  362.     register I;
  363.  
  364.     init_check();
  365.     Send_Byte(DLE);
  366.     Send_Byte('B');
  367.     Send_Byte(Seq+'0');
  368.     do_checksum(Seq+'0');
  369.  
  370.     for (I=0;I<Size;I++)
  371.         Send_Masked_Byte(Packet[I]),
  372.         do_checksum(Packet[I]);
  373.  
  374.     Send_Byte(ETX);
  375.     do_checksum(ETX);
  376.     if (Actual_Check==Check_B)
  377.         Send_Masked_Byte(Checksum);
  378.     else
  379.         Send_Masked_Byte(Checksum>>8),
  380.         Send_Masked_Byte(Checksum&0xff);
  381. }
  382.  
  383. static
  384. Wait_For_ACK(Have_DLE_B, Acknowledge, Resend)
  385. short Have_DLE_B, Acknowledge, Resend;
  386. {
  387.     Sender_Action Action;
  388.  
  389.     int i=0, n, RCV_Num, Errors=0;
  390.  
  391.     R_BUffer_Len=0;
  392.     Packet_Received=FALSE;
  393.  
  394.     if (Have_DLE_B)
  395.         Action=S_DLE_B_Seen;
  396.     else
  397.         Action=S_Get_DLE;
  398.  
  399.     while (Errors<Max_Errors)
  400.         switch (Action){
  401.         case S_Get_Data:
  402.             if (Read_Masked_Byte()==FAILURE){
  403.                 Action=S_Send_NAK;
  404.                 Why_NAK("couldn't read next data byte");
  405.             } else if (Not_Masked && Ch==ETX)
  406.                 Action=S_Get_check;
  407.             else if (Not_Masked && Ch==ENQ)
  408.                 Action=S_SenD_ACK;
  409.             else if (i==PackeT_Size){
  410.                 Action=S_Send_NAK;
  411.                 Why_NAK("incoming buffer overflow");
  412.             } else
  413.                 R_Buffer[i++]=Ch,
  414.                 do_checksum(Ch);
  415.             break;
  416.  
  417.         case S_Get_DLE:
  418.             if (Packets_Btwn_ACKs>Window_Size+2&&PendinG_Count){
  419.                 Packets_Btwn_ACKs=0;
  420.                 Action=S_SEnd_ENQ;
  421.                 continue;
  422.             }
  423.             if (!Read_Byte())
  424.                 Action=S_SEnd_ENQ;
  425.             else if (Ch==DLE)
  426.                 Action=S_DLE_Seen;
  427.             else if (Ch==NAK)
  428.                 Action=S_SEnd_ENQ;
  429.             else if (Ch==ENQ)
  430.                 Action=S_SenD_ACK;
  431.             else if (Ch==ETX){
  432.                 Action=S_Send_NAK;
  433.                 Why_NAK("awaiting DLE, got ETX");
  434.             }
  435.             break;
  436.  
  437.         case S_DLE_Seen:
  438.             if (!Read_Byte())
  439.                 Action=S_SEnd_ENQ;
  440.             else if (Ch>='0'&&Ch<='9')
  441.                 if (Sent_ENQ&&Ch==Last_ACK){
  442.                     Sent_ENQ=FALSE;
  443.  
  444.                     if (!PendinG_Count)
  445.                         return SUCCESS;
  446.                     else
  447.                         Action=S_Resend_Packets;
  448.                 } else {
  449.                     Discard_ACKed_Packets();
  450.                     if (Sent_ENQ)
  451.                         Action=S_Get_DLE;
  452.                     else
  453.                         return SUCCESS;
  454.                 }
  455.             else if (Ch==';')
  456.                 Action=S_Get_DLE;
  457.             else if (Ch=='B')
  458.                 Action=S_DLE_B_Seen;
  459.             else if (Ch==ENQ)
  460.                 Action=S_SenD_ACK;
  461.             else
  462.                 Action=S_Get_DLE;
  463.             break;
  464.  
  465.         case S_DLE_B_Seen:
  466.             if (!Read_Byte()){
  467.                 Action=S_Send_NAK;
  468.                 Why_NAK("no data byte after DLE-B");
  469.             } else if (Ch==ENQ)
  470.                 Action=S_SenD_ACK;
  471.             else {
  472.                 init_check();
  473.                 RCV_Num=Ch-'0';
  474.                 do_checksum(Ch);
  475.                 i=0;
  476.                 Action=S_Get_Data;
  477.             }
  478.             break;
  479.  
  480.         case S_Get_check:
  481.             do_checksum(ETX);
  482.  
  483.             if (Read_Masked_Byte()==FAILURE){
  484.                 Action=S_Send_NAK;
  485.                 Why_NAK("no incoming checksum");
  486.             } else if (Not_Masked&&Ch==ENQ)
  487.                 Action=S_SenD_ACK;
  488.             else if (Actual_Check==Check_CRC)
  489.                 Action=S_Get_CRC;
  490.             else
  491.                 Action=S_VErify_CKS;
  492.             break;
  493.  
  494.         case S_Get_CRC:
  495.             do_checksum(Ch);
  496.  
  497.             if (Read_Masked_Byte()==FAILURE){
  498.                 Action=S_Send_NAK;
  499.                 Why_NAK("no incoming CRC value");
  500.             } else if (Not_Masked&&Ch==ENQ)
  501.                 Action=S_SenD_ACK;
  502.             else
  503.                 Action=S_Verify_CRC;
  504.             break;
  505.  
  506.         case S_Verify_CRC:
  507.             do_checksum(Ch);
  508.  
  509.             if (!Checksum)
  510.                 Action=S_VerIfy_Packet;
  511.             else {
  512.                 Action=S_Send_NAK;
  513.                 Why_NAK("CRC error");
  514.             }
  515.             break;
  516.  
  517.         case S_VErify_CKS:
  518.             if (Checksum==Ch)
  519.                 Action=S_VerIfy_Packet;
  520.             else {
  521.                 Action=S_Send_NAK;
  522.                 Why_NAK("Checksum error");
  523.             }
  524.             break;
  525.  
  526.         case S_VerIfy_Packet:
  527.             if (RCV_Num==((Seq_Num+1)%10)||R_Buffer[0]=='F'){
  528.                 Packets_Btwn_ACKs++;
  529.                 Seq_Num=RCV_Num;
  530.                 if (Acknowledge)
  531.                     Send_ACK();
  532.                 R_BUffer_Len=i;
  533.                 Packet_Received=TRUE;
  534.                 return FAILURE;
  535.             } else if (RCV_Num==Seq_Num)
  536.                 Action=S_SenD_ACK;
  537.             else {
  538.                 Action=S_Send_NAK;
  539.                 Why_NAK("packet out of sequence");
  540.             }
  541.             break;
  542.  
  543.         case S_Send_NAK:
  544.             ttgoto(LI-2,20);
  545.             sprintf(Msg,"Read Errors: %2.1d",++Read_Errors);
  546.             S;
  547.             Errors++;
  548.             Send_Byte(NAK);
  549.             Action=S_Get_DLE;
  550.             break;
  551.  
  552.         case S_SenD_ACK:
  553.             Send_ACK();
  554.             Action=S_Get_DLE;
  555.             break;
  556.  
  557.         case S_SEnd_ENQ:
  558.             ttgoto(LI-2,40);
  559.             sprintf(Msg,"Send Errors: %2.1d",++Send_Errors);
  560.             S;
  561.             Errors++;
  562.             Sent_ENQ=TRUE;
  563.             Send_Byte(ENQ);
  564.             Send_Byte(ENQ);
  565.             Action=S_Get_DLE;
  566.             break;
  567.  
  568.         case S_Resend_Packets:
  569.             if (Resend)
  570.                 for (i=0;i<PendinG_Count;i++)
  571.                     n=(Next_Packet+i)%Send_Ahead_Buffers,
  572.                     Xmit_Packet(
  573.                         Pending[n].PackeT_Size,
  574.                         Pending[n].Seq,
  575.                         Pending[n].packet);
  576.             else
  577.                 return FAILURE;
  578.  
  579.             Action=S_Get_DLE;
  580.             break;
  581.         }
  582.     return FAILURE;
  583. }
  584.  
  585. static void
  586. Send_Failure(Code, Text)
  587. char Code;
  588. char *Text;
  589. {
  590.     int Len, Seq;
  591.  
  592.     S_Buffer[0]='F';
  593.     S_Buffer[1]=Code;
  594.     Len=2;
  595.     while (*Text)
  596.         S_Buffer[Len++]= *Text++;
  597.  
  598.     Seq=(Seq_Num+1)%10;
  599.  
  600.     while (PendinG_Count&&Wait_For_ACK(FALSE,FALSE,FALSE))
  601.         ;
  602.  
  603.     Xmit_Packet(Len,Seq,S_Buffer);
  604.  
  605.     do
  606.         Wait_For_ACK(FALSE,FALSE,FALSE);
  607.     while (Packet_Received);
  608. }
  609.  
  610. static
  611. Flush_Pending()
  612. {
  613.     while (PendinG_Count)
  614.         if (!Wait_For_ACK(FALSE,TRUE,TRUE))
  615.             return FAILURE;
  616.  
  617.     return SUCCESS;
  618. }
  619.  
  620. static void
  621. Send_Abort()
  622. {
  623.     fclose(Data_File);
  624.     sprintf(Msg,"Transfer abort requested");
  625.     S0(Msg);
  626.     Send_Failure('A',Msg);
  627. }
  628.  
  629. static
  630. Send_Packet(Size)
  631. int Size;
  632. {
  633.     int Next, Next_Seq;
  634.  
  635.     while ((PendinG_Count>Window_Size))
  636.         if (!Wait_For_ACK(FALSE,TRUE,TRUE)){
  637.             Send_Abort();
  638.             return FAILURE;
  639.         }
  640.  
  641.     Next=(Next_Packet+PendinG_Count)%Send_Ahead_Buffers;
  642.     PendinG_Count++;
  643.  
  644.     Next_Seq=Seq_Num=(Seq_Num+1)%10;
  645.     Pending[Next].Seq=Next_Seq;
  646.     Pending[Next].packet=strdup(S_Buffer);
  647.     Pending[Next].PackeT_Size=Size;
  648.     Packets_Btwn_ACKs=0;
  649.  
  650.     Xmit_Packet(Size,Next_Seq,S_Buffer);
  651.  
  652.     return SUCCESS;
  653. }
  654.  
  655. static ulong
  656. cnvAtoL(ptr)
  657. char *ptr;
  658. {
  659.     ushort sign=FALSE;
  660.     char ch;
  661.     ulong result=0;
  662.  
  663.     ch= *ptr++;
  664.  
  665.     if (ch=='-')
  666.         sign=TRUE,
  667.         ch= *ptr++;
  668.  
  669.     while (ch>='0'&&ch<='9')
  670.         result=result*10+(ch-'0'),
  671.         ch= *ptr++;
  672.  
  673.     return(sign?-result:result);
  674. }
  675.  
  676. static
  677. char *cnvLtoA(ptr, n)
  678. char *ptr;
  679. ulong n;
  680. {
  681.     char tmp1[11], *tmp2=tmp1;
  682.  
  683.     if (!n){
  684.         *ptr++ ='0';
  685.         return ptr;
  686.     }
  687.  
  688.     *tmp2++ =0;
  689.     do 
  690.         *tmp2++ =((char)(n%10))+'0',
  691.         n/=10;
  692.     while (n>0);
  693.  
  694.     tmp2--;
  695.     while (*tmp2)
  696.         *ptr++ = *tmp2--;
  697.  
  698.     return ptr;
  699. }
  700.  
  701. static void
  702. Send_Unexpected_Packet()
  703. {
  704.     sprintf(Msg,"Unexpected packet type");
  705.     S0(Msg);
  706.     Send_Failure('N',Msg);
  707. }
  708.  
  709. FILE *
  710. QueryCreate(Offer_Resume)
  711. short Offer_Resume;
  712. {
  713.     int key;
  714.     short Condition;
  715.     FILE *fileptr;
  716.  
  717.     Condition = isregfile(Name) ? Offer_Resume : Resume_Denied;
  718.  
  719.     if (access(Name,0)&&(fileptr=fopen(Name,"w"))){
  720.         Result=Overwrite;
  721.         return fileptr;
  722.     } else if (access(Name,2))
  723.         Condition = Resume_Denied;
  724.  
  725.     switch(Condition){
  726.     case Resume_Allowed:
  727.         sprintf(Msg,"'%s' exists; Overwrite, Resume, reName, or Abort?",Name);
  728.         break;
  729.  
  730.     case Resume_Not_Allowed:
  731.         sprintf(Msg,"'%s' exists; Overwrite, reName, or Abort?",Name);
  732.         break;
  733.  
  734.     case Resume_Failed:
  735.         sprintf(Msg,"'%s' CRC error; Overwrite, reName or Abort?",Name);
  736.         break;
  737.  
  738.     case Resume_Denied:
  739.         sprintf(Msg,"Permission denied for '%s'; reName, or Abort?",Name);
  740.         break;
  741.     }
  742.     if (cismode)
  743.         S0(Msg);
  744.     else
  745.         S2(Msg);
  746.  
  747.     for (;;){
  748.         beep();
  749.         key=toupper(fgetc(stdin));
  750.         if (isupper(key)){
  751.             fputc(key,tfp);
  752.  
  753.             switch(key){
  754.             case 'O':
  755.                 if (Condition!=Resume_Denied){
  756.                     Result=Overwrite;
  757.                     return fopen(Name,"w");
  758.                 }
  759.                 break;
  760.  
  761.             case 'N':
  762.                 fputc('\r',tfp);
  763.                 cl_line();
  764.                 show(-1,"Enter New Name:");
  765.                 getline();
  766.                 getword();
  767.                 strcpy(Name,word);
  768.                 return QueryCreate(Offer_Resume);
  769.  
  770.             case 'A':
  771.                 return NIL(FILE);
  772.  
  773.             case 'R':
  774.                 if (Condition==Resume_Allowed){
  775.                     Result=Resume;
  776.                     return fopen(Name,"r+");
  777.                 }
  778.                 break;
  779.             }
  780.             fputc('\b',tfp);
  781.         }
  782.     }
  783. }
  784.  
  785. static
  786. Read(fp, buf, want)
  787. FILE *fp;
  788. char *buf;
  789. register int want;
  790. {
  791.     register c;
  792.     int read=0;
  793.  
  794.     while (want--)
  795.         switch(c=getc(fp)){
  796.         case EOF:
  797.             return read;
  798.  
  799.         case '\n':
  800.             if (cr_add&&textmode&&Last_Chr!='\r')
  801.                 ungetc(c,fp),
  802.                 carriage_return++,
  803.                 c='\r';
  804.  
  805.         default:
  806.             Last_Chr= *buf++ =c;
  807.             read++;
  808.         }
  809.  
  810.     return read;
  811. }
  812.  
  813. static
  814. Write(fp, buf, want)
  815. FILE *fp;
  816. char *buf;
  817. register int want;
  818. {
  819.     int written=0;
  820.  
  821.     for (;want-->0;buf++){
  822.         if (textmode){
  823.             if (*buf=='\r'){
  824.                 Last_Chr= *buf;
  825.                 continue;
  826.             }
  827.             if (Last_Chr=='\r')
  828.                 if (*buf=='\n')
  829.                     carriage_return--;
  830.                 else
  831.                     if (fputc('\r',fp)== -1)
  832.                         return -1;
  833.                     else
  834.                         written++;
  835.  
  836.             Last_Chr= *buf;
  837.         }
  838.  
  839.     if (fputc(*buf,fp)== -1)
  840.         return -1;
  841.     else
  842.         written++;
  843.     }
  844.  
  845.     return written;
  846. }
  847.  
  848. static
  849. Receive_File()
  850. {
  851.     char *ptr;
  852.     int N, i;
  853.     short Request_Resume;
  854.  
  855.     Result=Overwrite;
  856.     if (Valid_To_Resume_Download==2)
  857.         Request_Resume=Resume_Allowed;
  858.     else
  859.         Request_Resume=Resume_Not_Allowed;
  860.  
  861.     if (!(Data_File=QueryCreate(Request_Resume))){
  862.         Send_Abort();
  863.         return FAILURE;
  864.     }
  865.  
  866.     chown(Name,getuid(),getgid());
  867.  
  868.     if (Result==Resume){
  869.         strcpy(tdir,"Attempting receive resume of");
  870.         showmode();
  871.  
  872.         init_check();
  873.  
  874.         do {
  875.             S_Buffer[0]='N';
  876.             N=Read(Data_File,&S_Buffer[0],PackeT_Size-1);
  877.  
  878.             if (N>0){
  879.                 for (i=0;i<N;i++)
  880.                     do_checksum(S_Buffer[i]);
  881.                 if (Abort_Flag){
  882.                     Send_Abort();
  883.                     return FAILURE;
  884.                 }
  885.  
  886.                 already_have+=N;
  887.             }
  888.         } while (N>0);
  889.  
  890.         ptr= &S_Buffer[0];
  891.  
  892.         *ptr++ ='T';
  893.         *ptr++ ='r';
  894.  
  895.         ptr=cnvLtoA(ptr,already_have);
  896.         *ptr++ =' ';
  897.         ptr=cnvLtoA(ptr,Checksum);
  898.  
  899.         if (!Send_Packet(ptr- &S_Buffer[0])||!Flush_Pending()){
  900.             fclose(Data_File);
  901.             S0("Can't resume transfer");
  902.             return FAILURE;
  903.         }
  904.  
  905.         fseek(Data_File,0L,2);
  906.  
  907.         strcpy(tdir,"Resuming receive of");
  908.         data=already_have-carriage_return;
  909.         carriage_return= -carriage_return;
  910.         showmode();
  911.     } else
  912.         Send_ACK(),
  913.         strcpy(tdir,"Receiving"),
  914.         already_have=0;
  915.  
  916.     for (;;){
  917.         if (Abort_Flag){
  918.             Send_Abort();
  919.             return FAILURE;
  920.         }
  921.  
  922.         Wait_For_ACK(FALSE,TRUE,TRUE);
  923.  
  924.         if (Packet_Received)
  925.             switch(R_Buffer[0]){
  926.             case 'N':
  927.                 if ((N=Write(Data_File,&R_Buffer[1],R_BUffer_Len-1))== -1){
  928.                     sprintf(Msg,"Disk write error");
  929.                     S0(Msg);
  930.                     Send_Failure('I',Msg);
  931.                     fclose(Data_File);
  932.                     return FAILURE;
  933.                 }
  934.  
  935.                 stats(N);
  936.                 break;
  937.  
  938.             case 'T':
  939.                 switch(R_Buffer[1]){
  940.                 case 'I':
  941.                     fsize=cnvAtoL(&R_Buffer[4]);
  942.                     showmode();
  943.                     break;
  944.  
  945.                 case 'C':
  946.                     fclose(Data_File);
  947.                     return SUCCESS;
  948.  
  949.                 case 'f':
  950.                     fclose(Data_File);
  951.  
  952.                     if (!(Data_File=QueryCreate(Resume_Failed))){
  953.                         Send_Abort();
  954.                         return FAILURE;
  955.                     }
  956.  
  957.                     chown(Name,getuid(),getgid());
  958.                     strcpy(tdir,"Receiving");
  959.                     data=already_have=carriage_return=0;
  960.                     showmode();
  961.                     break;
  962.  
  963.                 default:
  964.                     Send_Unexpected_Packet();
  965.                     fclose(Data_File);
  966.                     return FAILURE;
  967.                 }
  968.                 break;
  969.  
  970.             case 'F':
  971.                 fclose(Data_File);
  972.                 R_Buffer[R_BUffer_Len]=0;
  973.  
  974.                 if (Result==Resume)
  975.                     sprintf(Msg,"Can't resume transfer: %s",&R_Buffer[3]);
  976.                 else
  977.                     sprintf(Msg,"B protocol Failure: %s",&R_Buffer[3]);
  978.  
  979.                 S0(Msg);
  980.                 return FAILURE;
  981.  
  982.             default:
  983.                 Send_Unexpected_Packet();
  984.                 fclose(Data_File);
  985.                 return FAILURE;
  986.             }
  987.         else {
  988.             fclose(Data_File);
  989.             return FAILURE;
  990.         }
  991.     }
  992. }
  993.  
  994. static char *
  995. Handle_Send_Failure()
  996. {
  997.     if (!R_BUffer_Len)
  998.         return("Remote is not responding");
  999.     else {
  1000.         if (R_Buffer[0]=='F'){
  1001.             if (R_BUffer_Len>=2){
  1002.                     R_Buffer[min(81,R_BUffer_Len)]='\0';
  1003.                     return(&R_Buffer[1]);
  1004.                 } else
  1005.                     return("No reason given by remote");
  1006.         } else {
  1007.             Send_Failure('E',"Unexpected packet type");
  1008.             return("Unexpected packet type");
  1009.         }
  1010.     }
  1011. }
  1012.  
  1013. static
  1014. Send_File()
  1015. {
  1016.     int N;
  1017.     struct stat statbuf;
  1018.  
  1019.     if (!(Data_File=fopen(Name,"r"))){
  1020.         sprintf(Msg,"Can't access '%s'",Name);
  1021.         S0(Msg);
  1022.         Send_Failure('M',Msg);
  1023.         return FAILURE;
  1024.     }
  1025.  
  1026.     fstat(fileno(Data_File),&statbuf);
  1027.     fsize=statbuf.st_size;
  1028.  
  1029.     strcpy(tdir,"Transmitting");
  1030.     showmode();
  1031.  
  1032.     do {
  1033.         S_Buffer[0]='N';
  1034.         N=Read(Data_File,&S_Buffer[1],PackeT_Size-1);
  1035.  
  1036.         if (N>0){
  1037.             if (!Send_Packet(N+1)){
  1038.                 fclose(Data_File);
  1039.                 S0(Handle_Send_Failure());
  1040.                 return FAILURE;
  1041.             }
  1042.  
  1043.             if (Abort_Flag){
  1044.                 Send_Abort();
  1045.                 return FAILURE;
  1046.             }
  1047.  
  1048.             stats(N);
  1049.         }
  1050.     } while (N>0);
  1051.  
  1052.     if (!N){
  1053.         fclose(Data_File);
  1054.         S_Buffer[0]='T';
  1055.         S_Buffer[1]='C';
  1056.  
  1057.         if (!Send_Packet(2)){
  1058.             S0(Handle_Send_Failure());
  1059.             return FAILURE;
  1060.         }
  1061.  
  1062.         return Flush_Pending();
  1063.     } else {
  1064.         sprintf(Msg,"Disk read error");
  1065.         S0(Msg);
  1066.         Send_Failure('I',Msg);
  1067.         return FAILURE;
  1068.     }
  1069. }
  1070.  
  1071. #define Plus_PackeT_Size    18
  1072. #define LowRange        7
  1073. #define HiRange            11
  1074.  
  1075. #define My_Send_Window_Size    1
  1076. #define My_Recv_Window_Size    1
  1077. #define My_Buffer_Size        8
  1078. #define My_Check_Method        Check_CRC
  1079. #define My_Download_Resume    2
  1080. #define My_Upload_Resume    0
  1081. #define My_File_Information    1
  1082.  
  1083. static char Quote_Level_Select_Low[]={
  1084.     1, 3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1085.     0, 0, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  1086. };
  1087.  
  1088.  
  1089. static char QuotE_Level_select_Hi[]={
  1090.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  1091.     3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  1092. };
  1093.  
  1094. static char QUote_Level_Mapping[]={
  1095.     Quote_Not_NULL,
  1096.     Quote_Default,
  1097.     Quote_Extended,
  1098.     Quote_Full
  1099. };
  1100.  
  1101. static
  1102. Plus_Respond()
  1103. {
  1104.     int Status, temp_window_size, temp_method, temp_size, MaskByte, Bit, i;
  1105.     char Estimated_Quote_Level=0;
  1106.  
  1107.     S_Buffer[0]='+';
  1108.     S_Buffer[1]=My_Send_Window_Size;
  1109.     S_Buffer[2]=My_Recv_Window_Size;
  1110.  
  1111.     S_Buffer[3]=PackeT_Size/128;
  1112.  
  1113.     S_Buffer[4]=My_Check_Method;
  1114.  
  1115.     S_Buffer[5]=Quote_Default;
  1116.     S_Buffer[6]=FALSE;
  1117.  
  1118.     S_Buffer[15]=My_Download_Resume;
  1119.     S_Buffer[16]=My_Upload_Resume;
  1120.     S_Buffer[17]=My_File_Information;
  1121.  
  1122.     for (i=0;i<8;i++)
  1123.         S_Buffer[i+LowRange]=0;
  1124.  
  1125.     for (MaskByte=0;MaskByte<4;MaskByte++)
  1126.         for (Bit=0;Bit<8;Bit++){
  1127.             if (Mask[MaskByte*8+Bit]&MaskLowRange)
  1128.                 S_Buffer[MaskByte+LowRange]|=0x80>>Bit;
  1129.  
  1130.             if (Mask[MaskByte*8+Bit]&MaskHiRange)
  1131.                 S_Buffer[MaskByte+HiRange]|=0x80>>Bit;
  1132.         }
  1133.  
  1134.     for (i=R_BUffer_Len;i<Plus_PackeT_Size;i++)
  1135.         R_Buffer[i]=0;
  1136.  
  1137.     if (R_Buffer[3]<S_Buffer[3])
  1138.         temp_size=(R_Buffer[3]*128)+1;
  1139.     else
  1140.         temp_size=(S_Buffer[3]*128)+1;
  1141.  
  1142.  
  1143.     temp_window_size=min(R_Buffer[2],My_Send_Window_Size);
  1144.     temp_method=min(R_Buffer[4],My_Check_Method);
  1145.     Valid_To_Resume_Download=min(R_Buffer[15],My_Download_Resume);
  1146.     ValiD_To_Resume_Upload=min(R_Buffer[16],My_Upload_Resume);
  1147.     Send_FIle_Information=min(R_Buffer[17],My_File_Information);
  1148.  
  1149.     if (R_BUffer_Len>=Plus_PackeT_Size)
  1150.         for (MaskByte=0;MaskByte<4;MaskByte++)
  1151.             for (Bit=0;Bit<8;Bit++){
  1152.                 if (R_Buffer[LowRange+MaskByte]&(0x80>>Bit))
  1153.                     Mask[MaskByte*8+Bit]|=MaskLowRange;
  1154.  
  1155.                 if (R_Buffer[HiRange+MaskByte]&(0x80>>Bit))
  1156.                     Mask[MaskByte*8+Bit]|=MaskHiRange;
  1157.             }
  1158.     else {
  1159.         for (i=0;i<32&&Estimated_Quote_Level<3;i++){
  1160.             if (Mask[i]&MaskLowRange)
  1161.                 Estimated_Quote_Level=
  1162.                     max(Quote_Level_Select_Low[i],Estimated_Quote_Level);
  1163.  
  1164.             if (Mask[i]&MaskHiRange)
  1165.                 Estimated_Quote_Level=
  1166.                     max(QuotE_Level_select_Hi[i],Estimated_Quote_Level);
  1167.         }
  1168.     }
  1169.  
  1170.     Quoting=Quote_Full;
  1171.     S_Buffer[5]=QUote_Level_Mapping[Estimated_Quote_Level];
  1172.  
  1173.     if (Status=Send_Packet(Plus_PackeT_Size))
  1174.         if (Status=Flush_Pending()){
  1175.             Actual_Check=temp_method;
  1176.             PackeT_Size=temp_size;
  1177.             Window_Size=temp_window_size;
  1178.         }
  1179.     Quoting=Quote_Mask;
  1180.  
  1181.     return Status;
  1182. }
  1183.  
  1184. static
  1185. Do_Transfer()
  1186. {
  1187.     int I, N;
  1188.     short Have_DLE_B=TRUE;
  1189.  
  1190.     for (;;){
  1191.         Wait_For_ACK(Have_DLE_B,FALSE,TRUE);
  1192.         if (Packet_Received){
  1193.             if (R_Buffer[0]=='T'){
  1194.                 if (R_Buffer[1]!='D'&&R_Buffer[1]!='U'){
  1195.                     S0("Invalid transfer direction");
  1196.                     Send_Failure('N',"Not implemented");
  1197.                     return FAILURE;
  1198.                 }
  1199.                 if (R_Buffer[2]!='A'&&R_Buffer[2]!='B'){
  1200.                     S0("Invalid transfer type");
  1201.                     Send_Failure('N',"Not implemented");
  1202.                     return FAILURE;
  1203.                 }
  1204.                 N=min(R_BUffer_Len-3,SM_BUFF-1);
  1205.                 for (I=0;I<N;I++)
  1206.                     Name[I]=R_Buffer[I+3];
  1207.                 Name[I]='\0';
  1208.                 textmode=(R_Buffer[2]=='A');
  1209.  
  1210.                 if (R_Buffer[1]=='U'){
  1211.                     Send_ACK();
  1212.                     return Send_File();
  1213.                 } else
  1214.                     return Receive_File();
  1215.  
  1216.             } else if (R_Buffer[0]=='+'){
  1217.                 if (Plus_Respond())
  1218.                     Have_DLE_B=FALSE;
  1219.                 else {
  1220.                     S0("Could not negotiate B-Plus parameters");
  1221.                     return FAILURE;
  1222.                 }
  1223.             } else {
  1224.                 Send_Unexpected_Packet();
  1225.                 return FAILURE;
  1226.             }
  1227.         } else {
  1228.             S0("Remote is not responding");
  1229.             return FAILURE;
  1230.         }
  1231.     }
  1232. }
  1233.  
  1234. static
  1235. void cisbsigint(junk)
  1236. int junk;
  1237. {
  1238.     signal(SIGINT,cisbsigint);
  1239.     Abort_Flag=TRUE;
  1240. }
  1241.  
  1242. void
  1243. B_Transfer()
  1244. {
  1245.     short Status=FALSE;
  1246.     void (*oldvec)();
  1247.  
  1248.     oldvec = signal(SIGINT,cisbsigint);
  1249.     cur_off();
  1250.     Init();
  1251.     purge();
  1252.     Send_Byte(DLE);
  1253.     Send_Byte('+');
  1254.     Send_Byte('+');
  1255.     Send_ACK();
  1256.  
  1257.     Read_Byte();
  1258.     switch(Ch){
  1259.     case DLE:
  1260.         Read_Byte();
  1261.         if (Ch=='B')
  1262.             Status=Do_Transfer();
  1263.         break;
  1264.  
  1265.     default:
  1266.         fputc(Ch,tfp);
  1267.         break;
  1268.     }
  1269.  
  1270.     sprintf(Msg,"File Transfer %s",Status?"Succeeded":"Failed");
  1271.     S0(Msg);
  1272.     beep();
  1273.  
  1274.     if (Abort_Flag){
  1275.         while (Read_Byte() && Ch==ENQ){
  1276.             Seq_Num=0;
  1277.             Send_Byte(DLE);
  1278.             Send_Byte('+');
  1279.             Send_Byte('+');
  1280.             Send_ACK();
  1281.         }
  1282.     }
  1283.  
  1284.     cur_on();
  1285.     signal(SIGINT,oldvec);
  1286. }
  1287.