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.

1361 lines
30 KiB

  1. /* zmdm_snd.c -- Routines to handle zmodem sending for HyperACCESS
  2. *
  3. * Copyright 1990 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 20 $
  7. * $Date: 7/12/02 8:32a $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <setjmp.h>
  12. #include <tdll\stdtyp.h>
  13. #include <tdll\mc.h>
  14. #include <tdll\com.h>
  15. #include <tdll\assert.h>
  16. #include <tdll\session.h>
  17. #include <tdll\load_res.h>
  18. #include <term\res.h>
  19. #include <tdll\globals.h>
  20. #include <tdll\file_io.h>
  21. #include <tdll\htchar.h>
  22. #define BYTE unsigned char
  23. #include "itime.h"
  24. #include "xfr_dsp.h"
  25. #include "xfr_todo.h"
  26. #include "xfr_srvc.h"
  27. #include "xfer.h"
  28. #include "xfer.hh"
  29. #include "xfer_tsc.h"
  30. #include "foo.h"
  31. #include "zmodem.hh"
  32. #include "zmodem.h"
  33. /*lint -e502*/ /* lint seems to want the ~ operator applied only
  34. * only to unsigned, we're using uchar
  35. */
  36. #define ZBUF_SIZE 1024
  37. /* * * * * * * * * * * * * * * *
  38. * local function prototypes *
  39. * * * * * * * * * * * * * * * */
  40. VOID long_to_octal(LONG lVal, TCHAR *pszStr);
  41. /* * * * * * * *
  42. * Functions *
  43. * * * * * * * */
  44. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  45. * zmdm_snd
  46. *
  47. * DESCRIPTION:
  48. * Sends a file using ZMODEM protocol. Does not support starting task
  49. * at other end (sending a "rz\r" text string) or remote commands.
  50. *
  51. * ARGUMENTS:
  52. * attended -- TRUE if user is probably in attendance. Controls the display
  53. * of some messages.
  54. *
  55. * RETURNS:
  56. * True if transfer completes successfully, FALSE otherwise.
  57. */
  58. USHORT zmdm_snd(HSESSION h, int method, int attended, unsigned nfiles, long nbytes)
  59. {
  60. ZC *zc = NULL;
  61. TCHAR sfname[FNAME_LEN]; // file name of file being sent
  62. BOOL got_file = FALSE; // controls when to complete batch op
  63. int tries = 0; // number of retries for each packet
  64. unsigned total_tries = 0; // number of retries for entire transfer
  65. int xstatus = TSC_OK; // winds up with overall status of transfer
  66. int override = FALSE; // set TRUE if comm. details changed to
  67. unsigned int uiOldOptions = 0;
  68. // int hld_send_cdelay; // accomodate xmodem
  69. // char hld_bits_per_char; // hld* vars. used to restore port after
  70. // char hld_parity_type; // transfer if override is used
  71. XFR_Z_PARAMS *pZ = NULL;
  72. #if defined(DEADWOOD)
  73. DWORD nLen;
  74. #endif // defined(DEADWOOD)
  75. // tzset();
  76. if (xfer_set_comport(h, TRUE, &uiOldOptions) != TRUE)
  77. {
  78. goto done;
  79. }
  80. else
  81. {
  82. override = TRUE;
  83. }
  84. // RemoteClear();
  85. zc = malloc(sizeof(ZC));
  86. if (zc == NULL)
  87. {
  88. goto done;
  89. }
  90. memset(zc, 0, sizeof(ZC));
  91. zc->hSession = h;
  92. zc->hCom = sessQueryComHdl(h);
  93. zc->nMethod = method;
  94. zc->fSavePartial = TRUE;
  95. zc->ulOverride = (unsigned long)0;
  96. zc->real_bytes = 0L;
  97. zc->file_bytes = 0L;
  98. zc->total_bytes = 0L;
  99. zc->actual_bytes = 0L;
  100. zc->nSkip = FALSE;
  101. zc->flagkey = NULL;
  102. // zc->flagkey_buf = NULL;
  103. // zc->intrjmp = NULL;
  104. zc->fh = NULL;
  105. zc->basesize = 0L;
  106. zc->xfertimer = -1L;
  107. zc->xfertime = -1L;
  108. zc->nfiles = nfiles; /* make these available to display routines */
  109. zc->filen = 0;
  110. zc->filesize = -1L;
  111. zc->nbytes = nbytes;
  112. //zc->Rxtimeout = 0L; // Set below.
  113. zc->z_crctab = NULL;
  114. #if defined(DEADWOOD)
  115. resLoadDataBlock(glblQueryDllHinst(),
  116. IDT_CSB_CRC_TABLE,
  117. &zc->z_crctab,
  118. &nLen);
  119. assert(nLen != 0);
  120. #else // defined(DEADWOOD)
  121. zc->z_crctab = usCrc16Lookup;
  122. #endif // defined(DEADWOOD)
  123. if (zc->z_crctab == NULL)
  124. {
  125. xstatus = TSC_NO_MEM;
  126. goto done;
  127. }
  128. zc->z_cr3tab = NULL;
  129. #if defined(DEADWOOD)
  130. resLoadDataBlock(glblQueryDllHinst(),
  131. IDT_CRC_32_TAB,
  132. &zc->z_cr3tab,
  133. &nLen);
  134. assert(nLen != 0);
  135. #else // defined(DEADWOOD)
  136. zc->z_cr3tab = ulCrc32Lookup;
  137. #endif // defined(DEADWOOD)
  138. if (zc->z_cr3tab == NULL)
  139. {
  140. xstatus = TSC_NO_MEM;
  141. goto done;
  142. }
  143. zc->Rxframeind = 0; // Not used in file sends.
  144. //zc->Rxtype = 0; // Not used in file sends.
  145. //memset(zc->Rxhdr, '\0', sizeof(zc->Rxhdr)); // Not used in file sends.
  146. //memset(zc->Txdr, '\0', sizeof(zc->Txdr));
  147. zc->Rxpos = 0L;
  148. zc->Txpos = 0L;
  149. //zc->Txfcs32 = TRUE; // Set below.
  150. zc->Crc32t = TRUE;
  151. //zc->Crc32 = TRUE; // Set below.
  152. memset(zc->Attn, '\0', sizeof(zc->Attn));
  153. zc->lastsent = 0;
  154. zc->Not8bit = 0;
  155. zc->displayed_time = 0L;
  156. //zc->Zctlesc = 0; // Set below.
  157. zc->Zrwindow = 0;
  158. zc->Eofseen = FALSE;
  159. zc->tryzhdrtype = ZRQINIT;
  160. zc->Thisbinary = FALSE;
  161. zc->Filemode = 0;
  162. zc->Modtime = 0L;
  163. zc->do_init = FALSE;
  164. //zc->zconv = TEXT('\0'); // Should be set here?
  165. //zc->zmanag = TEXT('\0'); // Should be set here?
  166. //zc->ztrans = TEXT('\0'); // Should be set here?
  167. zc->secbuf = NULL;
  168. zc->fname = NULL;
  169. zc->our_fname = NULL;
  170. //memset(zc->stP, 0, sizeof(zc->stP);
  171. zc->txbuf = malloc(ZBUF_SIZE);
  172. if (zc->txbuf == NULL)
  173. {
  174. xstatus = TSC_NO_MEM;
  175. goto done;
  176. }
  177. TCHAR_Fill(zc->txbuf, TEXT('\0'), ZBUF_SIZE);
  178. //zc->Filesleft = 0; // Set below.
  179. //zc->Totalleft = 0; // Set below.
  180. zc->blklen = ZBUF_SIZE;
  181. zc->blkopt = 0;
  182. zc->Beenhereb4 = 0;
  183. //zc->Wantfcs32 = FALSE; // Set below.
  184. zc->Rxflags = 0;
  185. //zc->Rxbuflen = (unsigned)0; // Set below.
  186. zc->Txwindow = (unsigned)0;
  187. zc->Txwcnt = (unsigned)0;
  188. zc->Txwspac = (unsigned)0;
  189. zc->Myattn[0] = '\0';
  190. zc->errors = 0;
  191. zc->s_error = 0;
  192. zc->pstatus = -4;
  193. zc->last_event = -4;
  194. zc->Lskipnocor = FALSE;
  195. zc->Lastsync = zc->Rxpos;
  196. zc->Lrxpos = zc->Rxpos;
  197. // hp_report_xtime(0); /* make invalid in case transfer bombs */
  198. if (setjmp(zc->flagkey_buf) != 0)
  199. {
  200. stohdr(zc, 0L);
  201. zshhdr(zc, ZCAN, zc->Txhdr);
  202. canit(zc);
  203. if (zc->fh)
  204. {
  205. fio_close(zc->fh);
  206. }
  207. zc->fh = NULL;
  208. zmdm_retval(zc, TRUE, ZABORT);
  209. xstatus = TSC_USER_CANNED;
  210. canit(zc);
  211. goto done;
  212. }
  213. pZ = (XFR_Z_PARAMS *)xfer_get_params(zc->hSession, zc->nMethod);
  214. assert(pZ);
  215. if (pZ == NULL)
  216. {
  217. xstatus = TSC_NO_MEM;
  218. goto done;
  219. }
  220. zc->Zctlesc = pZ->nEscCtrlCodes;
  221. zc->Rxtimeout = pZ->nRetryWait;
  222. zc->Wantfcs32 = (pZ->nCrcType == ZP_CRC_32);
  223. if (zc->Rxtimeout <= 0)
  224. {
  225. zc->Rxtimeout = 10;
  226. }
  227. zc->Rxtimeout *= 10;
  228. zc->Txfcs32 = zc->Wantfcs32;
  229. zc->Rxbuflen = (unsigned)0;
  230. total_tries = 0;
  231. zc->Filesleft = zc->nfiles;
  232. zc->Totalleft = zc->nbytes;
  233. zmdmr_totalsize(zc, zc->nbytes);
  234. zmdmr_filecnt(zc, zc->nfiles);
  235. xferMsgErrorcnt(h, 0);
  236. got_file = TRUE;
  237. if (attended)
  238. {
  239. /* it might be necessary to start up the other end */
  240. sendline(zc, &zc->stP, 'r');
  241. sendline(zc, &zc->stP, 'z');
  242. sendline(zc, &zc->stP, '\r');
  243. flushmo(zc, &zc->stP);
  244. stohdr(zc, 0L);
  245. zshhdr(zc, ZRQINIT, zc->Txhdr);
  246. }
  247. else
  248. {
  249. stohdr(zc, 0L);
  250. }
  251. switch (xstatus = getzrxinit (zc))
  252. {
  253. case ZCAN:
  254. //
  255. // Set the last error to the TSC_USER_CANNED for
  256. // error reporting purposes. It seems as if the
  257. // errors are reversed in the error array, but
  258. // correcting them in the error array caused other
  259. // undesirable side effects. REV: 02/23/2001
  260. //
  261. xstatus = zmdm_error(zc, ZABORT);
  262. break;
  263. case ZABORT:
  264. //
  265. // Set the last error to the TSC_RMT_CANNED for
  266. // error reporting purposes. It seems as if the
  267. // errors are reversed in the error array, but
  268. // correcting them in the error array caused other
  269. // undesirable side effects. REV: 02/23/2001
  270. //
  271. xstatus = zmdm_error(zc, ZCAN);
  272. break;
  273. case TIMEOUT:
  274. case ZFERR:
  275. case ZBADFMT:
  276. case ERROR:
  277. case ZCARRIER_LOST:
  278. xstatus = zmdm_error(zc, xstatus);
  279. goto done;
  280. default:
  281. xstatus = zmdm_error(zc, xstatus);
  282. break;
  283. }
  284. while (got_file)
  285. {
  286. if ((got_file = xfer_nextfile(h, sfname)) == TRUE)
  287. {
  288. /* zc->total_bytes += zc->file_bytes; */
  289. /* zc->actual_bytes += zc->file_bytes; */
  290. /* zc->file_bytes = 0L; */
  291. ++zc->filen;
  292. xstatus = wcs(zc, sfname);
  293. switch (xstatus)
  294. {
  295. case ZABORT:
  296. //
  297. // Set the last error to the TSC_USER_CANNED for
  298. // error reporting purposes. It seems as if the
  299. // errors are reversed in the error array, but
  300. // correcting them in the error array caused other
  301. // undesirable side effects. REV: 02/23/2001
  302. //
  303. xstatus = zmdm_error(zc, ZCAN);
  304. goto done;
  305. case ZCAN:
  306. //
  307. // Set the last error to the TSC_RMT_CANNED for
  308. // error reporting purposes. It seems as if the
  309. // errors are reversed in the error array, but
  310. // correcting them in the error array caused other
  311. // undesirable side effects. REV: 02/23/2001
  312. //
  313. xstatus = zmdm_error(zc, ZABORT);
  314. goto done;
  315. case TIMEOUT:
  316. case ZFERR:
  317. case ZCARRIER_LOST:
  318. xstatus = zmdm_error(zc, xstatus);
  319. goto done;
  320. case ERROR:
  321. case ZBADFMT:
  322. case ZCOMPL:
  323. case ZSKIP:
  324. default:
  325. xstatus = zmdm_error(zc, xstatus);
  326. break;
  327. case OK:
  328. xstatus = TSC_OK;
  329. break;
  330. } /* end switch */
  331. xfer_log_xfer(h, TRUE, sfname, NULL, xstatus);
  332. zmdms_progress(zc, FILE_DONE);
  333. zc->xfertime = (long)interval(zc->xfertimer);
  334. zc->total_bytes += zc->file_bytes;
  335. zc->actual_bytes += zc->real_bytes;
  336. zc->file_bytes = 0L;
  337. zc->real_bytes = 0L;
  338. } /* end if */
  339. } /* end while */
  340. done:
  341. if (zc == NULL ||
  342. zc->txbuf == NULL ||
  343. zc->z_crctab == NULL ||
  344. zc->z_cr3tab == NULL)
  345. {
  346. xstatus = TSC_NO_MEM;
  347. }
  348. if (xstatus == TSC_OK)
  349. {
  350. if (zc != NULL)
  351. {
  352. /* if we recorded a previous error, use it, else check this */
  353. if (zc->filen == 0)
  354. {
  355. xstatus = TSC_CANT_START;
  356. }
  357. else if (zc->filen != zc->nfiles)
  358. {
  359. xstatus = TSC_GEN_FAILURE;
  360. }
  361. }
  362. else
  363. {
  364. xstatus = TSC_GEN_FAILURE;
  365. }
  366. }
  367. if (got_file)
  368. {
  369. xfer_log_xfer(h, TRUE, sfname, NULL, xstatus);
  370. }
  371. if (zc != NULL)
  372. {
  373. if (xstatus != TSC_USER_CANNED && xstatus != TSC_RMT_CANNED &&
  374. xstatus != TSC_LOST_CARRIER && xstatus != TSC_GEN_FAILURE &&
  375. xstatus != TSC_NO_RESPONSE && xstatus != TSC_CANT_START)
  376. {
  377. saybibi(zc);
  378. }
  379. zmdms_progress(zc, TRANSFER_DONE);
  380. }
  381. if (override)
  382. {
  383. xfer_restore_comport(h, uiOldOptions);
  384. }
  385. if (zc != NULL)
  386. {
  387. // hp_report_xtime((unsigned)zc->xfertime);
  388. if (zc->errors > 99)
  389. {
  390. xstatus = TSC_ERROR_LIMIT;
  391. }
  392. if (zc->fh)
  393. {
  394. fio_close(zc->fh);
  395. }
  396. if (zc->txbuf != NULL)
  397. {
  398. free(zc->txbuf);
  399. zc->txbuf = NULL;
  400. }
  401. if (zc->z_crctab != NULL)
  402. {
  403. #if defined(DEADWOOD)
  404. resFreeDataBlock(h, zc->z_crctab);
  405. zc->z_crctab = NULL;
  406. #else // defined(DEADWOOD
  407. //
  408. // We don't need to free zc->z_crctab since it is pointing
  409. // to a static constant array. REV: 4/10/2002
  410. //
  411. zc->z_crctab = NULL;
  412. #endif // defined(DEADWOOD)
  413. }
  414. if (zc->z_cr3tab)
  415. {
  416. #if defined(DEADWOOD)
  417. resFreeDataBlock(h, zc->z_cr3tab);
  418. zc->z_cr3tab = NULL;
  419. #else // defined(DEADWOOD
  420. //
  421. // We don't need to free zc->z_cr3tab since it is pointing
  422. // to a static constant array. REV: 4/10/2002
  423. //
  424. zc->z_cr3tab = NULL;
  425. #endif // defined(DEADWOOD)
  426. }
  427. free(zc);
  428. zc = NULL;
  429. }
  430. xferMsgClose(h);
  431. return((unsigned)xstatus);
  432. }
  433. /*----------------------------------------------------------------------+
  434. | wcs
  435. +----------------------------------------------------------------------*/
  436. int wcs(ZC *zc, TCHAR FAR *oname)
  437. {
  438. int c = OK;
  439. TCHAR name[PATHLEN];
  440. StrCharCopyN(name, oname, PATHLEN);
  441. if ((xfer_opensendfile(zc->hSession,
  442. &zc->fh,
  443. oname, /* full path name of file to open */
  444. &zc->filesize,
  445. NULL, /* name to send not needed yet */
  446. NULL)) != 0)
  447. {
  448. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  449. return ERROR;
  450. }
  451. zmdms_newfile(zc, zc->filen, oname, zc->filesize);
  452. zc->Eofseen = FALSE;
  453. switch (c = wctxpn(zc, name))
  454. {
  455. case ERROR:
  456. if (zc->fh != NULL)
  457. {
  458. fio_close(zc->fh);
  459. }
  460. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  461. break;
  462. default:
  463. break;
  464. }
  465. return c;
  466. }
  467. /*----------------------------------------------------------------------+
  468. | long_to_octal
  469. +----------------------------------------------------------------------*/
  470. VOID long_to_octal(LONG lVal, TCHAR *pszStr)
  471. {
  472. _ltoa(lVal, pszStr, 8);
  473. }
  474. /*----------------------------------------------------------------------+
  475. | wctxpn - Generate and transmit pathname block consisting of pathname
  476. | (null terminated), file length, mode time and file mode in
  477. | octal as povided by the Unix fstat call.
  478. | N.B.: modifies the passed name, may extend it!
  479. +----------------------------------------------------------------------*/
  480. int wctxpn(ZC *zc, TCHAR FAR *name)
  481. {
  482. register char *p;
  483. register char *q;
  484. int serial_number = 0;
  485. XFR_Z_PARAMS *pZ;
  486. pZ = (XFR_Z_PARAMS *)xfer_get_params(zc->hSession, zc->nMethod);
  487. assert(pZ);
  488. if(pZ == NULL)
  489. {
  490. return ERROR;
  491. }
  492. #if defined(UPPER_FEATURES)
  493. /* TODO: fix the way blklen and txbuf don't work together correctly */
  494. zc->blklen = 1 << (pZ->nBlkSize + 5);
  495. #endif // defined(UPPER_FEATURES)
  496. xfer_name_to_send(zc->hSession, name, zc->txbuf);
  497. q = &zc->txbuf[StrCharGetByteCount(zc->txbuf) + 1];
  498. /*
  499. * The ZMODEM spec says that file names must be send as lower case
  500. */
  501. //MPT:12-11-97 spec-schmeck - this is the cause of microsoft bug #32233
  502. // Since this character could be the second byte of a DBCS character
  503. // we should just leave things alone. Otherwise, we end up changing
  504. // the wide character.
  505. #if 0
  506. for (p = zc->txbuf; p < q; p++)
  507. {
  508. // Don't use this stuff in a Chicago DLL
  509. // if (isupper(*p))
  510. // *p = (char)tolower(*p);
  511. if ((*p >= 'A') && (*p <= 'Z'))
  512. {
  513. *p |= 0x20;
  514. }
  515. }
  516. #else
  517. //
  518. // Modified to lowercase filename characters only if they are not
  519. // DBCS characters. This way HyperTerminal will follow the Zmodem
  520. // specification for lowercase filenames. REV: 11/12/2001
  521. //
  522. for (p = zc->txbuf; p < q; p++)
  523. {
  524. if ((*p >= 'A') && (*p <= 'Z'))
  525. {
  526. //
  527. // Skip this character and the next if this is a DBCS
  528. // character, otherwise lowercase the character.
  529. //
  530. if (isDBCSChar(*p))
  531. {
  532. p++;
  533. }
  534. else
  535. {
  536. *p |= 0x20;
  537. }
  538. }
  539. }
  540. #endif
  541. p = q;
  542. while (q < (zc->txbuf + ZBUF_SIZE))
  543. {
  544. *q++ = 0; /* could be speeded up somewhat */
  545. }
  546. if (*name)
  547. {
  548. long lDosTime;
  549. BYTE acTime[32];
  550. BYTE acMode[32];
  551. lDosTime = itimeGetFileTime(name);
  552. // lDosTime -= timezone;
  553. long_to_octal(lDosTime, acTime);
  554. long_to_octal(0L, acMode);
  555. wsprintf(p, "%lu %s %s %d %d %ld",
  556. zc->filesize,
  557. acTime,
  558. acMode,
  559. serial_number,
  560. zc->Filesleft,
  561. zc->Totalleft);
  562. zc->Totalleft -= zc->filesize;
  563. }
  564. if (--zc->Filesleft <= 0)
  565. {
  566. zc->Totalleft = 0;
  567. }
  568. if (zc->Totalleft < 0)
  569. {
  570. zc->Totalleft = 0;
  571. }
  572. /* force 1k blocks if name won't fit in 128 byte block */
  573. if (zc->txbuf[125])
  574. zc->blklen=1024;
  575. else
  576. { /* A little goodie for IMP/KMD */
  577. zc->txbuf[127] = (char)((zc->filesize + 127) >>7);
  578. zc->txbuf[126] = (char)((zc->filesize + 127) >>15);
  579. }
  580. return zsendfile(zc, zc->txbuf, (int)(1+StrCharGetByteCount(p)+(p - zc->txbuf)));
  581. }
  582. /*----------------------------------------------------------------------+
  583. | zfilbuf - Fill buffer with blklen chars.
  584. +----------------------------------------------------------------------*/
  585. int zfilbuf(ZC *zc)
  586. {
  587. int n;
  588. int bsize;
  589. bsize = ZBUF_SIZE;
  590. if (zc->blklen <= ZBUF_SIZE)
  591. bsize = zc->blklen;
  592. n = fio_read(zc->txbuf, 1, bsize, zc->fh);
  593. if (n < bsize)
  594. {
  595. zc->Eofseen = TRUE;
  596. }
  597. return n;
  598. }
  599. /*----------------------------------------------------------------------+
  600. | canit - Send cancel string to get the other end to shut up.
  601. +----------------------------------------------------------------------*/
  602. void canit(ZC *zc)
  603. {
  604. int ii;
  605. for (ii = 0; ii < 10; ii++)
  606. {
  607. sendline(zc, &zc->stP, 24);
  608. }
  609. for (ii = 0; ii < 10; ii++)
  610. {
  611. sendline(zc, &zc->stP, 8);
  612. }
  613. flushmo(zc, &zc->stP);
  614. // purgeline(zc);
  615. ComRcvBufrClear(zc->hCom);
  616. }
  617. /*----------------------------------------------------------------------+
  618. | getzrzinit - Get the receiver's init parameters.
  619. +----------------------------------------------------------------------*/
  620. int getzrxinit(ZC *zc)
  621. {
  622. register int n;
  623. register int c = ERROR;
  624. int x;
  625. XFR_Z_PARAMS *pZ;
  626. pZ = (XFR_Z_PARAMS *)xfer_get_params(zc->hSession, zc->nMethod);
  627. assert(pZ);
  628. if (pZ == NULL)
  629. {
  630. return ERROR;
  631. }
  632. if (pZ->nXferMthd == ZP_XM_STREAM)
  633. {
  634. zc->Txwindow = (unsigned)0;
  635. }
  636. else
  637. {
  638. zc->Txwindow = (pZ->nWinSize + 1) * 1024;
  639. }
  640. for (n = 10; --n >= 0; )
  641. {
  642. switch (x = xfer_user_interrupt(zc->hSession))
  643. {
  644. case XFER_SKIP:
  645. case XFER_ABORT:
  646. zmdms_update(zc, ZCAN);
  647. longjmp(zc->flagkey_buf, 5);
  648. break;
  649. default:
  650. break;
  651. }
  652. if (xfer_carrier_lost(zc->hSession))
  653. {
  654. return ZCARRIER_LOST;
  655. }
  656. switch (c = zgethdr(zc, zc->Rxhdr, 'T'))
  657. {
  658. case ZCHALLENGE: /* Echo receiver's challenge numbr */
  659. stohdr(zc, zc->Rxpos);
  660. zshhdr(zc, ZACK, zc->Txhdr);
  661. continue;
  662. case ZCOMMAND: /* They didn't see out ZRQINIT */
  663. stohdr(zc, 0L);
  664. zshhdr(zc, ZRQINIT, zc->Txhdr);
  665. continue;
  666. case ZRINIT:
  667. zc->Rxflags = 0377 & zc->Rxhdr[ZF0];
  668. zc->Txfcs32 = (zc->Wantfcs32 && (zc->Rxflags & CANFC32));
  669. zc->Zctlesc |= zc->Rxflags & TESCCTL;
  670. zc->Rxbuflen = (0377 & zc->Rxhdr[ZP0])+((0377 & zc->Rxhdr[ZP1])<<8);
  671. if ( !(zc->Rxflags & CANFDX))
  672. {
  673. zc->Txwindow = (unsigned)0;
  674. }
  675. /* Set initial subpacket length */
  676. if (zc->blklen < 1024)
  677. { /* Command line override? */
  678. if (cnfgBitRate() > 2400)
  679. {
  680. zc->blklen = 1024;
  681. }
  682. else if (cnfgBitRate() > 1200)
  683. {
  684. zc->blklen = 512;
  685. }
  686. else if (cnfgBitRate() > 300)
  687. {
  688. zc->blklen = 256;
  689. }
  690. }
  691. if (zc->Rxbuflen && ((unsigned)zc->blklen > zc->Rxbuflen))
  692. {
  693. zc->blklen = zc->Rxbuflen;
  694. }
  695. if (zc->blkopt && (zc->blklen > zc->blkopt))
  696. {
  697. zc->blklen = zc->blkopt;
  698. }
  699. return (sendzsinit(zc));
  700. case TIMEOUT:
  701. continue;
  702. case ZCAN:
  703. case ZCARRIER_LOST:
  704. case ZABORT:
  705. case ZFERR:
  706. return c;
  707. case ZRQINIT:
  708. if (zc->Rxhdr[ZF0] == ZCOMMAND)
  709. {
  710. continue;
  711. }
  712. default:
  713. zshhdr(zc, ZNAK, zc->Txhdr);
  714. continue;
  715. }
  716. }
  717. if (c == TIMEOUT)
  718. {
  719. return TIMEOUT;
  720. }
  721. return ERROR;
  722. }
  723. /*----------------------------------------------------------------------+
  724. | sendzsinit - Send send-init information.
  725. +----------------------------------------------------------------------*/
  726. int sendzsinit(ZC *zc)
  727. {
  728. register int c;
  729. if (zc->Myattn[0] == '\0' && (!zc->Zctlesc || (zc->Rxflags & TESCCTL)))
  730. {
  731. return OK;
  732. }
  733. zc->errors = 0;
  734. for (;;)
  735. {
  736. stohdr(zc, 0L);
  737. if (zc->Zctlesc)
  738. {
  739. zc->Txhdr[ZF0] |= TESCCTL;
  740. zshhdr(zc, ZSINIT, zc->Txhdr);
  741. }
  742. else
  743. {
  744. zsbhdr(zc, ZSINIT, zc->Txhdr);
  745. }
  746. zsdata(zc, zc->Myattn, 1+StrCharGetByteCount(zc->Myattn), ZCRCW);
  747. c = zgethdr(zc, zc->Rxhdr, 'T');
  748. switch (c)
  749. {
  750. case ZRPOS:
  751. return c;
  752. case ZCAN:
  753. case ZABORT:
  754. case ZFERR:
  755. case TIMEOUT:
  756. case ZCARRIER_LOST:
  757. return c;
  758. case ZACK:
  759. return OK;
  760. default:
  761. if (++zc->errors > 99)
  762. {
  763. return ERROR;
  764. }
  765. xferMsgErrorcnt(zc->hSession, ++zc->errors);
  766. continue;
  767. }
  768. }
  769. }
  770. /*----------------------------------------------------------------------+
  771. | zsendfile - Send file name and releated info.
  772. +----------------------------------------------------------------------*/
  773. int zsendfile(ZC *zc, char *buf, int blen)
  774. {
  775. unsigned char chr;
  776. register int c;
  777. register unsigned long crc;
  778. XFR_Z_PARAMS *pZ;
  779. pZ = (XFR_Z_PARAMS *)xfer_get_params(zc->hSession, zc->nMethod);
  780. assert(pZ);
  781. if (pZ == NULL)
  782. {
  783. return ERROR;
  784. }
  785. for (;;)
  786. {
  787. zc->Txhdr[ZF0] = 0;
  788. if (zc->Txhdr[ZF0] == 0)
  789. {
  790. if (pZ->nCrashRecSend == ZP_CRS_ONCE ||
  791. pZ->nCrashRecSend == ZP_CRS_ALWAYS)
  792. {
  793. zc->Txhdr[ZF0] = ZCRESUM;
  794. }
  795. }
  796. if (zc->Txhdr[ZF0] == 0)
  797. {
  798. if (pZ->nCrashRecSend == ZP_CRS_NEG)
  799. {
  800. zc->Txhdr[ZF0] = ZCBIN;
  801. }
  802. }
  803. if (zc->Txhdr[ZF0] == 0)
  804. {
  805. if (pZ->nEolConvert)
  806. {
  807. zc->Txhdr[ZF0] = ZCNL;
  808. }
  809. }
  810. switch (pZ->nOverwriteOpt)
  811. {
  812. default:
  813. case ZP_OO_NONE:
  814. zc->Txhdr[ZF1] = 0;
  815. break;
  816. case ZP_OO_NEVER:
  817. zc->Txhdr[ZF1] = ZMPROT;
  818. break;
  819. case ZP_OO_L_D:
  820. zc->Txhdr[ZF1] = ZMDIFF;
  821. break;
  822. case ZP_OO_NEWER:
  823. zc->Txhdr[ZF1] = ZMNEW;
  824. break;
  825. case ZP_OO_ALWAYS:
  826. zc->Txhdr[ZF1] = ZMCLOB;
  827. break;
  828. case ZP_OO_APPEND:
  829. zc->Txhdr[ZF1] = ZMAPND;
  830. break;
  831. case ZP_OO_CRC:
  832. zc->Txhdr[ZF1] = ZMCRC;
  833. break;
  834. case ZP_OO_N_L:
  835. zc->Txhdr[ZF1] = ZMNEWL;
  836. break;
  837. }
  838. if (zc->Lskipnocor)
  839. {
  840. zc->Txhdr[ZF1] |= ZMSKNOLOC;
  841. }
  842. /* ZF2 is for ZTCRYPT (encryption) and ZTRLE and ZTLZW (compression) */
  843. zc->Txhdr[ZF2] = 0;
  844. /* ZF3 is for ZTSPARS (special sparse file option) */
  845. zc->Txhdr[ZF3] = 0;
  846. zsbhdr(zc, ZFILE, zc->Txhdr);
  847. zsdata(zc, buf, blen, ZCRCW);
  848. if (zc->xfertimer == (-1L))
  849. {
  850. zc->xfertimer = (long)startinterval();
  851. }
  852. again:
  853. c = zgethdr(zc, zc->Rxhdr, 'T');
  854. switch (c)
  855. {
  856. case ZRINIT:
  857. while ((c = readline(zc, 300)) > 0)
  858. {
  859. if (c == ZPAD)
  860. {
  861. goto again;
  862. }
  863. }
  864. continue;
  865. default:
  866. continue;
  867. case TIMEOUT:
  868. case ZCARRIER_LOST:
  869. case ZCAN:
  870. case ZABORT:
  871. case ZFERR:
  872. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  873. return c;
  874. case ZFIN:
  875. return ERROR;
  876. case ZCRC:
  877. crc = 0xFFFFFFFFL;
  878. while (fio_read(&chr, 1, 1, zc->fh) && --zc->Rxpos)
  879. {
  880. crc = UPDC32(zc, (int)chr, crc);
  881. }
  882. crc = ~crc;
  883. fio_errclr(zc->fh); /* Clear EOF */
  884. fio_seek(zc->fh, 1, FIO_SEEK_SET);
  885. stohdr(zc, crc);
  886. zsbhdr(zc, ZCRC, zc->Txhdr);
  887. goto again;
  888. case ZSKIP:
  889. zc->total_bytes += zc->filesize;
  890. fio_close(zc->fh);
  891. zc->fh = NULL;
  892. return c;
  893. case ZRPOS:
  894. /*
  895. * Suppress zcrcw request otherwise triggered by
  896. * lastyunc==bytcnt
  897. */
  898. if (zc->Rxpos)
  899. {
  900. if (fio_seek(zc->fh, zc->Rxpos, FIO_SEEK_SET) == (-1))
  901. {
  902. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  903. return ERROR;
  904. }
  905. }
  906. zc->Lastsync = (zc->file_bytes = zc->Txpos = zc->Rxpos) -1;
  907. return zsendfdata(zc);
  908. }
  909. }
  910. }
  911. /*----------------------------------------------------------------------+
  912. | zsendfdata - Send the data in the file.
  913. +----------------------------------------------------------------------*/
  914. int zsendfdata(ZC *zc)
  915. {
  916. int c, e, n;
  917. int newcnt;
  918. long tcount = 0;
  919. TCHAR ch;
  920. int junkcount; /* Counts garbage chars received by TX */
  921. static int tleft = 6; /* Counter for test mode */
  922. int x;
  923. zc->Lrxpos = 0;
  924. junkcount = 0;
  925. zc->Beenhereb4 = 0;
  926. somemore:
  927. if (setjmp(zc->intrjmp))
  928. {
  929. waitack:
  930. junkcount = 0;
  931. c = getinsync(zc, 0);
  932. gotack:
  933. switch (c)
  934. {
  935. default:
  936. case ZSKIP:
  937. case ZCAN:
  938. case ZFERR:
  939. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  940. if (zc->fh)
  941. fio_close(zc->fh);
  942. zc->fh = NULL;
  943. return c;
  944. case ZACK:
  945. case ZRPOS:
  946. break;
  947. case ZRINIT:
  948. return OK;
  949. }
  950. /*
  951. * If the reverse channel can be tested for data,
  952. * this logic may be used to detect error packets
  953. * sent by the receiver, in place of setjmp/longjmp
  954. * rdchk() returns non 0 if a character is available
  955. */
  956. // while (rdchk(zc) != ERROR)
  957. while (mComRcvBufrPeek(zc->hCom, &ch) != 0)
  958. {
  959. switch (readline(zc, 1))
  960. {
  961. case CAN:
  962. case ZPAD:
  963. c = getinsync(zc, 1);
  964. goto gotack;
  965. case XOFF: /* Wait a while for an XON */
  966. case XOFF|0200:
  967. readline(zc, zc->Rxtimeout);
  968. break;
  969. default:
  970. break;
  971. }
  972. }
  973. }
  974. newcnt = zc->Rxbuflen;
  975. zc->Txwcnt = (unsigned)0;
  976. stohdr(zc, zc->Txpos);
  977. zsbhdr(zc, ZDATA, zc->Txhdr);
  978. do {
  979. switch (x = xfer_user_interrupt(zc->hSession))
  980. {
  981. case XFER_SKIP:
  982. case XFER_ABORT:
  983. zmdms_update(zc, ZCAN);
  984. longjmp(zc->flagkey_buf, 6);
  985. break;
  986. default:
  987. break;
  988. }
  989. if (xfer_carrier_lost(zc->hSession))
  990. {
  991. return ZCARRIER_LOST;
  992. }
  993. n = zfilbuf(zc);
  994. if (zc->Eofseen)
  995. {
  996. e = ZCRCE;
  997. }
  998. else if (junkcount > 3)
  999. {
  1000. e = ZCRCW;
  1001. }
  1002. else if (zc->file_bytes == zc->Lastsync)
  1003. {
  1004. e = ZCRCW;
  1005. }
  1006. else if (zc->Rxbuflen && (newcnt -= n) <= 0)
  1007. {
  1008. e = ZCRCW;
  1009. }
  1010. else if (zc->Txwindow && (zc->Txwcnt += n) >= zc->Txwspac)
  1011. {
  1012. zc->Txwcnt = (unsigned)0;
  1013. e = ZCRCQ;
  1014. }
  1015. else
  1016. {
  1017. e = ZCRCG;
  1018. }
  1019. zsdata(zc, zc->txbuf, n, e);
  1020. zc->file_bytes = zc->Txpos += n;
  1021. zc->real_bytes += n;
  1022. zmdms_update(zc, ZRPOS);
  1023. zmdms_progress(zc, 0);
  1024. if (e == ZCRCW)
  1025. {
  1026. goto waitack;
  1027. }
  1028. /*
  1029. * If the reverse channel can be tested for data,
  1030. * this logic may be used to detect error packets
  1031. * sent by the receiver, in place of setjmp/longjmp
  1032. * rdchk() returns non 0 if a character is available
  1033. */
  1034. // while (rdchk(zc) != ERROR)
  1035. while (mComRcvBufrPeek(zc->hCom, &ch) != 0)
  1036. {
  1037. switch (readline(zc, 1))
  1038. {
  1039. case CAN:
  1040. case ZPAD:
  1041. c = getinsync(zc, 1);
  1042. if (c == ZACK)
  1043. {
  1044. break;
  1045. }
  1046. /* zcrce - dinna wanna starta ping-pong game */
  1047. zsdata(zc, zc->txbuf, 0, ZCRCE);
  1048. goto gotack;
  1049. case XOFF: /* Wait a while for an XON */
  1050. case XOFF|0200:
  1051. readline(zc, zc->Rxtimeout);
  1052. default:
  1053. if (ch != ZFREECNT)
  1054. {
  1055. ++junkcount;
  1056. }
  1057. break;
  1058. }
  1059. }
  1060. if (zc->Txwindow)
  1061. {
  1062. while ((unsigned)(tcount = zc->Txpos - zc->Lrxpos) >= zc->Txwindow)
  1063. {
  1064. if (e != ZCRCQ)
  1065. {
  1066. zsdata(zc, zc->txbuf, 0, e = ZCRCQ);
  1067. }
  1068. c = getinsync(zc, 1);
  1069. if (c != ZACK)
  1070. {
  1071. zsdata(zc, zc->txbuf, 0, ZCRCE);
  1072. goto gotack;
  1073. }
  1074. }
  1075. }
  1076. } while (!zc->Eofseen);
  1077. for (;;)
  1078. {
  1079. stohdr(zc, zc->Txpos);
  1080. zsbhdr(zc, ZEOF, zc->Txhdr);
  1081. switch (c = getinsync(zc, 0))
  1082. {
  1083. case ZACK:
  1084. continue;
  1085. case ZRPOS:
  1086. goto somemore;
  1087. case ZRINIT:
  1088. return OK;
  1089. case ZSKIP:
  1090. default:
  1091. fio_close(zc->fh);
  1092. zc->fh = NULL;
  1093. return c;
  1094. }
  1095. }
  1096. }
  1097. /*----------------------------------------------------------------------+
  1098. | getinsync - Respond to receiver's complaint, get back in sync with receiver.
  1099. +----------------------------------------------------------------------*/
  1100. int getinsync(ZC *zc, int flag)
  1101. {
  1102. register int c;
  1103. flushmo(zc, &zc->stP);
  1104. for (;;)
  1105. {
  1106. // xfer_idle(zc->hSession, XFER_IDLE_IO);
  1107. c = zgethdr(zc, zc->Rxhdr, 'T');
  1108. switch (c)
  1109. {
  1110. case ZCAN:
  1111. case ZABORT:
  1112. case ZFIN:
  1113. case TIMEOUT:
  1114. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  1115. return c;
  1116. case ZRPOS:
  1117. /* ************************************* */
  1118. /* If sending to a buffered modem, you */
  1119. /* might send a break at this point to */
  1120. /* dump the modem's buffer. */
  1121. fio_errclr(zc->fh); /* In case file EOF seen */
  1122. if (fio_seek(zc->fh, zc->Rxpos, FIO_SEEK_SET) == (-1))
  1123. {
  1124. DbgOutStr("ZMODEM error %s %d\r\n", TEXT(__FILE__), __LINE__,0,0,0);
  1125. return ERROR;
  1126. }
  1127. zc->Eofseen = FALSE;
  1128. zc->file_bytes = zc->Lrxpos = zc->Txpos = zc->Rxpos;
  1129. if (zc->Lastsync == zc->Rxpos)
  1130. {
  1131. if (++zc->Beenhereb4 > 4)
  1132. {
  1133. if (zc->blklen > 32)
  1134. {
  1135. zc->blklen /= 2;
  1136. }
  1137. }
  1138. }
  1139. zc->Lastsync = zc->Rxpos;
  1140. zmdms_update(zc, ZRPOS);
  1141. return c;
  1142. case ZACK:
  1143. zc->Lrxpos = zc->Rxpos;
  1144. if (flag || zc->Txpos == zc->Rxpos)
  1145. {
  1146. return c;
  1147. }
  1148. break;
  1149. case ZRINIT:
  1150. case ZSKIP:
  1151. fio_close(zc->fh);
  1152. zc->fh = NULL;
  1153. return c;
  1154. case ERROR:
  1155. default:
  1156. zsbhdr(zc, ZNAK, zc->Txhdr);
  1157. break;
  1158. }
  1159. }
  1160. }
  1161. /*----------------------------------------------------------------------+
  1162. | saybibi - Say "bibi" to the receiver, try to do it cleanly.
  1163. +----------------------------------------------------------------------*/
  1164. void saybibi(ZC *zc)
  1165. {
  1166. for (;;)
  1167. {
  1168. stohdr(zc, 0L); /* CAF Was zsbhdr - minor change */
  1169. zshhdr(zc, ZFIN, zc->Txhdr); /* to make debugging easier */
  1170. switch (zgethdr(zc, zc->Rxhdr, 'T'))
  1171. {
  1172. case ZFIN:
  1173. sendline(zc, &zc->stP, 'O');
  1174. sendline(zc, &zc->stP, 'O');
  1175. flushmo(zc, &zc->stP);
  1176. return;
  1177. case ZCAN:
  1178. case TIMEOUT:
  1179. return;
  1180. case TSC_USER_CANNED: // These cases should not occur, but
  1181. case TSC_RMT_CANNED: // this code is placed here to ignore
  1182. case ZCARRIER_LOST: // these cases should they occur.
  1183. case ZMDM_CARRIER_LOST:
  1184. assert(0);
  1185. return;
  1186. default:
  1187. break;
  1188. }
  1189. }
  1190. }
  1191. /*********************** end of zmdm_snd.c **************************/