YMODEM.MOD 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * YMODEM.MOD - COMMS Toolkit YMODEM file protocol *
  5. * *
  6. * COPYRIGHT (C) 1988..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. IMPLEMENTATION MODULE YModem;
  11. IMPORT CommUtil,Filenames,FIO,FTSupport,Lib,RS232,SPRINTF,Str;
  12. FROM FTSupport IMPORT ACK,CAN,CRCREQ,EOT,NAK,SOH,STX;
  13. (* This module is basically just a modified XModem module - simple *)
  14. (* Ymodem especially is just Xmodem with 1k blocks. The Seperate *)
  15. (* Xmodem is just for clarity.. *)
  16. VAR
  17. f : FIO.File;
  18. Response : CHAR;
  19. CRCCheck,
  20. ResponseWaiting,
  21. NoACKS : BOOLEAN;
  22. LastBlockNo,BlockNo,
  23. BlockSize : CARDINAL;
  24. (*..................................................*)
  25. PROCEDURE InitVars(VAR Filename:ARRAY OF CHAR);
  26. BEGIN
  27. FTSupport.Errors:=0;
  28. FTSupport.LastMessage:='';
  29. FTSupport.XferMode := 'CRC';
  30. FTSupport.Transferred:=0;
  31. FTSupport.Aborted := FALSE;
  32. FTSupport.SizeInBytes:=0;
  33. Str.Copy(FTSupport.FileSpec,Filename);
  34. BlockNo:=1;
  35. LastBlockNo:=0FFFFH;
  36. BlockSize:=128;
  37. CRCCheck:=TRUE;
  38. END InitVars;
  39. (*...............................................*)
  40. PROCEDURE ReceiveData():CARDINAL;
  41. VAR
  42. c : CHAR;
  43. RxBlk,CRC,RxCRC,
  44. CheckSum,Result,
  45. Cnt,CRCIndex : CARDINAL;
  46. RxState : (Blk,Compl,Data,Chk,CRCH,CRCL,Flushing);
  47. BEGIN
  48. (* Already had the first character SOH or STX *)
  49. RxState:=Blk;
  50. CRC:=0;
  51. CheckSum:=0;
  52. Cnt:=0;
  53. Result:=0;
  54. LOOP
  55. IF FTSupport.Aborted THEN
  56. RETURN(128+6);
  57. END;
  58. IF NOT RS232.SerialRead(c,50) THEN
  59. IF RxState=Flushing THEN
  60. RETURN(Result);
  61. ELSE
  62. FTSupport.LastMessage := 'Timeout';
  63. RETURN(3);
  64. END;
  65. END;
  66. CASE RxState OF
  67. Blk : RxBlk := ORD(c);
  68. RxState := Compl; |
  69. Compl : IF 255-ORD(c)<>RxBlk THEN
  70. Result:=11;
  71. FTSupport.LastMessage:='Bad Block No';
  72. RxState:=Flushing;
  73. ELSIF RxBlk=LastBlockNo THEN
  74. Result := 15;
  75. RxState := Data;
  76. ELSIF RxBlk<>BlockNo THEN
  77. Result := 128+10;
  78. FTSupport.LastMessage := 'Sequence Error';
  79. RxState := Flushing;
  80. ELSE
  81. RxState := Data;
  82. END; |
  83. Data : FTSupport.FBuff[Cnt] := c;
  84. IF CRCCheck THEN
  85. CRCIndex := CARDINAL(BITSET(CRC>>8)/BITSET(ORD(c)));
  86. CRC := CARDINAL(BITSET(FTSupport.CRCTable[CRCIndex])/BITSET(CRC<<8))
  87. ELSE
  88. CheckSum := (CheckSum+ORD(c)) MOD 100H;
  89. END;
  90. INC(Cnt);
  91. IF Cnt=BlockSize THEN
  92. IF CRCCheck THEN
  93. RxState:=CRCH;
  94. ELSE
  95. RxState:=Chk;
  96. END;
  97. END; |
  98. Chk : IF ORD(c)=CheckSum THEN
  99. RETURN Result;
  100. ELSE
  101. Result := 8;
  102. FTSupport.LastMessage := 'Bad Checksum';
  103. RxState := Flushing;
  104. END; |
  105. CRCH : RxCRC := ORD(c)<<8;
  106. RxState := CRCL; |
  107. CRCL : RxCRC := RxCRC+ORD(c);
  108. IF CRC=RxCRC THEN
  109. RETURN Result;
  110. ELSE
  111. Result := 9;
  112. FTSupport.LastMessage := 'Bad CRC';
  113. RxState := Flushing;
  114. END; |
  115. Flushing : (* do nothing *) |
  116. END; (* case *)
  117. END; (* loop *)
  118. END ReceiveData;
  119. (*...............................................*)
  120. PROCEDURE YMReceive(OneBlockOnly:BOOLEAN):CARDINAL;
  121. VAR
  122. c : CHAR;
  123. EOTCount,Result : CARDINAL;
  124. IncomingData,
  125. Negotiating,
  126. EndOfFile,Skippit : BOOLEAN;
  127. BEGIN
  128. Negotiating:=TRUE;
  129. EOTCount:=0;
  130. Skippit:=FALSE;
  131. EndOfFile:=FALSE;
  132. REPEAT
  133. IncomingData := FALSE;
  134. REPEAT
  135. FTSupport.UpdateStatus;
  136. IF FTSupport.Aborted THEN
  137. RETURN(6);
  138. END;
  139. IF (NOT Skippit) AND ((Response<>ACK) OR (NOT NoACKS)) THEN
  140. RS232.SerialWrite(Response,1);
  141. END;
  142. Skippit := FALSE;
  143. LOOP
  144. IF RS232.SerialRead(c,100) THEN
  145. IF (c=SOH) OR (c=EOT) OR (c=STX) THEN
  146. FTSupport.LastMessage:='';
  147. Negotiating:=FALSE;
  148. IncomingData := TRUE;
  149. EXIT;
  150. END;
  151. ELSE
  152. Response := NAK;
  153. IF NOT NoACKS THEN
  154. RS232.SerialWrite(Response,1);
  155. END;
  156. FTSupport.LastMessage := 'Timeout';
  157. INC(FTSupport.Errors);
  158. IF (NoACKS) OR (FTSupport.Errors>1) THEN
  159. IF Negotiating THEN
  160. RETURN(1);
  161. ELSE
  162. RETURN(2);
  163. END;
  164. END;
  165. EXIT;
  166. END;
  167. END;
  168. UNTIL IncomingData;
  169. IF c=EOT THEN
  170. FTSupport.LastMessage := 'End of File';
  171. INC(EOTCount);
  172. IF (EOTCount=2) OR (NoACKS) THEN
  173. EndOfFile := TRUE;
  174. Response:=ACK;
  175. RS232.SerialWrite(Response,1);
  176. ELSE
  177. Response:=NAK
  178. END;
  179. ELSE
  180. EOTCount:=0;
  181. IF (c=SOH) THEN
  182. BlockSize:=128;
  183. ELSE
  184. BlockSize:=1024;
  185. END;
  186. Result := ReceiveData();
  187. IF Result=0 THEN
  188. (* ACK good blocks immediately so that the background receiver can*)
  189. (* be getting the next packet while we write this one to disk. *)
  190. Response := ACK;
  191. IF NOT NoACKS THEN
  192. RS232.SerialWrite(Response,1);
  193. END;
  194. Skippit := TRUE;
  195. LastBlockNo := BlockNo;
  196. BlockNo := (BlockNo+1) MOD 100H;
  197. IF OneBlockOnly THEN
  198. RETURN(0);
  199. END;
  200. IF FTSupport.SizeInBytes>0 THEN
  201. IF FTSupport.Transferred+LONGCARD(BlockSize)>FTSupport.SizeInBytes THEN
  202. BlockSize := CARDINAL(FTSupport.SizeInBytes-FTSupport.Transferred);
  203. END;
  204. END;
  205. FIO.WrBin(f,FTSupport.FBuff,BlockSize);
  206. IF FIO.IOresult()<>0 THEN
  207. FTSupport.LastMessage := 'Disk Write Error';
  208. FTSupport.UpdateStatus;
  209. RETURN(4);
  210. END;
  211. FTSupport.Transferred := FTSupport.Transferred+LONGCARD(BlockSize);
  212. FTSupport.Errors:=0;
  213. FTSupport.LastMessage:='';
  214. FTSupport.UpdateStatus;
  215. ELSIF Result=15 THEN
  216. (* Sender resent previous block - ACK and ignore *)
  217. Response := ACK;
  218. FTSupport.Errors := 0;
  219. FTSupport.LastMessage := '';
  220. FTSupport.UpdateStatus;
  221. ELSE
  222. INC(FTSupport.Errors);
  223. FTSupport.UpdateStatus;
  224. IF (Result>127) OR NoACKS (*fatal*) THEN
  225. FTSupport.Aborted := TRUE;
  226. RETURN(Result MOD 100H);
  227. END;
  228. Response := NAK;
  229. IF FTSupport.Errors>5 (* too many *) THEN
  230. RETURN(Result);
  231. END;
  232. END;
  233. END;
  234. UNTIL EndOfFile OR FTSupport.Aborted;
  235. IF FTSupport.Aborted THEN
  236. RETURN(6);
  237. ELSE
  238. RETURN(0);
  239. END;
  240. END YMReceive;
  241. (*...............................................*)
  242. PROCEDURE YModemReceive(VAR Filename:ARRAY OF CHAR):CARDINAL;
  243. VAR
  244. Result : CARDINAL;
  245. HookSave : BOOLEAN;
  246. BEGIN
  247. InitVars(Filename);
  248. FTSupport.CompleteFilename;
  249. f := FIO.Create(FTSupport.FileSpec);
  250. IF FIO.IOresult()=0 THEN
  251. HookSave := RS232.Hooked;
  252. RS232.Hooked := FTSupport.HookOnFT;
  253. FTSupport.OpenStatusWindow('YModem Download');
  254. FTSupport.NewFilename;
  255. Response := CRCREQ;
  256. Result := YMReceive(FALSE);
  257. IF Result=1 THEN
  258. CRCCheck:=FALSE;
  259. FTSupport.XferMode:='CHK';
  260. Response := NAK;
  261. Result := YMReceive(FALSE);
  262. END;
  263. FIO.Close(f);
  264. IF FTSupport.Aborted THEN
  265. FTSupport.Cancel;
  266. END;
  267. FTSupport.CloseStatusWindow;
  268. RS232.Hooked := HookSave;
  269. RETURN Result;
  270. ELSE
  271. CommUtil.ErrorMessage('Could not open file!');
  272. RETURN 12;
  273. END;
  274. END YModemReceive;
  275. (*..................................................*)
  276. PROCEDURE GetFileDetails(VAR Filename:ARRAY OF CHAR; VAR Size:LONGCARD);
  277. VAR
  278. i : CARDINAL;
  279. c : CHAR;
  280. BEGIN
  281. i := 0;
  282. REPEAT
  283. c := FTSupport.FBuff[i];
  284. Filename[i] := c;
  285. INC(i);
  286. UNTIL c = 0C;
  287. Size := 0;
  288. c := FTSupport.FBuff[i];
  289. WHILE (c>='0') AND (c<='9') DO
  290. Size := Size*10 + LONGCARD(ORD(c)-48);
  291. INC(i);
  292. c := FTSupport.FBuff[i];
  293. END;
  294. END GetFileDetails;
  295. (*...............................................*)
  296. PROCEDURE YModemBatchReceive():CARDINAL;
  297. VAR
  298. c : CHAR;
  299. Result : CARDINAL;
  300. HookSave : BOOLEAN;
  301. BEGIN
  302. HookSave := RS232.Hooked;
  303. RS232.Hooked := FTSupport.HookOnFT;
  304. FTSupport.OpenStatusWindow('YModem Batch Download');
  305. REPEAT
  306. FTSupport.FileSpec:='';
  307. InitVars(FTSupport.FileSpec);
  308. BlockNo := 0;
  309. IF NoACKS THEN
  310. Response:='G';
  311. Result := YMReceive(TRUE);
  312. END;
  313. IF (NOT NoACKS) OR (Result=1) THEN
  314. NoACKS := FALSE;
  315. Response := CRCREQ;
  316. Result := YMReceive(TRUE);
  317. IF Result=1 THEN
  318. CRCCheck:=FALSE;
  319. FTSupport.XferMode:='CHK';
  320. Response := NAK;
  321. Result := YMReceive(TRUE);
  322. END;
  323. END;
  324. IF Result=0 THEN
  325. IF NOT NoACKS THEN
  326. RS232.SerialWrite(ACK,1);
  327. END;
  328. GetFileDetails(FTSupport.FileSpec,FTSupport.SizeInBytes);
  329. IF FTSupport.FileSpec[0]<>0C THEN
  330. FTSupport.CompleteFilename;
  331. f := FIO.Create(FTSupport.FileSpec);
  332. IF FIO.IOresult()<>0 THEN
  333. RS232.Hooked := HookSave;
  334. RETURN(12);
  335. END;
  336. FTSupport.NewFilename;
  337. Response := CRCREQ;
  338. BlockNo := 1;
  339. Result := YMReceive(FALSE);
  340. IF Result=1 THEN
  341. CRCCheck:=FALSE;
  342. FTSupport.XferMode:='CHK';
  343. Response := NAK;
  344. Result := YMReceive(FALSE);
  345. END;
  346. FIO.Close(f);
  347. END;
  348. END;
  349. UNTIL (Result<>0) OR FTSupport.Aborted OR (FTSupport.FileSpec[0]=0C);
  350. IF FTSupport.Aborted THEN
  351. FTSupport.Cancel;
  352. END;
  353. FTSupport.CloseStatusWindow;
  354. RS232.Hooked := HookSave;
  355. RETURN Result;
  356. END YModemBatchReceive;
  357. (*..................................................*)
  358. PROCEDURE YModemGReceive():CARDINAL;
  359. VAR
  360. Result : CARDINAL;
  361. BEGIN
  362. NoACKS := TRUE;
  363. FTSupport.OpenStatusWindow('YModem-g Batch Download');
  364. Result := YModemBatchReceive();
  365. NoACKS := FALSE;
  366. RETURN Result;
  367. END YModemGReceive;
  368. (*..................................................*)
  369. PROCEDURE GetResponse(VAR c:CHAR):CARDINAL;
  370. VAR
  371. CANCount : CARDINAL;
  372. GotResponse : BOOLEAN;
  373. BEGIN
  374. CANCount := 0;
  375. REPEAT
  376. IF FTSupport.AbortRequested() THEN
  377. RETURN(6);
  378. END;
  379. IF ResponseWaiting THEN
  380. c:=Response;
  381. GotResponse:=TRUE;
  382. ResponseWaiting:=FALSE;
  383. ELSE
  384. GotResponse := RS232.SerialRead(c,100);
  385. END;
  386. IF GotResponse THEN
  387. IF c=CAN THEN
  388. INC(CANCount);
  389. IF CANCount=3 THEN
  390. RETURN(13);
  391. END;
  392. END;
  393. ELSE
  394. FTSupport.LastMessage := 'Timeout';
  395. INC(FTSupport.Errors);
  396. FTSupport.UpdateStatus;
  397. IF FTSupport.Errors=5 THEN
  398. RETURN(2);
  399. END;
  400. END;
  401. UNTIL GotResponse AND ((c=NAK) OR (c=ACK) OR (c=CRCREQ));
  402. FTSupport.LastMessage := '';
  403. FTSupport.UpdateStatus;
  404. RETURN 0;
  405. END GetResponse;
  406. (*..................................................*)
  407. PROCEDURE SendBlock(VAR c:CHAR):CARDINAL;
  408. VAR
  409. Result,i,Lnth,
  410. CRC,CheckSum,
  411. CRCIndex : CARDINAL;
  412. Header : ARRAY[0..2] OF CHAR;
  413. BEGIN
  414. CRC:=0;
  415. CheckSum:=0;
  416. Lnth:=BlockSize;
  417. IF Lnth=128 THEN
  418. Header[0]:=SOH;
  419. ELSE
  420. Header[0]:=STX;
  421. END;
  422. Header[1]:=CHR(BlockNo);
  423. Header[2]:=CHR(255-BlockNo);
  424. RS232.SerialWrite(Header,3);
  425. IF CRCCheck THEN
  426. FOR i:=0 TO Lnth-1 DO
  427. RS232.SerialWrite(FTSupport.FBuff[i],1);
  428. CRCIndex := CARDINAL(BITSET(CRC>>8)/BITSET(ORD(FTSupport.FBuff[i])));
  429. CRC := CARDINAL(BITSET(FTSupport.CRCTable[CRCIndex])/BITSET(CRC<<8))
  430. END;
  431. FTSupport.FBuff[Lnth] := CHR(CRC DIV 100H);
  432. FTSupport.FBuff[Lnth+1] := CHR(CRC MOD 100H);
  433. RS232.SerialWrite(FTSupport.FBuff[Lnth],2);
  434. INC(Lnth,2);
  435. ELSE
  436. FOR i:=0 TO Lnth-1 DO
  437. RS232.SerialWrite(FTSupport.FBuff[i],1);
  438. CheckSum := (CheckSum + ORD(FTSupport.FBuff[i])) MOD 100H;
  439. END;
  440. FTSupport.FBuff[Lnth] := CHR(CheckSum);
  441. RS232.SerialWrite(CHR(CheckSum),1);
  442. INC(Lnth);
  443. END;
  444. REPEAT
  445. IF NOT NoACKS THEN
  446. Result := GetResponse(c);
  447. IF Result # 0 THEN
  448. RETURN(Result);
  449. END;
  450. IF c # ACK THEN
  451. FTSupport.LastMessage := 'Received NAK';
  452. INC(FTSupport.Errors);
  453. FTSupport.UpdateStatus;
  454. IF FTSupport.Errors=5 THEN
  455. RETURN(14);
  456. END;
  457. RS232.SerialWrite(Header,3);
  458. RS232.SerialWrite(FTSupport.FBuff,Lnth);
  459. END;
  460. ELSE
  461. c:=ACK;
  462. IF FTSupport.AbortRequested() THEN
  463. RETURN(6);
  464. END;
  465. END;
  466. UNTIL c = ACK;
  467. RETURN 0;
  468. END SendBlock;
  469. (*..................................................*)
  470. PROCEDURE GetStartChar(VAR c:CHAR):CARDINAL;
  471. VAR
  472. Result : CARDINAL;
  473. BEGIN
  474. REPEAT
  475. Result := GetResponse(c);
  476. IF Result<>0 THEN
  477. RETURN(Result);
  478. END;
  479. UNTIL (c=NAK) OR (c=CRCREQ) OR (c='G');
  480. IF c=NAK THEN
  481. CRCCheck:=FALSE;
  482. FTSupport.XferMode:='CHK'
  483. END;
  484. RS232.FlushInBuf;
  485. RETURN 0;
  486. END GetStartChar;
  487. (*..................................................*)
  488. PROCEDURE YMSend():CARDINAL;
  489. VAR
  490. c : CHAR;
  491. Result,BytesRead,
  492. CANCount : CARDINAL;
  493. BEGIN
  494. Result := GetStartChar(c);
  495. IF Result<>0 THEN
  496. RETURN(Result);
  497. END;
  498. FTSupport.UpdateStatus;
  499. WHILE NOT FIO.EOF DO
  500. BytesRead := FIO.RdBin(f,FTSupport.FBuff,BlockSize);
  501. IF FIO.IOresult()<>0 THEN
  502. RETURN(5);
  503. END;
  504. IF BytesRead<BlockSize THEN
  505. Lib.Fill(ADR(FTSupport.FBuff[BytesRead]),BlockSize-BytesRead,CHR(26));
  506. END;
  507. FTSupport.Errors := 0;
  508. Result := SendBlock(c);
  509. IF Result<>0 THEN
  510. RETURN(Result);
  511. END;
  512. FTSupport.LastMessage := '';
  513. FTSupport.Transferred := FTSupport.Transferred+LONGCARD(BlockSize);
  514. BlockNo := (BlockNo+1) MOD 100H;
  515. FTSupport.Errors := 0;
  516. FTSupport.UpdateStatus;
  517. END;
  518. FTSupport.LastMessage := 'End of File';
  519. FTSupport.UpdateStatus;
  520. REPEAT
  521. REPEAT
  522. RS232.SerialWrite(EOT,1);
  523. Result := GetResponse(c);
  524. IF Result<>0 THEN
  525. RETURN(Result);
  526. END;
  527. UNTIL (c=NAK) OR (c=ACK);
  528. UNTIL c=ACK;
  529. RETURN 0;
  530. END YMSend;
  531. (*..................................................*)
  532. PROCEDURE YModemSend(VAR Filename:ARRAY OF CHAR):CARDINAL;
  533. VAR
  534. Result : CARDINAL;
  535. HookSave : BOOLEAN;
  536. BEGIN
  537. IF FIO.Exists(Filename) THEN
  538. HookSave := RS232.Hooked;
  539. RS232.Hooked := FTSupport.HookOnFT;
  540. InitVars(Filename);
  541. BlockSize := 1024;
  542. f := FIO.Open(Filename);
  543. FIO.EOF := FALSE;
  544. FTSupport.SizeInBytes := FIO.Size(f);
  545. FTSupport.OpenStatusWindow('YModem Upload');
  546. FTSupport.NewFilename;
  547. Result := YMSend();
  548. FTSupport.CloseStatusWindow;
  549. RS232.Hooked := HookSave;
  550. FIO.Close(f);
  551. RETURN Result;
  552. ELSE
  553. CommUtil.ErrorMessage('Could not open file!');
  554. RETURN 7;
  555. END;
  556. END YModemSend;
  557. (*..................................................*)
  558. PROCEDURE GetPath(Wild:ARRAY OF CHAR; VAR Path:ARRAY OF CHAR):BOOLEAN;
  559. VAR
  560. Drive,Ext : ARRAY[0..4] OF CHAR;
  561. Name : ARRAY[0..12] OF CHAR;
  562. BEGIN
  563. IF NOT Filenames.ParseFilename(Wild,Drive,Path,Name,Ext) THEN
  564. RETURN(FALSE);
  565. END;
  566. Name := '';
  567. Ext:='';
  568. Filenames.MakeFilename(Drive,Path,Name,Ext,Path);
  569. RETURN TRUE;
  570. END GetPath;
  571. (*...............................................*)
  572. PROCEDURE YModemBatchSend(VAR Wild:ARRAY OF CHAR):CARDINAL;
  573. VAR
  574. c : CHAR;
  575. GotFile : BOOLEAN;
  576. Result : CARDINAL;
  577. Path : ARRAY[0..70] OF CHAR;
  578. entry : FIO.DirEntry;
  579. HookSave : BOOLEAN;
  580. BEGIN
  581. IF GetPath(Wild,Path) THEN
  582. HookSave := RS232.Hooked;
  583. RS232.Hooked := FTSupport.HookOnFT;
  584. FTSupport.OpenStatusWindow('YModem Batch Upload');
  585. GotFile := FIO.ReadFirstEntry(Wild,FIO.FileAttr{},entry);
  586. WHILE GotFile DO
  587. FTSupport.FileSpec:='';
  588. InitVars(FTSupport.FileSpec);
  589. Str.Concat(FTSupport.FileSpec,Path,entry.Name);
  590. FTSupport.NewFilename;
  591. f := FIO.Open(FTSupport.FileSpec);
  592. FIO.EOF := FALSE;
  593. FTSupport.SizeInBytes := FIO.Size(f);
  594. Lib.Fill(ADR(FTSupport.FBuff),128,0C);
  595. SPRINTF.SPrintF2('%s\000%u',entry.Name,FTSupport.SizeInBytes,FTSupport.FBuff);
  596. BlockNo := 0;
  597. Result := GetStartChar(c);
  598. IF Result<>0 THEN
  599. FIO.Close(f);
  600. FTSupport.CloseStatusWindow;
  601. RETURN(Result);
  602. END;
  603. IF c='G' THEN
  604. NoACKS:=TRUE;
  605. END;
  606. REPEAT
  607. Result := SendBlock(c);
  608. IF Result<>0 THEN
  609. FIO.Close(f);
  610. NoACKS:=FALSE;
  611. FTSupport.CloseStatusWindow;
  612. RETURN Result;
  613. END;
  614. UNTIL c<>NAK;
  615. Response := c;
  616. ResponseWaiting := TRUE;
  617. BlockNo:=1;
  618. BlockSize:=1024;
  619. Result := YMSend();
  620. FIO.Close(f);
  621. IF Result<>0 THEN
  622. FTSupport.CloseStatusWindow;
  623. NoACKS:=FALSE;
  624. RETURN(Result);
  625. END;
  626. GotFile := FIO.ReadNextEntry(entry);
  627. END;
  628. BlockNo:=0;
  629. BlockSize:=128;
  630. Lib.Fill(ADR(FTSupport.FBuff),128,0C);
  631. Result := GetStartChar(c);
  632. IF Result=0 THEN
  633. Result := SendBlock(c);
  634. END;
  635. FTSupport.CloseStatusWindow;
  636. RS232.Hooked := HookSave;
  637. ELSE
  638. CommUtil.ErrorMessage('Bad filename');
  639. RETURN 7;
  640. END;
  641. RETURN 0;
  642. END YModemBatchSend;
  643. (*..................................................*)
  644. BEGIN
  645. ResponseWaiting := FALSE;
  646. NoACKS := FALSE;
  647. END YModem.
  648.