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.

1156 lines
27 KiB

  1. /* File: C:\WACKER\xfer\krm_rcv.c (Created: 28-Jan-1994)
  2. * created from HAWIN source file
  3. * krm_rcv.c -- Routines for handling file transmission using KERMIT
  4. * file transfer protocol.
  5. *
  6. * Copyright 1989,1990,1991,1994 by Hilgraeve Inc. -- Monroe, MI
  7. * All rights reserved
  8. *
  9. * $Revision: 6 $
  10. * $Date: 7/11/02 11:10a $
  11. */
  12. #include <windows.h>
  13. #pragma hdrstop
  14. #include <time.h>
  15. #include <stdlib.h>
  16. #include <sys\types.h>
  17. #include <sys\utime.h>
  18. #include <term\res.h>
  19. #include <tdll\stdtyp.h>
  20. #include <tdll\mc.h>
  21. #include <tdll\assert.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\session.h>
  27. #include <tdll\htchar.h>
  28. #if !defined(BYTE)
  29. #define BYTE unsigned char
  30. #endif
  31. #include "cmprs.h"
  32. #include "itime.h"
  33. #include "xfr_dsp.h"
  34. #include "xfr_todo.h"
  35. #include "xfr_srvc.h"
  36. #include "xfer.h"
  37. #include "xfer.hh"
  38. #include "xfer_tsc.h"
  39. #include "krm.h"
  40. #include "krm.hh"
  41. // struct s_krm_rcv_control FAR *krc;
  42. // metachar (NEAR *p_kputc)(metachar);
  43. // long kbytes_received;
  44. // #define DO_DATE(hS) ((xfer_flags(hS)&XF_USE_DATETIME)!=0L)
  45. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  46. * krm_rcv
  47. *
  48. * DESCRIPTION:
  49. *
  50. *
  51. * ARGUMENTS:
  52. *
  53. *
  54. * RETURNS:
  55. *
  56. */
  57. int krm_rcv(HSESSION hS, int attended, int single_file)
  58. {
  59. ST_KRM *kc;
  60. unsigned total_retries;
  61. unsigned uabort_seq = 0;
  62. int kr_state;
  63. int iret;
  64. kc = NULL;
  65. kc = malloc(sizeof(*kc));
  66. if (kc == NULL)
  67. {
  68. xferMsgClose(hS);
  69. return TSC_NO_MEM;
  70. }
  71. kc->hSession = hS;
  72. kc->hCom = sessQueryComHdl(hS);
  73. kc->kbytes_received = 0;
  74. krmGetParameters(kc);
  75. kc->KrmProgress = kr_progress;
  76. kc->fhdl = NULL;
  77. kc->total_thru = 0L;
  78. kc->its_maxl = 80;
  79. kc->its_timeout = 10;
  80. kc->its_npad = 0;
  81. kc->its_padc = '\0';
  82. kc->its_eol = '\r';
  83. kc->its_chkt = 1;
  84. kc->its_qctl = K_QCTL;
  85. kc->its_qbin = '\0';
  86. kc->its_rept = '\0';
  87. kc->its_capat = FALSE;
  88. kc->files_done = 0;
  89. kc->xfertime = -1L;
  90. kc->kr.files_received = kc->kr.files_aborted = 0;
  91. kr_state = KREC_INIT;
  92. kc->ksequence = 0;
  93. kc->packetnum = 1;
  94. kc->tries = total_retries = 0;
  95. kc->kr.lasterr = KE_NOERROR;
  96. kc->abort_code = KA_OK;
  97. kc->kr.uabort_code = '\0';
  98. kc->kr.data_packet_rcvd = FALSE;
  99. kc->kr.dsptries = 0;
  100. kc->kr.store_later = FALSE;
  101. /* normally, the sender initiates a transfer, but if we're the terminal
  102. * end of the transfer, we may be able to get the sender to start up
  103. * without waiting for a timeout by sending a NAK packet as soon as we
  104. * start up.
  105. */
  106. ksend_packet(kc, 'N', 0, kc->ksequence, &kc->kr.resp_pckt);
  107. for ( ; ; )
  108. {
  109. xfer_idle(kc->hSession, XFER_IDLE_IO);
  110. switch(kr_state)
  111. {
  112. case KREC_INIT:
  113. kr_state = krec_init(kc);
  114. if (kr_state == KREC_FILE)
  115. {
  116. /* clear init errors */
  117. xferMsgErrorcnt(kc->hSession, total_retries = 0);
  118. xferMsgLasterror(kc->hSession, 0);
  119. }
  120. break;
  121. case KREC_FILE:
  122. kc->kr.data_packet_rcvd = FALSE;
  123. kc->kr.next_rtype = '\0'; /* init for krec_data routine */
  124. kr_state = krec_file(kc);
  125. if (!kc->tries && kr_state == KREC_DATA)
  126. {
  127. xferMsgNewfile(kc->hSession,
  128. ++kc->files_done,
  129. kc->their_fname,
  130. kc->our_fname);
  131. }
  132. break;
  133. case KREC_DATA:
  134. kr_state = krec_data(kc);
  135. if ((kc->kr.uabort_code == 'Z') &&
  136. (uabort_seq > (unsigned)(kc->packetnum + 3)))
  137. kr_state = KREC_ABORT;
  138. break;
  139. case KREC_COMPLETE:
  140. {
  141. int kret;
  142. kret = kresult_code[kc->abort_code];
  143. free(kc);
  144. kc = NULL;
  145. xferMsgClose(hS);
  146. return(kret);
  147. }
  148. /*lint -unreachable*/
  149. break;
  150. case KREC_ABORT:
  151. {
  152. int kret;
  153. xferMsgLasterror(kc->hSession, kc->kr.lasterr);
  154. if (kc->fhdl != NULL)
  155. xfer_close_rcv_file(hS,
  156. kc->fhdl,
  157. kresult_code[kc->abort_code],
  158. kc->their_fname,
  159. kc->our_fname,
  160. FALSE,
  161. 0L,
  162. 0);
  163. kret = kresult_code[kc->abort_code];
  164. free(kc);
  165. kc = NULL;
  166. xferMsgClose(hS);
  167. return(kret);
  168. }
  169. /*lint -unreachable*/
  170. break;
  171. default:
  172. assert(FALSE);
  173. break;
  174. }
  175. xferMsgPacketErrcnt(kc->hSession,
  176. kc->kr.dsptries ? kc->kr.dsptries : kc->tries);
  177. if (kc->tries || kc->kr.dsptries)
  178. {
  179. xferMsgErrorcnt(kc->hSession, ++kc->total_retries);
  180. xferMsgLasterror(kc->hSession, kc->kr.lasterr);
  181. kc->kr.dsptries = 0;
  182. }
  183. else
  184. xferMsgPacketnumber(kc->hSession, kc->packetnum);
  185. /* check for keyboard abort */
  186. if (iret = xfer_user_interrupt(kc->hSession))
  187. {
  188. if (iret == XFER_ABORT)
  189. {
  190. if (kc->kr.uabort_code) /* not the first time */
  191. {
  192. kc->abort_code = KA_IMMEDIATE;
  193. kr_state = KREC_ABORT;
  194. }
  195. else /* start user abort process */
  196. {
  197. if (single_file)
  198. kc->kr.uabort_code = 'Z';
  199. else
  200. kc->kr.uabort_code = 'X';
  201. /* force it */
  202. kc->kr.uabort_code = 'Z';
  203. uabort_seq = kc->packetnum;
  204. kc->abort_code = (kc->kr.uabort_code == 'X' ?
  205. KA_LABORT1 : KA_LABORTALL);
  206. }
  207. }
  208. else
  209. {
  210. if (kc->kr.uabort_code == 0)
  211. {
  212. kc->kr.uabort_code = 'X';
  213. uabort_seq = kc->packetnum;
  214. kc->abort_code = KA_LABORT1;
  215. }
  216. }
  217. }
  218. if (xfer_carrier_lost(kc->hSession))
  219. {
  220. kc->abort_code = KA_LOST_CARRIER;
  221. kr_state = KREC_ABORT;
  222. }
  223. }
  224. /*lint -unreachable*/
  225. }
  226. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  227. * krec_init
  228. *
  229. * DESCRIPTION:
  230. *
  231. *
  232. * ARGUMENTS:
  233. *
  234. *
  235. * RETURNS:
  236. *
  237. */
  238. int krec_init(ST_KRM *kc)
  239. {
  240. int rtype;
  241. int plen, rseq;
  242. unsigned slen;
  243. unsigned char packet[MAXPCKT];
  244. unsigned char tchkt;
  245. if (kc->tries++ > kc->k_retries)
  246. {
  247. kc->abort_code = KA_ERRLIMIT ;
  248. return(KREC_ABORT);
  249. }
  250. switch (rtype = krec_packet(kc, &plen, &rseq, packet))
  251. {
  252. case 'S':
  253. kc->xfertime = (long)startinterval();
  254. getparams(kc, FALSE, packet);
  255. slen = (unsigned)buildparams(kc, FALSE, kc->kr.resp_pckt.pdata);
  256. tchkt = kc->its_chkt;
  257. kc->its_chkt = 1; /* response must use checktype 1 */
  258. ksend_packet(kc, 'Y', slen, kc->ksequence, &kc->kr.resp_pckt);
  259. kc->its_chkt = tchkt;
  260. kc->kr.oldtries = kc->tries;
  261. kc->tries = 0;
  262. kc->ksequence = (kc->ksequence + 1) % 64;
  263. ++kc->packetnum;
  264. return(KREC_FILE);
  265. /*lint -unreachable*/
  266. break;
  267. case 'T':
  268. case BAD_PACKET:
  269. kc->kr.lasterr = (rtype == 'T' ? KE_TIMEOUT : KE_BAD_PACKET);
  270. ksend_packet(kc, 'N', 0, kc->ksequence, &kc->kr.resp_pckt);
  271. return(KREC_INIT); /* try again */
  272. /*lint -unreachable*/
  273. break;
  274. case 'E':
  275. kc->kr.lasterr = KE_RMTERR;
  276. StrCharCopyN(kc->xtra_err, packet, MAXLINE);
  277. kc->abort_code = KA_RMTERR;
  278. return(KREC_ABORT);
  279. /*lint -unreachable*/
  280. break;
  281. default:
  282. kc->kr.lasterr = KE_WRONG;
  283. kc->abort_code = KA_BAD_FORMAT;
  284. return(KREC_ABORT);
  285. /*lint -unreachable*/
  286. break;
  287. }
  288. /*lint -unreachable*/
  289. }
  290. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  291. * krec_file
  292. *
  293. * DESCRIPTION:
  294. *
  295. *
  296. * ARGUMENTS:
  297. *
  298. *
  299. * RETURNS:
  300. *
  301. */
  302. int krec_file(ST_KRM *kc)
  303. {
  304. int rtype;
  305. int plen, rseq;
  306. unsigned slen;
  307. int result;
  308. unsigned char packet[MAXPCKT];
  309. struct st_rcv_open stRcv;
  310. // struct fn_parts fns;
  311. // int disk;
  312. if (kc->tries++ > kc->k_retries)
  313. {
  314. kc->abort_code = KA_ERRLIMIT ;
  315. return(KREC_ABORT);
  316. }
  317. rtype = krec_packet(kc, &plen, &rseq, packet);
  318. if (kc->kr.store_later && (rtype != 'B' || rseq != kc->ksequence))
  319. {
  320. /* if kc->kr.store_later is TRUE, it means a file has been received
  321. * but it hasn't been closed yet to allow us to come here and
  322. * see if we should stop the transfer timer before closing and
  323. * logging the file. If the transfer isn't over, take care of
  324. * the last file.
  325. */
  326. // bf_setcheck(NULL);
  327. xfer_close_rcv_file(kc->hSession,
  328. kc->fhdl,
  329. TSC_OK,
  330. kc->their_fname,
  331. kc->our_fname,
  332. FALSE,
  333. kc->basesize + kc->kbytes_received,
  334. kc->k_useattr ? kc->kr.ul_filetime : 0);
  335. kc->kr.store_later = FALSE;
  336. kc->total_thru += kc->kbytes_received;
  337. kc->kbytes_received = 0;
  338. }
  339. switch (rtype)
  340. {
  341. case 'F':
  342. if (rseq != kc->ksequence)
  343. {
  344. kc->kr.lasterr = KE_SEQUENCE;
  345. kc->abort_code = KA_OUT_OF_SEQ;
  346. return(KREC_ABORT);
  347. }
  348. StrCharCopyN(kc->their_fname, packet, MAXPCKT);
  349. stRcv.pszSuggestedName = kc->their_fname;
  350. stRcv.pszActualName = kc->our_fname;
  351. kc->kr.ul_compare_time = 0;
  352. xfer_build_rcv_name(kc->hSession, &stRcv);
  353. result = xfer_open_rcv_file(kc->hSession, &stRcv, 0L);
  354. if (result != 0)
  355. {
  356. unsigned char buffer[64];
  357. LoadString(glblQueryDllHinst(),
  358. IDS_TM_KRM_CANT_OPEN,
  359. buffer, sizeof(buffer) / sizeof(TCHAR));
  360. StrCharCopyN(kc->kr.resp_pckt.pdata, buffer, MAXPCKT);
  361. ksend_packet(kc, 'E', StrCharGetByteCount(kc->kr.resp_pckt.pdata),
  362. kc->ksequence,
  363. &kc->kr.resp_pckt);
  364. kc->kr.lasterr = KE_FATAL;
  365. switch (result)
  366. {
  367. case -6:
  368. kc->abort_code = KA_USER_REFUSED;
  369. break;
  370. case -5:
  371. kc->abort_code = KA_CANT_OPEN;
  372. break;
  373. case -4:
  374. kc->abort_code = KA_NO_FILETIME;
  375. break;
  376. case -3:
  377. kc->abort_code = KA_TOO_MANY;
  378. break;
  379. case -2:
  380. kc->abort_code = KA_OLDER_FILE;
  381. break;
  382. case -1:
  383. default:
  384. kc->abort_code = KA_DISK_ERROR;
  385. break;
  386. }
  387. return(KREC_ABORT);
  388. }
  389. kc->fhdl = stRcv.bfHdl;
  390. kc->basesize = stRcv.lInitialSize;
  391. /* return our file name in Y packet */
  392. StrCharCopyN(kc->kr.resp_pckt.pdata, kc->our_fname, MAXPCKT);
  393. ksend_packet(kc, 'Y', StrCharGetByteCount(kc->our_fname), kc->ksequence,
  394. &kc->kr.resp_pckt);
  395. kc->kr.oldtries = kc->tries;
  396. kc->tries = 0;
  397. kc->ksequence = (kc->ksequence + 1) % 64;
  398. ++kc->packetnum;
  399. kc->kr.ul_filetime = 0; /* no date received yet */
  400. kc->kr.size_known = FALSE;
  401. kc->kbytes_received = 0L;
  402. kc->p_kputc = kr_putc;
  403. return(KREC_DATA);
  404. /*lint -unreachable*/
  405. break;
  406. case 'B': /* end of batch */
  407. if (rseq != kc->ksequence)
  408. {
  409. kc->kr.lasterr = KE_SEQUENCE;
  410. kc->abort_code = KA_OUT_OF_SEQ;
  411. return(KREC_ABORT);
  412. }
  413. ksend_packet(kc, 'Y', 0, kc->ksequence, &kc->kr.resp_pckt);
  414. kc->xfertime = (long)interval(kc->xfertime);
  415. kr_progress(kc, TRANSFER_DONE);
  416. //hp_report_xtime((unsigned)(kc->xfertime / 10L));
  417. if (kc->kr.store_later)
  418. {
  419. /* This stuff is here to allow us to stop the transfer timer
  420. before spending time closing the last file and logging the
  421. transfer.
  422. */
  423. //bf_setcheck(NULL);
  424. xfer_close_rcv_file(kc->hSession,
  425. kc->fhdl,
  426. TSC_OK,
  427. kc->their_fname,
  428. kc->our_fname,
  429. FALSE,
  430. kc->basesize + kc->kbytes_received,
  431. kc->k_useattr ? kc->kr.ul_filetime : 0);
  432. kc->kr.store_later = FALSE;
  433. kc->total_thru += kc->kbytes_received;
  434. kc->kbytes_received = 0;
  435. }
  436. kc->tries = 0;
  437. return(KREC_COMPLETE);
  438. /*lint -unreachable*/
  439. break;
  440. case 'S': /* received another send init packet, maybe they missed ACK */
  441. if (kc->kr.oldtries++ > kc->k_retries)
  442. {
  443. kc->abort_code = KA_ERRLIMIT ;
  444. return(KREC_ABORT);
  445. }
  446. if (rseq == ((kc->ksequence == 0) ? 63 : kc->ksequence - 1))
  447. {
  448. slen = (unsigned)buildparams(kc, FALSE, kc->kr.resp_pckt.pdata);
  449. ksend_packet(kc, 'Y', slen, rseq, &kc->kr.resp_pckt);
  450. kc->tries = 0;
  451. kc->kr.dsptries = kc->kr.oldtries;
  452. kc->kr.lasterr = KE_REPEAT;
  453. return(KREC_FILE);
  454. }
  455. else
  456. {
  457. kc->kr.lasterr = KE_WRONG;
  458. kc->abort_code = KA_BAD_FORMAT;
  459. return(KREC_ABORT);
  460. }
  461. /*lint -unreachable*/
  462. break;
  463. case 'Z':
  464. if (kc->kr.oldtries++ > kc->k_retries)
  465. {
  466. kc->abort_code = KA_ERRLIMIT ;
  467. return(KREC_ABORT);
  468. }
  469. if (rseq == ((kc->ksequence == 0) ? 63 : kc->ksequence - 1))
  470. {
  471. ksend_packet(kc, 'Y', 0, rseq, &kc->kr.resp_pckt);
  472. kc->tries = 0;
  473. kc->kr.dsptries = kc->kr.oldtries;
  474. kc->kr.lasterr = KE_REPEAT;
  475. return(KREC_FILE);
  476. }
  477. else
  478. {
  479. kc->abort_code = KA_BAD_FORMAT;
  480. kc->kr.lasterr = KE_WRONG;
  481. return(KREC_ABORT);
  482. }
  483. /*lint -unreachable*/
  484. break;
  485. case 'T':
  486. case BAD_PACKET:
  487. kc->kr.lasterr = (rtype == 'T' ? KE_TIMEOUT : KE_BAD_PACKET);
  488. ksend_packet(kc, 'N', 0, kc->ksequence, &kc->kr.resp_pckt);
  489. return(KREC_FILE); /* try again */
  490. /*lint -unreachable*/
  491. break;
  492. case 'E':
  493. kc->kr.lasterr = KE_RMTERR;
  494. StrCharCopyN(kc->xtra_err, packet, MAXLINE);
  495. kc->abort_code = KA_RMTERR;
  496. return(KREC_ABORT);
  497. /*lint -unreachable*/
  498. break;
  499. default:
  500. kc->kr.lasterr = KE_WRONG;
  501. kc->abort_code = KA_BAD_FORMAT;
  502. return(KREC_ABORT);
  503. /*lint -unreachable*/
  504. break;
  505. }
  506. /*lint -unreachable*/
  507. }
  508. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  509. * krec_data
  510. *
  511. * DESCRIPTION:
  512. *
  513. *
  514. * ARGUMENTS:
  515. *
  516. *
  517. * RETURNS:
  518. *
  519. */
  520. int krec_data(ST_KRM *kc)
  521. {
  522. int rtype;
  523. int kplen, krseq;
  524. unsigned char packet[MAXPCKT];
  525. if (kc->tries++ > kc->k_retries)
  526. {
  527. kc->abort_code = KA_ERRLIMIT;
  528. return(KREC_ABORT);
  529. }
  530. if (kc->kr.next_rtype == '\0')
  531. rtype = krec_packet(kc, &kplen, &krseq, packet);
  532. else
  533. {
  534. rtype = kc->kr.next_rtype;
  535. kplen = kc->kr.next_plen;
  536. krseq = kc->kr.next_rseq;
  537. MemCopy(packet, kc->kr.next_packet, (unsigned)MAXPCKT);
  538. kc->kr.next_rtype = '\0';
  539. }
  540. switch (rtype)
  541. {
  542. case 'A': /* attribute packet */
  543. case 'D': /* data packet */
  544. if (krseq != kc->ksequence)
  545. {
  546. if (kc->kr.oldtries++ > kc->k_retries)
  547. {
  548. kc->abort_code = KA_ERRLIMIT;
  549. return(KREC_ABORT);
  550. }
  551. if (krseq == ((kc->ksequence == 0) ? 63 : kc->ksequence - 1))
  552. {
  553. ksend_packet(kc, 'Y', 0, krseq, &kc->kr.resp_pckt);
  554. kc->tries = 0;
  555. kc->kr.dsptries = kc->kr.oldtries;
  556. kc->kr.lasterr = KE_REPEAT;
  557. return(KREC_DATA);
  558. }
  559. else
  560. {
  561. kc->abort_code = KA_OUT_OF_SEQ;
  562. return(KREC_ABORT);
  563. }
  564. }
  565. if (rtype == 'D')
  566. {
  567. /* got good data */
  568. /* If the /N option is being used, and an older file is being
  569. * received, a request was made to reject the file in the
  570. * response to the attribute packet. If a data packet comes
  571. * in anyway it means the sender failed to respond appropriately
  572. * and we must abort the transfer.
  573. */
  574. if (kc->kr.uabort_code == 'N')
  575. {
  576. kc->abort_code = KA_WONT_CANCEL;
  577. return(KREC_ABORT);
  578. }
  579. /* If there is a compare_time still specified, it means the /N
  580. * option was specified but the sender failed to include an
  581. * attribute packet with a filetime. We must abort the transfer
  582. */
  583. if (kc->kr.ul_compare_time != 0)
  584. {
  585. kc->abort_code = KA_NO_FILETIME;
  586. return(KREC_ABORT);
  587. }
  588. /* check for pending kbd abort and inlcude 'Z' or 'X' in packet */
  589. kc->kr.data_packet_rcvd = TRUE;
  590. kc->kr.resp_pckt.pdata[0] = kc->kr.uabort_code;
  591. ksend_packet(kc, 'Y', kc->kr.uabort_code ? 1 : 0, kc->ksequence,
  592. &kc->kr.resp_pckt);
  593. kr_progress(kc, 0);
  594. if (kunload_packet(kc, kplen, packet) == ERROR)
  595. { /* storage file error */
  596. kc->kr.lasterr = KE_FATAL;
  597. kc->abort_code = KA_DISK_ERROR;
  598. LoadString(glblQueryDllHinst(),
  599. IDS_TM_KRM_CANT_WRITE,
  600. kc->xtra_err, sizeof(kc->xtra_err) / sizeof(TCHAR));
  601. /* we're already sent response to this packet, wait & send
  602. error packet with next packet number */
  603. Sleep((DWORD)1000);
  604. StrCharCopyN(kc->kr.resp_pckt.pdata, kc->xtra_err, MAXPCKT);
  605. ksend_packet(kc, 'E',
  606. StrCharGetByteCount(kc->kr.resp_pckt.pdata),
  607. (kc->ksequence + 1) % 64, &kc->kr.resp_pckt);
  608. return(KREC_ABORT);
  609. }
  610. }
  611. else if (rtype == 'A')
  612. {
  613. if (kc->kr.data_packet_rcvd) /* all 'A' packets must precede 'D' packets */
  614. {
  615. kc->kr.lasterr = KE_WRONG;
  616. kc->abort_code = KA_BAD_FORMAT;
  617. return(KREC_ABORT);
  618. }
  619. // strblank(kc->kr.resp_pckt.pdata);
  620. kc->kr.resp_pckt.pdata[0] = TEXT('\0');
  621. kunload_attributes(kc, packet, &kc->kr.resp_pckt);
  622. ksend_packet(kc, 'Y',
  623. StrCharGetByteCount(kc->kr.resp_pckt.pdata),
  624. kc->ksequence,
  625. &kc->kr.resp_pckt);
  626. }
  627. kc->kr.oldtries = kc->tries;
  628. kc->tries = 0;
  629. kc->ksequence = (kc->ksequence + 1) % 64;
  630. ++kc->packetnum;
  631. return(KREC_DATA);
  632. /*lint -unreachable*/
  633. break;
  634. case 'Z': /* end of file */
  635. if (krseq != kc->ksequence)
  636. {
  637. kc->kr.lasterr = KE_WRONG;
  638. kc->abort_code = KA_OUT_OF_SEQ;
  639. return(KREC_ABORT);
  640. }
  641. if (strcmp(packet, "D") == 0) /* discard file? */
  642. {
  643. if (!kc->kr.uabort_code)
  644. kc->abort_code = KA_RABORT1;
  645. xfer_close_rcv_file(kc->hSession,
  646. kc->fhdl,
  647. kresult_code[kc->abort_code],
  648. kc->their_fname,
  649. kc->our_fname,
  650. FALSE,
  651. 0L,
  652. kc->k_useattr ? kc->kr.ul_filetime : 0);
  653. kc->total_thru += kc->kbytes_received;
  654. kc->kbytes_received = 0;
  655. ++kc->kr.files_aborted;
  656. }
  657. else
  658. {
  659. /* file has been received */
  660. kr_progress(kc, FILE_DONE);
  661. ++kc->kr.files_received;
  662. /* if all is well, hold off on closing file and logging tranfer
  663. * until after the next packet is in. This way we can stop the
  664. * transfer timer earlier
  665. */
  666. if (kc->abort_code == KA_OK)
  667. kc->kr.store_later = TRUE;
  668. else
  669. {
  670. xfer_close_rcv_file(kc->hSession,
  671. kc->fhdl,
  672. kresult_code[kc->abort_code],
  673. kc->their_fname,
  674. kc->our_fname,
  675. FALSE,
  676. kc->basesize + kc->kbytes_received,
  677. kc->k_useattr ? kc->kr.ul_filetime : 0);
  678. kc->total_thru += kc->kbytes_received;
  679. kc->kbytes_received = 0;
  680. }
  681. }
  682. ksend_packet(kc, 'Y', 0, kc->ksequence, &kc->kr.resp_pckt);
  683. if (kc->kr.uabort_code == 'X' || kc->kr.uabort_code == 'N')
  684. kc->kr.uabort_code = '\0', kc->abort_code = KA_OK;
  685. kc->kr.oldtries = kc->tries;
  686. kc->tries = 0;
  687. kc->ksequence = (kc->ksequence + 1) % 64;
  688. ++kc->packetnum;
  689. return(KREC_FILE);
  690. /*lint -unreachable*/
  691. break;
  692. case 'F': /* receiving file name again? */
  693. if (kc->kr.oldtries++ > kc->k_retries)
  694. {
  695. kc->abort_code = KA_ERRLIMIT;
  696. return(KREC_ABORT);
  697. }
  698. if (krseq == ((kc->ksequence == 0) ? 63 : kc->ksequence - 1))
  699. {
  700. StrCharCopyN(kc->kr.resp_pckt.pdata, kc->our_fname, MAXPCKT);
  701. ksend_packet(kc, 'Y',
  702. StrCharGetByteCount(kc->our_fname),
  703. krseq,
  704. &kc->kr.resp_pckt);
  705. kc->tries = 0;
  706. kc->kr.lasterr = KE_REPEAT;
  707. kc->kr.dsptries = kc->kr.oldtries;
  708. return(KREC_DATA);
  709. }
  710. else
  711. {
  712. kc->kr.lasterr = KE_WRONG;
  713. kc->abort_code = KA_BAD_FORMAT;
  714. return(KREC_ABORT);
  715. }
  716. /*lint -unreachable*/
  717. break;
  718. /* account for repeated 'X' packet here */
  719. case 'T':
  720. case BAD_PACKET:
  721. kc->kr.lasterr = (rtype == 'T' ? KE_TIMEOUT : KE_BAD_PACKET);
  722. ksend_packet(kc, 'N', 0, kc->ksequence, &kc->kr.resp_pckt);
  723. return(KREC_DATA); /* try again */
  724. /*lint -unreachable*/
  725. break;
  726. case 'E':
  727. kc->kr.lasterr = KE_RMTERR;
  728. StrCharCopyN(kc->xtra_err, packet, MAXLINE);
  729. kc->abort_code = KA_RMTERR;
  730. return(KREC_ABORT);
  731. /*lint -unreachable*/
  732. break;
  733. default:
  734. kc->kr.lasterr = KE_WRONG;
  735. kc->abort_code = KA_BAD_FORMAT;
  736. return(KREC_ABORT);
  737. /*lint -unreachable*/
  738. break;
  739. }
  740. /*lint -unreachable*/
  741. }
  742. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  743. * kr_progress
  744. *
  745. * DESCRIPTION:
  746. * Displays transfer progress indicators for Kermit receive
  747. *
  748. * ARGUMENTS:
  749. * final -- TRUE if final display for a file.
  750. *
  751. * RETURNS:
  752. * nothing
  753. */
  754. void kr_progress(ST_KRM *kc, int status)
  755. {
  756. long ttime, stime;
  757. long bytes_rcvd;
  758. long cps;
  759. int k_rcvd;
  760. long krm_stime = -1;
  761. long krm_ttime = -1;
  762. long krm_cps = -1;
  763. long krm_file_so_far = -1;
  764. long krm_total_so_far = -1;
  765. if (kc->xfertime == -1L)
  766. return;
  767. ttime = bittest(status, TRANSFER_DONE) ?
  768. kc->xfertime : (long)interval(kc->xfertime);
  769. if ((stime = ttime / 10L) != kc->displayed_time ||
  770. bittest(status, FILE_DONE | TRANSFER_DONE))
  771. {
  772. krm_stime = stime;
  773. bytes_rcvd = kc->total_thru + kc->kbytes_received;
  774. if (bittest(status, FILE_DONE | TRANSFER_DONE))
  775. k_rcvd = (int)PART_HUNKS(bytes_rcvd, 1024);
  776. else
  777. k_rcvd = (int)FULL_HUNKS(bytes_rcvd, 1024);
  778. krm_total_so_far = k_rcvd;
  779. krm_file_so_far = kc->kbytes_received;
  780. if (stime > 0 && (cps = (bytes_rcvd * 10L) / ttime) > 0)
  781. {
  782. krm_cps = cps;
  783. if ((kc->kr.bytes_expected > 0))
  784. {
  785. ttime = (kc->kr.bytes_expected - kc->kbytes_received) / cps;
  786. krm_ttime = ttime;
  787. }
  788. }
  789. kc->displayed_time = stime;
  790. }
  791. xferMsgProgress(kc->hSession,
  792. krm_stime,
  793. krm_ttime,
  794. krm_cps,
  795. krm_file_so_far,
  796. krm_total_so_far);
  797. }
  798. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  799. * krm_rcheck
  800. *
  801. * DESCRIPTION:
  802. *
  803. *
  804. * ARGUMENTS:
  805. *
  806. *
  807. * RETURNS:
  808. *
  809. */
  810. #if 0
  811. void krm_rcheck(HSESSION hS, bool before)
  812. {
  813. if (before)
  814. {
  815. /* wait till next packet is in before writing to disk */
  816. Dbg(krm_dbg, D_KRM_RCHECK);
  817. kc->kr.next_rtype = krec_packet(hS, &kc->kr.next_plen, &kc->kr.next_rseq,
  818. kc->kr.next_packet);
  819. }
  820. }
  821. #endif
  822. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  823. * krm_check_input
  824. *
  825. * DESCRIPTION:
  826. *
  827. * ARGUEMENTS:
  828. *
  829. * RETURNS:
  830. *
  831. */
  832. #if 0
  833. void krm_check_input(bool suspend)
  834. {
  835. int disk;
  836. struct fn_parts fns;
  837. static USHORT old_ovr;
  838. USHORT new_ovr;
  839. if (suspend)
  840. {
  841. (VOID)mComGetErrors(comhdl, FALSE, NULL, &old_ovr, NULL, NULL);
  842. }
  843. else
  844. {
  845. (VOID)mComGetErrors(comhdl, FALSE, NULL, &new_ovr, NULL, NULL);
  846. if (new_ovr > old_ovr)
  847. {
  848. /*
  849. * Got an error. Make sure things are taken care of
  850. * so that we don't get any more errors.
  851. */
  852. if (kc->fhdl != NULL)
  853. {
  854. /* only do this if it might have been our file I/O */
  855. bf_setcheck(NULL);
  856. bf_setcheck(krm_rcheck);
  857. fl_dissect_fn(bf_name(kc->fhdl), &fns);
  858. disk = (fns.fn_drv[0] - 'A') & 0x1F;
  859. transfer_setspeed(disk, cnfg.bit_rate);
  860. }
  861. }
  862. }
  863. }
  864. #endif
  865. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  866. * kunload_attributes
  867. *
  868. * DESCRIPTION:
  869. *
  870. *
  871. * ARGUMENTS:
  872. *
  873. *
  874. * RETURNS:
  875. *
  876. */
  877. void kunload_attributes(ST_KRM *kc, unsigned char *data, KPCKT *rsp_pckt)
  878. {
  879. unsigned char *limit = data + StrCharGetByteCount(data);
  880. unsigned len;
  881. unsigned char attrfield[20];
  882. while (data <= limit - 2)
  883. {
  884. len = (unsigned char)unchar(data[1]);
  885. if ((data + len + 1) >= limit)
  886. break;
  887. if (len <= sizeof(attrfield) - 1)
  888. {
  889. strncpy(attrfield, data + 2, len);
  890. attrfield[len] = '\0';
  891. switch (*data)
  892. {
  893. case '0':
  894. break;
  895. case '1':
  896. /* This attribute gives an exact byte count of a file as it
  897. * it was stored on the senders system. This is what we need
  898. * to display a vu_meter etc. as the file is received
  899. * (There is also a '!' field available that contains the
  900. * filesize expressed in K. We don't currently use that
  901. * field.
  902. */
  903. if ((kc->kr.bytes_expected = atol(attrfield)) > 0)
  904. {
  905. kc->kr.size_known = TRUE;
  906. xferMsgFilesize(kc->hSession, kc->kr.bytes_expected);
  907. }
  908. break;
  909. case '#':
  910. /* This field specifies the creation date of the file on the
  911. * senders system, expressed as "[yy]yymmdd[ hh:mm[:ss]]".
  912. * We use this for two things: If the user has asked us to use
  913. * received attributes, we set the time/date of the new file
  914. * based on this field. If the user specified the /N receive
  915. * option, we compare this received file time with the filetime
  916. * of any existing file of the same name and reject the file
  917. * unless the incoming file is newer.
  918. */
  919. /* extract date/time from the packet data field */
  920. krm_settime(attrfield, &kc->kr.ul_filetime);
  921. /* if kc->kr.compare_time contains a valid date/time, it means
  922. * that the /N option was used and the file being received
  923. * already exists. Compare the two times and reject any file
  924. * that is not newer than what we already have.
  925. */
  926. if (kc->kr.ul_compare_time != 0)
  927. {
  928. /* if incoming file (kc->kr.filetime) <= existing file
  929. * (kc->kr.compare_time), reject the file
  930. */
  931. if (kc->kr.ul_filetime <= kc->kr.ul_compare_time)
  932. {
  933. /* reject incoming file */
  934. StrCharCopyN(rsp_pckt->pdata, "N#", MAXPCKT);
  935. kc->kr.uabort_code = 'N';
  936. kc->abort_code = KA_OLDER_FILE;
  937. }
  938. else
  939. {
  940. /* clear compare_time or transfer would fail when
  941. * first data packet is received
  942. */
  943. kc->kr.ul_compare_time = 0;
  944. }
  945. }
  946. /* user may opt not to use received file time/date */
  947. if (!kc->k_useattr)
  948. kc->kr.ul_filetime = 0;
  949. break;
  950. default :
  951. /* ignore */
  952. break;
  953. }
  954. }
  955. data += (len + 2);
  956. }
  957. }
  958. #define atoc(c) ((c) - (CHAR)'0')
  959. #define isadigit(x) ((x >= '0') && (x <= '9'))
  960. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  961. * krm_settime
  962. *
  963. * DESCRIPTION:
  964. *
  965. *
  966. * ARGUMENTS:
  967. *
  968. *
  969. * RETURNS:
  970. *
  971. */
  972. void krm_settime(unsigned char *data, unsigned long *ptime)
  973. {
  974. unsigned long ltime;
  975. struct tm sT;
  976. unsigned char *datestr = data;
  977. unsigned char *timestr = NULL;
  978. char ch;
  979. int s;
  980. unsigned i;
  981. unsigned sl;
  982. sT.tm_year = sT.tm_hour = -1;
  983. if ((sl = StrCharGetByteCount(data)) > 7 && data[6] == ' ')
  984. {
  985. data[6] = '\0';
  986. timestr = &data[7];
  987. }
  988. else if (sl > 9 && data[8] == ' ')
  989. {
  990. data[8] = '\0';
  991. timestr = &data[9];
  992. }
  993. /* try to get date */
  994. if ((sl = StrCharGetByteCount(datestr)) == 6 || sl == 8)
  995. {
  996. for (i = 0; i < sl; ++i)
  997. if (!isadigit(datestr[i]))
  998. break;
  999. if (i == sl)
  1000. {
  1001. if (sl == 8)
  1002. {
  1003. ch = atoc(datestr[0]);
  1004. s = (int)ch;
  1005. sT.tm_year = s * 1000;
  1006. sT.tm_year += ((int)atoc(datestr[1]) * 100);
  1007. datestr += 2;
  1008. }
  1009. else
  1010. {
  1011. sT.tm_year = 1900;
  1012. }
  1013. sT.tm_year += (atoc(datestr[0]) * 10 + atoc(datestr[1]));
  1014. sT.tm_mon = atoc(datestr[2]) * 10 + atoc(datestr[3]);
  1015. sT.tm_mday = atoc(datestr[4]) * 10 + atoc(datestr[5]);
  1016. }
  1017. if (sT.tm_mon > 12 || sT.tm_mday > 31)
  1018. sT.tm_year = -1;
  1019. }
  1020. /* try to get a time */
  1021. if (timestr)
  1022. {
  1023. if (((sl = StrCharGetByteCount(timestr)) == 5 || (sl == 8 && timestr[5] == ':'))
  1024. && timestr[2] == ':')
  1025. {
  1026. sT.tm_hour = atoc(timestr[0]) * 10 + atoc(timestr[1]);
  1027. sT.tm_min = atoc(timestr[3]) * 10 + atoc(timestr[4]);
  1028. if (sl == 8)
  1029. sT.tm_sec = atoc(timestr[6]) * 10 + atoc(timestr[7]);
  1030. else
  1031. sT.tm_sec = 0;
  1032. }
  1033. if (sT.tm_hour > 24 || sT.tm_min > 59 || sT.tm_sec > 59)
  1034. sT.tm_hour = -1;
  1035. }
  1036. if (sT.tm_year == -1 || sT.tm_hour == -1)
  1037. return;
  1038. sT.tm_year -= 1900;
  1039. ltime = (unsigned long)mktime(&sT);
  1040. ltime += itimeGetBasetime();
  1041. *ptime = ltime;
  1042. }
  1043. /*********************** end of krm_rcv.c ****************************/