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.

802 lines
18 KiB

  1. /* File: C:\WACKER\xfer\krm_snd.c (Created: 28-Jan-1994)
  2. * created from HAWIN source code
  3. * krm_snd.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: 5 $
  10. * $Date: 7/11/02 11:10a $
  11. */
  12. // #define DEBUGSTR 1
  13. #include <windows.h>
  14. #pragma hdrstop
  15. #include <time.h>
  16. #include <stdlib.h>
  17. #include <sys\types.h>
  18. #include <sys\utime.h>
  19. #include <term\res.h>
  20. #include <tdll\stdtyp.h>
  21. #include <tdll\mc.h>
  22. #include <tdll\assert.h>
  23. #include <tdll\load_res.h>
  24. #include <tdll\xfer_msc.h>
  25. #include <tdll\globals.h>
  26. #include <tdll\file_io.h>
  27. #include <tdll\session.h>
  28. #include <tdll\htchar.h>
  29. #include <tdll\com.h>
  30. #if !defined(BYTE)
  31. #define BYTE unsigned char
  32. #endif
  33. #include "cmprs.h"
  34. #include "itime.h"
  35. #include "xfr_dsp.h"
  36. #include "xfr_todo.h"
  37. #include "xfr_srvc.h"
  38. #include "xfer.h"
  39. #include "xfer.hh"
  40. #include "xfer_tsc.h"
  41. #include "krm.h"
  42. #include "krm.hh"
  43. // unsigned total_retries;
  44. // metachar (NEAR *p_kgetc)(void);
  45. // long kbytes_sent = 0L;
  46. // KPCKT FAR * this_kpckt;
  47. // KPCKT FAR * next_kpckt;
  48. /* local funtion prototypes */
  49. void build_attributes(ST_KRM *kc,
  50. unsigned char *bufr,
  51. long size,
  52. unsigned long ul_time);
  53. int ksend_init(ST_KRM *kc);
  54. int ksend_break(ST_KRM *kc);
  55. int ksend_file(ST_KRM *kc, long fsize);
  56. int wldindexx(const char *string,
  57. const char FAR *substr,
  58. char wildcard,
  59. int ic);
  60. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  61. * krm_snd
  62. *
  63. * DESCRIPTION:
  64. * send a file or files using kermit protocol
  65. *
  66. * This routine also handles logging of kermit sending operations to the
  67. * optional log file.
  68. *
  69. * ARGUMENTS:
  70. * attended -- TRUE if transfer is run manually, FALSE if run under automation
  71. * such as in host or hyperpilot
  72. * nfile -- number of files to be sent
  73. * nbytes -- total number of bytes to be sent in all files
  74. *
  75. * RETURNS:
  76. * Returns TRUE if all files are sent successfully or if all cancellations
  77. * were user-requested, 'graceful' ones. Returns FALSE if an error occurs
  78. * at either end of transfer or if user forces an immediate exit.
  79. */
  80. int krm_snd(HSESSION hS, int attended, int nfiles, long nbytes)
  81. {
  82. ST_KRM *kc;
  83. int result;
  84. long sndsize;
  85. unsigned long filetime;
  86. long ttime;
  87. kc = malloc(sizeof(ST_KRM));
  88. if (kc == NULL)
  89. {
  90. xferMsgClose(hS);
  91. return TSC_NO_MEM;
  92. }
  93. memset(kc, 0, sizeof(ST_KRM));
  94. kc->hSession = hS;
  95. kc->hCom = sessQueryComHdl(hS);
  96. kc->kbytes_sent = 0L;
  97. kc->this_kpckt = NULL;
  98. kc->next_kpckt = NULL;
  99. if (kc != NULL)
  100. kc->this_kpckt = malloc(sizeof(KPCKT));
  101. if (kc->this_kpckt != NULL)
  102. kc->next_kpckt = malloc(sizeof(KPCKT));
  103. if (kc->next_kpckt == NULL)
  104. {
  105. if (kc->this_kpckt != NULL)
  106. {
  107. free(kc->this_kpckt);
  108. kc->this_kpckt = NULL;
  109. }
  110. if (kc != NULL)
  111. {
  112. free(kc);
  113. kc = NULL;
  114. }
  115. xferMsgClose(hS);
  116. return TSC_NO_MEM;
  117. }
  118. krmGetParameters(kc);
  119. kc->KrmProgress = ks_progress;
  120. kc->total_retries = 0;
  121. xferMsgFilecnt(kc->hSession, nfiles);
  122. xferMsgTotalsize(kc->hSession, nbytes);
  123. kc->nbytes = nbytes;
  124. kc->file_cnt = nfiles;
  125. kc->files_done = 0;
  126. kc->its_maxl = 80;
  127. kc->its_timeout = 15;
  128. kc->its_npad = 0;
  129. kc->its_padc = '\0';
  130. kc->its_eol = kc->k_eol;
  131. kc->its_chkt = 1;
  132. kc->its_qctl = K_QCTL;
  133. kc->its_qbin = '\0';
  134. kc->its_rept = '\0';
  135. kc->its_capat = FALSE;
  136. kc->ksequence = 0;
  137. kc->packetnum = 1;
  138. kc->abort_code = KA_OK;
  139. kc->xfertime = -1L;
  140. if (!ksend_init(kc))
  141. {
  142. int kret;
  143. kret = kresult_code[kc->abort_code];
  144. free(kc->this_kpckt);
  145. kc->this_kpckt = NULL;
  146. free(kc->next_kpckt);
  147. kc->next_kpckt = NULL;
  148. free(kc);
  149. kc = NULL;
  150. xferMsgClose(hS);
  151. return(kret);
  152. }
  153. /* don't show init errors once transfer has started */
  154. kc->total_dsp = kc->total_thru = 0L; /* new transfer starting */
  155. while(xfer_nextfile(kc->hSession, kc->our_fname))
  156. {
  157. // xfer_idle(kc->hSession, XFER_IDLE_IO);
  158. if (kc->abort_code == KA_LABORT1) /* TODO: figure this out */
  159. kc->abort_code = KA_LABORTALL;
  160. if (kc->abort_code >= KA_LABORTALL)
  161. break;
  162. kc->abort_code = KA_OK;
  163. result = xfer_opensendfile(kc->hSession,
  164. &kc->fhdl,
  165. kc->our_fname,
  166. &sndsize,
  167. kc->their_fname,
  168. &filetime);
  169. if (result != 0)
  170. {
  171. kc->abort_code = KA_CANT_OPEN;
  172. break;
  173. }
  174. if (kc->its_capat)
  175. build_attributes(kc, kc->next_kpckt->pdata, sndsize, filetime);
  176. ksend_file(kc, sndsize);
  177. ++kc->files_done;
  178. if (kc->fhdl)
  179. {
  180. fio_close(kc->fhdl);
  181. kc->fhdl = NULL;
  182. }
  183. /* log transfer status here based on kc->abort_code */
  184. xfer_log_xfer(kc->hSession,
  185. TRUE,
  186. kc->our_fname,
  187. NULL,
  188. kresult_code[kc->abort_code]);
  189. }
  190. if (kc->abort_code < KA_IMMEDIATE)
  191. ksend_break(kc);
  192. ks_progress(kc, TRANSFER_DONE);
  193. ttime = ((long)interval(kc->xfertime) / 10L);
  194. result = kresult_code[kc->abort_code];
  195. xferMsgClose(kc->hSession);
  196. free(kc->this_kpckt);
  197. kc->this_kpckt = NULL;
  198. free(kc->next_kpckt);
  199. kc->next_kpckt = NULL;
  200. free(kc);
  201. kc = NULL;
  202. xferMsgClose(hS);
  203. return(result);
  204. }
  205. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  206. * build_attributes
  207. *
  208. * DESCRIPTION:
  209. *
  210. * ARGUMENTS:
  211. *
  212. * RETURNS:
  213. *
  214. */
  215. void build_attributes(ST_KRM *kc,
  216. unsigned char *bufr,
  217. long size,
  218. unsigned long ul_time)
  219. {
  220. char str[15];
  221. int sl;
  222. struct tm *pt;
  223. /* add file size in K */
  224. wsprintf((LPSTR)str,
  225. (LPSTR)"%d",
  226. (int)(FULL_HUNKS(size, 1024)));
  227. wsprintf((LPSTR)bufr,
  228. (LPSTR)"!%c%s",
  229. tochar(sl = (int)StrCharGetByteCount(str)),
  230. (LPSTR)str);
  231. bufr += (sl + 2);
  232. /* add file size in bytes */
  233. wsprintf((LPSTR)str,
  234. (LPSTR)"%ld",
  235. (ULONG)size);
  236. wsprintf((LPSTR)bufr,
  237. (LPSTR)"1%c%s",
  238. tochar(sl = (int)StrCharGetByteCount(str)),
  239. (LPSTR)str);
  240. bufr += (sl + 2);
  241. /* add file date and time */
  242. ul_time += itimeGetBasetime(); /* Adjust to C7 and later */
  243. pt = localtime((time_t*)&ul_time);
  244. assert(pt);
  245. if (pt)
  246. {
  247. /*
  248. * Dimwitted thing sometimes returns 0
  249. */
  250. wsprintf((LPSTR)bufr,
  251. (LPSTR)"#%c%04d%02d%02d %02d:%02d:%02d",
  252. tochar(17),
  253. pt->tm_year + 1900,
  254. pt->tm_mon + 1,
  255. pt->tm_mday,
  256. pt->tm_hour,
  257. pt->tm_min,
  258. pt->tm_sec);
  259. bufr += 19;
  260. }
  261. /* system of origin */
  262. StrCharCat(bufr, ".\"U8");
  263. bufr += 4;
  264. }
  265. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  266. * ksend_init
  267. *
  268. * DESCRIPTION:
  269. *
  270. * ARGUMENTS:
  271. *
  272. * RETURNS:
  273. *
  274. */
  275. int ksend_init(ST_KRM *kc)
  276. {
  277. unsigned plen; /* length of outgoing packet data */
  278. char rpacket[MAXPCKT]; /* space to receive response packet */
  279. int rlen, rseq; /* length and sequence of response packet */
  280. int tries = 0;
  281. /* set init parameters as sender */
  282. plen = (unsigned)buildparams(kc, TRUE, kc->this_kpckt->pdata);
  283. xferMsgPacketnumber(kc->hSession, kc->packetnum);
  284. while (tries < kc->k_retries)
  285. {
  286. // xfer_idle(kc->hSession, XFER_IDLE_IO);
  287. xferMsgPacketErrcnt(kc->hSession, tries);
  288. ksend_packet(kc, 'S', plen, kc->ksequence, kc->this_kpckt);
  289. switch (krec_packet(kc, &rlen, &rseq, rpacket))
  290. {
  291. case 'Y':
  292. if (rseq == kc->ksequence)
  293. {
  294. kc->xfertime = (long)startinterval();
  295. getparams(kc, TRUE, rpacket);
  296. kc->ksequence = (kc->ksequence + 1) % 64;
  297. ++kc->packetnum;
  298. return(TRUE);
  299. }
  300. /* fall through */
  301. case 'N':
  302. xferMsgLasterror(kc->hSession, KE_NAK);
  303. ++tries;
  304. break;
  305. case 'T':
  306. xferMsgLasterror(kc->hSession, KE_TIMEOUT);
  307. ++tries;
  308. break;
  309. case BAD_PACKET:
  310. if (xfer_user_interrupt(kc->hSession))
  311. {
  312. kc->abort_code = KA_IMMEDIATE;
  313. return (FALSE);
  314. }
  315. if (xfer_carrier_lost(kc->hSession))
  316. {
  317. kc->abort_code = KA_LOST_CARRIER;
  318. return (FALSE);
  319. }
  320. xferMsgLasterror(kc->hSession, KE_BAD_PACKET);
  321. ++tries;
  322. break;
  323. case 'E':
  324. /* received error packet, abort transfer */
  325. xferMsgLasterror(kc->hSession, KE_RMTERR);
  326. strncpy(kc->xtra_err, rpacket, (unsigned)65);
  327. kc->abort_code = KA_RMTERR;
  328. return(FALSE);
  329. /*lint -unreachable*/
  330. break;
  331. default:
  332. /* unexpected packet type */
  333. kc->abort_code = KA_BAD_FORMAT;
  334. return(FALSE);
  335. /*lint -unreachable*/
  336. break;
  337. }
  338. }
  339. /* error count has been exceeded */
  340. kc->abort_code = KA_ERRLIMIT;
  341. return(FALSE);
  342. }
  343. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  344. * ksend_break
  345. *
  346. * DESCRIPTION:
  347. * Send 'B' packet to indicate end of transaction
  348. *
  349. * ARGUMENTS:
  350. * none
  351. *
  352. * RETURNS:
  353. *
  354. */
  355. int ksend_break(ST_KRM *kc)
  356. {
  357. char rpacket[MAXPCKT]; /* space to receive response packet */
  358. int rlen, rseq; /* length and sequence of response packet */
  359. int tries = 0;
  360. while (tries < kc->k_retries)
  361. {
  362. // xfer_idle(kc->hSession, XFER_IDLE_IO);
  363. ksend_packet(kc, 'B', 0, kc->ksequence, kc->this_kpckt);
  364. switch (krec_packet(kc, &rlen, &rseq, rpacket))
  365. {
  366. case 'Y':
  367. if (rseq == kc->ksequence)
  368. {
  369. kc->ksequence = (kc->ksequence + 1) % 64;
  370. ++kc->packetnum;
  371. return(TRUE);
  372. }
  373. /* fall through */
  374. case 'N':
  375. case 'T':
  376. case BAD_PACKET:
  377. if (xfer_user_interrupt(kc->hSession))
  378. {
  379. kc->abort_code = KA_IMMEDIATE;
  380. return FALSE;
  381. }
  382. if (xfer_carrier_lost(kc->hSession))
  383. {
  384. kc->abort_code = KA_LOST_CARRIER;
  385. return FALSE;
  386. }
  387. ++tries;
  388. break;
  389. case 'E':
  390. /* received error packet, abort transfer */
  391. StrCharCopyN(kc->xtra_err, rpacket, MAXLINE);
  392. kc->abort_code = KA_RMTERR;
  393. return(FALSE);
  394. /*lint -unreachable*/
  395. break;
  396. default:
  397. /* unexpected packet type */
  398. kc->abort_code = KA_BAD_FORMAT;
  399. return(FALSE);
  400. /*lint -unreachable*/
  401. break;
  402. }
  403. }
  404. /* error count has been exceeded */
  405. kc->abort_code = KA_ERRLIMIT;
  406. return(FALSE);
  407. }
  408. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  409. * ksend_file
  410. *
  411. * DESCRIPTION:
  412. *
  413. * ARGUMENTS:
  414. *
  415. * RETURNS:
  416. *
  417. */
  418. int ksend_file(ST_KRM *kc, long fsize)
  419. {
  420. int tries = 0;
  421. int file_sent = FALSE;
  422. int packet_sent = FALSE;
  423. int kbd_abort = KA_OK;
  424. char rtype;
  425. int rlen, rseq;
  426. char rpacket[MAXPCKT];
  427. int sendattr;
  428. KPCKT *tmp;
  429. DbgOutStr("ksend_file %s\r\n", (LPSTR)kc->our_fname, 0,0,0,0);
  430. xferMsgNewfile(kc->hSession,
  431. kc->files_done + 1,
  432. kc->our_fname,
  433. kc->our_fname);
  434. xferMsgFilesize(kc->hSession, fsize);
  435. xferMsgPacketErrcnt(kc->hSession, 0);
  436. xferMsgPacketnumber(kc->hSession, 0);
  437. kc->p_kgetc = ks_getc;
  438. kc->kbytes_sent = 0;
  439. /* prepare file-header packet in this_kpckt */
  440. kc->this_kpckt->ptype = 'F';
  441. StrCharCopyN(kc->this_kpckt->pdata, kc->their_fname, MAXPCKT);
  442. kc->this_kpckt->datalen = (int)StrCharGetByteCount(kc->this_kpckt->pdata);
  443. sendattr = kc->its_capat &&
  444. (size_t)StrCharGetByteCount(kc->next_kpckt->pdata) <= (size_t)(kc->its_maxl - 5);
  445. while (!file_sent && kc->abort_code == KA_OK) /* for each packet */
  446. {
  447. // xfer_idle(kc->hSession, XFER_IDLE_IO);
  448. tries = 0;
  449. packet_sent = FALSE;
  450. while (!packet_sent && tries++ < kc->k_retries && kc->abort_code == KA_OK)
  451. {
  452. // xfer_idle(kc->hSession, XFER_IDLE_IO);
  453. if (kbd_abort != KA_OK && tries == 1)
  454. {
  455. kc->this_kpckt->ptype = 'Z';
  456. kc->this_kpckt->datalen = 1;
  457. StrCharCopyN(kc->this_kpckt->pdata, "D", MAXPCKT);
  458. }
  459. DbgOutStr("Calling ksend_packet %d %c (0x%x)",
  460. tries, kc->this_kpckt->ptype, kc->this_kpckt->ptype, 0,0);
  461. ksend_packet(kc, kc->this_kpckt->ptype,
  462. (unsigned)kc->this_kpckt->datalen,
  463. kc->ksequence, kc->this_kpckt);
  464. if (xfer_carrier_lost(kc->hSession))
  465. {
  466. kc->abort_code = KA_LOST_CARRIER;
  467. break;
  468. }
  469. if (tries == 1) /* first try for this packet */
  470. {
  471. xferMsgPacketnumber(kc->hSession, kc->packetnum);
  472. if (fsize > 0)
  473. ks_progress(kc, 0);
  474. /* get next packet ready while first is being sent */
  475. if (sendattr) /* data alreay prepared in next_kpckt */
  476. {
  477. kc->next_kpckt->datalen = (int)StrCharGetByteCount(kc->next_kpckt->pdata);
  478. kc->next_kpckt->ptype = 'A';
  479. sendattr = FALSE;
  480. }
  481. else if ((kc->next_kpckt->datalen =
  482. kload_packet(kc, kc->next_kpckt->pdata)) == ERROR)
  483. {
  484. kc->next_kpckt->ptype = 'E';
  485. kc->next_kpckt->datalen = (int)StrCharGetByteCount(kc->xtra_err);
  486. StrCharCopyN(kc->next_kpckt->pdata, kc->xtra_err, MAXPCKT);
  487. }
  488. else
  489. kc->next_kpckt->ptype = (char)(kc->next_kpckt->datalen ? 'D':'Z');
  490. DbgOutStr(" next packet %c (0x%x)\r\n",
  491. kc->next_kpckt->ptype, kc->next_kpckt->ptype, 0,0,0);
  492. } /* end of if (tries == 1) */
  493. else
  494. {
  495. xferMsgPacketErrcnt(kc->hSession, tries - 1);
  496. xferMsgErrorcnt(kc->hSession, ++kc->total_retries);
  497. DbgOutStr(" retry\r\n", 0,0,0,0,0);
  498. }
  499. rtype = (char)krec_packet(kc, &rlen, &rseq, rpacket);
  500. if (rtype == 'N' && (--rseq < 0 ? 63 : rseq) == kc->ksequence)
  501. rtype = 'Y';
  502. DbgOutStr("called krec_packet %c (0x%x)\r\n", rtype, rtype, 0,0,0);
  503. switch(rtype)
  504. {
  505. case 'Y':
  506. if (rseq == kc->ksequence)
  507. {
  508. packet_sent = TRUE;
  509. kc->ksequence = (kc->ksequence + 1) % 64;
  510. ++kc->packetnum;
  511. if (kc->this_kpckt->ptype == 'A')/* response to attr pckt */
  512. {
  513. /* If receiver responded to an attribute packet with
  514. * an 'N' in the data field, do not transfer the file.
  515. */
  516. if (rlen > 0 && *rpacket == 'N')
  517. kbd_abort = KA_RABORT1;
  518. }
  519. if (kc->this_kpckt->ptype == 'Z')/* have we sent last one?*/
  520. {
  521. file_sent = TRUE;
  522. kc->abort_code = kbd_abort;
  523. kbd_abort = KA_OK;
  524. }
  525. if (rlen == 1)
  526. {
  527. if (*rpacket == 'X')
  528. kbd_abort = KA_RABORT1;
  529. else if (*rpacket == 'Z')
  530. kbd_abort = KA_RABORTALL;
  531. }
  532. tmp = kc->this_kpckt;
  533. kc->this_kpckt = kc->next_kpckt;
  534. kc->next_kpckt = tmp;
  535. }
  536. else
  537. xferMsgLasterror(kc->hSession, KE_SEQUENCE);
  538. break;
  539. case 'N':
  540. xferMsgLasterror(kc->hSession, KE_NAK);
  541. break;
  542. case BAD_PACKET:
  543. xferMsgLasterror(kc->hSession, KE_BAD_PACKET);
  544. break;
  545. case 'T':
  546. xferMsgLasterror(kc->hSession, KE_TIMEOUT);
  547. break;
  548. case 'E':
  549. xferMsgLasterror(kc->hSession, KE_RMTERR);
  550. StrCharCopyN(kc->xtra_err, rpacket, MAXLINE);
  551. kc->abort_code = KA_RMTERR;
  552. return(FALSE);
  553. /*lint -unreachable*/
  554. break;
  555. default:
  556. xferMsgLasterror(kc->hSession, KE_WRONG);
  557. kc->abort_code = KA_BAD_FORMAT;
  558. return(FALSE);
  559. /*lint -unreachable*/
  560. break;
  561. }
  562. if (xfer_user_interrupt(kc->hSession))
  563. {
  564. if (kbd_abort == KA_OK) /* first time */
  565. {
  566. kbd_abort = KA_LABORT1;
  567. }
  568. else
  569. kc->abort_code = KA_IMMEDIATE;
  570. }
  571. if (xfer_carrier_lost(kc->hSession))
  572. kc->abort_code = KA_LOST_CARRIER;
  573. } /* end while (!packet_sent && etc.) */
  574. xferMsgPacketErrcnt(kc->hSession, tries = 0);
  575. if (kc->abort_code == KA_OK && !packet_sent) /* error count exceeded */
  576. kc->abort_code = KA_ERRLIMIT;
  577. } /* end while (!file_sent etc.) */
  578. xferMsgPacketnumber(kc->hSession, kc->packetnum);
  579. ks_progress(kc, FILE_DONE);
  580. kc->total_dsp += fsize;
  581. kc->total_thru += kc->kbytes_sent;
  582. kc->kbytes_sent = 0;
  583. return(file_sent);
  584. } /* end ksend_file() */
  585. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  586. * ks_progress
  587. *
  588. * DESCRIPTION:
  589. * Displays transfer progress indicators for Kermit Send
  590. *
  591. * ARGUMENTS:
  592. * final -- TRUE if final display for a file.
  593. *
  594. * RETURNS:
  595. * nothing
  596. */
  597. void ks_progress(ST_KRM *kc, int status)
  598. {
  599. long ttime, stime;
  600. long bytes_sent;
  601. long cps;
  602. long krm_stime = -1;
  603. long krm_ttime = -1;
  604. long krm_cps = -1;
  605. long krm_file_so_far = -1;
  606. long krm_total_so_far = -1;
  607. if (kc->xfertime == -1L)
  608. return;
  609. ttime = (long)interval(kc->xfertime);
  610. if ((stime = ttime / 10L) != kc->displayed_time ||
  611. bittest(status, FILE_DONE | TRANSFER_DONE))
  612. {
  613. /* Display elapsed time */
  614. krm_stime = stime;
  615. /* Display amount transferred */
  616. bytes_sent = kc->total_dsp + kc->kbytes_sent;
  617. krm_file_so_far = kc->kbytes_sent;
  618. krm_total_so_far = bytes_sent;
  619. /* Display throughput and est. time to completion */
  620. if ((stime > 2 ||
  621. ttime > 0 && bittest(status, FILE_DONE | TRANSFER_DONE)) &&
  622. (cps = ((kc->total_thru + kc->kbytes_sent) * 10L) / ttime) > 0)
  623. {
  624. krm_cps = cps;
  625. if ((kc->nbytes > 0))
  626. {
  627. ttime = ((kc->nbytes - bytes_sent) / cps) +
  628. kc->file_cnt - kc->files_done;
  629. krm_ttime = ttime;
  630. }
  631. }
  632. kc->displayed_time = stime;
  633. }
  634. xferMsgProgress(kc->hSession,
  635. krm_stime,
  636. krm_ttime,
  637. krm_cps,
  638. krm_file_so_far,
  639. krm_total_so_far);
  640. }
  641. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  642. #define toupper(x) ((x)-'a'+'A')
  643. int wldindexx(const char *string,
  644. const char *substr,
  645. char wildcard,
  646. int ic)
  647. /* ic - ignore case */
  648. {
  649. short index, limit;
  650. const char *s;
  651. const char *ss;
  652. if (*substr == '\0')
  653. return(0);
  654. index = 0;
  655. limit = (short)StrCharGetByteCount(string) - (short)StrCharGetByteCount(substr);
  656. while (index <= limit)
  657. {
  658. s = &string[index];
  659. ss = substr;
  660. while (*ss == wildcard || *s == *ss || (ic && isascii(*s)
  661. && isascii(*ss) && toupper(*s) == toupper(*ss)))
  662. {
  663. ++s;
  664. if (*++ss == '\0')
  665. return(index);
  666. }
  667. ++index;
  668. }
  669. return(-1);
  670. }
  671. /********************* end of krm_snd.c ********************/