-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprogress.c
More file actions
117 lines (91 loc) · 2.2 KB
/
Copy pathprogress.c
File metadata and controls
117 lines (91 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* SPDX-License-Identifier: GPL-2.0 */
#include "compat.h"
#include "progress.h"
/*
* The code is based on following sources:
*
* https://salsa.debian.org/apt-team/apt/blob/master/apt-pkg/install-progress.cc
* https://salsa.debian.org/apt-team/apt/blob/master/apt-pkg/install-progress.h
*/
static struct winsize w;
static int initialised = 0;
static void progress_start();
static void progress_stop();
/* https://salsa.debian.org/apt-team/apt/blob/master/apt-pkg/install-progress.cc#L271-282 */
static void progress_set_window_height(int height)
{
fprintf(stderr, /* save cursor */
"\n\0337"
/* set scroll region (places cursor to the top left) */
"\033[0;%dr"
/* restore cursor but ensure it is inside the scrolling area */
"\0338\033[1A\033[J",
height);
fflush(stderr);
}
static void progress_init()
{
ioctl(STDERR_FILENO, TIOCGWINSZ, &w);
progress_set_window_height(w.ws_row - 1);
}
static void progress_abort()
{
progress_stop();
exit(0);
}
static void progress_step(float val)
{
char *bar;
int max;
if (isatty(STDERR_FILENO) == 0)
return;
if (initialised == 0)
progress_start();
bar = malloc(w.ws_col);
max = (w.ws_col - 20);
memset(bar, '.', max);
memset(bar, '#', (int) (max * val));
bar[max] = 0;
fprintf(stderr, "\e[s\e[%d;0H\e[42;30mProgress: [%3d%%]\e[0m [%s]\e[u",
w.ws_row + 1, (int) (val * 100.0), bar);
fflush(stderr);
free(bar);
}
static void progress_add(struct progress *ctx, unsigned long val)
{
ctx->pos += val;
progress_step((float) ctx->pos / (float) ctx->max);
}
static void progress_start()
{
if (isatty(STDERR_FILENO) == 0)
return;
signal(SIGWINCH, progress_init);
signal(SIGINT, progress_abort);
signal(SIGKILL, progress_abort);
progress_init();
initialised = 1;
progress_step(0);
}
static void progress_stop()
{
if (isatty(STDERR_FILENO) == 0)
return;
progress_set_window_height(w.ws_row);
}
struct progress *progress_alloc(unsigned long max)
{
struct progress *progress;
progress = malloc(sizeof(*progress));
if (progress == NULL)
return NULL;
progress->max = max;
progress->pos = 0;
progress->add = progress_add;
return progress;
}
void progress_drop(struct progress *progress)
{
progress_stop(progress);
free(progress);
}