xref: /aosp_15_r20/external/toybox/toys/other/count.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* count.c - Progress indicator from stdin to stdout
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2002 Rob Landley <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker 
5*cf5a6c84SAndroid Build Coastguard Worker USE_COUNT(NEWTOY(count, "<0>0l", TOYFLAG_USR|TOYFLAG_BIN))
6*cf5a6c84SAndroid Build Coastguard Worker 
7*cf5a6c84SAndroid Build Coastguard Worker config COUNT
8*cf5a6c84SAndroid Build Coastguard Worker   bool "count"
9*cf5a6c84SAndroid Build Coastguard Worker   default y
10*cf5a6c84SAndroid Build Coastguard Worker   help
11*cf5a6c84SAndroid Build Coastguard Worker     usage: count [-l]
12*cf5a6c84SAndroid Build Coastguard Worker 
13*cf5a6c84SAndroid Build Coastguard Worker     -l	Long output (total bytes, human readable, transfer rate, elapsed time)
14*cf5a6c84SAndroid Build Coastguard Worker 
15*cf5a6c84SAndroid Build Coastguard Worker     Copy stdin to stdout, displaying simple progress indicator to stderr.
16*cf5a6c84SAndroid Build Coastguard Worker */
17*cf5a6c84SAndroid Build Coastguard Worker 
18*cf5a6c84SAndroid Build Coastguard Worker #define FOR_count
19*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
20*cf5a6c84SAndroid Build Coastguard Worker 
21*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
22*cf5a6c84SAndroid Build Coastguard Worker   unsigned long long size, start;
23*cf5a6c84SAndroid Build Coastguard Worker   unsigned tick, *slice;
24*cf5a6c84SAndroid Build Coastguard Worker )
25*cf5a6c84SAndroid Build Coastguard Worker 
display(unsigned long long now)26*cf5a6c84SAndroid Build Coastguard Worker static void display(unsigned long long now)
27*cf5a6c84SAndroid Build Coastguard Worker {
28*cf5a6c84SAndroid Build Coastguard Worker   unsigned long long bb;
29*cf5a6c84SAndroid Build Coastguard Worker   unsigned seconds, ii, len = TT.tick ? minof(TT.tick, 63): 1;
30*cf5a6c84SAndroid Build Coastguard Worker 
31*cf5a6c84SAndroid Build Coastguard Worker   // bytes, human readable size, elapsed time, rate over last 16 seconds
32*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(l)) {
33*cf5a6c84SAndroid Build Coastguard Worker     human_readable(toybuf+256, TT.size, 0);
34*cf5a6c84SAndroid Build Coastguard Worker     seconds = (now - TT.start)/1000;
35*cf5a6c84SAndroid Build Coastguard Worker 
36*cf5a6c84SAndroid Build Coastguard Worker     // We zero new period and count it immediately, which lowers the average
37*cf5a6c84SAndroid Build Coastguard Worker     // if we haven't had time to fill it yet. Compensate by keeping one extra
38*cf5a6c84SAndroid Build Coastguard Worker     // old period and adding prorated fraction of it.
39*cf5a6c84SAndroid Build Coastguard Worker     bb = (TT.slice[63&(TT.tick-len)]*(250-(now%250)))/250;
40*cf5a6c84SAndroid Build Coastguard Worker 
41*cf5a6c84SAndroid Build Coastguard Worker     // Add up periods, convert to seconds via elapsed milliseconds
42*cf5a6c84SAndroid Build Coastguard Worker     for (ii = 0; ii<len;) bb += TT.slice[63&(TT.tick-ii++)];
43*cf5a6c84SAndroid Build Coastguard Worker     len *= 250;
44*cf5a6c84SAndroid Build Coastguard Worker     if (now>TT.start && len>now-TT.start) len = now-TT.start;
45*cf5a6c84SAndroid Build Coastguard Worker     human_readable(toybuf+512, (bb*1000)/len, 0);
46*cf5a6c84SAndroid Build Coastguard Worker 
47*cf5a6c84SAndroid Build Coastguard Worker     sprintf(toybuf+1024, ", %sb, %sb/s, %um%02us", toybuf+256, toybuf+512,
48*cf5a6c84SAndroid Build Coastguard Worker       seconds/60, seconds%60);
49*cf5a6c84SAndroid Build Coastguard Worker   }
50*cf5a6c84SAndroid Build Coastguard Worker   dprintf(2, "%llu bytes%s   \r", TT.size, toybuf+1024);
51*cf5a6c84SAndroid Build Coastguard Worker }
52*cf5a6c84SAndroid Build Coastguard Worker 
count_main(void)53*cf5a6c84SAndroid Build Coastguard Worker void count_main(void)
54*cf5a6c84SAndroid Build Coastguard Worker {
55*cf5a6c84SAndroid Build Coastguard Worker   struct pollfd pfd = {0, POLLIN, 0};
56*cf5a6c84SAndroid Build Coastguard Worker   unsigned long long now, then;
57*cf5a6c84SAndroid Build Coastguard Worker   char *buf = xmalloc(65536);
58*cf5a6c84SAndroid Build Coastguard Worker   int len;
59*cf5a6c84SAndroid Build Coastguard Worker 
60*cf5a6c84SAndroid Build Coastguard Worker   TT.slice = (void *)toybuf;
61*cf5a6c84SAndroid Build Coastguard Worker   TT.start = now = then = millitime();
62*cf5a6c84SAndroid Build Coastguard Worker 
63*cf5a6c84SAndroid Build Coastguard Worker   // poll, print if data not ready, update 4x/second otherwise
64*cf5a6c84SAndroid Build Coastguard Worker   for (;;) {
65*cf5a6c84SAndroid Build Coastguard Worker     // Update display 4x/second
66*cf5a6c84SAndroid Build Coastguard Worker     if ((now = millitime())>=then) {
67*cf5a6c84SAndroid Build Coastguard Worker       display(now);
68*cf5a6c84SAndroid Build Coastguard Worker       while (then<=now) {
69*cf5a6c84SAndroid Build Coastguard Worker         then += 250;
70*cf5a6c84SAndroid Build Coastguard Worker         if (FLAG(l)) TT.slice[63&++TT.tick] = 0;
71*cf5a6c84SAndroid Build Coastguard Worker       }
72*cf5a6c84SAndroid Build Coastguard Worker     }
73*cf5a6c84SAndroid Build Coastguard Worker     if (!(len = poll(&pfd, 1, then-now))) continue;
74*cf5a6c84SAndroid Build Coastguard Worker     if (len<0 && errno != EINTR && errno != ENOMEM) perror_exit(0);
75*cf5a6c84SAndroid Build Coastguard Worker     if ((len = xread(0, buf, 65536))) {
76*cf5a6c84SAndroid Build Coastguard Worker       xwrite(1, buf, len);
77*cf5a6c84SAndroid Build Coastguard Worker       TT.size += len;
78*cf5a6c84SAndroid Build Coastguard Worker       TT.slice[63&TT.tick] += len;
79*cf5a6c84SAndroid Build Coastguard Worker       if ((now = millitime())-then<250) continue;
80*cf5a6c84SAndroid Build Coastguard Worker     }
81*cf5a6c84SAndroid Build Coastguard Worker     if (!len) break;
82*cf5a6c84SAndroid Build Coastguard Worker   }
83*cf5a6c84SAndroid Build Coastguard Worker   display(now);
84*cf5a6c84SAndroid Build Coastguard Worker   dprintf(2, "\n");
85*cf5a6c84SAndroid Build Coastguard Worker }
86