Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1414 lines
32 KiB

  1. /* zmdm_rcv.c -- ZMODEM compatible file receiving routines for HyperACCESS
  2. *
  3. * Copyright 1990 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 15 $
  7. * $Date: 7/12/02 8:35a $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. //#define DEBUGSTR
  12. #include <setjmp.h>
  13. #include <time.h>
  14. #include <term\res.h>
  15. #include <sys\types.h>
  16. #include <sys\utime.h>
  17. #include <tdll\stdtyp.h>
  18. #include <tdll\mc.h>
  19. #include <tdll\com.h>
  20. #include <tdll\assert.h>
  21. #include <tdll\session.h>
  22. #include <tdll\load_res.h>
  23. #include <tdll\xfer_msc.h>
  24. #include <tdll\globals.h>
  25. #include <tdll\file_io.h>
  26. #include <tdll\file_msc.h>
  27. #include <tdll\htchar.h>
  28. #define BYTE unsigned char
  29. #include "itime.h"
  30. #include "xfr_dsp.h"
  31. #include "xfr_todo.h"
  32. #include "xfr_srvc.h"
  33. #include "xfer.h"
  34. #include "xfer.hh"
  35. #include "xfer_tsc.h"
  36. #include "foo.h"
  37. #include "zmodem.hh"
  38. #include "zmodem.h"
  39. /* * * * * * * * * * * * *
  40. * Function Prototypes *
  41. * * * * * * * * * * * * */
  42. #if defined(DEBUG_DUMPPACKET)
  43. #include <stdio.h>
  44. FILE* fpPacket;
  45. #endif // defined(DEBUG_DUMPPACKET)
  46. int procheader (ZC *zc, TCHAR *name);
  47. int putsec (ZC *zc, BYTE *buf, int n);
  48. int isvalid (TCHAR c, int base);
  49. TCHAR *stoi (TCHAR *ptr, int *val, int base);
  50. TCHAR *stol (TCHAR *ptr, long *val, int base);
  51. int IsAnyLower (TCHAR *s);
  52. long getfree (void);
  53. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  54. * zmdm_rcv
  55. *
  56. * DESCRIPTION:
  57. *
  58. * ARGUMENTS:
  59. *
  60. * RETURNS:
  61. *
  62. */
  63. USHORT zmdm_rcv(HSESSION h, int method, int attended, int single_file)
  64. {
  65. ZC *zc = NULL;
  66. BOOL still_trying = TRUE;
  67. BOOL override = FALSE;
  68. int nJmpVal = 0;
  69. int xstatus;
  70. unsigned int uiOldOptions;
  71. int tvar;
  72. TCHAR ch;
  73. XFR_Z_PARAMS *pZ;
  74. #if defined(DEADWOOD)
  75. DWORD nLen;
  76. #endif // defined(DEADWOOD)
  77. #if defined(DEBUG_DUMPPACKET)
  78. fpPacket = fopen("zpacket.dbg", "a");
  79. assert(fpPacket);
  80. fputs("----- Starting Zmodem rcv -----\n", fpPacket);
  81. #endif // defined(DEBUG_DUMPPACKET)
  82. (void)&single_file;
  83. xstatus = TSC_NO_MEM;
  84. zc = malloc(sizeof(ZC));
  85. if (zc == NULL)
  86. {
  87. xstatus = TSC_NO_MEM;
  88. goto done;
  89. }
  90. memset(zc, 0, sizeof(ZC));
  91. zc->nMethod = method; // Zmodem, or Zmodem crash recovery
  92. // This makes it easy to override some settings when
  93. // Zmodem crash recovery is selected.
  94. if (method == XF_ZMODEM_CR)
  95. {
  96. zc->fSavePartial = TRUE; // Leave partial files around
  97. zc->ulOverride = XFR_RO_ALWAYS; // Always overwrite existing file
  98. }
  99. else
  100. {
  101. // Use default settings otherwise.
  102. //
  103. zc->fSavePartial = xfer_save_partial(h);
  104. zc->ulOverride = (unsigned long)0;
  105. }
  106. zc->hSession = h;
  107. zc->hCom = sessQueryComHdl(h);
  108. zc->secbuf = NULL;
  109. zc->fname = NULL;
  110. zc->our_fname = NULL;
  111. zc->z_crctab = NULL;
  112. zc->z_cr3tab = NULL;
  113. /* allocate space for large packets since we don't necessarily know what
  114. * we'll be getting.
  115. */
  116. zc->secbuf = malloc(1025 * sizeof(TCHAR));
  117. if (zc->secbuf == NULL)
  118. {
  119. xstatus = TSC_NO_MEM;
  120. goto done;
  121. }
  122. zc->fname = malloc(FNAME_LEN * sizeof(TCHAR));
  123. if (zc->fname == NULL)
  124. {
  125. xstatus = TSC_NO_MEM;
  126. goto done;
  127. }
  128. zc->our_fname = malloc(FNAME_LEN * sizeof(TCHAR));
  129. if (zc->our_fname == NULL)
  130. {
  131. xstatus = TSC_NO_MEM;
  132. goto done;
  133. }
  134. #if defined(DEADWOOD)
  135. resLoadDataBlock(glblQueryDllHinst(),
  136. IDT_CSB_CRC_TABLE,
  137. &zc->z_crctab,
  138. &nLen);
  139. assert(nLen != 0);
  140. #else // defined(DEADWOOD)
  141. zc->z_crctab = usCrc16Lookup;
  142. #endif // defined(DEADWOOD)
  143. if (zc->z_crctab == NULL)
  144. {
  145. xstatus = TSC_NO_MEM;
  146. goto done;
  147. }
  148. #if defined(DEADWOOD)
  149. resLoadDataBlock(glblQueryDllHinst(),
  150. IDT_CRC_32_TAB,
  151. &zc->z_cr3tab,
  152. &nLen);
  153. assert(nLen != 0);
  154. #else // defined(DEADWOOD)
  155. zc->z_cr3tab = ulCrc32Lookup;
  156. #endif // defined(DEADWOOD)
  157. if (zc->z_cr3tab == NULL)
  158. {
  159. xstatus = TSC_NO_MEM;
  160. goto done;
  161. }
  162. xstatus = TSC_OK;
  163. if (xfer_set_comport(h, FALSE, &uiOldOptions) != TRUE)
  164. {
  165. goto done;
  166. }
  167. else
  168. {
  169. override = TRUE;
  170. }
  171. zmdm_retval (zc, TRUE, ZACK);
  172. zc->file_bytes = 0L;
  173. zc->real_bytes = 0L;
  174. zc->total_bytes = 0L;
  175. zc->actual_bytes = 0L;
  176. zc->nSkip = FALSE;
  177. zc->fh = NULL;
  178. zc->pstatus = zc->last_event = -4;
  179. zc->xfertimer = -1L;
  180. zc->nfiles = 0;
  181. zc->filen = 0;
  182. zc->filesize = -1L;
  183. zc->nbytes = -1L;
  184. zc->errors = 0;
  185. // Capture the current execution environment into the flagkey_buf buffer.
  186. // The Trow() function will later use it to restore the execution
  187. // environment (i.e., the state of all system registers and the instruction
  188. // counter.
  189. //
  190. nJmpVal = setjmp(zc->flagkey_buf);
  191. if (nJmpVal != 0)
  192. {
  193. if (nJmpVal == 4)
  194. {
  195. xstatus = TSC_DISK_FULL;
  196. zmdm_retval(zc, TRUE, ZFERR);
  197. }
  198. else
  199. {
  200. xstatus = TSC_USER_CANNED;
  201. zmdm_retval(zc, TRUE, ZCAN);
  202. }
  203. zc->xfertime = (long)interval(zc->xfertimer);
  204. stohdr(zc, 0L);
  205. zshhdr(zc, ZCAN, zc->Txhdr);
  206. canit(zc);
  207. if (zc->fh)
  208. xfer_close_rcv_file(h,
  209. zc->fh,
  210. xstatus,
  211. zc->fname,
  212. zc->our_fname,
  213. zc->fSavePartial,
  214. zc->basesize + zc->filesize,
  215. 0);
  216. zc->fh = NULL;
  217. // zmdm_retval(zc, TRUE, ZABORT); jkh, 2/12/95 see above
  218. goto done;
  219. }
  220. pZ = (XFR_Z_PARAMS *)xfer_get_params(zc->hSession, zc->nMethod);
  221. assert(pZ);
  222. if (pZ == NULL)
  223. {
  224. xstatus = TSC_NO_MEM;
  225. goto done;
  226. }
  227. zc->Zctlesc = pZ->nEscCtrlCodes;
  228. zc->Rxtimeout = pZ->nRetryWait;
  229. if (zc->Rxtimeout <= 0)
  230. {
  231. zc->Rxtimeout = 10;
  232. }
  233. zc->Rxtimeout *= 10;
  234. zc->do_init = TRUE; // Always start right up since we may be autostarted
  235. zc->tryzhdrtype = ZRINIT;
  236. if (tryz(zc) == ZFILE)
  237. {
  238. // tzset();
  239. if (zc->xfertimer == (-1L))
  240. {
  241. zc->xfertimer = (long)startinterval();
  242. }
  243. // Receive files with Z-modem protocol.
  244. //
  245. switch (xstatus = rzfiles(zc))
  246. {
  247. case OK:
  248. xstatus = TSC_OK;
  249. break;
  250. case ZABORT:
  251. xstatus = TSC_USER_CANNED;
  252. do {
  253. // purgeline(zc);
  254. ComRcvBufrClear(zc->hCom);
  255. Sleep(100);
  256. } while (mComRcvBufrPeek(zc->hCom, &ch) != 0);
  257. // } while (rdchk(h) != ERROR);
  258. /* we try to eat any characters until the other end quits */
  259. break;
  260. case RCDO: /* Not too sure about this one */
  261. case ZCARRIER_LOST:
  262. xstatus = TSC_LOST_CARRIER;
  263. break;
  264. case ERROR:
  265. canit(zc);
  266. /* fall through */
  267. case ZMDM_VIRUS:
  268. do {
  269. // purgeline(zc);
  270. ComRcvBufrClear(zc->hCom);
  271. Sleep(100);
  272. } while (mComRcvBufrPeek(zc->hCom, &ch) != 0);
  273. // } while (rdchk(zc) != ERROR);
  274. /* fall thru to the default case */
  275. default:
  276. xstatus = zmdm_error(zc, xstatus);
  277. break;
  278. }
  279. }
  280. done:
  281. zmdmr_progress(zc, TRANSFER_DONE);
  282. if (override)
  283. {
  284. xfer_restore_comport(h, uiOldOptions);
  285. }
  286. // Fool around with the return code to get a useful status return
  287. if ((tvar = zmdm_retval(zc, FALSE, 0)) != ZACK)
  288. // Retrieve last error message
  289. {
  290. if (tvar == ZMDM_VIRUS)
  291. {
  292. do {
  293. // purgeline(zc);
  294. ComRcvBufrClear(zc->hCom);
  295. Sleep(100);
  296. } while (mComRcvBufrPeek(zc->hCom, &ch) != 0);
  297. // } while (rdchk(zc) != ERROR);
  298. }
  299. xstatus = zmdm_error(zc, tvar);
  300. }
  301. if (xstatus != TSC_OK)
  302. {
  303. if (zc->fh)
  304. {
  305. xfer_close_rcv_file(h,
  306. zc->fh,
  307. xstatus,
  308. zc->fname,
  309. zc->our_fname,
  310. zc->fSavePartial,
  311. zc->basesize + zc->filesize,
  312. 0);
  313. }
  314. }
  315. if (zc->secbuf != NULL)
  316. {
  317. free(zc->secbuf);
  318. zc->secbuf = NULL;
  319. }
  320. if (zc->fname != NULL)
  321. {
  322. free(zc->fname);
  323. zc->fname = NULL;
  324. }
  325. if (zc->our_fname != NULL)
  326. {
  327. free(zc->our_fname);
  328. zc->our_fname = NULL;
  329. }
  330. if (zc->z_crctab != NULL)
  331. {
  332. #if defined(DEADWOOD)
  333. resFreeDataBlock(h, zc->z_crctab);
  334. zc->z_crctab = NULL;
  335. #else // defined(DEADWOOD
  336. //
  337. // We don't need to free zc->z_crctab since it is pointing
  338. // to a static constant array. REV: 4/10/2002
  339. //
  340. zc->z_crctab = NULL;
  341. #endif // defined(DEADWOOD)
  342. }
  343. if (zc->z_cr3tab)
  344. {
  345. #if defined(DEADWOOD)
  346. resFreeDataBlock(h, zc->z_cr3tab);
  347. zc->z_cr3tab = NULL;
  348. #else // defined(DEADWOOD
  349. //
  350. // We don't need to free zc->z_cr3tab since it is pointing
  351. // to a static constant array. REV: 4/10/2002
  352. //
  353. zc->z_cr3tab = NULL;
  354. #endif // defined(DEADWOOD)
  355. }
  356. if (zc != NULL)
  357. {
  358. free(zc);
  359. zc = NULL;
  360. }
  361. xferMsgClose(h);
  362. #if defined(DEBUG_DUMPPACKET)
  363. fputs("------- Ending Zmodem rcv -----\n", fpPacket);
  364. fclose(fpPacket);
  365. #endif // defined(DEBUG_DUMPPACKET)
  366. return((USHORT)xstatus);
  367. }
  368. /*----------------------------------------------------------------------+
  369. | getfree - Calculates the free bytes on the current file system.
  370. | ~0 means many free bytes (unknown).
  371. +----------------------------------------------------------------------*/
  372. long getfree(void)
  373. {
  374. return(~0L); /* many free bytes ... */
  375. }
  376. /*----------------------------------------------------------------------+
  377. | tryz - Initialize for ZMODEM receive attempt, try to activate ZMODEM
  378. | sender. Handles ZSINIT frame. Returns ZFILE if ZMODEM filename
  379. | received, -1 on error, ZCOMPL if transaction finished, else 0.
  380. +----------------------------------------------------------------------*/
  381. int tryz(ZC *zc)
  382. {
  383. register int c;
  384. register int n;
  385. int x;
  386. int retrys;
  387. for ( n = 10; --n >= 0; )
  388. {
  389. /* Set buffer length (0) and capability flags */
  390. stohdr(zc, 0L);
  391. /* Do we need an option to set the block size ? */
  392. zc->Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO /* |CANBRK */ ;
  393. if (zc->Zctlesc)
  394. zc->Txhdr[ZF0] |= TESCCTL;
  395. if (n <= 8)
  396. zc->do_init = TRUE;
  397. if (zc->do_init)
  398. zshhdr(zc, zc->tryzhdrtype, zc->Txhdr);
  399. if (zc->tryzhdrtype == ZSKIP) /* Don't skip too far */
  400. zc->tryzhdrtype = ZRINIT; /* CAF 8-21-87 */
  401. retrys = 25;
  402. again:
  403. switch (x = xfer_user_interrupt(zc->hSession))
  404. {
  405. case XFER_ABORT:
  406. zmdmr_update(zc, ZCAN);
  407. longjmp(zc->flagkey_buf, 1);
  408. break;
  409. case XFER_SKIP:
  410. /* This MUST only happen while receiving */
  411. stohdr(zc, zc->filesize);
  412. #if defined(DEBUG_DUMPPACKET)
  413. fputs("tryz: User skipped. ZRPOS\n", fpPacket);
  414. #endif // defined(DEBUG_DUMPPACKET)
  415. zshhdr(zc, ZRPOS, zc->Txhdr);
  416. zc->nSkip = TRUE;
  417. zc->file_bytes = zc->filesize;
  418. break;
  419. default:
  420. break;
  421. }
  422. if (xfer_carrier_lost(zc->hSession))
  423. {
  424. zmdm_retval(zc, TRUE, ZCARRIER_LOST);
  425. return ZCARRIER_LOST;
  426. }
  427. switch (zgethdr(zc, zc->Rxhdr, 'R'))
  428. {
  429. case ZRQINIT:
  430. zc->do_init = TRUE;
  431. continue;
  432. case ZEOF:
  433. zc->do_init = TRUE;
  434. continue;
  435. case TIMEOUT:
  436. continue;
  437. case ZFILE:
  438. zc->zconv = zc->Rxhdr[ZF0];
  439. zc->zmanag = zc->Rxhdr[ZF1];
  440. zc->ztrans = zc->Rxhdr[ZF2];
  441. zc->tryzhdrtype = ZRINIT;
  442. c = zrdata(zc, zc->secbuf, 1024);
  443. /* mode(3); TODO: figure out what this was supposed to do */
  444. if (c == GOTCRCW)
  445. return ZFILE;
  446. if (--retrys <= 0)
  447. {
  448. zmdm_retval(zc, TRUE, ZNAK);
  449. return ZNAK;
  450. }
  451. zshhdr(zc, ZNAK, zc->Txhdr);
  452. goto again;
  453. case ZSINIT:
  454. zc->Zctlesc = TESCCTL & zc->Rxhdr[ZF0];
  455. if (zrdata(zc, zc->Attn, ZATTNLEN) == GOTCRCW)
  456. {
  457. stohdr(zc, 1L);
  458. zshhdr(zc, ZACK, zc->Txhdr);
  459. goto again;
  460. }
  461. if (--retrys <= 0)
  462. {
  463. zmdm_retval(zc, TRUE, ZNAK);
  464. return ZNAK;
  465. }
  466. zshhdr(zc, ZNAK, zc->Txhdr);
  467. goto again;
  468. case ZFREECNT:
  469. stohdr(zc, getfree());
  470. zshhdr(zc, ZACK, zc->Txhdr);
  471. goto again;
  472. case ZCOMMAND:
  473. zmdm_retval(zc, TRUE, ZCOMMAND);
  474. return ZCOMMAND;
  475. case ZCOMPL:
  476. goto again;
  477. default:
  478. zc->do_init = TRUE;
  479. continue;
  480. case ZFIN:
  481. zc->xfertime = (long)interval(zc->xfertimer);
  482. ackbibi(zc);
  483. return ZCOMPL;
  484. case ZCAN:
  485. zmdm_retval(zc, TRUE, ZABORT);
  486. return ZCAN;
  487. }
  488. }
  489. zmdm_retval(zc, TRUE, TIMEOUT);
  490. return TIMEOUT;
  491. }
  492. /*----------------------------------------------------------------------+
  493. | rzfiles - Receive 1 or more files with ZMODEM protocol.
  494. +----------------------------------------------------------------------*/
  495. int rzfiles(ZC *zc)
  496. {
  497. register int c;
  498. register int d;
  499. for (;;)
  500. {
  501. switch (c = rzfile(zc))
  502. {
  503. case ZEOF:
  504. case ZSKIP:
  505. switch (d = tryz(zc))
  506. {
  507. case ZCOMPL:
  508. return OK;
  509. default:
  510. return d;
  511. case ZFILE:
  512. break;
  513. }
  514. continue;
  515. case ERROR:
  516. default:
  517. return c;
  518. }
  519. }
  520. }
  521. /*----------------------------------------------------------------------+
  522. | rzfile - Receive single file with ZMODEM protocol.
  523. | NOTE: Assumes file name frame is in secbuf.
  524. +----------------------------------------------------------------------*/
  525. int rzfile(ZC *zc)
  526. {
  527. register int c;
  528. register int n;
  529. int x;
  530. int fBlocking = FALSE;
  531. long lBlockStart = 0L;
  532. zc->Eofseen = FALSE;
  533. zc->file_bytes = 0L;
  534. zc->real_bytes = 0L;
  535. if (procheader(zc, (TCHAR *)zc->secbuf) == ERROR)
  536. {
  537. return (zc->tryzhdrtype = ZSKIP);
  538. }
  539. n = 20;
  540. for (;;)
  541. {
  542. // If we're blocking and we've timed out, reset for another ZRPOS
  543. if( fBlocking && (long)interval( lBlockStart ) > 100L )
  544. fBlocking = FALSE;
  545. // If we're not blocking already, set up for ZRPOS
  546. if( ! fBlocking )
  547. {
  548. DbgOutStr( "Sending ZRPOS to %ld", zc->file_bytes, 0, 0, 0, 0 );
  549. stohdr(zc, zc->file_bytes);
  550. #if defined(DEBUG_DUMPPACKET)
  551. fprintf(fpPacket, "rzfile: ZRPOS to %ld\n", zc->file_bytes);
  552. #endif // defined(DEBUG_DUMPPACKET)
  553. zshhdr(zc, ZRPOS, zc->Txhdr);
  554. fBlocking = 1;
  555. lBlockStart = (long)startinterval( );
  556. DbgOutStr("Now blocked at t=%lu",lBlockStart,0,0,0,0);
  557. }
  558. nxthdr:
  559. switch (x = xfer_user_interrupt(zc->hSession))
  560. {
  561. case XFER_ABORT:
  562. zmdmr_update(zc, ZCAN);
  563. longjmp(zc->flagkey_buf, 1);
  564. break;
  565. case XFER_SKIP:
  566. /* This MUST only happen while receiving */
  567. stohdr(zc, zc->filesize);
  568. #if defined(DEBUG_DUMPPACKET)
  569. fputs("rzfile: User skipped (1). ZRPOS\n", fpPacket);
  570. #endif // defined(DEBUG_DUMPPACKET)
  571. zshhdr(zc, ZRPOS, zc->Txhdr);
  572. zc->nSkip = TRUE;
  573. zc->file_bytes = zc->filesize;
  574. break;
  575. default:
  576. break;
  577. }
  578. if (xfer_carrier_lost(zc->hSession))
  579. {
  580. zmdm_retval(zc, TRUE, ZCARRIER_LOST);
  581. return ZCARRIER_LOST;
  582. }
  583. switch (c = zgethdr(zc, zc->Rxhdr, 'R'))
  584. {
  585. default:
  586. if (--n < 0) /* A little fix from Delrina */
  587. {
  588. /* return ERROR; */
  589. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  590. zmdm_retval(zc, TRUE, c);
  591. return c;
  592. }
  593. continue;
  594. case ZCARRIER_LOST:
  595. zmdm_retval(zc, TRUE, ZCARRIER_LOST);
  596. return c;
  597. case ZNAK:
  598. case TIMEOUT:
  599. if ( --n < 0)
  600. {
  601. /* return ERROR; */
  602. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  603. zmdm_retval(zc, TRUE, TIMEOUT);
  604. return c;
  605. }
  606. continue; /* Another fix from Delrina */
  607. case ZFILE:
  608. if( fBlocking )
  609. {
  610. DbgOutStr( "rzfile: ZFILE && fBlocking!\n", 0, 0, 0, 0, 0 );
  611. }
  612. else
  613. zrdata(zc, zc->secbuf, 1024);
  614. continue;
  615. case ZEOF:
  616. if (rclhdr(zc->Rxhdr) != zc->file_bytes)
  617. {
  618. /*
  619. * Ignore eof if it's at wrong place - force
  620. * a timeout because the eof might have gone
  621. * out before we sent our zrpos.
  622. */
  623. goto nxthdr;
  624. }
  625. if (closeit(zc))
  626. {
  627. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  628. zc->tryzhdrtype = ZFERR;
  629. /* return ERROR; */
  630. return ZEOF;
  631. }
  632. zmdmr_progress(zc, FILE_DONE);
  633. return c;
  634. case ERROR: /* Too much garbage in header search error */
  635. if ( --n < 0)
  636. {
  637. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  638. zmdm_retval(zc, TRUE, ERROR);
  639. return ERROR;
  640. }
  641. if( ! fBlocking )
  642. zmputs(zc, zc->Attn);
  643. continue;
  644. case ZSKIP:
  645. closeit(zc);
  646. zmdmr_progress(zc, FILE_DONE);
  647. return c;
  648. case ZDATA:
  649. if( ! fBlocking )
  650. {
  651. if( rclhdr(zc->Rxhdr) != zc->file_bytes)
  652. {
  653. // DbgOutStr( "rzfile: ZDATA: n=%d\n", n, 0, 0, 0, 0 );
  654. if ( --n < 0)
  655. {
  656. DbgOutStr("ZMODEM error %s %d", TEXT(__FILE__), __LINE__,0,0,0);
  657. #if defined(DEBUG_DUMPPACKET)
  658. fprintf(fpPacket, "rzfile: ZDATA pos = 0x%08lX vs. 0x%08lX\n",
  659. rclhdr(zc->Rxhdr), zc->file_bytes);
  660. #endif // defined(DEBUG_DUMPPACKET)
  661. zmdm_retval(zc, TRUE, ZBADFMT);
  662. return ERROR;
  663. }
  664. zmputs(zc, zc->Attn); continue;
  665. }
  666. }
  667. else
  668. {
  669. // Did sender finally respond to our ZRPOS?
  670. if( rclhdr(zc->Rxhdr) == zc->file_bytes )
  671. {
  672. // DbgOutStr("Now unblocked after %lu t-sec\n",interval(lBlockStart),0,0,0,0);
  673. fBlocking = FALSE;
  674. }
  675. else
  676. {
  677. // Read the buffer and toss it
  678. c = zrdata(zc, zc->secbuf, 1024);
  679. continue;
  680. }
  681. }
  682. moredata:
  683. zmdmr_update(zc, ZDATA);
  684. switch (x = xfer_user_interrupt(zc->hSession))
  685. {
  686. case XFER_ABORT:
  687. zmdmr_update(zc, ZCAN);
  688. longjmp(zc->flagkey_buf, 1);
  689. break;
  690. case XFER_SKIP:
  691. /* This MUST only happen while receiving */
  692. stohdr(zc, zc->filesize);
  693. #if defined(DEBUG_DUMPPACKET)
  694. fputs("rzfile: User skipped (2). ZRPOS\n", fpPacket);
  695. #endif // defined(DEBUG_DUMPPACKET)
  696. zshhdr(zc, ZRPOS, zc->Txhdr);
  697. zc->nSkip = TRUE;
  698. zc->file_bytes = zc->filesize;
  699. break;
  700. default:
  701. break;
  702. }
  703. if (xfer_carrier_lost(zc->hSession))
  704. {
  705. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  706. zmdm_retval(zc, TRUE, ZCARRIER_LOST);
  707. return ZCARRIER_LOST;
  708. }
  709. switch (c = zrdata(zc, zc->secbuf, 1024))
  710. {
  711. case ZCAN:
  712. zmdm_retval(zc, TRUE, ZABORT);
  713. return c;
  714. case ERROR: /* CRC error */
  715. if ( --n < 0)
  716. {
  717. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  718. zmdm_retval(zc, TRUE, ERROR);
  719. return ERROR;
  720. }
  721. zmputs(zc, zc->Attn);
  722. continue;
  723. case TIMEOUT:
  724. if ( --n < 0)
  725. {
  726. /* return ERROR; */
  727. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  728. zmdm_retval(zc, TRUE, c);
  729. return c;
  730. }
  731. continue;
  732. case GOTCRCW:
  733. n = 20;
  734. putsec(zc, zc->secbuf, zc->Rxcount);
  735. zc->file_bytes += zc->Rxcount;
  736. zc->real_bytes += zc->Rxcount;
  737. zmdmr_update(zc, ZMDM_ACKED);
  738. zmdmr_progress(zc, 0);
  739. stohdr(zc, zc->file_bytes);
  740. zshhdr(zc, ZACK, zc->Txhdr);
  741. sendline(zc, &zc->stP, XON);
  742. goto nxthdr;
  743. case GOTCRCQ:
  744. n = 20;
  745. putsec(zc, zc->secbuf, zc->Rxcount);
  746. zc->file_bytes += zc->Rxcount;
  747. zc->real_bytes += zc->Rxcount;
  748. zmdmr_update(zc, ZMDM_ACKED);
  749. zmdmr_progress(zc, 0);
  750. stohdr(zc, zc->file_bytes);
  751. zshhdr(zc, ZACK, zc->Txhdr);
  752. goto moredata;
  753. case GOTCRCG:
  754. n = 20;
  755. putsec(zc, zc->secbuf, zc->Rxcount);
  756. zc->file_bytes += zc->Rxcount;
  757. zc->real_bytes += zc->Rxcount;
  758. zmdmr_progress(zc, 0);
  759. goto moredata;
  760. case GOTCRCE:
  761. n = 20;
  762. putsec(zc, zc->secbuf, zc->Rxcount);
  763. zc->file_bytes += zc->Rxcount;
  764. zc->real_bytes += zc->Rxcount;
  765. zmdmr_progress(zc, 0);
  766. goto nxthdr;
  767. }
  768. } /* switch */
  769. } /* end for */
  770. }
  771. /*----------------------------------------------------------------------+
  772. | zmputs - Send a string to the modem, processing for \336 (sleep 1 sec)
  773. | and \335 (break signal).
  774. +----------------------------------------------------------------------*/
  775. void zmputs(ZC *zc, char *s)
  776. {
  777. register c;
  778. while (*s)
  779. {
  780. switch (c = *s++)
  781. {
  782. case '\336':
  783. Sleep(1000);
  784. continue;
  785. case '\335':
  786. /* TODO: put in a call to sendbreak */
  787. // sendbreak(h);
  788. continue;
  789. default:
  790. sendline(zc, &zc->stP, (UCHAR)c);
  791. }
  792. }
  793. }
  794. /*----------------------------------------------------------------------+
  795. | IsAnyLower - Returns TRUE if string s has lower case letters.
  796. +----------------------------------------------------------------------*/
  797. int IsAnyLower(char *s)
  798. {
  799. for ( ; *s; ++s)
  800. // Don't use this stuff in a Chicago DLL
  801. // if (islower(*s))
  802. if ((*s >= 'a') && (*s <= 'z'))
  803. return TRUE;
  804. return FALSE;
  805. }
  806. /*----------------------------------------------------------------------+
  807. | closeit - Close the receive dataset, return OK or ERROR
  808. +----------------------------------------------------------------------*/
  809. int closeit(ZC *zc)
  810. {
  811. // struct utimbuf timep;
  812. int reason;
  813. XFR_PARAMS *pX;
  814. reason = TSC_COMPLETE; /* TODO: Get the real reason */
  815. if (zc->nSkip)
  816. {
  817. reason = TSC_USER_SKIP;
  818. }
  819. if (xfer_close_rcv_file(zc->hSession,
  820. zc->fh,
  821. reason,
  822. zc->fname,
  823. zc->our_fname,
  824. zc->fSavePartial,
  825. 0,
  826. 0) == ERROR)
  827. {
  828. return ERROR;
  829. }
  830. zc->fh = NULL;
  831. zc->actual_bytes += zc->real_bytes;
  832. zc->real_bytes = 0L;
  833. zc->total_bytes += zc->file_bytes;
  834. zc->file_bytes = 0L;
  835. zc->filesize = 0L;
  836. zc->nSkip = FALSE;
  837. pX = (XFR_PARAMS *)0;
  838. xfrQueryParameters(sessQueryXferHdl(zc->hSession), (VOID **)&pX);
  839. if ((pX != (XFR_PARAMS *)0) && (pX->fUseDateTime))
  840. {
  841. if (zc->Modtime)
  842. {
  843. // BYTE acName[FNAME_LEN];
  844. // zc->Modtime += timezone; /* Convert from GMT to local timezone */
  845. // timep.actime = time(NULL);
  846. // timep.modtime = zc->Modtime;
  847. // CharToOem(zc->our_fname, acName);
  848. // utime(acName, (void FAR *)&timep);
  849. itimeSetFileTime(zc->our_fname, zc->Modtime);
  850. }
  851. }
  852. // Disable this, it needs conversion and we only ever got complaints
  853. // about it anyway
  854. //if ((zc->Filemode & S_IFMT) == S_IFREG)
  855. // far_chmod(zc->our_fname, (07777 & zc->Filemode));
  856. return OK;
  857. }
  858. /*----------------------------------------------------------------------+
  859. | ackbibi - Ack a ZFIN packet, let byegones be byegones
  860. +----------------------------------------------------------------------*/
  861. void ackbibi(ZC *zc)
  862. {
  863. register int n;
  864. stohdr(zc, 0L);
  865. for (n = 3; --n >= 0; )
  866. {
  867. // purgeline(zc);
  868. ComRcvBufrClear(zc->hCom);
  869. zshhdr(zc, ZFIN, zc->Txhdr);
  870. // switch (readline(h, 100))
  871. switch (readline(zc, zc->Rxtimeout)) // Mobidem
  872. {
  873. case 'O':
  874. // readline(h, 1); /* Discard 2nd 'O' */
  875. readline(zc, zc->Rxtimeout); /* Discard 2nd 'O' */ // Mobidem
  876. return;
  877. case RCDO:
  878. return;
  879. case TIMEOUT:
  880. default:
  881. break;
  882. }
  883. }
  884. }
  885. /*----------------------------------------------------------------------+
  886. | isvalid
  887. +----------------------------------------------------------------------*/
  888. int isvalid(char c, int base)
  889. {
  890. if (c < '0')
  891. return FALSE;
  892. switch (base)
  893. {
  894. case 8:
  895. if (c > '7')
  896. return FALSE;
  897. break;
  898. case 10:
  899. if (c > '9')
  900. return FALSE;
  901. break;
  902. case 16:
  903. if (c <= '9')
  904. return TRUE;
  905. // Don't use this stuff in a Chicago DLL
  906. // if (toupper(c) < 'A')
  907. // return FALSE;
  908. //if (toupper(c) > 'F')
  909. // return FALSE;
  910. if ((c >= 'a') && (c <= 'f'))
  911. break;
  912. if ((c >= 'A') && (c <= 'F'))
  913. break;
  914. return FALSE;
  915. }
  916. return TRUE;
  917. }
  918. /*----------------------------------------------------------------------+
  919. | ourspace -- replacement for isspace
  920. +----------------------------------------------------------------------*/
  921. int ourspace(char c)
  922. {
  923. if (c == 0x20)
  924. return TRUE;
  925. if ((c >= 0x9) && (c <= 0xD))
  926. return TRUE;
  927. return FALSE;
  928. }
  929. /*----------------------------------------------------------------------+
  930. | stoi - string to integer.
  931. +----------------------------------------------------------------------*/
  932. char *stoi(char *ptr, int *val, int base)
  933. {
  934. int cnt;
  935. if (ptr == NULL)
  936. return NULL;
  937. // Don't do this in a Chicago DLL
  938. // while ((*ptr) && (isspace(*ptr)))
  939. while ((*ptr) && ourspace(*ptr))
  940. ptr++;
  941. cnt = 0;
  942. while ((*ptr) && (isvalid(*ptr, base)))
  943. {
  944. cnt *= base;
  945. cnt += (*ptr++ - '0');
  946. }
  947. *val = cnt;
  948. return ptr;
  949. }
  950. /*----------------------------------------------------------------------+
  951. | stol - string to long.
  952. +----------------------------------------------------------------------*/
  953. char *stol(char *ptr, long *val, int base)
  954. {
  955. long cnt;
  956. if (ptr == NULL)
  957. return NULL;
  958. // Don't do this in a Chicago DLL
  959. // while ((*ptr) && (isspace(*ptr)))
  960. while ((*ptr) && (ourspace(*ptr)))
  961. ptr++;
  962. cnt = 0;
  963. while ((*ptr) && (isvalid(*ptr, base)))
  964. {
  965. cnt *= base;
  966. cnt += (*ptr++ - '0');
  967. }
  968. *val = cnt;
  969. return ptr;
  970. }
  971. /*----------------------------------------------------------------------+
  972. | procheader - Process incoming file information header.
  973. +----------------------------------------------------------------------*/
  974. int procheader(ZC *zc, TCHAR *name)
  975. {
  976. int zRecover = FALSE;
  977. int lconv = 0;
  978. int file_err;
  979. register char *p;
  980. int serial_number;
  981. int files_remaining;
  982. long bytes_remaining;
  983. long our_size;
  984. LONG lOptions = 0;
  985. XFR_Z_PARAMS *pZ;
  986. struct st_rcv_open stRcv;
  987. TCHAR loc_fname[FNAME_LEN];
  988. StrCharCopy(zc->fname, name);
  989. #if !defined(NT_EDITION)
  990. //
  991. // Removed uppercasing the filename per MS request. REV: 11/12/2001
  992. //
  993. CharUpper(zc->fname);
  994. #endif //!defined(NT_EDITION)
  995. zc->Thisbinary = FALSE;
  996. zc->filesize = 0L;
  997. zc->Filemode = 0;
  998. zc->Modtime = 0L;
  999. serial_number = 0;
  1000. files_remaining = -1;
  1001. bytes_remaining = -1L;
  1002. p = name + 1 + StrCharGetByteCount(name);
  1003. if (*p)
  1004. { /* file coming from Unix or DOS system */
  1005. if (*p)
  1006. p = stol(p, &zc->filesize, 10);
  1007. if (*p)
  1008. p = stol(p, &zc->Modtime, 8);
  1009. if (*p)
  1010. p = stoi(p, &zc->Filemode, 8);
  1011. if (*p)
  1012. p = stoi(p, &serial_number, 10);
  1013. if (*p)
  1014. p = stoi(p, &files_remaining, 10);
  1015. if (*p)
  1016. p = stol(p, &bytes_remaining, 10);
  1017. if ((zc->nfiles == 0) && (files_remaining != -1))
  1018. {
  1019. zc->nfiles = files_remaining;
  1020. zmdmr_filecnt (zc, zc->nfiles);
  1021. }
  1022. if ((zc->nbytes == (-1L)) && (bytes_remaining != (-1L)))
  1023. {
  1024. zc->nbytes = bytes_remaining;
  1025. zmdmr_totalsize (zc, zc->nbytes);
  1026. }
  1027. }
  1028. else
  1029. { /* File coming from CP/M system */
  1030. for (p = zc->fname; *p; ++p) /* change / to _ */
  1031. if ( *p == '/')
  1032. *p = '_';
  1033. if ( *--p == '.') /* zap trailing period */
  1034. *p = 0;
  1035. }
  1036. StrCharCopy(zc->our_fname, zc->fname);
  1037. StrCharCopy(loc_fname, zc->fname);
  1038. stRcv.pszSuggestedName = loc_fname;
  1039. stRcv.pszActualName = zc->our_fname;
  1040. stRcv.lFileTime = zc->Modtime;
  1041. xfer_build_rcv_name(zc->hSession, &stRcv);
  1042. //zc->ssMch = stRcv.ssmchVscanHdl;
  1043. lconv = 0;
  1044. pZ = (XFR_Z_PARAMS *)xfer_get_params(zc->hSession, zc->nMethod);
  1045. assert(pZ);
  1046. if (pZ)
  1047. {
  1048. switch (pZ->nCrashRecRecv)
  1049. {
  1050. case ZP_CRR_ALWAYS:
  1051. lconv = ZCRECOV;
  1052. break;
  1053. case ZP_CRR_NEVER:
  1054. if ((lconv = zc->zconv) == ZCRECOV)
  1055. lconv = 0;
  1056. break;
  1057. case ZP_CRR_NEG:
  1058. default:
  1059. lconv = zc->zconv;
  1060. break;
  1061. }
  1062. }
  1063. switch (lconv)
  1064. {
  1065. case ZCNL:
  1066. zc->Thisbinary = FALSE;
  1067. break;
  1068. case ZCRECOV:
  1069. /*
  1070. * This is a little complicated. To do recovery, we need to check
  1071. * the following:
  1072. * 1. Does the file exist on OUR side.
  1073. * 2. Has the sender sent over a file size.
  1074. * 3. Is the size sent greater than the size of OUR file.
  1075. * If so, we fudge around a little with the file and let things rip.
  1076. */
  1077. zRecover = TRUE;
  1078. our_size = 0L;
  1079. if (zRecover)
  1080. {
  1081. if (GetFileSizeFromName(stRcv.pszActualName, &our_size))
  1082. zRecover = TRUE;
  1083. else
  1084. zRecover = FALSE;
  1085. }
  1086. if (zRecover)
  1087. {
  1088. /* Has the sender sent over a file size ? */
  1089. if (zc->filesize <= 0)
  1090. zRecover = FALSE;
  1091. }
  1092. if (zRecover)
  1093. {
  1094. /* This gets set up above after checking for existance */
  1095. if (our_size != 0L)
  1096. {
  1097. if (our_size < zc->filesize)
  1098. {
  1099. /*
  1100. * We do this in the vain hope of avoiding problems with
  1101. * files terminated by ^Z and padded last blocks
  1102. *
  1103. * Given that we don't know if it is necessary, it might be
  1104. * possible to eliminate it
  1105. */
  1106. our_size = (our_size - 1) & ~255L;
  1107. }
  1108. else
  1109. {
  1110. return ERROR;
  1111. //zRecover = FALSE;
  1112. }
  1113. }
  1114. else
  1115. {
  1116. zRecover = FALSE;
  1117. }
  1118. }
  1119. if (zRecover)
  1120. {
  1121. zc->file_bytes = our_size;
  1122. }
  1123. /* FALL THROUGH */
  1124. case ZCBIN:
  1125. default:
  1126. zc->Thisbinary = TRUE;
  1127. break;
  1128. }
  1129. if (zRecover)
  1130. {
  1131. lOptions = XFR_RO_APPEND;
  1132. }
  1133. else if (pZ && pZ->nFileExists == ZP_FE_SENDER)
  1134. {
  1135. switch (zc->zmanag & ZMMASK)
  1136. {
  1137. case ZMNEWL:
  1138. /* TODO: complete this option */
  1139. lOptions = 0;
  1140. break;
  1141. case ZMCRC:
  1142. /* TODO: complete this option */
  1143. lOptions = 0;
  1144. break;
  1145. case ZMAPND:
  1146. lOptions = XFR_RO_APPEND;
  1147. break;
  1148. case ZMCLOB:
  1149. lOptions = XFR_RO_ALWAYS;
  1150. break;
  1151. case ZMNEW:
  1152. lOptions = XFR_RO_NEWER;
  1153. break;
  1154. case ZMDIFF:
  1155. /* TODO: complete this option */
  1156. lOptions = 0;
  1157. break;
  1158. case ZMPROT:
  1159. lOptions = XFR_RO_NEVER;
  1160. break;
  1161. default:
  1162. break;
  1163. }
  1164. }
  1165. else
  1166. {
  1167. lOptions = zc->ulOverride;
  1168. }
  1169. StrCharCopy(zc->our_fname, zc->fname);
  1170. StrCharCopy(loc_fname, zc->fname);
  1171. stRcv.pszSuggestedName = loc_fname;
  1172. stRcv.pszActualName = zc->our_fname;
  1173. stRcv.lFileTime = zc->Modtime;
  1174. /* TODO: pick up override options as necessary, like above */
  1175. file_err = xfer_open_rcv_file(zc->hSession, &stRcv, lOptions);
  1176. if (file_err != 0)
  1177. {
  1178. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  1179. switch (file_err)
  1180. {
  1181. case -8:
  1182. zmdm_retval(zc, TRUE, ZMDM_INUSE);
  1183. break;
  1184. case -6: // File was rejected unconditionally
  1185. zmdm_retval(zc, TRUE, ZMDM_REFUSE);
  1186. break;
  1187. case -5: // Were unable to create needed directories
  1188. zmdm_retval(zc, TRUE, ZFERR);
  1189. break;
  1190. case -4: // No date, time supplied when required
  1191. zmdm_retval(zc, TRUE, ZFERR);
  1192. break;
  1193. case -3: // File could not be saved
  1194. zmdm_retval(zc, TRUE, ZFERR);
  1195. break;
  1196. case -2: // File was rejected due to date
  1197. zmdm_retval(zc, TRUE, ZMDM_OLDER);
  1198. break;
  1199. case -1: // Read/Write error occured
  1200. default:
  1201. zmdm_retval(zc, TRUE, ZFERR);
  1202. break;
  1203. }
  1204. zc->total_bytes += zc->filesize;
  1205. zc->filen += 1;
  1206. zmdmr_newfile (zc, zc->filen, zc->fname, stRcv.pszActualName);
  1207. return ERROR;
  1208. }
  1209. else
  1210. {
  1211. zmdm_retval(zc, TRUE, ZACK);
  1212. }
  1213. zc->fh = stRcv.bfHdl;
  1214. zc->basesize = stRcv.lInitialSize;
  1215. if (zRecover)
  1216. {
  1217. //jmh 04-02-96 Sure we opened it in "append" mode (which really
  1218. // opens the file for write and seeks to the end), but we
  1219. // might actually seek to a spot just before that due to the
  1220. // possible padding of the file with ^Z's.
  1221. //
  1222. fio_seek(zc->fh, zc->file_bytes, FIO_SEEK_SET);
  1223. }
  1224. zc->filen += 1;
  1225. zmdmr_newfile (zc, zc->filen, zc->fname, stRcv.pszActualName);
  1226. zmdmr_filesize(zc, zc->filesize);
  1227. return OK;
  1228. }
  1229. /*----------------------------------------------------------------------+
  1230. | putsec - Putsec writes the n characters of buf to receive file.
  1231. | If not in binary mode, carriage returns, and all characters
  1232. | starting with CPMEOF are discarded.
  1233. +----------------------------------------------------------------------*/
  1234. int putsec(ZC *zc, BYTE *buf, int n)
  1235. {
  1236. register BYTE *p;
  1237. register int ii;
  1238. if (n == 0)
  1239. return OK;
  1240. if (zc->Thisbinary)
  1241. {
  1242. // jkh, 2/11 Added error check
  1243. if (fio_write(buf, 1, n, zc->fh) != n)
  1244. longjmp(zc->flagkey_buf, 4);
  1245. }
  1246. else
  1247. {
  1248. if (zc->Eofseen)
  1249. return OK;
  1250. ii = FALSE;
  1251. for (p=buf; --n>=0; ++p )
  1252. {
  1253. if ( *p == '\n')
  1254. {
  1255. /*
  1256. * If we get a <NL> that wasn't preceeded by a <CR>
  1257. */
  1258. if (ii == FALSE)
  1259. fio_putc('\r', zc->fh);
  1260. }
  1261. ii = (*p == '\r');
  1262. if (*p == CPMEOF)
  1263. {
  1264. zc->Eofseen=TRUE;
  1265. return OK;
  1266. }
  1267. fio_putc(*p, zc->fh);
  1268. }
  1269. }
  1270. return OK;
  1271. }
  1272. /* *********** end of zmdm_rcv.c *********** */