~ubuntu-branches/ubuntu/hardy/wget/hardy-security

« back to all changes in this revision

Viewing changes to src/progress.c

  • Committer: Bazaar Package Importer
  • Author(s): Noèl Köthe
  • Date: 2005-06-26 16:46:25 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050626164625-jjcde8hyztx7xq7o
Tags: 1.10-2
* wget-fix_error--save-headers patch from upstream
  (closes: Bug#314728)
* don't pattern-match server redirects patch from upstream
  (closes: Bug#163243)
* correct de.po typos
  (closes: Bug#313883)
* wget-E_html_behind_file_counting fix problem with adding the
  numbers after the html extension
* updated Standards-Version: to 3.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
50
50
#include "retr.h"
51
51
 
52
52
struct progress_implementation {
53
 
  char *name;
54
 
  void *(*create) PARAMS ((long, long));
55
 
  void (*update) PARAMS ((void *, long, double));
 
53
  const char *name;
 
54
  int interactive;
 
55
  void *(*create) PARAMS ((wgint, wgint));
 
56
  void (*update) PARAMS ((void *, wgint, double));
56
57
  void (*finish) PARAMS ((void *, double));
57
58
  void (*set_params) PARAMS ((const char *));
58
59
};
59
60
 
60
61
/* Necessary forward declarations. */
61
62
 
62
 
static void *dot_create PARAMS ((long, long));
63
 
static void dot_update PARAMS ((void *, long, double));
 
63
static void *dot_create PARAMS ((wgint, wgint));
 
64
static void dot_update PARAMS ((void *, wgint, double));
64
65
static void dot_finish PARAMS ((void *, double));
65
66
static void dot_set_params PARAMS ((const char *));
66
67
 
67
 
static void *bar_create PARAMS ((long, long));
68
 
static void bar_update PARAMS ((void *, long, double));
 
68
static void *bar_create PARAMS ((wgint, wgint));
 
69
static void bar_update PARAMS ((void *, wgint, double));
69
70
static void bar_finish PARAMS ((void *, double));
70
71
static void bar_set_params PARAMS ((const char *));
71
72
 
72
73
static struct progress_implementation implementations[] = {
73
 
  { "dot", dot_create, dot_update, dot_finish, dot_set_params },
74
 
  { "bar", bar_create, bar_update, bar_finish, bar_set_params }
 
74
  { "dot", 0, dot_create, dot_update, dot_finish, dot_set_params },
 
75
  { "bar", 1, bar_create, bar_update, bar_finish, bar_set_params }
75
76
};
76
77
static struct progress_implementation *current_impl;
77
78
static int current_impl_locked;
95
96
int
96
97
valid_progress_implementation_p (const char *name)
97
98
{
98
 
  int i = 0;
 
99
  int i;
99
100
  struct progress_implementation *pi = implementations;
100
101
  char *colon = strchr (name, ':');
101
102
  int namelen = colon ? colon - name : strlen (name);
155
156
   advance.  */
156
157
 
157
158
void *
158
 
progress_create (long initial, long total)
 
159
progress_create (wgint initial, wgint total)
159
160
{
160
161
  /* Check if the log status has changed under our feet. */
161
162
  if (output_redirected)
168
169
  return current_impl->create (initial, total);
169
170
}
170
171
 
 
172
/* Return non-zero if the progress gauge is "interactive", i.e. if it
 
173
   can profit from being called regularly even in absence of data.
 
174
   The progress bar is interactive because it regularly updates the
 
175
   ETA and current update.  */
 
176
 
 
177
int
 
178
progress_interactive_p (void *progress)
 
179
{
 
180
  return current_impl->interactive;
 
181
}
 
182
 
171
183
/* Inform the progress gauge of newly received bytes.  DLTIME is the
172
184
   time in milliseconds since the beginning of the download.  */
173
185
 
174
186
void
175
 
progress_update (void *progress, long howmuch, double dltime)
 
187
progress_update (void *progress, wgint howmuch, double dltime)
176
188
{
177
189
  current_impl->update (progress, howmuch, dltime);
178
190
}
189
201
/* Dot-printing. */
190
202
 
191
203
struct dot_progress {
192
 
  long initial_length;          /* how many bytes have been downloaded
 
204
  wgint initial_length;         /* how many bytes have been downloaded
193
205
                                   previously. */
194
 
  long total_length;            /* expected total byte count when the
 
206
  wgint total_length;           /* expected total byte count when the
195
207
                                   download finishes */
196
208
 
197
209
  int accumulated;
204
216
/* Dot-progress backend for progress_create. */
205
217
 
206
218
static void *
207
 
dot_create (long initial, long total)
 
219
dot_create (wgint initial, wgint total)
208
220
{
209
 
  struct dot_progress *dp = xmalloc (sizeof (struct dot_progress));
210
 
 
211
 
  memset (dp, 0, sizeof (*dp));
212
 
 
 
221
  struct dot_progress *dp = xnew0 (struct dot_progress);
213
222
  dp->initial_length = initial;
214
223
  dp->total_length   = total;
215
224
 
216
225
  if (dp->initial_length)
217
226
    {
218
227
      int dot_bytes = opt.dot_bytes;
219
 
      long row_bytes = opt.dot_bytes * opt.dots_in_line;
 
228
      wgint row_bytes = opt.dot_bytes * opt.dots_in_line;
220
229
 
221
230
      int remainder = (int) (dp->initial_length % row_bytes);
222
 
      long skipped = dp->initial_length - remainder;
 
231
      wgint skipped = dp->initial_length - remainder;
223
232
 
224
233
      if (skipped)
225
234
        {
235
244
                     2 + skipped_k_len, "", skipped_k);
236
245
        }
237
246
 
238
 
      logprintf (LOG_VERBOSE, "\n%5ldK", skipped / 1024);
 
247
      logprintf (LOG_VERBOSE, "\n%5ldK", (long) (skipped / 1024));
239
248
      for (; remainder >= dot_bytes; remainder -= dot_bytes)
240
249
        {
241
250
          if (dp->dots % opt.dot_spacing == 0)
253
262
}
254
263
 
255
264
static void
256
 
print_percentage (long bytes, long expected)
 
265
print_percentage (wgint bytes, wgint expected)
257
266
{
258
267
  int percentage = (int)(100.0 * bytes / expected);
259
268
  logprintf (LOG_VERBOSE, "%3d%%", percentage);
260
269
}
261
270
 
262
271
static void
263
 
print_download_speed (struct dot_progress *dp, long bytes, double dltime)
 
272
print_download_speed (struct dot_progress *dp, wgint bytes, double dltime)
264
273
{
265
274
  logprintf (LOG_VERBOSE, " %s",
266
275
             retr_rate (bytes, dltime - dp->last_timer_value, 1));
270
279
/* Dot-progress backend for progress_update. */
271
280
 
272
281
static void
273
 
dot_update (void *progress, long howmuch, double dltime)
 
282
dot_update (void *progress, wgint howmuch, double dltime)
274
283
{
275
284
  struct dot_progress *dp = progress;
276
285
  int dot_bytes = opt.dot_bytes;
277
 
  long row_bytes = opt.dot_bytes * opt.dots_in_line;
 
286
  wgint row_bytes = opt.dot_bytes * opt.dots_in_line;
278
287
 
279
288
  log_set_flush (0);
280
289
 
282
291
  for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes)
283
292
    {
284
293
      if (dp->dots == 0)
285
 
        logprintf (LOG_VERBOSE, "\n%5ldK", dp->rows * row_bytes / 1024);
 
294
        logprintf (LOG_VERBOSE, "\n%5ldK", (long) (dp->rows * row_bytes / 1024));
286
295
 
287
296
      if (dp->dots % opt.dot_spacing == 0)
288
297
        logputs (LOG_VERBOSE, " ");
291
300
      ++dp->dots;
292
301
      if (dp->dots >= opt.dots_in_line)
293
302
        {
294
 
          long row_qty = row_bytes;
 
303
          wgint row_qty = row_bytes;
295
304
          if (dp->rows == dp->initial_length / row_bytes)
296
305
            row_qty -= dp->initial_length % row_bytes;
297
306
 
314
323
{
315
324
  struct dot_progress *dp = progress;
316
325
  int dot_bytes = opt.dot_bytes;
317
 
  long row_bytes = opt.dot_bytes * opt.dots_in_line;
 
326
  wgint row_bytes = opt.dot_bytes * opt.dots_in_line;
318
327
  int i;
319
328
 
320
329
  log_set_flush (0);
321
330
 
322
331
  if (dp->dots == 0)
323
 
    logprintf (LOG_VERBOSE, "\n%5ldK", dp->rows * row_bytes / 1024);
 
332
    logprintf (LOG_VERBOSE, "\n%5ldK", (long) (dp->rows * row_bytes / 1024));
324
333
  for (i = dp->dots; i < opt.dots_in_line; i++)
325
334
    {
326
335
      if (i % opt.dot_spacing == 0)
336
345
    }
337
346
 
338
347
  {
339
 
    long row_qty = dp->dots * dot_bytes + dp->accumulated;
 
348
    wgint row_qty = dp->dots * dot_bytes + dp->accumulated;
340
349
    if (dp->rows == dp->initial_length / row_bytes)
341
350
      row_qty -= dp->initial_length % row_bytes;
342
351
    print_download_speed (dp, row_qty, dltime);
411
420
   create_image will overflow the buffer.  */
412
421
#define MINIMUM_SCREEN_WIDTH 45
413
422
 
414
 
static int screen_width = DEFAULT_SCREEN_WIDTH;
 
423
/* The last known screen width.  This can be updated by the code that
 
424
   detects that SIGWINCH was received (but it's never updated from the
 
425
   signal handler).  */
 
426
static int screen_width;
 
427
 
 
428
/* A flag that, when set, means SIGWINCH was received.  */
 
429
static volatile sig_atomic_t received_sigwinch;
415
430
 
416
431
/* Size of the download speed history ring. */
417
432
#define DLSPEED_HISTORY_SIZE 20
422
437
   past.  */
423
438
#define DLSPEED_SAMPLE_MIN 150
424
439
 
 
440
/* The time after which the download starts to be considered
 
441
   "stalled", i.e. the current bandwidth is not printed and the recent
 
442
   download speeds are scratched.  */
 
443
#define STALL_START_TIME 5000
 
444
 
425
445
struct bar_progress {
426
 
  long initial_length;          /* how many bytes have been downloaded
 
446
  wgint initial_length;         /* how many bytes have been downloaded
427
447
                                   previously. */
428
 
  long total_length;            /* expected total byte count when the
 
448
  wgint total_length;           /* expected total byte count when the
429
449
                                   download finishes */
430
 
  long count;                   /* bytes downloaded so far */
 
450
  wgint count;                  /* bytes downloaded so far */
431
451
 
432
452
  double last_screen_update;    /* time of the last screen update,
433
453
                                   measured since the beginning of
450
470
     details.  */
451
471
  struct bar_progress_hist {
452
472
    int pos;
453
 
    long times[DLSPEED_HISTORY_SIZE];
454
 
    long bytes[DLSPEED_HISTORY_SIZE];
 
473
    wgint times[DLSPEED_HISTORY_SIZE];
 
474
    wgint bytes[DLSPEED_HISTORY_SIZE];
455
475
 
456
476
    /* The sum of times and bytes respectively, maintained for
457
477
       efficiency. */
458
 
    long total_time;
459
 
    long total_bytes;
 
478
    wgint total_time;
 
479
    wgint total_bytes;
460
480
  } hist;
461
481
 
462
482
  double recent_start;          /* timestamp of beginning of current
463
483
                                   position. */
464
 
  long recent_bytes;            /* bytes downloaded so far. */
 
484
  wgint recent_bytes;           /* bytes downloaded so far. */
 
485
 
 
486
  int stalled;                  /* set when no data arrives for longer
 
487
                                   than STALL_START_TIME, then reset
 
488
                                   when new data arrives. */
465
489
 
466
490
  /* create_image() uses these to make sure that ETA information
467
 
     doesn't flash. */
 
491
     doesn't flicker. */
468
492
  double last_eta_time;         /* time of the last update to download
469
493
                                   speed and ETA, measured since the
470
494
                                   beginning of download. */
471
 
  long last_eta_value;
 
495
  wgint last_eta_value;
472
496
};
473
497
 
474
498
static void create_image PARAMS ((struct bar_progress *, double));
475
499
static void display_image PARAMS ((char *));
476
500
 
477
501
static void *
478
 
bar_create (long initial, long total)
 
502
bar_create (wgint initial, wgint total)
479
503
{
480
 
  struct bar_progress *bp = xmalloc (sizeof (struct bar_progress));
481
 
 
482
 
  memset (bp, 0, sizeof (*bp));
 
504
  struct bar_progress *bp = xnew0 (struct bar_progress);
483
505
 
484
506
  /* In theory, our callers should take care of this pathological
485
507
     case, but it can sometimes happen. */
489
511
  bp->initial_length = initial;
490
512
  bp->total_length   = total;
491
513
 
 
514
  /* Initialize screen_width if this hasn't been done or if it might
 
515
     have changed, as indicated by receiving SIGWINCH.  */
 
516
  if (!screen_width || received_sigwinch)
 
517
    {
 
518
      screen_width = determine_screen_width ();
 
519
      if (!screen_width)
 
520
        screen_width = DEFAULT_SCREEN_WIDTH;
 
521
      else if (screen_width < MINIMUM_SCREEN_WIDTH)
 
522
        screen_width = MINIMUM_SCREEN_WIDTH;
 
523
      received_sigwinch = 0;
 
524
    }
 
525
 
492
526
  /* - 1 because we don't want to use the last screen column. */
493
527
  bp->width = screen_width - 1;
494
528
  /* + 1 for the terminating zero. */
496
530
 
497
531
  logputs (LOG_VERBOSE, "\n");
498
532
 
499
 
  create_image (bp, 0);
 
533
  create_image (bp, 0.0);
500
534
  display_image (bp->buffer);
501
535
 
502
536
  return bp;
503
537
}
504
538
 
505
 
static void update_speed_ring PARAMS ((struct bar_progress *, long, double));
 
539
static void update_speed_ring PARAMS ((struct bar_progress *, wgint, double));
506
540
 
507
541
static void
508
 
bar_update (void *progress, long howmuch, double dltime)
 
542
bar_update (void *progress, wgint howmuch, double dltime)
509
543
{
510
544
  struct bar_progress *bp = progress;
511
545
  int force_screen_update = 0;
522
556
 
523
557
  update_speed_ring (bp, howmuch, dltime);
524
558
 
525
 
  if (screen_width - 1 != bp->width)
 
559
  /* If SIGWINCH (the window size change signal) been received,
 
560
     determine the new screen size and update the screen.  */
 
561
  if (received_sigwinch)
526
562
    {
527
 
      bp->width = screen_width - 1;
528
 
      bp->buffer = xrealloc (bp->buffer, bp->width + 1);
529
 
      force_screen_update = 1;
 
563
      int old_width = screen_width;
 
564
      screen_width = determine_screen_width ();
 
565
      if (!screen_width)
 
566
        screen_width = DEFAULT_SCREEN_WIDTH;
 
567
      else if (screen_width < MINIMUM_SCREEN_WIDTH)
 
568
        screen_width = MINIMUM_SCREEN_WIDTH;
 
569
      if (screen_width != old_width)
 
570
        {
 
571
          bp->width = screen_width - 1;
 
572
          bp->buffer = xrealloc (bp->buffer, bp->width + 1);
 
573
          force_screen_update = 1;
 
574
        }
 
575
      received_sigwinch = 0;
530
576
    }
531
577
 
532
578
  if (dltime - bp->last_screen_update < 200 && !force_screen_update)
576
622
   3-second average would be too erratic.  */
577
623
 
578
624
static void
579
 
update_speed_ring (struct bar_progress *bp, long howmuch, double dltime)
 
625
update_speed_ring (struct bar_progress *bp, wgint howmuch, double dltime)
580
626
{
581
627
  struct bar_progress_hist *hist = &bp->hist;
582
628
  double recent_age = dltime - bp->recent_start;
590
636
  if (recent_age < DLSPEED_SAMPLE_MIN)
591
637
    return;
592
638
 
 
639
  if (howmuch == 0)
 
640
    {
 
641
      /* If we're not downloading anything, we might be stalling,
 
642
         i.e. not downloading anything for an extended period of time.
 
643
         Since 0-reads do not enter the history ring, recent_age
 
644
         effectively measures the time since last read.  */
 
645
      if (recent_age >= STALL_START_TIME)
 
646
        {
 
647
          /* If we're stalling, reset the ring contents because it's
 
648
             stale and because it will make bar_update stop printing
 
649
             the (bogus) current bandwidth.  */
 
650
          bp->stalled = 1;
 
651
          xzero (*hist);
 
652
          bp->recent_bytes = 0;
 
653
        }
 
654
      return;
 
655
    }
 
656
 
 
657
  /* We now have a non-zero amount of to store to the speed ring.  */
 
658
 
 
659
  /* If the stall status was acquired, reset it. */
 
660
  if (bp->stalled)
 
661
    {
 
662
      bp->stalled = 0;
 
663
      /* "recent_age" includes the the entired stalled period, which
 
664
         could be very long.  Don't update the speed ring with that
 
665
         value because the current bandwidth would start too small.
 
666
         Start with an arbitrary (but more reasonable) time value and
 
667
         let it level out.  */
 
668
      recent_age = 1000;
 
669
    }
 
670
 
593
671
  /* Store "recent" bytes and download time to history ring at the
594
672
     position POS.  */
595
673
 
641
719
create_image (struct bar_progress *bp, double dl_total_time)
642
720
{
643
721
  char *p = bp->buffer;
644
 
  long size = bp->initial_length + bp->count;
 
722
  wgint size = bp->initial_length + bp->count;
645
723
 
646
 
  char *size_legible = legible (size);
 
724
  char *size_legible = with_thousand_seps (size);
647
725
  int size_legible_len = strlen (size_legible);
648
726
 
649
727
  struct bar_progress_hist *hist = &bp->hist;
750
828
    }
751
829
 
752
830
  /* " 234,567,890" */
753
 
  sprintf (p, " %-11s", legible (size));
 
831
  sprintf (p, " %-11s", with_thousand_seps (size));
754
832
  p += strlen (p);
755
833
 
756
834
  /* " 1012.45K/s" */
757
835
  if (hist->total_time && hist->total_bytes)
758
836
    {
759
 
      static char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
 
837
      static const char *short_units[] = { "B/s", "K/s", "M/s", "G/s" };
760
838
      int units = 0;
761
839
      /* Calculate the download speed using the history ring and
762
840
         recent data that hasn't made it to the ring yet.  */
763
 
      long dlquant = hist->total_bytes + bp->recent_bytes;
 
841
      wgint dlquant = hist->total_bytes + bp->recent_bytes;
764
842
      double dltime = hist->total_time + (dl_total_time - bp->recent_start);
765
843
      double dlspeed = calc_rate (dlquant, dltime, &units);
766
844
      sprintf (p, " %7.2f%s", dlspeed, short_units[units]);
772
850
  /* " ETA xx:xx:xx"; wait for three seconds before displaying the ETA.
773
851
     That's because the ETA value needs a while to become
774
852
     reliable.  */
775
 
  if (bp->total_length > 0 && dl_total_time > 3000)
 
853
  if (bp->total_length > 0 && bp->count > 0 && dl_total_time > 3000)
776
854
    {
777
 
      long eta;
 
855
      wgint eta;
778
856
      int eta_hrs, eta_min, eta_sec;
779
857
 
780
858
      /* Don't change the value of ETA more than approximately once
793
871
             I found that doing that results in a very jerky and
794
872
             ultimately unreliable ETA.  */
795
873
          double time_sofar = (double)dl_total_time / 1000;
796
 
          long bytes_remaining = bp->total_length - size;
797
 
          eta = (long) (time_sofar * bytes_remaining / bp->count);
 
874
          wgint bytes_remaining = bp->total_length - size;
 
875
          eta = (wgint) (time_sofar * bytes_remaining / bp->count);
798
876
          bp->last_eta_value = eta;
799
877
          bp->last_eta_time = dl_total_time;
800
878
        }
849
927
static void
850
928
bar_set_params (const char *params)
851
929
{
852
 
  int sw;
853
930
  char *term = getenv ("TERM");
854
931
 
855
932
  if (params
862
939
          TTY -- when logging to file, it is better to review the
863
940
          dots.  */
864
941
       || !isatty (fileno (stderr))
865
 
#else
866
 
       1
867
942
#endif
868
943
       /* Normally we don't depend on terminal type because the
869
944
          progress bar only uses ^M to move the cursor to the
882
957
      set_progress_implementation (FALLBACK_PROGRESS_IMPLEMENTATION);
883
958
      return;
884
959
    }
885
 
 
886
 
  sw = determine_screen_width ();
887
 
  if (sw && sw >= MINIMUM_SCREEN_WIDTH)
888
 
    screen_width = sw;
889
960
}
890
961
 
891
962
#ifdef SIGWINCH
892
963
RETSIGTYPE
893
964
progress_handle_sigwinch (int sig)
894
965
{
895
 
  int sw = determine_screen_width ();
896
 
  if (sw && sw >= MINIMUM_SCREEN_WIDTH)
897
 
    screen_width = sw;
 
966
  received_sigwinch = 1;
898
967
  signal (SIGWINCH, progress_handle_sigwinch);
899
968
}
900
969
#endif