1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef PROGRESS_METER
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/*
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Copyright (c) 2003 Nils Nordman.  All rights reserved.
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Redistribution and use in source and binary forms, with or without
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * modification, are permitted provided that the following conditions
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * are met:
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *    documentation and/or other materials provided with the distribution.
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "includes.h"
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/*RCSID("$OpenBSD: progressmeter.c,v 1.24 2005/06/07 13:25:23 jaredy Exp $");*/
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "progressmeter.h"
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "atomicio.h"
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "scpmisc.h"
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define DEFAULT_WINSIZE 40
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define MAX_WINSIZE 512
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define PADDING 1		/* padding between the progress indicators */
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define UPDATE_INTERVAL 1	/* update the progress meter every second */
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define STALL_TIME 5		/* we're stalled after this many seconds */
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* determines whether we can output to the terminal */
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int can_output(void);
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* formats and inserts the specified size into the given buffer */
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void format_size(char *, int, off_t);
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void format_rate(char *, int, off_t);
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* window resizing */
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void sig_winch(int);
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void setscreensize(void);
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* updates the progressmeter to reflect the current state of the transfer */
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid refresh_progress_meter(void);
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* signal handler for updating the progress meter */
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void update_progress_meter(int);
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic time_t start;		/* start progress */
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic time_t last_update;	/* last progress update */
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic char *file;		/* name of the file being transferred */
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic off_t end_pos;		/* ending position of transfer */
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic off_t cur_pos;		/* transfer position as of last refresh */
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic volatile off_t *counter;	/* progress counter */
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic long stalled;		/* how long we have been stalled */
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int bytes_per_second;	/* current speed in bytes per second */
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int win_size;		/* terminal window size */
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic volatile sig_atomic_t win_resized; /* for window resizing */
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* units for format_size */
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic const char unit[] = " KMGT";
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectcan_output(void)
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return (getpgrp() == tcgetpgrp(STDOUT_FILENO));
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectformat_rate(char *buf, int size, off_t bytes)
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int i;
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bytes *= 100;
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++)
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		bytes = (bytes + 512) / 1024;
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (i == 0) {
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		i++;
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		bytes = (bytes + 512) / 1024;
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	snprintf(buf, size, "%3lld.%1lld%c%s",
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    (long long) (bytes + 5) / 100,
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    (long long) (bytes + 5) / 10 % 10,
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    unit[i],
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    i ? "B" : " ");
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectformat_size(char *buf, int size, off_t bytes)
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int i;
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++)
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		bytes = (bytes + 512) / 1024;
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	snprintf(buf, size, "%4lld%c%s",
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    (long long) bytes,
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    unit[i],
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    i ? "B" : " ");
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectrefresh_progress_meter(void)
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	char buf[MAX_WINSIZE + 1];
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	time_t now;
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	off_t transferred;
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	double elapsed;
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int percent;
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	off_t bytes_left;
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int cur_speed;
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int hours, minutes, seconds;
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int i, len;
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int file_len;
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	transferred = *counter - cur_pos;
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	cur_pos = *counter;
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	now = time(NULL);
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bytes_left = end_pos - cur_pos;
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (bytes_left > 0)
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		elapsed = now - last_update;
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	else {
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		elapsed = now - start;
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* Calculate true total speed when done */
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		transferred = end_pos;
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		bytes_per_second = 0;
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* calculate speed */
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (elapsed != 0)
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		cur_speed = (transferred / elapsed);
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	else
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		cur_speed = transferred;
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define AGE_FACTOR 0.9
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (bytes_per_second != 0) {
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		bytes_per_second = (bytes_per_second * AGE_FACTOR) +
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		    (cur_speed * (1.0 - AGE_FACTOR));
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		bytes_per_second = cur_speed;
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* filename */
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf[0] = '\0';
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	file_len = win_size - 35;
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (file_len > 0) {
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		len = snprintf(buf, file_len + 1, "\r%s", file);
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (len < 0)
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			len = 0;
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (len >= file_len + 1)
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			len = file_len;
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		for (i = len;  i < file_len; i++ )
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			buf[i] = ' ';
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		buf[file_len] = '\0';
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* percent of transfer done */
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (end_pos != 0)
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		percent = ((float)cur_pos / end_pos) * 100;
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	else
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		percent = 100;
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	snprintf(buf + strlen(buf), win_size - strlen(buf),
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    " %3d%% ", percent);
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* amount transferred */
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	format_size(buf + strlen(buf), win_size - strlen(buf),
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    cur_pos);
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	strlcat(buf, " ", win_size);
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* bandwidth usage */
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	format_rate(buf + strlen(buf), win_size - strlen(buf),
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    (off_t)bytes_per_second);
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	strlcat(buf, "/s ", win_size);
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* ETA */
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!transferred)
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		stalled += elapsed;
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	else
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		stalled = 0;
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (stalled >= STALL_TIME)
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		strlcat(buf, "- stalled -", win_size);
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	else if (bytes_per_second == 0 && bytes_left)
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		strlcat(buf, "  --:-- ETA", win_size);
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	else {
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (bytes_left > 0)
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			seconds = bytes_left / bytes_per_second;
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		else
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			seconds = elapsed;
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		hours = seconds / 3600;
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		seconds -= hours * 3600;
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		minutes = seconds / 60;
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		seconds -= minutes * 60;
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (hours != 0)
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			snprintf(buf + strlen(buf), win_size - strlen(buf),
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			    "%d:%02d:%02d", hours, minutes, seconds);
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		else
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			snprintf(buf + strlen(buf), win_size - strlen(buf),
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			    "  %02d:%02d", minutes, seconds);
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (bytes_left > 0)
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			strlcat(buf, " ETA", win_size);
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		else
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			strlcat(buf, "    ", win_size);
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1);
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	last_update = now;
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectupdate_progress_meter(int ignore)
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int save_errno;
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	save_errno = errno;
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (win_resized) {
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		setscreensize();
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		win_resized = 0;
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (can_output())
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		refresh_progress_meter();
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	signal(SIGALRM, update_progress_meter);
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	alarm(UPDATE_INTERVAL);
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	errno = save_errno;
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstart_progress_meter(char *f, off_t filesize, off_t *ctr)
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	start = last_update = time(NULL);
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	file = f;
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	end_pos = filesize;
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	cur_pos = 0;
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	counter = ctr;
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	stalled = 0;
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	bytes_per_second = 0;
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	setscreensize();
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (can_output())
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		refresh_progress_meter();
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	signal(SIGALRM, update_progress_meter);
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	signal(SIGWINCH, sig_winch);
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	alarm(UPDATE_INTERVAL);
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstop_progress_meter(void)
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	alarm(0);
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!can_output())
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Ensure we complete the progress */
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (cur_pos != end_pos)
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		refresh_progress_meter();
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	atomicio(vwrite, STDOUT_FILENO, "\n", 1);
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectsig_winch(int sig)
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	win_resized = 1;
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectsetscreensize(void)
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct winsize winsize;
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 &&
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	    winsize.ws_col != 0) {
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (winsize.ws_col > MAX_WINSIZE)
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			win_size = MAX_WINSIZE;
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		else
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			win_size = winsize.ws_col;
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		win_size = DEFAULT_WINSIZE;
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	win_size += 1;					/* trailing \0 */
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* PROGRESS_METER */
295