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