3 * Copyright (c) 1992-2001 by Mike Gleason.
20 extern const char *tcap_normal
;
21 extern const char *tcap_boldface
;
22 extern const char *tcap_underline
;
23 extern const char *tcap_reverse
;
24 extern int gScreenColumns
;
27 extern char gRemoteCWD
[];
32 FileSize(const double size
, const char **uStr0
, double *const uMult0
)
37 /* The comparisons below may look odd, but the reason
38 * for them is that we only want a maximum of 3 digits
39 * before the decimal point. (I.e., we don't want to
40 * see "1017.2 kB", instead we want "0.99 MB".
42 if (size
> (999.5 * kGigabyte
)) {
45 } else if (size
> (999.5 * kMegabyte
)) {
48 } else if (size
> (999.5 * kKilobyte
)) {
51 } else if (size
> 999.5) {
62 uTotal
= size
/ ((double) uMult
);
72 PrSizeAndRateMeter(const FTPCIPtr cip
, int mode
)
76 static const char *uStr
;
84 if (cip
->expectedSize
!= kSizeUnknown
) {
85 cip
->progress
= PrStatBar
;
89 (void) FileSize((double) cip
->expectedSize
, &uStr
, &uMult
);
91 if (cip
->lname
== NULL
) {
94 AbbrevStr(localName
, cip
->lname
, sizeof(localName
) - 2, 0);
95 if ((cip
->usingTAR
) && (strlen(localName
) < (sizeof(localName
) - 6))) {
96 STRNCAT(localName
, " (TAR)");
98 (void) STRNCAT(localName
, ":");
100 if (cip
->useProgressMeter
) {
103 if (OneTimeMessage("tar") != 0) {
104 (void) fprintf(stderr
, "\n\
105 Note: NcFTP is using on-the-fly TAR on the remote server, which retrieves the\n\
106 entire directory as one operation. This allows you to preserve exact file\n\
107 timestamps, ownerships, and permissions, as well as a slight performance\n\
110 If you would rather retrieve each file individually, use the \"-T\" flag with\n\
111 \"get\". TAR mode cannot be resumed if the transfer fails, so if that happens\n\
112 try \"get -T\" to resume the directory transfer.\n\n");
116 (void) fprintf(stderr
, "%-32s", localName
);
121 rate
= FileSize(cip
->kBytesPerSec
* 1024.0, &rStr
, NULL
);
123 if (cip
->lname
== NULL
) {
126 AbbrevStr(localName
, cip
->lname
, sizeof(localName
) - 2, 0);
127 if ((cip
->usingTAR
) && (strlen(localName
) < (sizeof(localName
) - 6))) {
128 STRNCAT(localName
, " (TAR)");
130 (void) STRNCAT(localName
, ":");
133 #if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
134 (void) sprintf(line
, "%-32s %10lld bytes %6.2f %s/s",
136 (longest_int
) (cip
->bytesTransferred
+ cip
->startPoint
),
140 #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
141 (void) sprintf(line
, "%-32s %10qd bytes %6.2f %s/s",
143 (longest_int
) (cip
->bytesTransferred
+ cip
->startPoint
),
147 #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
148 (void) sprintf(line
, "%-32s %10I64d bytes %6.2f %s/s",
150 (longest_int
) (cip
->bytesTransferred
+ cip
->startPoint
),
155 (void) sprintf(line
, "%-32s %10ld bytes %6.2f %s/s",
157 (long) (cip
->bytesTransferred
+ cip
->startPoint
),
163 /* Pad the rest of the line with spaces, to erase any
164 * stuff that might have been left over from the last
167 for (i
= (int) strlen(line
); i
< 80 - 2; i
++)
171 /* Print the updated information. */
172 (void) fprintf(stderr
, "\r%s", line
);
174 #if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
175 SetXtermTitle("%s - [%lld bytes]", cip
->lname
, (longest_int
) (cip
->bytesTransferred
+ cip
->startPoint
));
176 #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
177 SetXtermTitle("%s - [%qd bytes]", cip
->lname
, (longest_int
) (cip
->bytesTransferred
+ cip
->startPoint
));
178 #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
179 SetXtermTitle("%s - [%I64d bytes]", cip
->lname
, (longest_int
) (cip
->bytesTransferred
+ cip
->startPoint
));
181 SetXtermTitle("%s - [%ld bytes]", cip
->lname
, (long) (cip
->bytesTransferred
+ cip
->startPoint
));
186 (void) fprintf(stderr
, "\n\r");
188 if (cip
->rname
!= NULL
) {
191 FileToURL(url
, sizeof(url
), cip
->rname
, gRemoteCWD
, cip
->startingWorkingDirectory
, cip
->user
, cip
->pass
, cip
->host
, cip
->port
);
192 LogXfer((cip
->netMode
== kNetReading
) ? "get" : "put", url
);
197 } /* PrSizeAndRateMeter */
203 PrStatBar(const FTPCIPtr cip
, int mode
)
206 int secLeft
, minLeft
;
208 static const char *uStr
;
209 static double uTotal
, uMult
;
218 if (cip
->expectedSize
== kSizeUnknown
) {
219 cip
->progress
= PrSizeAndRateMeter
;
220 PrSizeAndRateMeter(cip
, mode
);
223 uTotal
= FileSize((double) cip
->expectedSize
, &uStr
, &uMult
);
225 if (cip
->lname
== NULL
) {
228 /* Leave room for a ':' and '\0'. */
229 AbbrevStr(localName
, cip
->lname
, sizeof(localName
) - 2, 0);
230 (void) STRNCAT(localName
, ":");
233 if (cip
->useProgressMeter
)
234 (void) fprintf(stderr
, "%-32s", localName
);
238 secLeft
= (int) (cip
->secLeft
+ 0.5);
239 minLeft
= secLeft
/ 60;
240 secLeft
= secLeft
- (minLeft
* 60);
246 rate
= FileSize(cip
->kBytesPerSec
* 1024.0, &rStr
, NULL
);
247 done
= (double) (cip
->bytesTransferred
+ cip
->startPoint
) / uMult
;
249 if (cip
->lname
== NULL
) {
252 AbbrevStr(localName
, cip
->lname
, 31, 0);
253 (void) STRNCAT(localName
, ":");
256 if (cip
->stalled
< 2)
258 else if (cip
->stalled
< 15)
263 (void) sprintf(line
, "%-32s ETA: %3d:%02d %6.2f/%6.2f %.2s %6.2f %.2s/s %.1s",
275 /* Print the updated information. */
276 (void) fprintf(stderr
, "\r%s", line
);
278 SetXtermTitle("%s - [%.1f%%]", cip
->lname
, cip
->percentCompleted
);
283 rate
= FileSize(cip
->kBytesPerSec
* 1024.0, &rStr
, NULL
);
284 done
= (double) (cip
->bytesTransferred
+ cip
->startPoint
) / uMult
;
286 if (cip
->expectedSize
== (cip
->bytesTransferred
+ cip
->startPoint
)) {
287 if (cip
->lname
== NULL
) {
290 AbbrevStr(localName
, cip
->lname
, 52, 0);
291 (void) STRNCAT(localName
, ":");
294 (void) sprintf(line
, "%-53s %6.2f %.2s %6.2f %.2s/s ",
302 if (cip
->lname
== NULL
) {
305 AbbrevStr(localName
, cip
->lname
, 45, 0);
306 (void) STRNCAT(localName
, ":");
309 (void) sprintf(line
, "%-46s %6.2f/%6.2f %.2s %6.2f %.2s/s ",
319 /* Pad the rest of the line with spaces, to erase any
320 * stuff that might have been left over from the last
323 for (i
= (int) strlen(line
); i
< 80 - 2; i
++)
327 /* Print the updated information. */
328 (void) fprintf(stderr
, "\r%s\n\r", line
);
330 if (cip
->rname
!= NULL
) {
333 FileToURL(url
, sizeof(url
), cip
->rname
, gRemoteCWD
, cip
->startingWorkingDirectory
, cip
->user
, cip
->pass
, cip
->host
, cip
->port
);
334 LogXfer((cip
->netMode
== kNetReading
) ? "get" : "put", url
);
344 /* This one is the brainchild of my comrade, Phil Dietz. It shows the
345 * progress as a fancy bar graph.
348 PrPhilBar(const FTPCIPtr cip
, int mode
)
353 static int maxBarLen
;
354 char spec1
[64], spec3
[64];
355 static char bar
[256];
357 int secsLeft
, minLeft
;
358 static const char *uStr
;
365 if (cip
->expectedSize
== kSizeUnknown
) {
366 cip
->progress
= PrSizeAndRateMeter
;
367 PrSizeAndRateMeter(cip
, mode
);
370 (void) FileSize((double) cip
->expectedSize
, &uStr
, &uMult
);
372 fprintf(stderr
, "%s file: %s \n",
373 (cip
->netMode
== kNetReading
) ? "Receiving" : "Sending",
377 for (i
=0; i
< (int) sizeof(bar
) - 1; i
++)
381 /* Compute the size of the bar itself. This sits between
382 * two numbers, one on each side of the screen. So the
383 * bar length will vary, depending on how many digits we
384 * need to display the size of the file.
386 maxBarLen
= gScreenColumns
- 1 - 28;
387 for (s
= cip
->expectedSize
; s
> 0; s
/= 10L)
390 /* Create a specification we can hand to printf. */
391 #if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
392 (void) sprintf(spec1
, " 0 %%%ds %%lld bytes. ETA: --:--", maxBarLen
);
394 /* Print the first invocation, which is an empty graph
395 * plus the other stuff.
397 fprintf(stderr
, spec1
, " ", cip
->expectedSize
);
398 #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
399 (void) sprintf(spec1
, " 0 %%%ds %%qd bytes. ETA: --:--", maxBarLen
);
400 fprintf(stderr
, spec1
, " ", cip
->expectedSize
);
401 #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
402 (void) sprintf(spec1
, " 0 %%%ds %%I64d bytes. ETA: --:--", maxBarLen
);
403 fprintf(stderr
, spec1
, " ", cip
->expectedSize
);
405 (void) sprintf(spec1
, " 0 %%%ds %%ld bytes. ETA: --:--", maxBarLen
);
406 fprintf(stderr
, spec1
, " ", (long) cip
->expectedSize
);
412 /* Compute how much of the bar should be colored in. */
413 curBarLen
= (int) (cip
->percentCompleted
* 0.01 * (double)maxBarLen
);
415 /* Colored portion must be at least one character so
416 * the spec isn't '%0s' which would screw the right side
422 bar
[curBarLen
- 1] = '>';
423 bar
[curBarLen
] = '\0';
425 /* Make the spec, so we can print the bar and the other stuff. */
426 STRNCPY(spec1
, "\r%3d%% 0 ");
428 #if defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_LLD)
429 (void) sprintf(spec3
, "%%%ds %%lld bytes. %s%%3d:%%02d",
430 maxBarLen
- curBarLen
,
433 #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_QD)
434 (void) sprintf(spec3
, "%%%ds %%qd bytes. %s%%3d:%%02d",
435 maxBarLen
- curBarLen
,
438 #elif defined(HAVE_LONG_LONG) && defined(PRINTF_LONG_LONG_I64D)
439 (void) sprintf(spec3
, "%%%ds %%I64d bytes. %s%%3d:%%02d",
440 maxBarLen
- curBarLen
,
444 (void) sprintf(spec3
, "%%%ds %%ld bytes. %s%%3d:%%02d",
445 maxBarLen
- curBarLen
,
450 /* We also show the percentage as a number at the left side. */
451 perc
= (int) (cip
->percentCompleted
);
452 secsLeft
= (int) (cip
->secLeft
);
453 minLeft
= secsLeft
/ 60;
454 secsLeft
= secsLeft
- (minLeft
* 60);
460 /* Print the updated information. */
461 fprintf(stderr
, spec1
, perc
);
462 fprintf(stderr
, "%s%s%s", tcap_reverse
, bar
, tcap_normal
);
463 fprintf(stderr
, spec3
,
470 bar
[curBarLen
- 1] = '=';
471 bar
[curBarLen
] = '=';
474 SetXtermTitle("%s - [%.1f%%]", cip
->lname
, cip
->percentCompleted
);
478 rate
= FileSize(cip
->kBytesPerSec
* 1024.0, &rStr
, NULL
);
480 (void) fprintf(stderr
, "%s: finished in %ld:%02ld:%02ld, %.2f %s/s\n",
481 (cip
->lname
== NULL
) ? "remote" : cip
->lname
,
482 (long) cip
->sec
/ 3600L,
483 ((long) cip
->sec
/ 60L) % 60L,
484 ((long) cip
->sec
% 60L),
489 if (cip
->rname
!= NULL
) {
492 FileToURL(url
, sizeof(url
), cip
->rname
, gRemoteCWD
, cip
->startingWorkingDirectory
, cip
->user
, cip
->pass
, cip
->host
, cip
->port
);
493 LogXfer((cip
->netMode
== kNetReading
) ? "get" : "put", url
);