Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30c4a059af | ||
|
|
404cc417d6 | ||
|
|
ded6b69c3f | ||
|
|
e5cc71b4d2 | ||
|
|
7bc91e10de | ||
|
|
2033c6085f | ||
|
|
780b65a648 | ||
|
|
20b8c9700a | ||
|
|
b1b5e9197a | ||
|
|
252213fbc2 | ||
|
|
e696b737e3 | ||
|
|
153285bec0 | ||
|
|
304b87503e | ||
|
|
455f819ec0 | ||
|
|
2942c312a7 | ||
|
|
c6315365e2 | ||
|
|
7b6a91422d | ||
|
|
cb3daa3b63 | ||
|
|
2e6a3937d4 | ||
|
|
8a2ddac50e | ||
|
|
052c182278 | ||
|
|
e11c58cf3b | ||
|
|
df67cee38a | ||
|
|
7f1cdc8527 | ||
|
|
896727b664 | ||
|
|
b0a67878bb | ||
|
|
e8dab7daf7 | ||
|
|
e7c332ad0b | ||
|
|
e21ed5d2c5 | ||
|
|
2a8e6b36b3 | ||
|
|
8bc088d016 | ||
|
|
175e66cd43 | ||
|
|
849c5e2a90 | ||
|
|
538546f5fb | ||
|
|
25884e823e | ||
|
|
3cb239c202 | ||
|
|
c6a001bbc6 | ||
|
|
89f81bb7d6 | ||
|
|
52399ee812 | ||
|
|
7f735b7282 | ||
|
|
8e781e0b51 | ||
|
|
1ad63a7a37 | ||
|
|
7fcf65e9c3 | ||
|
|
63251ef650 | ||
|
|
befcddc994 | ||
|
|
7d7d5ddf2e | ||
|
|
760cb41a61 | ||
|
|
926e74fd02 | ||
|
|
86feafb721 | ||
|
|
57f66c0b99 | ||
|
|
05f964ee25 | ||
|
|
ff571539cb | ||
|
|
307db0d802 | ||
|
|
78bb93b288 | ||
|
|
756b48e7b6 | ||
|
|
2f975cd3d2 | ||
|
|
2b341c1a7f | ||
|
|
14ce832249 | ||
|
|
f7ccb79147 | ||
|
|
decae290d4 | ||
|
|
d51a1b10f0 | ||
|
|
a8867b1882 | ||
|
|
749d23705e | ||
|
|
a6849012a6 | ||
|
|
1f320dd7a2 | ||
|
|
46e5948425 | ||
|
|
b7eb3c9e90 | ||
|
|
9e5bdeb3a4 | ||
|
|
2cd74c7ff7 | ||
|
|
4c71e96cba | ||
|
|
f67d173aef | ||
|
|
a59465ff6e | ||
|
|
0bd1b82d3a | ||
|
|
65eac50c21 | ||
|
|
2a092c9495 | ||
|
|
10296f93e4 | ||
|
|
66cae656d1 | ||
|
|
b1ef744058 | ||
|
|
7d07db6526 | ||
|
|
a8e232e894 | ||
|
|
e99548ea8a | ||
|
|
5495e0e808 | ||
|
|
11e654ec90 | ||
|
|
4854fcf3e0 | ||
|
|
fb8bea390c | ||
|
|
fe22f0e449 | ||
|
|
c0abc9ce3c | ||
|
|
c39d81b71a | ||
|
|
9ab690b7c0 | ||
|
|
6cb207667d | ||
|
|
4c9f304a46 | ||
|
|
a9c4c6e049 | ||
|
|
4cd28b23f0 | ||
|
|
b2989efd5c | ||
|
|
cc4d1a15e4 | ||
|
|
7f25aff91d | ||
|
|
32f984de56 | ||
|
|
f01117d84e | ||
|
|
f3cd9a2664 | ||
|
|
fff425ec61 | ||
|
|
c78e082192 | ||
|
|
34ba94ae63 | ||
|
|
82e1297d77 | ||
|
|
25baeb4375 | ||
|
|
18d17beb93 | ||
|
|
34c18d47a4 | ||
|
|
6560137233 | ||
|
|
ada5748d2f | ||
|
|
c2e77cd005 | ||
|
|
8e3b47bf89 | ||
|
|
e7e7649d2f | ||
|
|
e63b6225f8 | ||
|
|
14fb0e7832 | ||
|
|
303d3ea359 | ||
|
|
318954d21e | ||
|
|
85dd2603bf | ||
|
|
b6c797af1a | ||
|
|
40b9ef2a9d | ||
|
|
146add0ed3 | ||
|
|
911969c2a8 | ||
|
|
4b3b49806f | ||
|
|
943c05a8a0 | ||
|
|
630d92fef6 | ||
|
|
34fe796806 | ||
|
|
907b449c6b | ||
|
|
b59b1bad4b | ||
|
|
7e374be0d7 | ||
|
|
b9f96d9508 | ||
|
|
08a8c2ea70 | ||
|
|
1f103d6a11 | ||
|
|
7f3924db77 | ||
|
|
cd9f057f15 | ||
|
|
7088833627 | ||
|
|
57f8daff30 | ||
|
|
275cc6c10d | ||
|
|
8491b5cdd5 | ||
|
|
6496c8785b | ||
|
|
506ec4a8ec | ||
|
|
5a140b689f | ||
|
|
38ddb5e32a | ||
|
|
173de4fafd | ||
|
|
ae81f83e9b | ||
|
|
9f07a28065 | ||
|
|
60913618be | ||
|
|
43dc9d6469 | ||
|
|
6cff3c1c2a | ||
|
|
caf7d6ff18 | ||
|
|
d343669f45 | ||
|
|
ecaa5ce6cd | ||
|
|
e5b5e67e57 | ||
|
|
1efe1d60b5 | ||
|
|
f83927e451 | ||
|
|
678f655116 | ||
|
|
7794df7182 | ||
|
|
923ef47056 | ||
|
|
0a509fb535 | ||
|
|
1927e88350 | ||
|
|
760ee403fe | ||
|
|
6ecf31b5ee | ||
|
|
8051f5808c | ||
|
|
0518357560 | ||
|
|
e0856df8ef | ||
|
|
d4590e1f3b | ||
|
|
99c5e0988c | ||
|
|
6a24d75022 | ||
|
|
82aa30c306 | ||
|
|
4fa3331f88 | ||
|
|
fd0850f1ab | ||
|
|
cecc8649c2 | ||
|
|
c39e97ec5a | ||
|
|
909355619b | ||
|
|
b086ddf599 | ||
|
|
a0e5d5e9e7 | ||
|
|
dbcae4a9ae | ||
|
|
4ba1343c20 | ||
|
|
ee3c02fd7f | ||
|
|
c7e0bb727e | ||
|
|
80e3f791c4 | ||
|
|
74325282e7 | ||
|
|
ab20f9406f | ||
|
|
e94600d7a4 | ||
|
|
9783f7ebef | ||
|
|
b6d1f62979 | ||
|
|
cab177814a | ||
|
|
2303da77db | ||
|
|
264e3a5879 | ||
|
|
5f6f418cfd | ||
|
|
3b2e274907 | ||
|
|
a24342a072 | ||
|
|
101294195b | ||
|
|
5cf5eda406 | ||
|
|
8c284d863d | ||
|
|
7448c7f320 | ||
|
|
b923afc385 | ||
|
|
88dd09393c | ||
|
|
29124c585e | ||
|
|
65828899ea | ||
|
|
853190d36d | ||
|
|
f13f5e70c1 | ||
|
|
4e2ab087e5 | ||
|
|
242c19e4f6 | ||
|
|
3003f46313 | ||
|
|
c718a00e2c | ||
|
|
01f627b2de | ||
|
|
461486ec4f | ||
|
|
fd46c9b1f6 | ||
|
|
001dfb71c2 | ||
|
|
bcb33ce2aa | ||
|
|
c8090806f9 | ||
|
|
3403ebd857 | ||
|
|
4fddf40436 | ||
|
|
62b5ac26df | ||
|
|
e8c0b6717f | ||
|
|
2bf76577dd | ||
|
|
90d9638488 | ||
|
|
f6d0135cc6 | ||
|
|
56adce8edf | ||
|
|
008ee74a98 | ||
|
|
fa8aa85248 | ||
|
|
442a298c38 | ||
|
|
bb0c5bdfca | ||
|
|
29908cff6c | ||
|
|
456ab7cebb | ||
|
|
0d1d5b77ec | ||
|
|
ff5efbe3eb | ||
|
|
81d008a325 | ||
|
|
288dd633d7 | ||
|
|
9dce037cdc | ||
|
|
6ae07496d2 | ||
|
|
cd60822380 | ||
|
|
0fdd9f0787 | ||
|
|
0d520172ac | ||
|
|
04ea58f786 | ||
|
|
94a9f658e1 | ||
|
|
0ec9e208df | ||
|
|
4c84060940 | ||
|
|
8fb3aecde5 | ||
|
|
e228b3397d | ||
|
|
d1d1999334 | ||
|
|
685c91a1cb | ||
|
|
50c0b329c9 | ||
|
|
5c8e2707a4 | ||
|
|
5768166460 | ||
|
|
6bdb951af4 | ||
|
|
06824aee2d | ||
|
|
c5cd932fb0 | ||
|
|
a6ecf60ad1 | ||
|
|
b0cad6d3e3 | ||
|
|
a9cef81657 | ||
|
|
cc95aa67a3 | ||
|
|
b78e58ab87 | ||
|
|
12d22b5ab0 | ||
|
|
3255f72f39 | ||
|
|
c79eb8540a | ||
|
|
0ca8ef5187 | ||
|
|
386e3ac5fa | ||
|
|
6e24924a23 | ||
|
|
b0720194e1 | ||
|
|
613642ba3d | ||
|
|
103df51a59 |
+16
-1
@@ -1,3 +1,18 @@
|
||||
*~
|
||||
build-aux
|
||||
missing
|
||||
compile
|
||||
depcomp
|
||||
install-sh
|
||||
config.sub
|
||||
config.guess
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autoscan.log
|
||||
configure
|
||||
configure.scan
|
||||
autom4te.cache
|
||||
ABOUT-NLS
|
||||
m4
|
||||
*~
|
||||
*.tar.gz
|
||||
patch-backlog
|
||||
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
|
||||
SUBDIRS = po
|
||||
|
||||
bin_PROGRAMS = pv
|
||||
dist_doc_DATA = README.md docs/INSTALL docs/COPYING docs/NEWS.md docs/ACKNOWLEDGEMENTS.md docs/DEVELOPERS.md docs/TODO.md docs/benchmark.sh
|
||||
dist_man1_MANS = docs/pv.1
|
||||
|
||||
EXTRA_DIST = docs/pv.1.md
|
||||
|
||||
pv_SOURCES = \
|
||||
src/main/debug.c \
|
||||
src/main/help.c \
|
||||
src/main/main.c \
|
||||
src/main/options.c \
|
||||
src/main/remote.c \
|
||||
src/main/version.c \
|
||||
src/pv/cursor.c \
|
||||
src/pv/display.c \
|
||||
src/pv/elapsedtime.c \
|
||||
src/pv/file.c \
|
||||
src/pv/loop.c \
|
||||
src/pv/number.c \
|
||||
src/pv/signal.c \
|
||||
src/pv/state.c \
|
||||
src/pv/string.c \
|
||||
src/pv/transfer.c \
|
||||
src/pv/watchpid.c \
|
||||
src/include/config-aux.h \
|
||||
src/include/options.h \
|
||||
src/include/pv-internal.h \
|
||||
src/include/pv.h
|
||||
|
||||
## Allow tests to write diagnostic info to fd 9 to reach the original
|
||||
## stderr even when the test driver is sending test output to a file.
|
||||
AM_TESTS_FD_REDIRECT = 9>&2
|
||||
|
||||
AM_TESTS_ENVIRONMENT = \
|
||||
. $(srcdir)/tests/test-env.sh \
|
||||
;
|
||||
TESTS = \
|
||||
tests/Bug_-_Display_length_at_magnitude_boundary_-_Bytes.test \
|
||||
tests/Bug_-_Display_length_at_magnitude_boundary_-_Rate.test \
|
||||
tests/Bug_-_Install_all_files.test \
|
||||
tests/Display_-_--average-rate.test \
|
||||
tests/Display_-_--bits.test \
|
||||
tests/Display_-_--buffer-percent.test \
|
||||
tests/Display_-_--bytes.test \
|
||||
tests/Display_-_--eta_-_plausible_values.test \
|
||||
tests/Display_-_--fineta_-_plausible_values.test \
|
||||
tests/Display_-_--last-written.test \
|
||||
tests/Display_-_--numeric_--bytes_--line-mode.test \
|
||||
tests/Display_-_--numeric_--bytes.test \
|
||||
tests/Display_-_--numeric.test \
|
||||
tests/Display_-_--numeric_--timer.test \
|
||||
tests/Display_-_--progress_-_basic_movement.test \
|
||||
tests/Display_-_--progress_-_increasing.test \
|
||||
tests/Display_-_--quiet.test \
|
||||
tests/Display_-_--rate_-_displayed_value_changes.test \
|
||||
tests/Display_-_--timer_-_displayed_value_changes.test \
|
||||
tests/General_-_--pidfile.test \
|
||||
tests/General_-_--size_argument_handling.test \
|
||||
tests/Integrity_-_Basic.test \
|
||||
tests/Integrity_-_Binary_data.test \
|
||||
tests/Integrity_-_From_bursty_source.test \
|
||||
tests/Integrity_-_Large_file_support.test \
|
||||
tests/Integrity_-_On_output_pipe_close.test \
|
||||
tests/Integrity_-_When_adjusted_remotely.test \
|
||||
tests/Memory_safety_-_Basic.test \
|
||||
tests/Memory_safety_-_Remote_control_receiver.test \
|
||||
tests/Memory_safety_-_Remote_control_sender.test \
|
||||
tests/Modifiers_-_--direct-io.test \
|
||||
tests/Modifiers_-_--force.test \
|
||||
tests/Modifiers_-_--interval.test \
|
||||
tests/Modifiers_-_--line-mode.test \
|
||||
tests/Modifiers_-_--size_from_file_size.test \
|
||||
tests/Modifiers_-_--size.test \
|
||||
tests/Modifiers_-_--sync.test \
|
||||
tests/Terminal_-_Detect_width.test \
|
||||
tests/Transfer_-_--rate-limit.test \
|
||||
tests/Transfer_-_--remote.test \
|
||||
tests/Transfer_-_--stop-at-size.test
|
||||
|
||||
EXTRA_DIST += $(TESTS) tests/run-valgrind.sh tests/test-env.sh
|
||||
|
||||
docs/pv.1.md: $(srcdir)/docs/pv.1
|
||||
test -d docs || mkdir docs
|
||||
pandoc --from man --to markdown < $< | sed '/\*\*\*\*/{s/\*//g;s/^/**/;s/$$/**/}' | sed '/^```/,/^```/d' > $@
|
||||
|
||||
SUFFIXES = .c .o .e
|
||||
|
||||
.c.e:
|
||||
-splint -badflag +posixlib $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) -DSPLINT=1 $< > $@ 2>&1
|
||||
-flawfinder $< >> $@ 2>&1
|
||||
|
||||
indent:
|
||||
cd $(srcdir) && indent -npro -kr -i8 -cd42 -c45 -l120 src/*/*.c
|
||||
|
||||
indentclean:
|
||||
rm -f $(srcdir)/*/*.c~
|
||||
|
||||
analyse: $(pv_SOURCES:.c=.e) FORCE
|
||||
grep -E -e '^Finished checking --' -e 'Hits = ' $+ 2>/dev/null || true
|
||||
|
||||
FORCE:
|
||||
|
||||
clean-local:
|
||||
rm -f src/*/*.e
|
||||
|
||||
# Convenience alias for "make check": "make test"
|
||||
test: check
|
||||
|
||||
# "release" target - requires MAINTAINER variable to select GPG key.
|
||||
release: distcheck
|
||||
gpg --list-secret-keys 2>&1 | grep -F 'uid' | grep -Fq "$(MAINTAINER)"
|
||||
gpg -u "$(MAINTAINER)" -ab $(distdir).tar.gz
|
||||
cp -f $(distdir).tar.gz.asc $(distdir).tar.gz.txt
|
||||
chmod 644 $(distdir).tar.gz $(distdir).tar.gz.asc $(distdir).tar.gz.txt
|
||||
@@ -1,265 +0,0 @@
|
||||
Introduction
|
||||
************
|
||||
|
||||
This is the README for `pv' ("Pipe Viewer"), a terminal-based tool for
|
||||
monitoring the progress of data through a pipeline. It can be inserted into
|
||||
any normal pipeline between two processes to give a visual indication of how
|
||||
quickly data is passing through, how long it has taken, how near to
|
||||
completion it is, and an estimate of how long it will be until completion.
|
||||
|
||||
|
||||
Documentation
|
||||
*************
|
||||
|
||||
A manual page is included in this distribution. See `man ./doc/quickref.1',
|
||||
or `man pv' after installation.
|
||||
|
||||
|
||||
Compilation
|
||||
***********
|
||||
|
||||
If this is not a packaged release, first run "./generate.sh".
|
||||
|
||||
To compile the package, type "sh ./configure", which should generate a
|
||||
Makefile for your system. You may then type "make" to build everything.
|
||||
Note that GNU `make' is required; this may be installed as `gmake' on some
|
||||
systems, so if typing "make" gives an error, try "gmake" instead.
|
||||
|
||||
See the file `doc/INSTALL' for more about the `configure' script.
|
||||
|
||||
Developers note that you can do "./configure --enable-debugging" to cause
|
||||
debugging support to be built in, and "--enable-profiling" builds in
|
||||
profiling support (see "man gprof"). Also note that doing "make index" will
|
||||
generate an HTML code index (using "ctags" and "cproto"); this index lists
|
||||
all files used, all functions defined, and all TODOs marked in the code.
|
||||
|
||||
|
||||
Author and acknowledgements
|
||||
***************************
|
||||
|
||||
This package is copyright 2021 Andrew Wood, and is being distributed under
|
||||
the terms of the Artistic License 2.0. For more details of this license,
|
||||
see the file `doc/COPYING'.
|
||||
|
||||
Report bugs in `pv' using the contact form linked from the home page.
|
||||
|
||||
The `pv' home page is at:
|
||||
|
||||
http://www.ivarch.com/programs/pv.shtml
|
||||
|
||||
The latest version can always be found here.
|
||||
|
||||
Credit is also due to:
|
||||
|
||||
Jakub Hrozek <jhrozek@redhat.com>
|
||||
- Fedora package maintainer
|
||||
|
||||
Antoine Beaupré <anarcat@debian.org>
|
||||
- Debian package maintainer
|
||||
|
||||
Kevin Coyner <kcoyner@debian.org>
|
||||
Cédric Delfosse <cedric@debian.org>
|
||||
- previous Debian package maintainers
|
||||
|
||||
Eduardo Aguiar <eduardo.oliveira@sondabrasil.com.br>
|
||||
- provided Portuguese (Brazilian) translation
|
||||
|
||||
Stéphane Lacasse <stephane@gorfou.ca>
|
||||
- provided French translation
|
||||
|
||||
Marcos Kreinacke <public@kreinacke.com>
|
||||
- provided German translation
|
||||
|
||||
Bartosz Feñski <fenio@o2.pl> <http://skawina.eu.org/>
|
||||
- provided Polish translation along with Krystian Zubel
|
||||
|
||||
Joshua Jensen
|
||||
- reported RPM installation bug
|
||||
|
||||
Boris Folgmann <http://www.folgmann.com/en/>
|
||||
- reported cursor handling bug
|
||||
|
||||
Mathias Gumz
|
||||
- reported NLS bug
|
||||
|
||||
Daniel Roethlisberger
|
||||
- submitted patch to use lockfiles for -c if terminal locking fails
|
||||
|
||||
Adam Buchbinder
|
||||
- lots of help with a Cygwin port of -c
|
||||
|
||||
Mark Tomich <http://metuchen.dyndns.org>
|
||||
- suggested -B option
|
||||
|
||||
Gert Menke
|
||||
- reported bug when piping to dd with a large input buffer size
|
||||
|
||||
Ville Herva <Ville.Herva@iki.fi>
|
||||
- informative bug report about rate limiting performance
|
||||
|
||||
Elias Pipping
|
||||
- patch to compile properly on Darwin 9; potential NULL deref report
|
||||
|
||||
Patrick Collison
|
||||
- similar patch for OS X
|
||||
|
||||
Boris Lohner
|
||||
- reported problem that "-L" does not complain if given non-numeric value
|
||||
|
||||
Sebastian Kayser
|
||||
- supplied testing for SIGPIPE, demonstrated internationalisation problem
|
||||
|
||||
Laszlo Ersek <http://phptest11.atw.hu/>
|
||||
- reported shared memory leak on SIGINT with -c
|
||||
|
||||
Phil Rutschman <http://bandgap.rsnsoft.com/>
|
||||
- provided a patch for fully restoring terminal state on exit
|
||||
|
||||
Henry Precheur <http://henry.precheur.org/>
|
||||
- reporting and suggestions for --rate-limit bug when rate is under 10
|
||||
|
||||
E. Rosten <http://mi.eng.cam.ac.uk/~er258/>
|
||||
- supplied patch for block buffering in line mode
|
||||
|
||||
Kjetil Torgrim Homme
|
||||
- reported compilation error with default CFLAGS on non-GCC compilers
|
||||
|
||||
Alexandre de Verteuil
|
||||
- reported bug in OS X build and supplied test environment to fix in
|
||||
|
||||
Martin Baum
|
||||
- supplied patch to return nonzero exit status if terminated by signal
|
||||
|
||||
Sam Nelson <http://www.siliconfuture.net/>
|
||||
- supplied patch to fix trailing slash on DESTDIR
|
||||
|
||||
Daniel Pape
|
||||
- reported Cygwin installation problem due to DESTDIR
|
||||
|
||||
Philipp Beckers
|
||||
- ported to the Syabas PopcornHour A-100 series
|
||||
|
||||
Henry Gebhard <hsggebhardt@googlemail.com>
|
||||
- supplied patches to improve SI prefixes and add --average-rate
|
||||
|
||||
Vladimir Kokarev, Alexander Leo
|
||||
- reported that exit status did not reflect file errors
|
||||
|
||||
Thomas Rachel
|
||||
- submitted patches for IEEE1541 (MiB suffixes), 1+e03 bug
|
||||
|
||||
Guillaume Marcais
|
||||
- submitted speedup patch for line mode
|
||||
|
||||
Moritz Barsnick
|
||||
- submitted patch for compile warning in size calculation
|
||||
|
||||
Pawel Piatek
|
||||
- submitted RPM and patches for AIX
|
||||
|
||||
Sami Liedes
|
||||
- submitted patch for --timer and --bytes with --numeric
|
||||
|
||||
Steven Willis
|
||||
- reported problem with "-R" killing non-PV remote processes
|
||||
|
||||
Vladimir Pal, Vladimir Ermakov
|
||||
- submitted patch which led to development of --format option
|
||||
|
||||
Peter Samuelson <peter@p12n.org>
|
||||
- submitted patch to calculate size if stdout is a block device
|
||||
|
||||
Miguel Diaz
|
||||
- much Cygwin help (and packaging), found narrow-terminal bug
|
||||
|
||||
Jim Salter <http://ubuntuwiki.net>
|
||||
- commissioned work on the --skip-errors option
|
||||
|
||||
Wouter Pronk
|
||||
- reported build problem on SCO
|
||||
|
||||
Bryan Dongray <http://www.dongrays.com>
|
||||
- provided patches for test scripts failing on older Red Hats
|
||||
|
||||
Zev Weiss <www.bewilderbeest.net>
|
||||
- provided patch to fix splice() not using stdin
|
||||
|
||||
Zing Shishak
|
||||
- provided patch for --null / -0 (count null terminated lines)
|
||||
|
||||
Jacek Wielemborek <http://deetah.jogger.pl/kategorie/english>
|
||||
- implemented fdwatch in Python, suggested PV port
|
||||
- reported bug with "-l" and ETA / size
|
||||
- suggested common switches
|
||||
|
||||
Kim Krecht
|
||||
- suggested buffer fill status and last bytes output display options
|
||||
|
||||
Cristian Ciupitu <http://ciupicri.github.io>, Josh Stone
|
||||
- pointed out file descriptor leak with helpful suggestions
|
||||
(Josh Stone initially noticed the missing close)
|
||||
|
||||
Jan Seda
|
||||
- found issue with splice() and SPLICE_F_NONBLOCK causing slowdown
|
||||
|
||||
André Stapf
|
||||
- pointed out formatting problem e.g. 13GB -> 13.1GB which should be
|
||||
shown 13.0GB -> 13.1GB; highlighted on-startup row swapping in -c
|
||||
|
||||
Damon Harper <http://www.usrbin.ca/>
|
||||
- suggested "-D" / "--delay-start" option
|
||||
|
||||
Ganaël Laplanche <http://www.martymac.org>
|
||||
- provided patch for lstat64 on systems that do not support it
|
||||
|
||||
Peter Korsgaard <http://www.buildroot.net/>
|
||||
- provided similar patch for lstat64, specifically for uClibc support
|
||||
- provided AIX cross-compilation patch to fix bug in -lc128 check
|
||||
|
||||
Ralf Ramsauer <https://blog.ramses-pyramidenbau.de/>
|
||||
- reported bug which dropped transfer rate on terminal resize
|
||||
|
||||
Michiel Van Herwegen
|
||||
- reported and discussed bug with "-l" and ETA / size
|
||||
|
||||
Erkki Seppälä <http://www.inside.org/~flux/>
|
||||
- provided patch implementing "-I"
|
||||
|
||||
Eric A. Borisch
|
||||
- provided details of compatibility fix for "%Lu" in watchpid code
|
||||
|
||||
Jan Venekamp
|
||||
- reported MacOS buffer size interactions with pipes
|
||||
|
||||
Matt <https://github.com/lemonsqueeze/pv>
|
||||
- provided "rate-window" patches for rate calculation
|
||||
|
||||
Filippo Valsorda
|
||||
- provided patch for stat64 issue on Apple Silicon
|
||||
|
||||
Matt Koscica, William Dillon
|
||||
- also reported stat64 issue on Apple Silicon
|
||||
|
||||
Norman Rasmussen
|
||||
- suggested -c with -d PID:FD, reject -N with -d PID
|
||||
|
||||
Andriy Gapon, Jonathan Elchison
|
||||
- reported bug where "pv /dev/zero >/dev/null &" stops immediately
|
||||
|
||||
Marcelo Chiesa
|
||||
- reported unused-result warnings when compiling PV 1.6.6
|
||||
|
||||
Jered Floyd
|
||||
- provided patches to improve --rate-limit
|
||||
|
||||
Christoph Biedl
|
||||
- provided ETA and dynamic interval patches
|
||||
|
||||
Richard Fonfara
|
||||
- provided German translations for "pv --help"
|
||||
|
||||
Johannes Gerer <http://johannesgerer.com>
|
||||
- suggested that "-B" should enable "-C"
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,65 @@
|
||||
# Introduction
|
||||
|
||||
This is the README for **pv** ("Pipe Viewer"), a terminal-based tool for
|
||||
monitoring the progress of data through a pipeline. It can be inserted into
|
||||
any normal pipeline between two processes to give a visual indication of how
|
||||
quickly data is passing through, how long it has taken, how near to
|
||||
completion it is, and an estimate of how long it will be until completion.
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
A manual page is included in this distribution ("`man pv`"). Before
|
||||
installation, it is in "[docs/pv.1](./docs/pv.1.md)".
|
||||
|
||||
Changes are listed in "[docs/NEWS.md](./docs/NEWS.md)". The to-do list is "[docs/TODO.md](./docs/TODO.md)".
|
||||
|
||||
Developers and translators, please see "[docs/DEVELOPERS.md](./docs/DEVELOPERS.md)".
|
||||
|
||||
|
||||
# Compilation
|
||||
|
||||
To compile the package, type "`sh ./configure`", which should generate a
|
||||
Makefile for your system. You may then type "`make`" to build everything,
|
||||
and "`make install`" to install it.
|
||||
|
||||
See the file "[docs/INSTALL](./docs/INSTALL)" for more about the _configure_ script.
|
||||
|
||||
If this is not a packaged release, you will need the GNU build system tools
|
||||
(`autoconf`, `aclocal`, `autopoint`, `automake`) and the `gettext`
|
||||
development tools. You can then run "`autoreconf -is`" to generate the
|
||||
"`configure`" script.
|
||||
|
||||
|
||||
# Copyright, bug reporting, and acknowledgements
|
||||
|
||||
Copyright (C) 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood.
|
||||
|
||||
License GPLv3+: GNU GPL version 3 or later <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License, version
|
||||
3, in "[docs/COPYING](./docs/COPYING)". If not, see
|
||||
<https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||
|
||||
Please report any bugs to **pv@ivarch.com**, or use the issue tracker linked
|
||||
from the **pv** home page.
|
||||
|
||||
The **pv** home page is at:
|
||||
|
||||
[https://www.ivarch.com/programs/pv.shtml](https://www.ivarch.com/programs/pv.shtml)
|
||||
|
||||
The latest version can always be found here.
|
||||
|
||||
**Please see "[docs/ACKNOWLEDGEMENTS.md](./docs/ACKNOWLEDGEMENTS.md)" for a list of contributors.**
|
||||
|
||||
---
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# Files from which this is generated (inside directory `autoconf/make'):
|
||||
#
|
||||
# package.mk # package name and distribution details
|
||||
# vars.mk # compilation, shell and linking variables
|
||||
# filelist.mk~ # lists of files
|
||||
# unreal.mk # phony targets
|
||||
# modules.mk~ # module linking rules
|
||||
# rules.mk # compilation rules
|
||||
# link.mk # real top-level targets
|
||||
# depend.mk~ # dependencies
|
||||
#
|
||||
#
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(src/main/version.c)
|
||||
|
||||
dnl We're using C.
|
||||
dnl
|
||||
AC_LANG_C
|
||||
|
||||
dnl Output a header file.
|
||||
dnl
|
||||
AC_CONFIG_HEADER(src/include/config.h:autoconf/header.in)
|
||||
|
||||
dnl Set directory to check for Configure scripts in.
|
||||
dnl
|
||||
AC_CONFIG_AUX_DIR(autoconf/scripts)
|
||||
|
||||
dnl Read in package details.
|
||||
dnl
|
||||
PACKAGE=`cat $srcdir/doc/PACKAGE`
|
||||
VERSION=`cat $srcdir/doc/VERSION`
|
||||
UCPACKAGE=`tr a-z A-Z < $srcdir/doc/PACKAGE`
|
||||
AC_SUBST(PACKAGE)
|
||||
AC_SUBST(VERSION)
|
||||
AC_SUBST(UCPACKAGE)
|
||||
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
|
||||
AC_DEFINE_UNQUOTED(PROGRAM_NAME, "$PACKAGE")
|
||||
AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
|
||||
|
||||
dnl Check for compile-time options.
|
||||
dnl
|
||||
AC_ARG_ENABLE(debugging,
|
||||
[ --enable-debugging compile with debugging support],
|
||||
if test "$enable_debugging" = "yes"; then
|
||||
CFLAGS="-g -Wall"
|
||||
AC_DEFINE(ENABLE_DEBUGGING)
|
||||
fi
|
||||
)
|
||||
AC_ARG_ENABLE(profiling,
|
||||
[ --enable-profiling compile with profiling support],
|
||||
if test "$enable_profiling" = "yes"; then
|
||||
CFLAGS="-pg $CFLAGS"
|
||||
fi
|
||||
)
|
||||
LFS_SUPPORT="no"
|
||||
AC_ARG_ENABLE(lfs, [ --disable-lfs disable LFS support],
|
||||
if test "$enable_lfs" = "yes"; then
|
||||
LFS_SUPPORT="yes"
|
||||
fi,
|
||||
LFS_SUPPORT="yes"
|
||||
)
|
||||
STATIC_NLS="no"
|
||||
AC_ARG_ENABLE(static-nls, [ --enable-static-nls hardcode NLS with no support files],
|
||||
if test "$enable_static_nls" = "yes"; then
|
||||
STATIC_NLS="yes"
|
||||
fi,
|
||||
STATIC_NLS="no"
|
||||
)
|
||||
NLS_SUPPORT="no"
|
||||
AC_ARG_ENABLE(nls, [ --disable-nls do not use Native Language Support],
|
||||
if test "$enable_nls" = "yes"; then
|
||||
NLS_SUPPORT="yes"
|
||||
fi,
|
||||
NLS_SUPPORT="yes"
|
||||
)
|
||||
SPLICE_SUPPORT="no"
|
||||
AC_ARG_ENABLE(splice, [ --disable-splice do not use splice system call],
|
||||
if test "$enable_splice" = "yes"; then
|
||||
SPLICE_SUPPORT="yes"
|
||||
fi,
|
||||
SPLICE_SUPPORT="yes"
|
||||
)
|
||||
IPC_SUPPORT="no"
|
||||
AC_ARG_ENABLE(ipc, [ --disable-ipc turn off IPC messaging],
|
||||
if test "$enable_ipc" = "yes"; then
|
||||
IPC_SUPPORT="yes"
|
||||
fi,
|
||||
IPC_SUPPORT="yes"
|
||||
)
|
||||
|
||||
dnl Check for various programs.
|
||||
dnl
|
||||
CFLAGS=${CFLAGS:-"-O"}
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
dnl AIX needs -lc128
|
||||
dnl
|
||||
AC_EGREP_CPP([^yes$], [#ifdef _AIX
|
||||
yes
|
||||
#endif
|
||||
], [LIBS="$LIBS -lc128"])
|
||||
|
||||
dnl NLS stuff.
|
||||
dnl
|
||||
ALL_LINGUAS="de fr pl pt"
|
||||
if test "$NLS_SUPPORT" = "yes"; then
|
||||
AC_DEFINE(ENABLE_NLS)
|
||||
AC_PATH_PROG(MSGFMT, msgfmt, NOMSGFMT)
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
|
||||
AC_PATH_PROG(XGETTEXT, xgettext, xgettext)
|
||||
if test "x$MSGFMT" = "xNOMSGFMT"; then
|
||||
MSGFMT=""
|
||||
STATIC_NLS="yes"
|
||||
fi
|
||||
if test "$STATIC_NLS" = "yes"; then
|
||||
CATALOGS=""
|
||||
NLSOBJ="src/nls/table.o"
|
||||
else
|
||||
AC_CHECK_LIB(intl, main)
|
||||
AC_CHECK_LIB(i, main)
|
||||
fi
|
||||
CATOBJEXT=.mo
|
||||
INSTOBJEXT=.mo
|
||||
for lang in $ALL_LINGUAS; do
|
||||
GMOFILES="$GMOFILES $lang.gmo"
|
||||
POFILES="$POFILES \$(srcdir)/src/nls/$lang.po"
|
||||
CATALOGS="$CATALOGS src/nls/$lang$CATOBJEXT";
|
||||
done
|
||||
if test "$STATIC_NLS" = "yes"; then
|
||||
CATALOGS=""
|
||||
else
|
||||
AC_CHECK_FUNC(gettext,
|
||||
[AC_DEFINE(HAVE_GETTEXT)
|
||||
NLSOBJ=""
|
||||
], [CATALOGS=""; NLSOBJ="src/nls/table.o"
|
||||
]
|
||||
)
|
||||
fi
|
||||
fi
|
||||
AC_CHECK_HEADERS(libintl.h)
|
||||
AC_CHECK_HEADERS(locale.h)
|
||||
AC_SUBST(MSGFMT)
|
||||
AC_SUBST(GMSGFMT)
|
||||
AC_SUBST(XGETTEXT)
|
||||
AC_SUBST(CATOBJEXT)
|
||||
AC_SUBST(INSTOBJEXT)
|
||||
AC_SUBST(GMOFILES)
|
||||
AC_SUBST(POFILES)
|
||||
AC_SUBST(CATALOGS)
|
||||
AC_SUBST(NLSOBJ)
|
||||
|
||||
dnl Getopt checks.
|
||||
dnl
|
||||
AC_CHECK_FUNCS(getopt_long getopt)
|
||||
AC_CHECK_HEADERS(getopt.h)
|
||||
|
||||
dnl LFS checks.
|
||||
dnl
|
||||
if test "$LFS_SUPPORT" = "yes"; then
|
||||
AC_CHECK_FUNCS(open64, AC_DEFINE(ENABLE_LARGEFILE))
|
||||
fi
|
||||
|
||||
dnl Check for various header files and set various other macros.
|
||||
dnl
|
||||
AC_DEFINE(HAVE_CONFIG_H)
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_STDBOOL
|
||||
AC_CHECK_FUNCS(memcpy basename snprintf stat64)
|
||||
AC_CHECK_HEADERS(limits.h)
|
||||
|
||||
if test "$IPC_SUPPORT" = "yes"; then
|
||||
AC_CHECK_HEADERS(sys/ipc.h sys/param.h libgen.h)
|
||||
fi
|
||||
|
||||
if test "$SPLICE_SUPPORT" = "yes"; then
|
||||
AC_CHECK_FUNCS(splice)
|
||||
fi
|
||||
|
||||
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
|
||||
AC_SUBST(INSTALL_DATA)
|
||||
|
||||
dnl Fudging for separate build directories.
|
||||
dnl
|
||||
subdirs=""
|
||||
for i in `find $srcdir/src -type d -print | sed s,$srcdir/,,`; do
|
||||
subdirs="$subdirs $i"
|
||||
done
|
||||
|
||||
dnl Stitch together the Makefile fragments.
|
||||
dnl
|
||||
mk_segments="autoconf/Makefile.in"
|
||||
for i in vars.mk package.mk filelist.mk~ unreal.mk modules.mk~ \
|
||||
rules.mk link.mk depend.mk~; do
|
||||
mk_segments="$mk_segments:autoconf/make/$i"
|
||||
done
|
||||
|
||||
dnl Output files (and create build directory structure too).
|
||||
dnl
|
||||
AC_OUTPUT(Makefile:$mk_segments doc/lsm:doc/lsm.in
|
||||
doc/quickref.1:doc/quickref.1.in
|
||||
doc/$PACKAGE.spec:doc/spec.in
|
||||
src/.dummy:doc/NEWS,
|
||||
rm -f src/.dummy
|
||||
for i in $subdirs; do
|
||||
test -d $i || mkdir $i
|
||||
done
|
||||
, subdirs="$subdirs")
|
||||
|
||||
dnl EOF
|
||||
@@ -1,114 +0,0 @@
|
||||
/*!NOINDEX*/
|
||||
/* Define if you have standard C headers. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define if you have "config.h" (yes, you have). */
|
||||
#undef HAVE_CONFIG_H
|
||||
|
||||
/* Various other header files. */
|
||||
#undef HAVE_GETOPT_H
|
||||
#undef HAVE_LIMITS_H
|
||||
#undef HAVE_SYS_IPC_H
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
#undef HAVE_LIBGEN_H
|
||||
|
||||
/* Functions. */
|
||||
#undef HAVE_GETOPT
|
||||
#undef HAVE_GETOPT_LONG
|
||||
#undef HAVE_MEMCPY
|
||||
#undef HAVE_BASENAME
|
||||
#undef HAVE_SNPRINTF
|
||||
#undef HAVE_STAT64
|
||||
|
||||
#undef HAVE_SPLICE
|
||||
#ifdef HAVE_SPLICE
|
||||
# define _GNU_SOURCE 1
|
||||
#endif
|
||||
/* NB the above must come before NLS, as NLS includes other system headers. */
|
||||
|
||||
/* NLS stuff. */
|
||||
#undef ENABLE_NLS
|
||||
#undef HAVE_LIBINTL_H
|
||||
#undef HAVE_LOCALE_H
|
||||
#undef HAVE_GETTEXT
|
||||
#ifdef ENABLE_NLS
|
||||
# include "library/gettext.h"
|
||||
#else
|
||||
# define _(String) (String)
|
||||
# define N_(String) (String)
|
||||
#endif
|
||||
|
||||
/* The name of the program. */
|
||||
#define PROGRAM_NAME "progname"
|
||||
|
||||
/* The name of the package. */
|
||||
#define PACKAGE ""
|
||||
|
||||
/* The current package version. */
|
||||
#define VERSION "0.0.0"
|
||||
|
||||
/* Various identification and legal stuff. */
|
||||
#define COPYRIGHT_YEAR _("2015")
|
||||
#define COPYRIGHT_HOLDER _("Andrew Wood <andrew.wood@ivarch.com>")
|
||||
#define PROJECT_HOMEPAGE "http://www.ivarch.com/programs/" PROGRAM_NAME ".shtml"
|
||||
#define BUG_REPORTS_TO _("<pv@ivarch.com>")
|
||||
|
||||
/* LFS support. */
|
||||
#undef ENABLE_LARGEFILE
|
||||
#ifdef ENABLE_LARGEFILE
|
||||
# define __USE_LARGEFILE64 1
|
||||
# define _LARGEFILE64_SOURCE 1
|
||||
#else
|
||||
/*
|
||||
* Some Macs have stat64 despite not having open64 while others don't have
|
||||
* either, so here even if we don't have open64 or LFS is disabled, we have
|
||||
* to check whether stat64 exists and only redefine it if it doesn't
|
||||
* otherwise some Macs fail to compile.
|
||||
*/
|
||||
# ifdef __APPLE__
|
||||
# ifndef HAVE_STAT64
|
||||
# define stat64 stat
|
||||
# define fstat64 fstat
|
||||
# define lstat64 lstat
|
||||
# endif
|
||||
# else
|
||||
# define stat64 stat
|
||||
# define fstat64 fstat
|
||||
# define lstat64 lstat
|
||||
# endif
|
||||
# define open64 open
|
||||
# define lseek64 lseek
|
||||
#endif
|
||||
|
||||
#undef HAVE_IPC
|
||||
#ifdef HAVE_SYS_IPC_H
|
||||
#define HAVE_IPC 1
|
||||
#endif
|
||||
|
||||
#undef CURSOR_ANSWERBACK_BYTE_BY_BYTE
|
||||
#ifndef _AIX
|
||||
#define CURSOR_ANSWERBACK_BYTE_BY_BYTE 1
|
||||
#endif
|
||||
|
||||
/* Boolean type support. */
|
||||
#undef HAVE_STDBOOL_H
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#else
|
||||
# ifndef HAVE__BOOL
|
||||
# ifdef __cplusplus
|
||||
typedef bool _Bool;
|
||||
# else
|
||||
# define _Bool signed char
|
||||
# endif
|
||||
# endif
|
||||
# define bool _Bool
|
||||
# define false 0
|
||||
# define true 1
|
||||
# define __bool_true_false_are_defined 1
|
||||
#endif
|
||||
|
||||
/* Support for debugging output. */
|
||||
#undef ENABLE_DEBUGGING
|
||||
|
||||
/* EOF */
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# Targets.
|
||||
#
|
||||
|
||||
$(package): src/main.o src/library.o src/pv.o @NLSOBJ@
|
||||
$(CC) $(LINKFLAGS) $(CFLAGS) -o $@ src/main.o src/library.o src/pv.o @NLSOBJ@ $(LIBS)
|
||||
|
||||
$(package)-static: src/main.o src/library.o src/pv.o @NLSOBJ@
|
||||
$(CC) $(LINKFLAGS) $(CFLAGS) -static -o $@ src/main.o src/library.o src/pv.o @NLSOBJ@ $(LIBS)
|
||||
|
||||
# EOF
|
||||
@@ -1,17 +0,0 @@
|
||||
#
|
||||
# Package name, version, and distribution files.
|
||||
#
|
||||
|
||||
package = @PACKAGE@
|
||||
version = @VERSION@
|
||||
PACKAGE = @PACKAGE@
|
||||
|
||||
distfiles = \
|
||||
$(srcdir)/README \
|
||||
$(srcdir)/autoconf \
|
||||
$(srcdir)/configure \
|
||||
$(srcdir)/doc \
|
||||
$(srcdir)/src \
|
||||
$(srcdir)/tests
|
||||
|
||||
# EOF
|
||||
@@ -1,43 +0,0 @@
|
||||
#
|
||||
# Compilation rules.
|
||||
#
|
||||
|
||||
.SUFFIXES: .c .d .o
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||
|
||||
.c.d:
|
||||
sh $(srcdir)/autoconf/scripts/depend.sh \
|
||||
$(CC) $< $(<:%.c=%) $(srcdir) $(CFLAGS) $(CPPFLAGS) > $@
|
||||
|
||||
#
|
||||
# NLS stuff
|
||||
#
|
||||
|
||||
%.mo: %.po
|
||||
$(MSGFMT) -o $@ $<
|
||||
@touch $@
|
||||
@chmod 644 $@
|
||||
|
||||
%.gmo: %.po
|
||||
rm -f $@
|
||||
$(GMSGFMT) -o $@ $<
|
||||
@touch $@
|
||||
@chmod 644 $@
|
||||
|
||||
$(srcdir)/src/nls/$(PACKAGE).pot: $(allsrc)
|
||||
$(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(srcdir) \
|
||||
--add-comments --keyword=_ --keyword=N_ \
|
||||
$(allsrc)
|
||||
if cmp -s $(PACKAGE).po $@; then \
|
||||
rm -f $(PACKAGE).po; \
|
||||
else \
|
||||
rm -f $@; \
|
||||
mv $(PACKAGE).po $@; \
|
||||
chmod 644 $@; \
|
||||
fi
|
||||
|
||||
src/nls/table.c: $(POFILES)
|
||||
sh $(srcdir)/autoconf/scripts/po2table.sh $(POFILES) > src/nls/table.c
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
#
|
||||
# Rules for all phony targets.
|
||||
#
|
||||
|
||||
.PHONY: all help make dep depend test check \
|
||||
clean depclean indentclean distclean cvsclean svnclean \
|
||||
index manhtml indent update-po \
|
||||
doc dist release \
|
||||
install uninstall \
|
||||
rpm srpm
|
||||
|
||||
all: $(alltarg) $(CATALOGS)
|
||||
|
||||
help:
|
||||
@echo 'This Makefile has the following utility targets:'
|
||||
@echo
|
||||
@echo ' all build all binary targets'
|
||||
@echo ' install install compiled package and manual'
|
||||
@echo ' uninstall uninstall the package'
|
||||
@echo ' check / test run standardised tests on the compiled binary'
|
||||
@echo
|
||||
@echo 'Developer targets:'
|
||||
@echo
|
||||
@echo ' make rebuild the Makefile (after adding new files)'
|
||||
@echo ' dep / depend rebuild .d (dependency) files'
|
||||
@echo ' clean remove .o (object) and .c~ (backup) files'
|
||||
@echo ' depclean remove .d (dependency) files'
|
||||
@echo ' indentclean remove files left over from "make indent"'
|
||||
@echo ' distclean remove everything not distributed'
|
||||
@echo ' cvsclean remove everything not in CVS/SVN'
|
||||
@echo
|
||||
@echo ' index generate an HTML index of source code'
|
||||
@echo ' manhtml output HTML man page to stdout'
|
||||
@echo ' indent reformat all source files with "indent"'
|
||||
@echo ' update-po update the .po files'
|
||||
@echo
|
||||
@echo ' dist create a source tarball for distribution'
|
||||
@echo ' rpm build a binary RPM (passes $$RPMFLAGS to RPM)'
|
||||
@echo ' srpm build a source RPM (passes $$RPMFLAGS to RPM)'
|
||||
@echo ' release dist+rpm+srpm'
|
||||
@echo
|
||||
|
||||
make:
|
||||
echo > $(srcdir)/autoconf/make/filelist.mk~
|
||||
echo > $(srcdir)/autoconf/make/modules.mk~
|
||||
cd $(srcdir); \
|
||||
bash autoconf/scripts/makemake.sh \
|
||||
autoconf/make/filelist.mk~ \
|
||||
autoconf/make/modules.mk~
|
||||
sh ./config.status
|
||||
|
||||
dep depend: $(alldep)
|
||||
echo '#' > $(srcdir)/autoconf/make/depend.mk~
|
||||
echo '# Dependencies.' >> $(srcdir)/autoconf/make/depend.mk~
|
||||
echo '#' >> $(srcdir)/autoconf/make/depend.mk~
|
||||
echo >> $(srcdir)/autoconf/make/depend.mk~
|
||||
cat $(alldep) >> $(srcdir)/autoconf/make/depend.mk~
|
||||
sh ./config.status
|
||||
|
||||
clean:
|
||||
rm -f $(allobj)
|
||||
|
||||
depclean:
|
||||
rm -f $(alldep)
|
||||
|
||||
indentclean:
|
||||
cd $(srcdir) && for FILE in $(allsrc); do rm -f ./$${FILE}~; done
|
||||
|
||||
update-po: $(srcdir)/src/nls/$(PACKAGE).pot
|
||||
catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
lang=$(srcdir)/`echo $$cat | sed 's/$(CATOBJEXT)$$//'`; \
|
||||
mv $$lang.po $$lang.old.po; \
|
||||
if $(MSGMERGE) $$lang.old.po $(srcdir)/src/nls/$(PACKAGE).pot > $$lang.po; then \
|
||||
rm -f $$lang.old.po; \
|
||||
else \
|
||||
echo "msgmerge for $$cat failed!"; \
|
||||
rm -f $$lang.po; \
|
||||
mv $$lang.old.po $$lang.po; \
|
||||
chmod 644 $$lang.po; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
distclean: clean depclean
|
||||
rm -f $(alltarg) src/include/config.h
|
||||
rm -rf $(package)-$(version).tar* $(package)-$(version) $(package)-$(version)-*.rpm
|
||||
rm -f *.html config.*
|
||||
rm Makefile
|
||||
|
||||
cvsclean svnclean: distclean
|
||||
rm -f doc/lsm
|
||||
rm -f doc/$(package).spec
|
||||
rm -f doc/quickref.1
|
||||
rm -f configure
|
||||
rm -f src/nls/*.gmo src/nls/*.mo
|
||||
echo > $(srcdir)/autoconf/make/depend.mk~
|
||||
echo > $(srcdir)/autoconf/make/filelist.mk~
|
||||
echo > $(srcdir)/autoconf/make/modules.mk~
|
||||
|
||||
doc:
|
||||
:
|
||||
|
||||
index:
|
||||
(cd $(srcdir); sh autoconf/scripts/index.sh $(srcdir)) > index.html
|
||||
|
||||
manhtml:
|
||||
@man2html ./doc/quickref.1 \
|
||||
| sed -e '1,/<BODY/d' -e '/<\/BODY/,$$d' \
|
||||
-e 's|<A [^>]*> </A>||ig' \
|
||||
-e 's|<A [^>]*>\([^<]*\)</A>|\1|ig' \
|
||||
-e '/<H1/d' -e 's|\(</H[0-9]>\)|\1<P>|ig' \
|
||||
-e 's/<DL COMPACT>/<DL>/ig' \
|
||||
-e 's/<[0-9A-Za-z_.-]\+@[0-9A-Za-z_.-]\+>//g' \
|
||||
-e 's|<I>\(http://.*\)</I>|<A HREF="\1">\1</A>|ig' \
|
||||
| sed -e '1,/<HR/d' -e '/<H2>Index/,/<HR/d' \
|
||||
|
||||
indent:
|
||||
cd $(srcdir) && indent -npro -kr -i8 -cd42 -c45 $(allsrc)
|
||||
|
||||
dist: doc update-po
|
||||
rm -rf $(package)-$(version)
|
||||
mkdir $(package)-$(version)
|
||||
cp -dprf Makefile $(distfiles) $(package)-$(version)
|
||||
cd $(package)-$(version); $(MAKE) distclean
|
||||
cp -dpf doc/lsm $(package)-$(version)/doc/
|
||||
cp -dpf doc/$(package).spec $(package)-$(version)/doc/
|
||||
chmod 644 `find $(package)-$(version) -type f -print`
|
||||
chmod 755 `find $(package)-$(version) -type d -print`
|
||||
chmod 755 `find $(package)-$(version)/autoconf/scripts`
|
||||
chmod 755 $(package)-$(version)/configure
|
||||
rm -rf DUMMY `find $(package)-$(version) -type d -name CVS`
|
||||
rm -rf DUMMY `find $(package)-$(version) -type d -name .svn`
|
||||
tar cf $(package)-$(version).tar $(package)-$(version)
|
||||
rm -rf $(package)-$(version)
|
||||
-gzip -f9 $(package)-$(version).tar
|
||||
|
||||
check test: $(alltarg)
|
||||
sh $(srcdir)/autoconf/scripts/run-test.sh ./$(package) $(srcdir)
|
||||
|
||||
install: all doc
|
||||
$(srcdir)/autoconf/scripts/mkinstalldirs \
|
||||
"$(DESTDIR)$(bindir)"
|
||||
$(srcdir)/autoconf/scripts/mkinstalldirs \
|
||||
"$(DESTDIR)$(mandir)/man1"
|
||||
$(INSTALL) -m 755 $(package) \
|
||||
"$(DESTDIR)$(bindir)/$(package)"
|
||||
$(INSTALL) -m 644 doc/quickref.1 \
|
||||
"$(DESTDIR)$(mandir)/man1/$(package).1"
|
||||
if test -n "$(CATALOGS)"; then \
|
||||
catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
name=`echo $$cat | sed 's,^.*/,,g'`; \
|
||||
if test "`echo $$name | sed 's/.*\(\..*\)/\1/'`" = ".gmo"; then \
|
||||
destdir=$(gnulocaledir); \
|
||||
else \
|
||||
destdir=$(localedir); \
|
||||
fi; \
|
||||
lang=`echo $$name | sed 's/$(CATOBJEXT)$$//'`; \
|
||||
dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \
|
||||
$(srcdir)/autoconf/scripts/mkinstalldirs $$dir; \
|
||||
$(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \
|
||||
done; \
|
||||
fi
|
||||
|
||||
uninstall:
|
||||
-$(UNINSTALL) "$(DESTDIR)$(bindir)/$(package)"
|
||||
-$(UNINSTALL) "$(DESTDIR)$(mandir)/man1/$(package).1"
|
||||
-$(UNINSTALL) "$(DESTDIR)$(mandir)/man1/$(package).1.gz"
|
||||
-if test -n "$(CATALOGS)"; then \
|
||||
catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
name=`echo $$cat | sed 's,^.*/,,g'`; \
|
||||
if test "`echo $$name | sed 's/.*\(\..*\)/\1/'`" = ".gmo"; then \
|
||||
destdir=$(gnulocaledir); \
|
||||
else \
|
||||
destdir=$(localedir); \
|
||||
fi; \
|
||||
lang=`echo $$name | sed 's/$(CATOBJEXT)$$//'`; \
|
||||
dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \
|
||||
$(UNINSTALL) $$dir/$(PACKAGE)$(INSTOBJEXT); \
|
||||
done; \
|
||||
fi
|
||||
|
||||
rpm:
|
||||
test -e $(package)-$(version).tar.gz || $(MAKE) dist
|
||||
rpmbuild $(RPMFLAGS) --define="%_topdir `pwd`/rpm" -tb $(package)-$(version).tar.gz
|
||||
mv rpm/RPMS/*/$(package)-*.rpm .
|
||||
rm -rf rpm
|
||||
|
||||
srpm:
|
||||
test -e $(package)-$(version).tar.gz || $(MAKE) dist
|
||||
rpmbuild $(RPMFLAGS) --define="%_topdir `pwd`/rpm" -ts $(package)-$(version).tar.gz
|
||||
mv rpm/SRPMS/*$(package)-*.rpm .
|
||||
rm -rf rpm
|
||||
|
||||
release: dist rpm srpm
|
||||
zcat $(package)-$(version).tar.gz | bzip2 > $(package)-$(version).tar.bz2
|
||||
-grep -Fq '%_gpg_name' ~/.rpmmacros 2>/dev/null && rpm --addsign *.rpm
|
||||
-gpg --list-secret-keys 2>&1 | grep -Fq 'uid' && gpg -ab *.tar.gz && rename .asc .txt *.tar.gz.asc
|
||||
-gpg --list-secret-keys 2>&1 | grep -Fq 'uid' && gpg -ab *.tar.bz2 && rename .asc .txt *.tar.bz2.asc
|
||||
chmod 644 $(package)-$(version)*
|
||||
@@ -1,46 +0,0 @@
|
||||
#
|
||||
# Variables for Make.
|
||||
#
|
||||
|
||||
srcdir = @srcdir@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
bindir = @bindir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
etcdir = @prefix@/etc
|
||||
datadir = @datadir@
|
||||
sbindir = @sbindir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
gnulocaledir = $(prefix)/share/locale
|
||||
|
||||
CATALOGS = @CATALOGS@
|
||||
POFILES = @POFILES@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
MSGFMT = @MSGFMT@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
MSGMERGE = msgmerge
|
||||
CATOBJEXT = @CATOBJEXT@
|
||||
INSTOBJEXT = @INSTOBJEXT@
|
||||
|
||||
@SET_MAKE@
|
||||
SHELL = /bin/sh
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
UNINSTALL = rm -f
|
||||
|
||||
LDFLAGS = -r
|
||||
LINKFLAGS = @LDFLAGS@
|
||||
DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\"
|
||||
CFLAGS = @CFLAGS@
|
||||
CPPFLAGS = @CPPFLAGS@ -I$(srcdir)/src/include -Isrc/include $(DEFS)
|
||||
LIBS = @LIBS@
|
||||
|
||||
alltarg = @PACKAGE@
|
||||
|
||||
# EOF
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Generate dependencies for a C source file.
|
||||
#
|
||||
|
||||
CC=$1
|
||||
shift
|
||||
file=$1
|
||||
shift
|
||||
stem=$1
|
||||
shift
|
||||
srcdir=$1
|
||||
abssrc=`echo $srcdir | sed ':1
|
||||
s,^\./,,g
|
||||
t1'`
|
||||
shift
|
||||
|
||||
abssrc=`echo "$abssrc" | sed 's,\\.,\\\\.,g'`
|
||||
srcdir=`echo "$srcdir" | sed 's,\\.,\\\\.,g'`
|
||||
|
||||
$CC -M -MG $* $file \
|
||||
| sed -e 's, /[^ ]*,,g' -e "s,^.*\.o:,${stem}.d ${stem}.o:," \
|
||||
-e '/^ \\$/d' -e 's/ \\$//' \
|
||||
-e 's,'"$srcdir"'/,,g' -e 's,'"$abssrc"'/,,g' \
|
||||
| tr '\n' ' ' \
|
||||
| tr -s ' '
|
||||
|
||||
echo
|
||||
|
||||
# EOF
|
||||
@@ -1,171 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Script to generate an HTML index of all C code from the current directory
|
||||
# downwards (skipping directories ending in ~). The header comment in each
|
||||
# file is listed, and each function's prototype and comment are given. A
|
||||
# list of "TODO:" comments is also generated.
|
||||
#
|
||||
# Outputs the HTML on standard output.
|
||||
#
|
||||
# If a parameter is given, it is the prefix to put before any "view file"
|
||||
# links, eg ".." to link to "../dir/file.c" instead of "dir/file.c".
|
||||
#
|
||||
# Skips any files containing the string !NOINDEX.
|
||||
#
|
||||
# Requires ctags and cproto.
|
||||
#
|
||||
|
||||
OFFS=$1
|
||||
|
||||
|
||||
# Convert the given string to HTML-escaped values (<, >, & escaped) on
|
||||
# stdout.
|
||||
#
|
||||
html_safe () {
|
||||
echo "$*" \
|
||||
| sed -e 's|&|\&|g;s|<|\<|g;s|>|\>|g'
|
||||
}
|
||||
|
||||
|
||||
# Convert the given string to HTML-escaped values (<, >, & escaped) on
|
||||
# stdout, also adding a <BR> to the end of each line.
|
||||
#
|
||||
html_safebr () {
|
||||
echo "$*" \
|
||||
| sed -e 's|&|\&|g;s|<|\<|g;s|>|\>|g;s/$/<BR>/'
|
||||
}
|
||||
|
||||
ALLFILES=`find . -name '*~' -prune -o -type f -name '*.c' \
|
||||
-exec grep -FL '!NOINDEX' /dev/null '{}' ';'`
|
||||
|
||||
CTAGDATA=`echo "$ALLFILES" \
|
||||
| ctags -nRf- -L- --c-types=f \
|
||||
| sed 's/ .\// /;s/;" .*$//'`
|
||||
|
||||
FILELIST=`echo "$CTAGDATA" | cut -d ' ' -f 2 | sort | uniq`
|
||||
|
||||
echo '<HTML><HEAD>'
|
||||
echo '<TITLE>Source Code Index</TITLE>'
|
||||
echo '</HEAD><BODY>'
|
||||
echo '<H1><A NAME="top">Source Code Index</A></H1>'
|
||||
echo '<P><UL>'
|
||||
echo '<LI><A HREF="#files">File Listing</A></LI>'
|
||||
echo '<LI><A HREF="#funcs">Function Listing</A></LI>'
|
||||
echo '<LI><A HREF="#todo">To-Do Listing</A></LI>'
|
||||
echo '</UL></P>'
|
||||
|
||||
echo '<H2><A NAME="files">File Listing</A></H2>'
|
||||
echo '<P><UL>'
|
||||
echo "$FILELIST" \
|
||||
| sed -e \
|
||||
's|^.*$|<LI><CODE CLASS="filename"><A HREF="#file-\0">\0</A></CODE></LI>|'
|
||||
echo '</UL></P>'
|
||||
|
||||
for FILE in $FILELIST; do
|
||||
|
||||
DIR=`dirname $FILE`
|
||||
FUNCDEFS=`cproto -f1 -I. -Isrc/include -I$DIR $FILE 2>/dev/null \
|
||||
| sed -n 's/^.*[ *]\([^ *(]*\)(.*$/\1/p'`
|
||||
FILEHEAD="`sed -n -e \
|
||||
'1,/\*\//{/\/\*/,/\*\//{s/^[\/ *]//;s/^\*[\/]*//;p;};}' \
|
||||
< $FILE`"
|
||||
FILESHORTDESC=`echo "$FILEHEAD" | sed -n '1,/^ *$/{/^ *[^ ]*/p;}'`
|
||||
FILELONGDESC=`echo "$FILEHEAD" | sed '1,/^ *$/d'`
|
||||
|
||||
echo '<P><HR WIDTH="100%"></P>'
|
||||
echo '<P><TABLE BORDER="0"><TR>'
|
||||
echo '<TD VALIGN="TOP"><CODE CLASS="filename">'
|
||||
echo '<A NAME="file-'"$FILE"'">'"$FILE"'</A></CODE></TD>'
|
||||
echo '<TD VALIGN="TOP"> - </TD>'
|
||||
echo '<TD VALIGN="TOP">'`html_safe "$FILESHORTDESC"`'</TD>'
|
||||
echo '</TR></TABLE></P>'
|
||||
echo '<P><SMALL>[<A HREF="'"$OFFS/$FILE"'">View File</A>]</SMALL></P>'
|
||||
echo '<P><BLOCKQUOTE>'
|
||||
echo "`html_safebr "$FILELONGDESC"`"
|
||||
echo '</BLOCKQUOTE></P>'
|
||||
|
||||
if [ -n "$FUNCDEFS" ]; then
|
||||
echo '<P>Functions defined:</P>'
|
||||
echo '<P><UL>'
|
||||
echo "$FUNCDEFS" \
|
||||
| sed 's|^.*$|<A HREF="#func-\0---'"$FILE"'">\0</A>|' \
|
||||
| sed 's/^/<LI><CODE CLASS="funcname">/;s|$|</CODE></LI>|'
|
||||
echo '</UL></P>'
|
||||
fi
|
||||
|
||||
echo '<P ALIGN="RIGHT"><SMALL CLASS="navbar">['
|
||||
echo '<A HREF="#top">Top</A> |'
|
||||
echo '<A HREF="#todo">To Do</A> |'
|
||||
echo '<A HREF="#funcs">Functions</A> ]</SMALL></P>'
|
||||
done
|
||||
|
||||
echo '<H2><A NAME="funcs">Function Listing</A></H2>'
|
||||
echo '<P><UL>'
|
||||
echo "$CTAGDATA" | while read FUNC FILE LINENUM REST; do
|
||||
echo -n '<LI><CODE CLASS="funcname">'
|
||||
echo -n '<A HREF="#func-'"$FUNC"'---'"$FILE"'">'"$FUNC"'</A></CODE> '
|
||||
echo '[<CODE CLASS="filename">'"$FILE"'</CODE>]</LI>'
|
||||
done
|
||||
echo '</UL></P>'
|
||||
|
||||
echo "$CTAGDATA" | while read FUNC FILE LINENUM REST; do
|
||||
|
||||
FUNCDEF=`sed -n "$LINENUM,/{/p" < $FILE \
|
||||
| tr '\n' ' ' \
|
||||
| tr -d '{'`
|
||||
|
||||
LASTCOMLINE=`sed -n '1,'"$LINENUM"'{/\/\*/=;}' < $FILE | sed -n '$p'`
|
||||
[ -z "$LASTCOMLINE" ] && LASTCOMLINE=1
|
||||
LASTENDFUNCLINE=`sed -n '1,'"$LINENUM"'{/}/=;}' < $FILE | sed -n '$p'`
|
||||
[ -z "$LASTENDFUNCLINE" ] && LASTENDFUNCLINE=1
|
||||
FUNCHEAD="`sed -n -e \
|
||||
"$LASTCOMLINE,"'/\*\//{h;s/^[\/ *]//;s/^\*[\/]*//;p;x;/\*\//q;}' \
|
||||
< $FILE`"
|
||||
[ "$LASTCOMLINE" -le "$LASTENDFUNCLINE" ] && FUNCHEAD=""
|
||||
|
||||
echo '<P><HR WIDTH="100%"></P>'
|
||||
echo '<P ALIGN="LEFT">'
|
||||
echo -n '<CODE CLASS="funcname"><A NAME="func-'"$FUNC"'---'"$FILE"'">'
|
||||
echo -n "$FUNC"'</A></CODE> '
|
||||
echo -n '[<CODE CLASS="filename"><A HREF="#file-'"$FILE"'">'
|
||||
echo "$FILE"'</A></CODE>]'
|
||||
echo '</P>'
|
||||
|
||||
echo '<P><CODE CLASS="funcdef">'"`html_safe "$FUNCDEF"`"'</CODE></P>'
|
||||
|
||||
echo '<P><BLOCKQUOTE>'
|
||||
echo "`html_safebr "$FUNCHEAD"`"
|
||||
echo '</BLOCKQUOTE></P>'
|
||||
|
||||
echo '<P ALIGN="RIGHT"><SMALL CLASS="navbar">['
|
||||
echo '<A HREF="#top">Top</A> |'
|
||||
echo '<A HREF="#todo">To Do</A> |'
|
||||
echo '<A HREF="#files">Files</A> ]</SMALL></P>'
|
||||
done
|
||||
|
||||
echo '<H2><A NAME="todo">To Do Listing</A></H2>'
|
||||
echo '<P><UL>'
|
||||
for FILE in $FILELIST; do
|
||||
|
||||
TODOLINES=`sed -n \
|
||||
-e '/\/\*.*\*\//!{/\/\*/,/\*\//{/TODO:/{=;};};}' \
|
||||
-e '/\/\*.*\*\//{/TODO:/{=;};}' \
|
||||
< $FILE`
|
||||
|
||||
[ -z "$TODOLINES" ] && continue
|
||||
|
||||
echo -n '<LI><CODE CLASS="filename">'
|
||||
echo '<A HREF="#file-'"$FILE"'">'"$FILE"'</A></CODE>'
|
||||
echo '<UL>'
|
||||
|
||||
for NUM in $TODOLINES; do
|
||||
TODO=`sed -n "$NUM"'{s/^.*TODO://;s/\*\/.*$//;p;}' < $FILE`
|
||||
echo "<LI>[<B>$NUM</B>] `html_safe "$TODO"`</LI>"
|
||||
done
|
||||
|
||||
echo '</UL></LI>'
|
||||
done
|
||||
|
||||
echo '</BODY></HTML>'
|
||||
|
||||
# EOF
|
||||
@@ -1,250 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
||||
@@ -1,113 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Generate Makefile dependencies inclusion and module target file "depend.mk~"
|
||||
# by scanning the directory "src" for files ending in ".c" and ".d", and for
|
||||
# subdirectories not starting with "_".
|
||||
#
|
||||
# Modules live inside subdirectories called [^_]* - i.e. a directory "foo" will
|
||||
# have a rule created which links all code inside it to "foo.o".
|
||||
#
|
||||
# The directory "src/include" is never scanned; neither are CVS or SVN
|
||||
# directories.
|
||||
#
|
||||
|
||||
outlist=$1
|
||||
outlink=$2
|
||||
|
||||
FIND=find
|
||||
GREP=grep
|
||||
which gfind 2>/dev/null | grep /gfind >/dev/null && FIND=gfind
|
||||
which ggrep 2>/dev/null | grep /ggrep >/dev/null && GREP=ggrep
|
||||
|
||||
echo '# Automatically generated file listings' > $outlist
|
||||
echo '#' >> $outlist
|
||||
echo "# Creation time: `date`" >> $outlist
|
||||
echo >> $outlist
|
||||
|
||||
echo '# Automatically generated module linking rules' > $outlink
|
||||
echo '#' >> $outlink
|
||||
echo "# Creation time: `date`" >> $outlink
|
||||
echo >> $outlink
|
||||
|
||||
echo -n "Scanning for source files: "
|
||||
|
||||
allsrc=`$FIND src -type f -name "*.c" -print`
|
||||
allobj=`echo $allsrc | tr ' ' '\n' | sed 's/\.c$/.o/'`
|
||||
alldep=`echo $allsrc | tr ' ' '\n' | sed 's/\.c$/.d/'`
|
||||
|
||||
echo `echo $allsrc | wc -w | tr -d ' '` found
|
||||
|
||||
echo -n "Scanning for modules: "
|
||||
|
||||
modules=`$FIND src -type d -print \
|
||||
| $GREP -v '^src$' \
|
||||
| $GREP -v '/_' \
|
||||
| $GREP -v '^src/include' \
|
||||
| $GREP -v 'CVS' \
|
||||
| $GREP -v '.svn' \
|
||||
| while read DIR; do \
|
||||
CONTENT=\$(/bin/ls -d \$DIR/* \
|
||||
| $GREP -v '.po$' \
|
||||
| $GREP -v '.gmo$' \
|
||||
| $GREP -v '.mo$' \
|
||||
| $GREP -v '.h$' \
|
||||
| sed -n '$p'); \
|
||||
[ -n "\$CONTENT" ] || continue; \
|
||||
echo \$DIR; \
|
||||
done
|
||||
`
|
||||
|
||||
echo up to `echo $modules | wc -w | tr -d ' '` found
|
||||
|
||||
echo "Writing module linking rules"
|
||||
|
||||
echo -n [
|
||||
for i in $modules; do echo -n ' '; done
|
||||
echo -n -e ']\r['
|
||||
|
||||
for i in $modules; do
|
||||
echo -n '.'
|
||||
allobj="$allobj $i.o"
|
||||
deps=""
|
||||
for j in $i/*.c; do
|
||||
[ -f $j ] || continue
|
||||
newobj=`echo $j | sed -e 's@\.c$@.o@'`
|
||||
deps="$deps $newobj"
|
||||
done
|
||||
for j in $i/*; do
|
||||
[ -d "$j" ] || continue
|
||||
[ `basename $j` = "CVS" ] && continue
|
||||
[ `basename $j` = ".svn" ] && continue
|
||||
CONTENT=`/bin/ls -d $j/* \
|
||||
| $GREP -v '.po$' \
|
||||
| $GREP -v '.gmo$' \
|
||||
| $GREP -v '.mo$' \
|
||||
| $GREP -v '.h$' \
|
||||
| sed -n '$p'`
|
||||
[ -n "$CONTENT" ] || continue
|
||||
deps="$deps $j.o"
|
||||
done
|
||||
[ -n "$deps" ] || continue
|
||||
echo "$i.o: $deps" >> $outlink
|
||||
echo ' $(LD) $(LDFLAGS) -o $@' "$deps" >> $outlink
|
||||
echo >> $outlink
|
||||
done
|
||||
|
||||
echo ']'
|
||||
|
||||
echo "Listing source, object and dependency files"
|
||||
|
||||
echo -n "allsrc = " >> $outlist
|
||||
echo $allsrc | sed 's,src/nls/cat-id-tbl.c,,' | sed -e 's/ / \\!/g'\
|
||||
| tr '!' '\n' >> $outlist
|
||||
echo >> $outlist
|
||||
echo -n "allobj = " >> $outlist
|
||||
echo $allobj | sed -e 's/ / \\!/g' | tr '!' '\n' >> $outlist
|
||||
echo >> $outlist
|
||||
echo -n "alldep = " >> $outlist
|
||||
echo $alldep | sed -e 's/ / \\!/g' | tr '!' '\n' >> $outlist
|
||||
|
||||
echo >> $outlist
|
||||
echo >> $outlink
|
||||
|
||||
# EOF
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/sh
|
||||
# mkinstalldirs --- make directory hierarchy
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-05-16
|
||||
# Last modified: 1994-03-25
|
||||
# Public domain
|
||||
|
||||
errstatus=0
|
||||
|
||||
for file in ${1+"$@"} ; do
|
||||
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
|
||||
shift
|
||||
|
||||
pathcomp=
|
||||
for d in ${1+"$@"} ; do
|
||||
pathcomp="$pathcomp$d"
|
||||
case "$pathcomp" in
|
||||
-* ) pathcomp=./$pathcomp ;;
|
||||
esac
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
echo "mkdir $pathcomp" 1>&2
|
||||
mkdir "$pathcomp" || errstatus=$?
|
||||
chmod 755 $pathcomp 2>/dev/null
|
||||
fi
|
||||
|
||||
pathcomp="$pathcomp/"
|
||||
done
|
||||
done
|
||||
|
||||
exit $errstatus
|
||||
|
||||
# mkinstalldirs ends here
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Messy script to convert all of the given .po files to a single C file on
|
||||
# stdout.
|
||||
|
||||
cat <<EOF
|
||||
/*
|
||||
* Translation table - automatically generated by po2table.sh.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
struct msgtable_s {
|
||||
char *msgid;
|
||||
char *msgstr;
|
||||
};
|
||||
|
||||
|
||||
struct msgtable_s *minigettext__gettable(char *lang)
|
||||
{
|
||||
if (0 == lang)
|
||||
return 0;
|
||||
|
||||
EOF
|
||||
|
||||
for POFILE in $*; do
|
||||
LANG=`basename "$POFILE" | sed 's/.po$//'`
|
||||
echo " if (strncmp(lang, \"$LANG\", 2) == 0) {"
|
||||
echo " static struct msgtable_s data[] = {";
|
||||
|
||||
awk 'BEGIN{i=0;s=0;}
|
||||
/^msgid[ ]+/ {
|
||||
if (s) print " }, ";
|
||||
print " {";
|
||||
print " " substr($0,7);
|
||||
i=1;
|
||||
s=0;
|
||||
}
|
||||
/^msgstr[ ]+/ {
|
||||
print " ,";
|
||||
i=0;s=1;
|
||||
print " " substr($0,8);
|
||||
}
|
||||
/^[ ]*"/ {
|
||||
if (i||s) print " " $0;
|
||||
}
|
||||
END {if (i||s) print " }\n";}
|
||||
' < "$POFILE"
|
||||
echo ' , { 0, 0 } };'
|
||||
echo " return data;"
|
||||
echo " }"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
EOF
|
||||
|
||||
# EOF
|
||||
@@ -1,45 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Run a test. Parameters are program name and source directory; if
|
||||
# additional parameters are given, they are the tests to run, otherwise all
|
||||
# tests are run.
|
||||
#
|
||||
|
||||
PROG="$1"
|
||||
SRCDIR="$2"
|
||||
shift
|
||||
shift
|
||||
TESTS="$*"
|
||||
|
||||
# Temporary working files
|
||||
#
|
||||
TMP1=`mktemp 2>/dev/null` || TMP1=.tmp1
|
||||
TMP2=`mktemp 2>/dev/null` || TMP2=.tmp2
|
||||
TMP3=`mktemp 2>/dev/null` || TMP3=.tmp3
|
||||
TMP4=`mktemp 2>/dev/null` || TMP4=.tmp4
|
||||
|
||||
export PROG TMP1 TMP2 TMP3 TMP4 # variables used by test scripts
|
||||
|
||||
FAIL=0
|
||||
|
||||
test -n "$TESTS" || TESTS=`ls "$SRCDIR/tests" | sort -n`
|
||||
|
||||
for SCRIPT in $TESTS; do
|
||||
test -f "$SCRIPT" || SCRIPT="$SRCDIR/tests/$SCRIPT"
|
||||
test -f "$SCRIPT" || SCRIPT=`ls "$SRCDIR/tests/$SCRIPT"*`
|
||||
test -f "$SCRIPT" || continue
|
||||
|
||||
echo `basename "$SCRIPT"`: " " | cut -b1-20 | sed 's/-/ - /' | tr "\n" ' '
|
||||
|
||||
STATUS=0
|
||||
sh -e "$SCRIPT" || STATUS=1
|
||||
test $STATUS -eq 1 && FAIL=1
|
||||
|
||||
test $STATUS -eq 1 && echo "FAILED" || echo "OK"
|
||||
done
|
||||
|
||||
rm -f $TMP1 $TMP2 $TMP3 $TMP4
|
||||
|
||||
exit $FAIL
|
||||
|
||||
# EOF
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
dnl Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
dnl
|
||||
dnl License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
|
||||
AC_INIT([pv], [1.8.0], [pv@ivarch.com], [pv], [https://www.ivarch.com/programs/pv.shtml])
|
||||
AC_CONFIG_SRCDIR([src/include/config.h.in])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([src/include/config.h])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
|
||||
AC_LANG(C)
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_C_CONST
|
||||
AC_HEADER_STDBOOL
|
||||
AC_SYS_LARGEFILE
|
||||
AM_GNU_GETTEXT_VERSION([0.21])
|
||||
AM_GNU_GETTEXT([external])
|
||||
if test "$USE_NLS" = "yes"; then
|
||||
CPPFLAGS="$CPPFLAGS -DLOCALEDIR=\\\"\$(localedir)\\\""
|
||||
LIBS="$LIBS $LIBINTL"
|
||||
fi
|
||||
|
||||
dnl Items we can use if present, but can do without if not present.
|
||||
AC_CHECK_FUNCS([getopt_long])
|
||||
AC_CHECK_FUNCS([vsnprintf strlcat strtoul])
|
||||
AC_CHECK_FUNCS([fdatasync])
|
||||
AC_CHECK_FUNCS([fpathconf sysconf posix_memalign posix_fadvise])
|
||||
AC_CHECK_FUNCS([nanosleep])
|
||||
AC_CHECK_HEADERS([getopt.h])
|
||||
AC_CHECK_HEADERS([limits.h])
|
||||
AC_CHECK_HEADERS([wctype.h])
|
||||
AC_CHECK_HEADERS([termios.h])
|
||||
AC_CHECK_HEADERS([libgen.h])
|
||||
AC_CHECK_HEADERS([sys/ioctl.h])
|
||||
AC_CHECK_HEADERS([libintl.h locale.h])
|
||||
AC_CHECK_MEMBERS([struct stat.st_blksize])
|
||||
|
||||
dnl Libraries that may contain key functions.
|
||||
AC_SEARCH_LIBS([clock_gettime],[rt])
|
||||
|
||||
dnl Items we can't do without.
|
||||
AC_CHECK_FUNCS([alarm basename clock_gettime dup2 getcwd memcpy memmove memset select setlocale strchr strerror strrchr strstr], [], [AC_MSG_ERROR([required function is missing])])
|
||||
AC_CHECK_HEADERS([fcntl.h sys/file.h sys/time.h unistd.h], [], [AC_MSG_ERROR([required header file is missing])])
|
||||
|
||||
dnl Make sure all the types we use are defined.
|
||||
AC_TYPE_INT32_T
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_SSIZE_T
|
||||
AC_TYPE_UID_T
|
||||
|
||||
AH_BOTTOM([#include "config-aux.h"])
|
||||
|
||||
AC_ARG_ENABLE([debugging],
|
||||
[ --enable-debugging compile with debugging support],
|
||||
if test "$enable_debugging" = "yes"; then
|
||||
CFLAGS="$CFLAGS -g -Wall"
|
||||
AC_DEFINE([ENABLE_DEBUGGING], [1], [Debugging support enabled])
|
||||
fi
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([profiling],
|
||||
[ --enable-profiling compile with profiling support],
|
||||
if test "$enable_profiling" = "yes"; then
|
||||
CFLAGS="-pg $CFLAGS"
|
||||
fi
|
||||
)
|
||||
|
||||
SPLICE_SUPPORT="no"
|
||||
AC_ARG_ENABLE([splice], [ --disable-splice do not use splice system call],
|
||||
if test "$enable_splice" = "yes"; then
|
||||
SPLICE_SUPPORT="yes"
|
||||
fi,
|
||||
SPLICE_SUPPORT="yes"
|
||||
)
|
||||
|
||||
IPC_SUPPORT="no"
|
||||
AC_ARG_ENABLE([ipc], [ --disable-ipc turn off IPC messaging],
|
||||
if test "$enable_ipc" = "yes"; then
|
||||
IPC_SUPPORT="yes"
|
||||
fi,
|
||||
IPC_SUPPORT="yes"
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE([static],
|
||||
[AS_HELP_STRING([--enable-static], [enable static linking])],
|
||||
[
|
||||
if test "$enable_static" = "yes"; then
|
||||
CFLAGS="$CFLAGS -static"
|
||||
fi
|
||||
])
|
||||
|
||||
dnl AIX needs -lc128
|
||||
AC_EGREP_CPP([^yes$], [#ifdef _AIX
|
||||
yes
|
||||
#endif
|
||||
], [LIBS="$LIBS -lc128"])
|
||||
|
||||
if test "$IPC_SUPPORT" = "yes"; then
|
||||
AC_CHECK_HEADERS([sys/ipc.h], [], [IPC_SUPPORT=no])
|
||||
AC_CHECK_HEADERS([sys/msg.h], [], [IPC_SUPPORT=no])
|
||||
AC_CHECK_HEADERS([sys/param.h])
|
||||
if test "$IPC_SUPPORT" = "yes"; then
|
||||
AC_CHECK_FUNCS([msgget], [], [IPC_SUPPORT=no])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$IPC_SUPPORT" = "yes"; then
|
||||
AC_DEFINE([HAVE_IPC], [1], [IPC support enabled])
|
||||
fi
|
||||
|
||||
if test "$SPLICE_SUPPORT" = "yes"; then
|
||||
AC_CHECK_FUNCS([splice])
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/src/include"
|
||||
|
||||
dnl This must go after all the compiler based tests above.
|
||||
AC_LANG_WERROR
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
po/Makefile.in
|
||||
Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
-171
@@ -1,171 +0,0 @@
|
||||
This package is free software, and is being distributed under the terms
|
||||
of the Artistic License 2.0.
|
||||
|
||||
----------------------------------------------------------
|
||||
|
||||
Artistic License 2.0
|
||||
|
||||
Copyright (c) 2000-2006, The Perl Foundation.
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license document, but changing it is not allowed. Preamble
|
||||
|
||||
This license establishes the terms under which a given free software
|
||||
Package may be copied, modified, distributed, and/or redistributed. The
|
||||
intent is that the Copyright Holder maintains some artistic control
|
||||
over the development of that Package while still keeping the Package
|
||||
available as open source and free software.
|
||||
|
||||
You are always permitted to make arrangements wholly outside of this
|
||||
license directly with the Copyright Holder of a given Package. If the
|
||||
terms of this license do not permit the full use that you propose to
|
||||
make of the Package, you should contact the Copyright Holder and seek
|
||||
a different licensing arrangement. Definitions
|
||||
|
||||
"Copyright Holder" means the individual(s) or organization(s) named in
|
||||
the copyright notice for the entire Package.
|
||||
|
||||
"Contributor" means any party that has contributed code or other material
|
||||
to the Package, in accordance with the Copyright Holder's procedures.
|
||||
|
||||
"You" and "your" means any person who would like to copy, distribute,
|
||||
or modify the Package.
|
||||
|
||||
"Package" means the collection of files distributed by the Copyright
|
||||
Holder, and derivatives of that collection and/or of those files. A given
|
||||
Package may consist of either the Standard Version, or a Modified Version.
|
||||
|
||||
"Distribute" means providing a copy of the Package or making it accessible
|
||||
to anyone else, or in the case of a company or organization, to others
|
||||
outside of your company or organization.
|
||||
|
||||
"Distributor Fee" means any fee that you charge for Distributing this
|
||||
Package or providing support for this Package to another party. It does
|
||||
not mean licensing fees.
|
||||
|
||||
"Standard Version" refers to the Package if it has not been modified,
|
||||
or has been modified only in ways explicitly requested by the Copyright
|
||||
Holder.
|
||||
|
||||
"Modified Version" means the Package, if it has been changed, and such
|
||||
changes were not explicitly requested by the Copyright Holder.
|
||||
|
||||
"Original License" means this Artistic License as Distributed with the
|
||||
Standard Version of the Package, in its current version or as it may be
|
||||
modified by The Perl Foundation in the future.
|
||||
|
||||
"Source" form means the source code, documentation source, and
|
||||
configuration files for the Package.
|
||||
|
||||
"Compiled" form means the compiled bytecode, object code, binary, or any
|
||||
other form resulting from mechanical transformation or translation of
|
||||
the Source form. Permission for Use and Modification Without Distribution
|
||||
|
||||
(1) You are permitted to use the Standard Version and create and use
|
||||
Modified Versions for any purpose without restriction, provided that you
|
||||
do not Distribute the Modified Version. Permissions for Redistribution
|
||||
of the Standard Version
|
||||
|
||||
(2) You may Distribute verbatim copies of the Source form of the Standard
|
||||
Version of this Package in any medium without restriction, either gratis
|
||||
or for a Distributor Fee, provided that you duplicate all of the original
|
||||
copyright notices and associated disclaimers. At your discretion, such
|
||||
verbatim copies may or may not include a Compiled form of the Package.
|
||||
|
||||
(3) You may apply any bug fixes, portability changes, and other
|
||||
modifications made available from the Copyright Holder. The resulting
|
||||
Package will still be considered the Standard Version, and as such will
|
||||
be subject to the Original License. Distribution of Modified Versions
|
||||
of the Package as Source
|
||||
|
||||
(4) You may Distribute your Modified Version as Source (either gratis
|
||||
or for a Distributor Fee, and with or without a Compiled form of the
|
||||
Modified Version) provided that you clearly document how it differs
|
||||
from the Standard Version, including, but not limited to, documenting
|
||||
any non-standard features, executables, or modules, and provided that
|
||||
you do at least ONE of the following:
|
||||
|
||||
(a) make the Modified Version available to the Copyright Holder of the
|
||||
Standard Version, under the Original License, so that the Copyright Holder
|
||||
may include your modifications in the Standard Version.
|
||||
(b) ensure that installation of your Modified Version does not prevent the
|
||||
user installing or running the Standard Version. In addition, the Modified
|
||||
Version must bear a name that is different from the name of the Standard
|
||||
Version.
|
||||
(c) allow anyone who receives a copy of the Modified Version to make
|
||||
the Source form of the Modified Version available to others under
|
||||
(i) the Original License or
|
||||
(ii) a license that permits the licensee to freely copy, modify and
|
||||
redistribute the Modified Version using the same licensing terms that apply
|
||||
to the copy that the licensee received, and requires that the Source form of
|
||||
the Modified Version, and of any works derived from it, be made freely
|
||||
available in that license fees are prohibited but Distributor Fees are
|
||||
allowed. Distribution of Compiled Forms of the Standard Version or Modified
|
||||
Versions without the Source
|
||||
|
||||
(5) You may Distribute Compiled forms of the Standard Version without
|
||||
the Source, provided that you include complete instructions on how to
|
||||
get the Source of the Standard Version. Such instructions must be valid
|
||||
at the time of your distribution. If these instructions, at any time
|
||||
while you are carrying out such distribution, become invalid, you must
|
||||
provide new instructions on demand or cease further distribution. If
|
||||
you provide valid instructions or cease distribution within thirty days
|
||||
after you become aware that the instructions are invalid, then you do
|
||||
not forfeit any of your rights under this license.
|
||||
|
||||
(6) You may Distribute a Modified Version in Compiled form without the
|
||||
Source, provided that you comply with Section 4 with respect to the
|
||||
Source of the Modified Version. Aggregating or Linking the Package
|
||||
|
||||
(7) You may aggregate the Package (either the Standard Version or
|
||||
Modified Version) with other packages and Distribute the resulting
|
||||
aggregation provided that you do not charge a licensing fee for the
|
||||
Package. Distributor Fees are permitted, and licensing fees for other
|
||||
components in the aggregation are permitted. The terms of this license
|
||||
apply to the use and Distribution of the Standard or Modified Versions
|
||||
as included in the aggregation.
|
||||
|
||||
(8) You are permitted to link Modified and Standard Versions with other
|
||||
works, to embed the Package in a larger work of your own, or to build
|
||||
stand-alone binary or bytecode versions of applications that include the
|
||||
Package, and Distribute the result without restriction, provided the
|
||||
result does not expose a direct interface to the Package. Items That
|
||||
are Not Considered Part of a Modified Version
|
||||
|
||||
(9) Works (including, but not limited to, modules and scripts) that
|
||||
merely extend or make use of the Package, do not, by themselves, cause
|
||||
the Package to be a Modified Version. In addition, such works are not
|
||||
considered parts of the Package itself, and are not subject to the terms
|
||||
of this license. General Provisions
|
||||
|
||||
(10) Any use, modification, and distribution of the Standard or Modified
|
||||
Versions is governed by this Artistic License. By using, modifying or
|
||||
distributing the Package, you accept this license. Do not use, modify,
|
||||
or distribute the Package, if you do not accept this license.
|
||||
|
||||
(11) If your Modified Version has been derived from a Modified Version
|
||||
made by someone other than you, you are nevertheless required to ensure
|
||||
that your Modified Version complies with the requirements of this license.
|
||||
|
||||
(12) This license does not grant you the right to use any trademark,
|
||||
service mark, tradename, or logo of the Copyright Holder.
|
||||
|
||||
(13) This license includes the non-exclusive, worldwide, free-of-charge
|
||||
patent license to make, have made, use, offer to sell, sell, import
|
||||
and otherwise transfer the Package with respect to any patent claims
|
||||
licensable by the Copyright Holder that are necessarily infringed by the
|
||||
Package. If you institute patent litigation (including a cross-claim or
|
||||
counterclaim) against any party alleging that the Package constitutes
|
||||
direct or contributory patent infringement, then this Artistic License
|
||||
to you shall terminate on the date that such litigation is filed.
|
||||
|
||||
(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
|
||||
HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT
|
||||
PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER
|
||||
OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
|
||||
CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------
|
||||
@@ -1,336 +0,0 @@
|
||||
1.6.19 - 5 September 2021
|
||||
- fix: starting pv in the background no longer immediately stops unless
|
||||
the transfer is to/from the terminal (Andriy Gapon, Jonathan Elchison)
|
||||
- fix: using -B, -A, or -T now switches on -C implicitly
|
||||
(Johannes Gerer, André Stapf)
|
||||
- fix: AIX build fixes (Peter Korsgaard)
|
||||
- i18n: updated German "--help" translations (Richard Fonfara)
|
||||
- i18n: switched to UTF-8 encoding, added missing translations (de,fr,pt)
|
||||
- docs: new "common switches" manual section (Jacek Wielemborek)
|
||||
- docs: use placeholder instead of /dev/sda in the manual (Pranav Peshwe)
|
||||
- docs: mention MacOS pipes and "-B 1024" in the manual (Jan Venekamp)
|
||||
- docs: correct shell in autoconf/scripts/index.sh (Juan Picca)
|
||||
- cleanup: various compiler warnings cleaned up
|
||||
|
||||
Full changelog is below:
|
||||
- (r181) added common switches section to manual (Jacek Wielemborek)
|
||||
- (r184) use placeholder instead of /dev/sda in the manual (Pranav Peshwe)
|
||||
- (r185) replace ash with sh in autoconf/scripts/index.sh (Juan Picca)
|
||||
- (r185) added note to manual about "-B 1024" in MacOS pipes (Jan Venekamp)
|
||||
- (r185) fix AIX config check when the CWD contains "yes" (Peter Korsgaard)
|
||||
- (r189) (#1556) updated German "--help" translations (Richard Fonfara)
|
||||
- (r189) updated missing German translations and changed to UTF-8 encoding
|
||||
- (r191) updated missing French translations and changed to UTF-8 encoding
|
||||
- (r193) updated missing Portuguese translations, changed to UTF-8 encoding
|
||||
- (r196) (#1563) using -B, -A, or -T now switches on -C implicitly
|
||||
(Johannes Gerer, André Stapf)
|
||||
- (r199) fixed numerous compiler warnings in newer GCC versions
|
||||
- (r200,205) fixed bug where "pv /dev/zero >/dev/null &" stopped
|
||||
immediately (Jonathan Elchison, Andriy Gapon)
|
||||
- (r203,205) marked unused arguments with GCC unused attribute, started
|
||||
using boolean data type for flags, corrected more compiler warnings
|
||||
|
||||
1.6.6 - 30 June 2017
|
||||
- (r161) use %llu instead of %Lu for better compatibility (Eric A. Borisch)
|
||||
- (r162) (#1532) fix target buffer size (-B) being ignored (AndCycle, Ilya
|
||||
Basin, Antoine Beaupré)
|
||||
- (r164) cap read/write sizes, and check elapsed time during read/write
|
||||
cycles, to avoid display hangs with large buffers or slow media; also
|
||||
remove select() call from repeated_write function as it slows the
|
||||
transfer down and the wrapping alarm() means it is unnecessary
|
||||
- (r169) (#1477) use alternate form for transfer counter, such that 13GB
|
||||
is shown as 13.0GB so it's the same width as 13.1GB (André Stapf)
|
||||
- (r171) cleanup: units corrections in man page, of the form kb -> KiB
|
||||
- (r175) report error in "-d" if process fd directory is unreadable, or if
|
||||
process disappears before we start the main loop (Jacek Wielemborek)
|
||||
|
||||
1.6.0 - 15 March 2015
|
||||
- fix lstat64 support when unavailable - separate patches supplied by
|
||||
Ganael Laplanche and Peter Korsgaard
|
||||
- (#1506) new option "-D" / "--delay-start" to only show bar after N
|
||||
seconds (Damon Harper)
|
||||
- new option "--fineta" / "-I" to show ETA as time of day rather than time
|
||||
remaining - patch supplied by Erkki Seppälä (r147)
|
||||
- (#1509) change ETA (--eta / -e) so that days are given if the hours
|
||||
remaining are 24 or more (Jacek Wielemborek)
|
||||
- (#1499) repeat read and write attempts on partial buffer fill/empty to
|
||||
work around post-signal transfer rate drop reported by Ralf Ramsauer
|
||||
- (#1507) do not try to calculate total size in line mode, due to bug
|
||||
reported by Jacek Wielemborek and Michiel Van Herwegen
|
||||
- cleanup: removed defunct RATS comments and unnecessary copyright notices
|
||||
- clean up displayed lines when using --watchfd PID, when PID exits
|
||||
- output errors on a new line to avoid overwriting transfer bar
|
||||
|
||||
1.5.7 - 26 August 2014
|
||||
- show KiB instead of incorrect kiB (Debian bug #706175)
|
||||
- (#1284) do not gzip man page, for non-Linux OSes (Bob Friesenhahn)
|
||||
- work around "awk" bug in tests/016-numeric-timer in decimal "," locales
|
||||
- fix "make rpm" and "make srpm", extend "make release" to sign releases
|
||||
|
||||
1.5.3 - 4 May 2014
|
||||
- remove SPLICE_F_NONBLOCK to fix problem with slow splice() (Jan Seda)
|
||||
|
||||
1.5.2 - 10 February 2014
|
||||
- allow "--watchfd" to look at block devices
|
||||
- let "--watchfd PID:FD" work with "--size N"
|
||||
- moved contributors out of the manual as the list was too long
|
||||
(NB everyone is still listed in the README and always will be)
|
||||
|
||||
1.5.1 - 23 January 2014
|
||||
- new option "--watchfd" - suggested by Jacek Wielemborek and "fdwatch"
|
||||
- use non-block flag with splice()
|
||||
- new display option "--buffer-percent", suggested by Kim Krecht
|
||||
- new display option "--last-written", suggested by Kim Krecht
|
||||
- new transfer option "--no-splice"
|
||||
- fix for minor bug which dropped display elements after one empty one
|
||||
- fix for single fd leak on exit (Cristian Ciupitu)
|
||||
|
||||
1.4.12 - 5 August 2013
|
||||
- new option "--null" - patch supplied by Zing Shishak
|
||||
- AIX build fix (add "-lc128") - with help from Pawel Piatek
|
||||
- AIX "-c" fixes - with help from Pawel Piatek
|
||||
- SCO build fix (po2table.sh) - reported by Wouter Pronk
|
||||
- test scripts fix for older distributions - patch from Bryan Dongray
|
||||
- fix for splice() not using stdin - patch from Zev Weiss
|
||||
|
||||
1.4.6 - 22 January 2013
|
||||
- added patch from Pawel Piatek to omit O_NOFOLLOW in AIX
|
||||
|
||||
1.4.5 - 10 January 2013
|
||||
- updated manual page to show known problem with "-R" on Cygwin
|
||||
|
||||
1.4.4 - 11 December 2012
|
||||
- added debugging, see `pv -h' when configure run with "--enable-debugging"
|
||||
- rewrote cursor positioning code used when IPC is unavailable (Cygwin)
|
||||
- fixed cursor positioning cursor read answerback problem (Cygwin/Solaris)
|
||||
- fixed bug causing crash when progress displayed with too-small terminal
|
||||
|
||||
1.4.0 - 6 December 2012
|
||||
- new option "--skip-errors" commissioned by Jim Salter
|
||||
- if stdout is a block device, and we don't know the total size, use the
|
||||
size of that block device as the total (Peter Samuelson)
|
||||
- new option "--stop-at-size" to stop after "--size" bytes
|
||||
- report correct filename on read errors
|
||||
- fix use-after-free bug in remote PID cleanup code
|
||||
- refactored large chunks of code to make it more readable and to replace
|
||||
most static variables with a state structure
|
||||
|
||||
1.3.9 - 5 November 2012
|
||||
- allow "--format" parameters to be sent with "--remote"
|
||||
- configure option "--disable-ipc"
|
||||
- added tests for --numeric with --timer and --bytes
|
||||
- added tests for --remote
|
||||
|
||||
1.3.8 - 29 October 2012
|
||||
- new "--pidfile" option to save process ID to a file
|
||||
- integrated patch for --numeric with --timer and --bytes (Sami Liedes)
|
||||
- removed signalling from --remote to prevent accidental process kills
|
||||
- new "--format" option (originally Vladimir Pal / Vladimir Ermakov)
|
||||
|
||||
1.3.4 - 27 June 2012
|
||||
- new "--disable-splice" configure script option
|
||||
- fixed line mode size count with multiple files (Moritz Barsnick)
|
||||
- fixes for AIX core dumps (Pawel Piatek)
|
||||
|
||||
1.3.1 - 9 June 2012
|
||||
- do not use splice() if the write buffer is not empty (Thomas Rachel)
|
||||
- added test 15 (pipe transfers), and new test script
|
||||
|
||||
1.3.0 - 5 June 2012
|
||||
- added Tiger build patch from Olle Jonsson
|
||||
- fix 1024-boundary display garble (Debian bug #586763)
|
||||
- use splice(2) where available (Debian bug #601683)
|
||||
- added known bugs section of the manual page
|
||||
- fixed average rate test, 12 (Andrew Macheret)
|
||||
- use IEEE1541 units (Thomas Rachel)
|
||||
- bug with rate limit under 10 fixed (Henry Precheur)
|
||||
- speed up PV line mode (patch: Guillaume Marcais)
|
||||
- remove LD=ld from vars.mk to fix cross-compilation (paintitgray/PV#1291)
|
||||
|
||||
1.2.0 - 14 December 2010
|
||||
- integrated improved SI prefixes and --average-rate (Henry Gebhardt)
|
||||
- return nonzero if exiting due to SIGTERM (Martin Baum)
|
||||
- patch from Phil Rutschman to restore terminal properly on exit
|
||||
- fix i18n especially for --help (Sebastian Kayser)
|
||||
- refactored pv_display
|
||||
- we now have a coherent, documented, exit status
|
||||
- modified pipe test and new cksum test from Sebastian Kayser
|
||||
- default CFLAGS to just "-O" for non-GCC (Kjetil Torgrim Homme)
|
||||
- LFS compile fix for OS X 10.4 (Alexandre de Verteuil)
|
||||
- remove DESTDIR / suffix (Sam Nelson, Daniel Pape)
|
||||
- fixed potential NULL deref in transfer (Elias Pipping / LLVM/Clang)
|
||||
|
||||
1.1.4 - 6 March 2008
|
||||
- patch from Elias Pipping correcting compilation failure on Darwin 9
|
||||
- patch from Patrick Collison correcting similar problems on OS X
|
||||
- trap SIGINT/SIGHUP/SIGTERM so we clean up IPCs on exit (Laszlo Ersek)
|
||||
- abort if numeric option, eg -L, has non-numeric value (Boris Lohner)
|
||||
|
||||
1.1.0 - 30 August 2007
|
||||
- new option --remote (-R) to control an already-running process
|
||||
- new option --line-mode (-l) to count lines instead of bytes
|
||||
- fix for "-L" to be less resource intensive
|
||||
- fix for input/output equivalence check on Mac OS X
|
||||
- fix for size calculation in pipelines on Mac OS X
|
||||
- fixed "make uninstall"
|
||||
- removed /debian directory at request of new Debian maintainer
|
||||
|
||||
1.0.1 - 4 August 2007
|
||||
- licensing change from Artistic to Artistic 2.0
|
||||
- removed the "-l" / "--license" option
|
||||
|
||||
1.0.0 - 2 August 2007
|
||||
- act more like "cat" - just skip unreadable files, don't abort
|
||||
- removed text version of manual page, and obsolete Info file generation
|
||||
- code cleanup and separation of PV internals from CLI front-end
|
||||
|
||||
0.9.9 - 5 February 2007
|
||||
- new option --buffer-size (-B) suggested by Mark Tomich
|
||||
- build fix: HP/UX largefile compile fix from Timo Savinen
|
||||
- maintain better buffer filling during transfers
|
||||
- workaround: pv /dev/zero | dd bs=1M count=1k bug (reported by Gert Menke)
|
||||
- dropped support for the Texinfo manual
|
||||
|
||||
0.9.6 - 27 February 2006
|
||||
- bugfix: key_t incompatibility with Cygwin
|
||||
- bugfix: interval (-i) parameter parses numbers after decimal point
|
||||
- build fix: use static NLS if msgfmt is unavailable
|
||||
- on the final update, blank out the now-zero ETA
|
||||
|
||||
0.9.2 - 1 September 2005
|
||||
- Daniel Roethlisberger patch: use lockfiles if terminal locking fails
|
||||
|
||||
0.9.1 - 16 June 2005
|
||||
- minor RPM spec file fix for Fedora Core 4
|
||||
|
||||
0.9.0 - 15 November 2004
|
||||
- minor NLS bugfix
|
||||
|
||||
0.8.9 - 6 November 2004
|
||||
- decimal values now accepted for rate and size, eg "-L 1.23M"
|
||||
- code cleanup
|
||||
- developers: "make help" now lists Makefile targets
|
||||
|
||||
0.8.6 - 29 June 2004
|
||||
- use uu_lock() for terminal locking on FreeBSD
|
||||
|
||||
0.8.5 - 2 May 2004
|
||||
- cursor positioning (-c) reliability improved on systems with IPC
|
||||
- minor fix: made test 005 more reliable
|
||||
- new option --height (-H)
|
||||
|
||||
0.8.2 - 24 April 2004
|
||||
- allow k,m,g,t suffixes on numbers
|
||||
- added "srpm" and "release" Makefile targets
|
||||
|
||||
0.8.1 - 19 April 2004
|
||||
- bugfix in cursor positioning (-c)
|
||||
|
||||
0.8.0 - 12 February 2004
|
||||
- replaced GNU getopt with my library code
|
||||
- replaced GNU gettext with my very minimal replacement
|
||||
- use DESTDIR instead of RPM_BUILD_ROOT for optional installation prefix
|
||||
- looked for flaws using RATS, cleaned up code
|
||||
|
||||
0.7.0 - 8 February 2004
|
||||
- display buffer management fixes (thanks Cédric Delfosse)
|
||||
- replaced --enable-debug with --enable-debugging and --enable-profiling
|
||||
|
||||
0.6.4 - 14 January 2004
|
||||
- fixed minor bug in RPM installation
|
||||
- bugfix in "make index" (only of interest to developers)
|
||||
|
||||
0.6.3 - 22 December 2003
|
||||
- fixed transient bug that reported "resource unavailable" occasionally
|
||||
|
||||
0.6.2 - 6 August 2003
|
||||
- block devices now have their size read correctly, so pv /dev/hda1 works
|
||||
- minor code cleanups (mainly removal of CVS "Id" tags)
|
||||
|
||||
0.6.0 - 3 August 2003
|
||||
- doing ^Z then "bg" then "fg" now continues displaying
|
||||
|
||||
0.5.9 - 23 July 2003
|
||||
- fix for test 007 when not in C locale
|
||||
- fix for build process to use CPPFLAGS
|
||||
- fix for build process to use correct i18n libraries
|
||||
- fix for build process - more portable sed in dependency generator
|
||||
- fix for install process - remember to mkinstalldirs before installing
|
||||
- fixes for building on Mac OS X
|
||||
|
||||
0.5.3 - 4 May 2003
|
||||
- added Polish translation thanks to Bartosz Feñski
|
||||
<fenio@o2.pl> <http://skawina.eu.org/> and Krystian Zubel
|
||||
- moved doc/debian to ./debian at insistence of common sense
|
||||
- minor Solaris 8 compatibility fixes
|
||||
- seems to compile and test OK on Mac OS X
|
||||
|
||||
0.5.0 - 15 April 2003
|
||||
- added French translation thanks to Stéphane Lacasse
|
||||
<stephane@gorfou.ca>
|
||||
- added German translation thanks to Marcos Kreinacke
|
||||
<public@kreinacke.com>
|
||||
- switched LGPL reference from "Library" to "Lesser"
|
||||
|
||||
0.4.9 - 18 February 2003
|
||||
- support for >2GB files added where available (Debian bug #180986)
|
||||
- added doc/debian dir (from Cédric Delfosse)
|
||||
- added "make rpm" and "make deb" targets to build RPM and Debian packages
|
||||
- added a "make pv-static" rule to build a statically linked version
|
||||
|
||||
0.4.5 - 13 December 2002
|
||||
- added Portuguese (Brazilian) translation thanks to Eduardo Aguiar
|
||||
|
||||
0.4.4 - 7 December 2002
|
||||
- pause/resume support - don't count time while stopped
|
||||
- stop output when resumed in the background
|
||||
- terminal size change support
|
||||
- bugfix: <=> indicator no longer sticks at right hand edge
|
||||
|
||||
0.4.0 - 27 November 2002
|
||||
- allow decimal interval values, eg 0.1, 0.5, etc
|
||||
- some simple tests added (`make check')
|
||||
- smoother throughput limiting (--rate-limit), now done in 0.1sec chunks
|
||||
- bounds-check interval values (-i) - max update interval now 10 minutes
|
||||
- more reliable non-blocking output to keep display updated
|
||||
- no longer rely on atoll()
|
||||
- don't output final blank line if --numeric
|
||||
- use fcntl() instead of flock() for Solaris compatibility
|
||||
|
||||
0.3.0 - 25 November 2002
|
||||
- handle broken output pipe gracefully
|
||||
- continue updating display even when output pipe is blocking
|
||||
|
||||
0.2.6 - 21 October 2002
|
||||
- we now ignore EINTR on select()
|
||||
- variable-size buffer (still need to add code to change size)
|
||||
- added (tentative) support for internationalisation
|
||||
- removed superfluous --no-progress, etc options
|
||||
- optimised transfer by using bigger buffers, based on st_blksize
|
||||
- added --wait option to wait until transfer begins before showing progress
|
||||
- added --rate-limit option to limit rate to a maximum throughput
|
||||
- added --quiet option (no output at all) to be used with --rate-limit
|
||||
|
||||
0.2.5 - 23 July 2002
|
||||
- added [FILE]... arguments, like `cat'
|
||||
- function separation in code
|
||||
- some bug fixes related to numeric overflow
|
||||
|
||||
0.2.3 - 19 July 2002
|
||||
- Texinfo manual written, man page updated
|
||||
- byte counter added
|
||||
|
||||
0.2.0 - 18 July 2002
|
||||
- ETA counter added
|
||||
- screen width estimation added
|
||||
- progress bar added
|
||||
|
||||
0.1.0 - 17 July 2002
|
||||
- main loop created
|
||||
- rate counter added
|
||||
- elapsed time counter added
|
||||
- percentage calculation added
|
||||
|
||||
0.0.1 - 16 July 2002
|
||||
- package created
|
||||
- first draft of man page written
|
||||
@@ -1 +0,0 @@
|
||||
pv
|
||||
@@ -1,59 +0,0 @@
|
||||
Things still to do:
|
||||
|
||||
- store terminal state in shm seg (Lars Ellenberg - Feb 2018)
|
||||
- (as above) fix race condition with multiple "pv -c" (Viktor Ashirov - Jan 2020, Lars Ellenberg)
|
||||
- (#1287) if the first pv exits, should the second become IPC leader?
|
||||
- option to show bits/sec instead of bytes (John W. O'Brien - Jan 2019)
|
||||
- option for alternate units like kB (x1000) (David Henderson [cliquesoft.org] - Dec 2018)
|
||||
- (same as above) option to make input suffixes decimal not binary (ie kb rather than KiB)
|
||||
- allow decimal values for -s, -L, -B (suggestion - Thomas Watson)
|
||||
- allow -E to take a block size argument so errors cause a skip to the
|
||||
next block (Anthony DeRobertis)
|
||||
- (#1559) momentary ETA option (Luc Gommans)
|
||||
- (#1557) use clock_gettime() in ETA calculation (Mateju Miroslav)
|
||||
- (#1561) show days in same format in ETA as in elapsed time
|
||||
- (#1562) allow -r with -l and -n to output lines/sec (Roland Kletzing)
|
||||
- document zsh <() incompatibility (frederik@ofb.net - Frederik Eaton)
|
||||
- apply patch for MacOS 11 (Apple Silicon) stat64 issue (Filippo Valsorda)
|
||||
- do not check terminal in -q/-n mode (zsh <(pv -n) fails)
|
||||
- if -w/-H was specified, ignore SIGWINCH
|
||||
- reset ETA on SIGUSR1 (Jacek Wielemborek - Jan 2019)
|
||||
- option to enable O_DIRECT (Romain Kang, Jacek Wielemborek)
|
||||
- use posix_fadvise() like cat(1) does (Jacek Wielemborek)
|
||||
- before exit, flush output (e.g. writing to USB disk), update counters during flush (Kalin KOZHUHAROV - Jun 2018)
|
||||
- permit -c with -d PID:FD, reject -N with -d PID (Norman Rasmussen)
|
||||
- (#1508) add watchfd tests
|
||||
- (#1554) allow multiple -d options (Linus Heckemann for multiple PID:FD)
|
||||
- (#1553) one-shot option (Jacek Wielemborek)
|
||||
- (#1505) option to switch rate to per minute if really slow
|
||||
- (#1510) option "--progress-from FILE", read last number and use it as bytes read:
|
||||
pv --progress-from <( while sleep 1; do du -sb somedir; done ) -s 123g
|
||||
(Jacek Wielemborek)
|
||||
- (#1476) (Debian #507682) adjustable averaging window for rate display
|
||||
- (#1286) option for process title (Martin Sarsale) as "pv - name:FooProcess -xyz - transferred: 1.3GB - 500KB/s - running: 10:15:30s"
|
||||
- (#1290) look at effect of O_SYNC or fsync on performance
|
||||
- (#1281) option (-x?) to use xterm title line for status (Joachim Haga)
|
||||
- (#1560) use Unicode for more granular progress bar (Alexander Petrossian)
|
||||
- show fd backwards reads more neatly than negative huge numbers
|
||||
- "swallow" option to discard output (André Stapf - Apr 2017)
|
||||
- differentiate "eta" from "fineta" in display (André Stapf - Apr 2017)
|
||||
- continue timer even if input or output is blocking (Martin Probst - Jun 2017)
|
||||
- incorporate ETA patch from Christoph Biedl - Jul 2017
|
||||
- incorporate dynamic interval patch from Christoph Biedl - Dec 2019
|
||||
- option "--size-file" or similar to use size of a file for "-s"
|
||||
- fix rate limit downgrade as per patch (Stephen Kitt - Jan 2018)
|
||||
- normalise progress to 100% if overrun (Andrej Gantvorg - Mar 2018)
|
||||
- incorporate average rate interval patch "rate-window"/"eta-window" (lemonsqueeze/Matt - May/Sep 2018 - https://github.com/lemonsqueeze/pv)
|
||||
- incorporate rate limit patch (Jered Floyd - Dec 2018)
|
||||
- option --sparse (with block size option) to write sparse output (Andriy Galetski - Apr 2019)
|
||||
- correct "-n" behaviour when going past 100% of "-s" size (Marcel - Nov 2018)
|
||||
- option to show speed gauge (% max speed) if progress not known (Ryan Cooley - Jun 2019)
|
||||
- look at
|
||||
https://www.reddit.com/r/unix/comments/6gxduc/how_is_gnu_yes_so_fast/diua761/
|
||||
|
||||
- add development support for http://clang-analyzer.llvm.org/
|
||||
- stats for avg/min/max/stddev throughput (Venky.N.Iyer)
|
||||
- pv-ify a command line (Will Entriken) - "pv FOO | BAR | BAZ"
|
||||
- get more translations
|
||||
|
||||
Any assistance would be appreciated.
|
||||
@@ -1 +0,0 @@
|
||||
1.6.19
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
Begin3
|
||||
Title: @PACKAGE@
|
||||
Version: @VERSION@
|
||||
Entered-date: 05SEP21
|
||||
Description: A tool for monitoring the progress of data through a
|
||||
pipeline. It can be inserted into any normal pipeline
|
||||
between two processes to give a visual indication of how
|
||||
quickly data is passing through, how long it has taken, how
|
||||
near to completion it is, and an estimate of how long it
|
||||
will be until completion.
|
||||
Keywords: progress bar, console, pipe, transfer rate
|
||||
Author: Andrew Wood <andrew.wood@ivarch.com>
|
||||
Maintained-by: Andrew Wood <andrew.wood@ivarch.com>
|
||||
Primary-site: http://www.ivarch.com/programs/@PACKAGE@.shtml
|
||||
Alternate-site:
|
||||
Original-site:
|
||||
Platforms:
|
||||
Copying-policy: Artistic 2.0
|
||||
End
|
||||
@@ -1,20 +0,0 @@
|
||||
Before releasing a new version, go through this checklist:
|
||||
|
||||
- check for patches from http://packages.qa.debian.org/p/pv.html
|
||||
- bump doc/VERSION
|
||||
- bump doc/lsm.in
|
||||
- check doc/NEWS is up to date
|
||||
- check doc/spec.in is up to date (changelog)
|
||||
- check manual is up to date
|
||||
- make indent indentclean
|
||||
- make update-po
|
||||
- make test
|
||||
- commit to SVN
|
||||
- wipe build directory, re-run generate.sh and configure
|
||||
- make release
|
||||
- make manhtml | tidy -asxhtml | sed -e '1,/<body>/d' -e '/<\/body>/,$d'
|
||||
- update HTML for todo and news
|
||||
- copy and sign tar.gz to HTML directory (sig as both .asc and .txt)
|
||||
- submit new release to Sourceforge
|
||||
- upload HTML
|
||||
- check validator results for project page and manual
|
||||
-263
@@ -1,263 +0,0 @@
|
||||
Summary: Monitor the progress of data through a pipe
|
||||
Name: @PACKAGE@
|
||||
Version: @VERSION@
|
||||
Release: 1%{?dist}
|
||||
License: Artistic 2.0
|
||||
Group: Development/Tools
|
||||
Source: http://www.ivarch.com/programs/sources/@PACKAGE@-@VERSION@.tar.gz
|
||||
Url: http://www.ivarch.com/programs/pv.shtml
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: gettext
|
||||
|
||||
%description
|
||||
PV ("Pipe Viewer") is a tool for monitoring the progress of data through a
|
||||
pipeline. It can be inserted into any normal pipeline between two processes
|
||||
to give a visual indication of how quickly data is passing through, how long
|
||||
it has taken, how near to completion it is, and an estimate of how long it
|
||||
will be until completion.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
%configure
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT"
|
||||
mkdir -p "$RPM_BUILD_ROOT"%{_bindir}
|
||||
mkdir -p "$RPM_BUILD_ROOT"%{_mandir}/man1
|
||||
mkdir -p "$RPM_BUILD_ROOT"/usr/share/locale
|
||||
|
||||
make DESTDIR="$RPM_BUILD_ROOT" install
|
||||
%find_lang %{name}
|
||||
|
||||
%check
|
||||
make test
|
||||
|
||||
%clean
|
||||
[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT"
|
||||
|
||||
%files -f %{name}.lang
|
||||
%defattr(-, root, root)
|
||||
%{_bindir}/%{name}
|
||||
%{_mandir}/man1/%{name}.1.gz
|
||||
|
||||
%doc README doc/NEWS doc/TODO doc/COPYING
|
||||
|
||||
%changelog
|
||||
* Sun Sep 5 2021 Andrew Wood <andrew.wood@ivarch.com> 1.6.19-1
|
||||
- fix: starting pv in the background no longer immediately stops unless
|
||||
- the transfer is to/from the terminal (Andriy Gapon, Jonathan Elchison)
|
||||
- fix: using -B, -A, or -T now switches on -C implicitly
|
||||
- (Johannes Gerer, André Stapf)
|
||||
- fix: AIX build fixes (Peter Korsgaard)
|
||||
- i18n: updated German "--help" translations (Richard Fonfara)
|
||||
- i18n: switched to UTF-8 encoding, added missing translations (de,fr,pt)
|
||||
- docs: new "common switches" manual section (Jacek Wielemborek)
|
||||
- docs: use placeholder instead of /dev/sda in the manual (Pranav Peshwe)
|
||||
- docs: mention MacOS pipes and "-B 1024" in the manual (Jan Venekamp)
|
||||
- docs: correct shell in autoconf/scripts/index.sh (Juan Picca)
|
||||
- cleanup: various compiler warnings cleaned up
|
||||
|
||||
* Fri Jun 30 2017 Andrew Wood <andrew.wood@ivarch.com> 1.6.6-1
|
||||
- (r161) use %llu instead of %Lu for better compatibility (Eric A. Borisch)
|
||||
- (r162) (#1532) fix target buffer size (-B) being ignored (AndCycle, Ilya
|
||||
- Basin, Antoine Beaupré)
|
||||
- (r164) cap read/write sizes, and check elapsed time during read/write
|
||||
- cycles, to avoid display hangs with large buffers or slow media; also
|
||||
- remove select() call from repeated_write function as it slows the
|
||||
- transfer down and the wrapping alarm() means it is unnecessary
|
||||
- (r169) (#1477) use alternate form for transfer counter, such that 13GB
|
||||
- is shown as 13.0GB so it's the same width as 13.1GB (André Stapf)
|
||||
- (r171) cleanup: units corrections in man page, of the form kb -> KiB
|
||||
- (r175) report error in "-d" if process fd directory is unreadable, or if
|
||||
- process disappears before we start the main loop (Jacek Wielemborek)
|
||||
|
||||
* Sun Mar 15 2015 Andrew Wood <andrew.wood@ivarch.com> 1.6.0-1
|
||||
- fix lstat64 support when unavailable - separate patches supplied by Ganael
|
||||
- Laplanche and Peter Korsgaard
|
||||
- (#1506) new option "-D" / "--delay-start" to only show bar after N seconds
|
||||
- (Damon Harper)
|
||||
- new option "--fineta" / "-I" to show ETA as time of day rather than time
|
||||
- remaining - patch supplied by Erkki Seppälä (r147)
|
||||
- (#1509) change ETA (--eta / -e) so that days are given if the hours
|
||||
- remaining are 24 or more (Jacek Wielemborek)
|
||||
- (#1499) repeat read and write attempts on partial buffer fill/empty to
|
||||
- work around post-signal transfer rate drop reported by Ralf Ramsauer
|
||||
- (#1507) do not try to calculate total size in line mode, due to bug
|
||||
- reported by Jacek Wielemborek and Michiel Van Herwegen
|
||||
- cleanup: removed defunct RATS comments and unnecessary copyright notices
|
||||
- clean up displayed lines when using --watchfd PID, when PID exits
|
||||
- output errors on a new line to avoid overwriting transfer bar
|
||||
|
||||
* Tue Aug 26 2014 Andrew Wood <andrew.wood@ivarch.com> 1.5.7-1
|
||||
- show KiB instead of incorrect kiB (Debian bug #706175)
|
||||
- (#1284) do not gzip man page, for non-Linux OSes (Bob Friesenhahn)
|
||||
- work around "awk" bug in tests/016-numeric-timer in decimal "," locales
|
||||
- fix "make rpm" and "make srpm", extend "make release" to sign releases
|
||||
|
||||
* Sun May 4 2014 Andrew Wood <andrew.wood@ivarch.com> 1.5.3-1
|
||||
- remove SPLICE_F_NONBLOCK to fix problem with slow splice() (Jan Seda)
|
||||
|
||||
* Mon Feb 10 2014 Andrew Wood <andrew.wood@ivarch.com> 1.5.2-1
|
||||
- allow "--watchfd" to look at block devices
|
||||
- let "--watchfd PID:FD" work with "--size N"
|
||||
- moved contributors out of the manual as the list was too long
|
||||
- (NB everyone is still listed in the README and always will be)
|
||||
|
||||
* Thu Jan 23 2014 Andrew Wood <andrew.wood@ivarch.com> 1.5.1-1
|
||||
- new option "--watchfd" - suggested by Jacek Wielemborek and "fdwatch"
|
||||
- use non-block flag with splice()
|
||||
- new display option "--buffer-percent", suggested by Kim Krecht
|
||||
- new display option "--last-written", suggested by Kim Krecht
|
||||
- new transfer option "--no-splice"
|
||||
- fix for minor bug which dropped display elements after one empty one
|
||||
- fix for single fd leak on exit (Cristian Ciupitu, Josh Stone)
|
||||
|
||||
* Mon Aug 5 2013 Andrew Wood <andrew.wood@ivarch.com> 1.4.12-1
|
||||
- new option "--null" - patch supplied by Zing Shishak
|
||||
- AIX build fix (add "-lc128") - with help from Pawel Piatek
|
||||
- AIX "-c" fixes - with help from Pawel Piatek
|
||||
- SCO build fix (po2table.sh) - reported by Wouter Pronk
|
||||
- test scripts fix for older distributions - patch from Bryan Dongray
|
||||
- fix for splice() not using stdin - patch from Zev Weiss
|
||||
|
||||
* Tue Jan 22 2013 Andrew Wood <andrew.wood@ivarch.com> 1.4.6-1
|
||||
- added patch from Pawel Piatek to omit O_NOFOLLOW in AIX
|
||||
|
||||
* Thu Jan 10 2013 Andrew Wood <andrew.wood@ivarch.com> 1.4.5-1
|
||||
- updated manual page to show known problem with "-R" on Cygwin
|
||||
|
||||
* Tue Dec 11 2012 Andrew Wood <andrew.wood@ivarch.com> 1.4.4-1
|
||||
- added debugging, see `pv -h' when configure run with "--enable-debugging"
|
||||
- rewrote cursor positioning code used when IPC is unavailable (Cygwin)
|
||||
- fixed cursor positioning cursor read answerback problem (Cygwin/Solaris)
|
||||
- fixed bug causing crash when progress displayed with too-small terminal
|
||||
|
||||
* Thu Dec 6 2012 Andrew Wood <andrew.wood@ivarch.com> 1.4.0-1
|
||||
- new option "--skip-errors" commissioned by Jim Salter
|
||||
- if stdout is a block device, and we don't know the total size, use the
|
||||
- size of that block device as the total (Peter Samuelson)
|
||||
- new option "--stop-at-size" to stop after "--size" bytes
|
||||
- report correct filename on read errors
|
||||
- fix use-after-free bug in remote PID cleanup code
|
||||
- refactored large chunks of code to make it more readable and to replace
|
||||
- most static variables with a state structure
|
||||
|
||||
* Mon Nov 5 2012 Andrew Wood <andrew.wood@ivarch.com> 1.3.9-1
|
||||
- allow "--format" parameters to be sent with "--remote"
|
||||
- configure option "--disable-ipc"
|
||||
- added tests for --numeric with --timer and --bytes
|
||||
- added tests for --remote
|
||||
|
||||
* Mon Oct 29 2012 Andrew Wood <andrew.wood@ivarch.com> 1.3.8-1
|
||||
- new "--pidfile" option to save process ID to a file
|
||||
- integrated patch for --numeric with --timer and --bytes (Sami Liedes)
|
||||
- removed signalling from --remote to prevent accidental process kills
|
||||
- new "--format" option (originally Vladimir Pal / Vladimir Ermakov)
|
||||
|
||||
* Wed Jun 27 2012 Andrew Wood <andrew.wood@ivarch.com> 1.3.4-1
|
||||
- new "--disable-splice" configure script option
|
||||
- fixed line mode size count with multiple files (Moritz Barsnick)
|
||||
- fixes for AIX core dumps (Pawel Piatek)
|
||||
|
||||
* Sat Jun 9 2012 Andrew Wood <andrew.wood@ivarch.com> 1.3.1-1
|
||||
- do not use splice() if the write buffer is not empty (Thomas Rachel)
|
||||
- added test 15 (pipe transfers), and new test script
|
||||
|
||||
* Tue Jun 5 2012 Andrew Wood <andrew.wood@ivarch.com> 1.3.0-1
|
||||
- added Tiger build patch from Olle Jonsson.
|
||||
- fix 1024-boundary display garble (Debian bug #586763).
|
||||
- use splice(2) where available (Debian bug #601683).
|
||||
- added known bugs section of the manual page.
|
||||
- fixed average rate test, 12 (Andrew Macheret).
|
||||
- use IEEE1541 units (Thomas Rachel).
|
||||
- bug with rate limit under 10 fixed (Henry Precheur).
|
||||
- speed up PV line mode (patch: Guillaume Marcais).
|
||||
- remove LD=ld from vars.mk to fix cross-compilation (paintitgray/PV#1291).
|
||||
|
||||
* Tue Dec 14 2010 Andrew Wood <andrew.wood@ivarch.com> 1.2.0-1
|
||||
- Integrated improved SI prefixes and --average-rate (Henry Gebhardt).
|
||||
- Return nonzero if exiting due to SIGTERM (Martin Baum).
|
||||
- Patch from Phil Rutschman to restore terminal properly on exit.
|
||||
- Fix i18n especially for --help (Sebastian Kayser).
|
||||
- Refactored pv_display.
|
||||
- We now have a coherent, documented, exit status.
|
||||
- Modified pipe test and new cksum test from Sebastian Kayser.
|
||||
- Default CFLAGS to just "-O" for non-GCC (Kjetil Torgrim Homme).
|
||||
- LFS compile fix for OS X 10.4 (Alexandre de Verteuil).
|
||||
- Remove DESTDIR / suffix (Sam Nelson, Daniel Pape).
|
||||
- Fixed potential NULL deref in transfer (Elias Pipping / LLVM/Clang).
|
||||
|
||||
* Thu Mar 6 2008 Andrew Wood <andrew.wood@ivarch.com> 1.1.4-1
|
||||
- Trap SIGINT/SIGHUP/SIGTERM so we clean up IPCs on exit (Laszlo Ersek).
|
||||
- Abort if numeric option, eg -L, has non-numeric value (Boris Lohner).
|
||||
- Compilation fixes for Darwin 9 and OS X.
|
||||
|
||||
* Thu Aug 30 2007 Andrew Wood <andrew.wood@ivarch.com> 1.1.0-1
|
||||
- New option "-R" to remotely control another @PACKAGE@ process.
|
||||
- New option "-l" to count lines instead of bytes.
|
||||
- Performance improvement for "-L" (rate) option.
|
||||
- Some Mac OS X fixes, and packaging cleanups.
|
||||
|
||||
* Sat Aug 4 2007 Andrew Wood <andrew.wood@ivarch.com> 1.0.1-1
|
||||
- Changed license from Artistic to Artistic 2.0.
|
||||
- Removed "--license" option.
|
||||
|
||||
* Thu Aug 2 2007 Andrew Wood <andrew.wood@ivarch.com> 1.0.0-1
|
||||
- We now act more like "cat" - just skip unreadable files, don't abort.
|
||||
- Various code cleanups were done.
|
||||
|
||||
* Mon Feb 5 2007 Andrew Wood <andrew.wood@ivarch.com> 0.9.9-1
|
||||
- New option "-B" to set the buffer size, and a workaround for problems
|
||||
- piping to dd(1).
|
||||
|
||||
* Mon Feb 27 2006 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Minor bugfixes, and on the final update, blank out the now-zero ETA.
|
||||
|
||||
* Thu Sep 1 2005 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Terminal locking now uses lockfiles if the terminal itself cannot be locked.
|
||||
|
||||
* Thu Jun 16 2005 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- A minor problem with the spec file was fixed.
|
||||
|
||||
* Mon Nov 15 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- A minor bug in the NLS code was fixed.
|
||||
|
||||
* Sat Nov 6 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Code cleanups and minor usability fixes.
|
||||
|
||||
* Tue Jun 29 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- A port of the terminal locking code to FreeBSD.
|
||||
|
||||
* Sun May 2 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Major reliability improvements to the cursor positioning.
|
||||
|
||||
* Sat Apr 24 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Rate and size parameters can now take suffixes such as "k", "m" etc.
|
||||
|
||||
* Mon Apr 19 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- A bug in the cursor positioning was fixed.
|
||||
|
||||
* Thu Feb 12 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Code cleanups and portability fixes.
|
||||
|
||||
* Sun Feb 8 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- The display buffer is now dynamically allocated, fixing an overflow bug.
|
||||
|
||||
* Wed Jan 14 2004 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- A minor bug triggered when installing the RPM was fixed.
|
||||
|
||||
* Mon Dec 22 2003 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Fixed a minor bug that occasionally reported "resource unavailable".
|
||||
|
||||
* Wed Aug 6 2003 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Block devices now have their size read correctly, so pv /dev/hda1 works
|
||||
- Minor code cleanups (mainly removal of CVS "Id" tags)
|
||||
|
||||
* Sun Aug 3 2003 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- Doing ^Z then "bg" then "fg" now continues displaying
|
||||
|
||||
* Tue Jul 16 2002 Andrew Wood <andrew.wood@ivarch.com>
|
||||
- First draft of spec file created.
|
||||
@@ -0,0 +1,91 @@
|
||||
The following people have contributed to this project, and their assistance
|
||||
is acknowledged and greatly appreciated:
|
||||
|
||||
* Antoine Beaupré <anarcat@debian.org> - Debian package maintainer
|
||||
* Kevin Coyner <kcoyner@debian.org> - previous Debian package maintainer
|
||||
* Cédric Delfosse <cedric@debian.org> - previous Debian package maintainer
|
||||
* Jakub Hrozek <jhrozek@redhat.com> - Fedora package maintainer
|
||||
* Eduardo Aguiar <eduardo.oliveira@sondabrasil.com.br> - provided Portuguese (Brazilian) translation
|
||||
* Stéphane Lacasse <stephane@gorfou.ca> - provided French translation
|
||||
* Marcos Kreinacke <public@kreinacke.com> - provided German translation
|
||||
* Bartosz Feński <fenio@o2.pl> <http://skawina.eu.org/> - provided Polish translation along with Krystian Zubel
|
||||
* Joshua Jensen - reported RPM installation bug
|
||||
* Boris Folgmann <http://www.folgmann.com/en/> - reported cursor handling bug
|
||||
* Mathias Gumz - reported NLS bug
|
||||
* Daniel Roethlisberger - submitted patch to use lockfiles for "`-c`" if terminal locking fails
|
||||
* Adam Buchbinder - lots of help with a Cygwin port of "`-c`"
|
||||
* Mark Tomich <http://metuchen.dyndns.org> - suggested "`-B`" option
|
||||
* Gert Menke - reported bug when piping to `dd` with a large input buffer size
|
||||
* Ville Herva <Ville.Herva@iki.fi> - informative bug report about rate limiting performance
|
||||
* Elias Pipping - patch to compile properly on Darwin 9; potential NULL deref report
|
||||
* Patrick Collison - similar patch for OS X
|
||||
* Boris Lohner - reported problem that "`-L`" does not complain if given non-numeric value
|
||||
* Sebastian Kayser - supplied testing for *SIGPIPE*, demonstrated internationalisation problem
|
||||
* Laszlo Ersek <http://phptest11.atw.hu/> - reported shared memory leak on *SIGINT* with "`-c`"
|
||||
* Phil Rutschman <http://bandgap.rsnsoft.com/> - provided a patch for fully restoring terminal state on exit
|
||||
* Henry Precheur <http://henry.precheur.org/> - reporting and suggestions for "`--rate-limit`" bug when rate is under 10
|
||||
* E. Rosten <http://mi.eng.cam.ac.uk/~er258/> - supplied patch for block buffering in line mode
|
||||
* Kjetil Torgrim Homme - reported compilation error with default *CFLAGS* on non-GCC compilers
|
||||
* Alexandre de Verteuil - reported bug in OS X build and supplied test environment to fix in
|
||||
* Martin Baum - supplied patch to return nonzero exit status if terminated by signal
|
||||
* Sam Nelson <http://www.siliconfuture.net/> - supplied patch to fix trailing slash on *DESTDIR*
|
||||
* Daniel Pape - reported Cygwin installation problem due to *DESTDIR*
|
||||
* Philipp Beckers - ported to the Syabas PopcornHour A-100 series
|
||||
* Henry Gebhard <hsggebhardt@googlemail.com> - supplied patches to improve SI prefixes and add "`--average-rate`"
|
||||
* Vladimir Kokarev, Alexander Leo - reported that exit status did not reflect file errors
|
||||
* Thomas Rachel - submitted patches for IEEE1541 (MiB suffixes), 1+e03 bug
|
||||
* Guillaume Marcais - submitted speedup patch for line mode
|
||||
* Moritz Barsnick - submitted patch for compile warning in size calculation
|
||||
* Pawel Piatek - submitted RPM and patches for AIX
|
||||
* Sami Liedes - submitted patch for "`--timer`" and "`--bytes`" with "`--numeric`"
|
||||
* Steven Willis - reported problem with "`-R`" killing non-PV remote processes
|
||||
* Vladimir Pal, Vladimir Ermakov - submitted patch which led to development of "`--format`" option
|
||||
* Peter Samuelson <peter@p12n.org> - submitted patch to calculate size if stdout is a block device
|
||||
* Miguel Diaz - much Cygwin help (and packaging), found narrow-terminal bug
|
||||
* Jim Salter <http://ubuntuwiki.net> - commissioned work on the "`--skip-errors`" option
|
||||
* Wouter Pronk - reported build problem on SCO
|
||||
* Bryan Dongray <http://www.dongrays.com> - provided patches for test scripts failing on older Red Hats
|
||||
* Zev Weiss <www.bewilderbeest.net> - provided patch to fix `splice()` not using stdin
|
||||
* Zing Shishak - provided patch for "`--null`" / "`-0`" (count null terminated lines)
|
||||
* Jacek Wielemborek <http://deetah.jogger.pl/kategorie/english> - implemented fdwatch in Python, suggested PV port; reported bug with "`-l`" and ETA / size; many other contributions
|
||||
* Kim Krecht - suggested buffer fill status and last bytes output display options
|
||||
* Cristian Ciupitu <http://ciupicri.github.io>, Josh Stone - pointed out file descriptor leak with helpful suggestions (Josh Stone initially noticed the missing close)
|
||||
* Jan Seda - found issue with `splice()` and *SPLICE_F_NONBLOCK* causing slowdown
|
||||
* André Stapf - pointed out formatting problem e.g. 13GB -> 13.1GB which should be shown 13.0GB -> 13.1GB; highlighted on-startup row swapping in "`-c`", and suggested "`--discard`"
|
||||
* Damon Harper <http://www.usrbin.ca/> - suggested "`-D`" / "`--delay-start`" option
|
||||
* Ganaël Laplanche <http://www.martymac.org> - provided patch for `lstat64()` on systems that do not support it
|
||||
* Peter Korsgaard <http://www.buildroot.net/> - provided similar patch for `lstat64()`, specifically for uClibc support; provided AIX cross-compilation patch to fix bug in "`-lc128`" check
|
||||
* Ralf Ramsauer <https://blog.ramses-pyramidenbau.de/> - reported bug which dropped transfer rate on terminal resize
|
||||
* Michiel Van Herwegen - reported and discussed bug with "`-l`" and ETA / size
|
||||
* Erkki Seppälä <http://www.inside.org/~flux/> - provided patch implementing "`-I`"
|
||||
* Eric A. Borisch - provided details of compatibility fix for "`%Lu`" in watchpid code
|
||||
* Jan Venekamp - reported MacOS buffer size interactions with pipes
|
||||
* Matt <https://github.com/lemonsqueeze/pv> - provided "rate-window" patches for rate calculation
|
||||
* [Filippo Valsorda](https://github.com/FiloSottile) - provided patch for stat64 issue on Apple Silicon
|
||||
* Matt Koscica, William Dillon - also reported stat64 issue on Apple Silicon
|
||||
* [Demitri Muna](https://github.com/demitri) - assisted with stat64 patch on Apple Silicon
|
||||
* Norman Rasmussen - suggested "`-c`" with "`-d PID:FD`", reject "`-N`" with "`-d PID`"
|
||||
* Andriy Gapon, Jonathan Elchison - reported bug where "`pv /dev/zero >/dev/null &`" stops immediately
|
||||
* Marcelo Chiesa - reported unused-result warnings when compiling PV 1.6.6
|
||||
* Jered Floyd - provided patches to improve "`--rate-limit`"
|
||||
* Christoph Biedl - provided ETA and dynamic interval patches
|
||||
* Richard Fonfara - provided German translations for "`pv --help`"
|
||||
* Johannes Gerer <http://johannesgerer.com> - suggested that "`-B`" should enable "`-C`"
|
||||
* Sam James - provided fix for number.c build issue caused by missing stddef.h
|
||||
* Jakub Wilk <jwilk@jwilk.net> - corrected README encoding
|
||||
* Frederik Eaton - reported issue with `<()` shell constructs
|
||||
* [gray](https://github.com/gray) - reported issue with "`--force`" and terminal process groups, and proposed a patch
|
||||
* [Luc Gommans](https://github.com/lgommans) / https://lgms.nl/ - provided a "momentary ETA" patch
|
||||
* [ikasty](https://github.com/ikasty) - added relative filename display to "`--watchfd`"
|
||||
* [Michael Weiß](https://github.com/quitschbo) - corrected behaviour when not attached to a terminal
|
||||
* [christoph-zededa](https://github.com/christoph-zededa) - provided OS X support for "`--watchfd`"
|
||||
* [Dave Beckett](https://github.com/dajobe) - added "`@filename`" syntax to "`--size`", and corrected an autoconf problem with stat64 on OS X
|
||||
* [Volodymyr Bychkovyak](https://github.com/vbychkoviak) - provided fix for rate limit behaviour with bursty traffic
|
||||
* [Nick Black](https://nick-black.com) - added "`--bits`" option
|
||||
* [Andrew Schulman](https://github.com/andrew-schulman) - provided reproducible example of terminal size detection issue in 1.7.17/1.7.18
|
||||
* [fuschia74](https://github.com/fuchsia74) - provided "`--enable-static`" patch for "`configure`"
|
||||
* [Wilhelm von Thiele](https://github.com/TurtleWilly) - assisted with OS X cleanups ([#73](https://codeberg.org/a-j-wood/pv/issues/73), [#74](https://codeberg.org/a-j-wood/pv/issues/74))
|
||||
* Matějů Miroslav, Ing. - suggested fix for ETA and elapsed time faults when suspending and resuming a machine ([#13](https://codeberg.org/a-j-wood/pv/issues/13))
|
||||
* Anthony DeRobertis - suggested the "`--error-skip-block`" option ([#37](https://codeberg.org/a-j-wood/pv/issues/37))
|
||||
|
||||
---
|
||||
+674
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,136 @@
|
||||
# Notes for developers and translators
|
||||
|
||||
The following "`configure`" options will be of interest to developers and
|
||||
translators:
|
||||
|
||||
* `--enable-debugging` - build in debugging support
|
||||
* `--enable-profiling` - build in support for profiling
|
||||
|
||||
These "`make`" targets are available:
|
||||
|
||||
* `make analyse` - run _splint_ and _flawfinder_ on all C source files
|
||||
|
||||
|
||||
## Debugging and profiling support
|
||||
|
||||
When "`./configure --enable-debugging`" is used, the "`pv`" produced by
|
||||
"`make`" will support an extra option, "`--debug FILE`", which will cause
|
||||
debugging output to be written to *FILE*. This is not recommended for
|
||||
production builds due to the extra processing it introduces, and the
|
||||
potential size of the output.
|
||||
|
||||
Within the code, "`debug()`" is used in a similar way to "`printf()`". It
|
||||
will automatically include the calling function, source file, and line
|
||||
number, so they don't need to be included in the parameters. When debugging
|
||||
support is not enabled, it evaluates to a null statement.
|
||||
|
||||
This does mean that if you call "`debug()`", make sure it has no side
|
||||
effects, as they won't be present in builds without debugging support.
|
||||
|
||||
Builds produced after "`./configure --enable-profiling`" will write profile
|
||||
data when run, to be used with _gprof_. See "`man gprof`" for details.
|
||||
Please note that the memory safety checks will fail with profiling enabled.
|
||||
|
||||
|
||||
## Source code analysis
|
||||
|
||||
Running "`make analyse`" runs _splint_ and _flawfinder_ on all C sources,
|
||||
writing the output of both programs to files named "`*.e`" for each "`*.c`".
|
||||
|
||||
There are no dependency rules set up for these "`.e`" files, so if a header
|
||||
file is altered, manually remove the relevant "`.e`" files, or update the
|
||||
timestamp of the relevant "`.c`" files, before running "`make analyse`"
|
||||
again.
|
||||
|
||||
The goal is for all C source files to generate zero warnings from either
|
||||
tool.
|
||||
|
||||
Wherever warnings are disabled by annotations to the source, there should be
|
||||
associated commentary nearby explaining the rationale behind it, and any
|
||||
assumptions made. This is so that there can be some assurance that the
|
||||
issue highlighted by the analyser has been considered properly, as well as
|
||||
documenting anything that might need further work if the surrounding code is
|
||||
altered in future.
|
||||
|
||||
|
||||
## Translation notes
|
||||
|
||||
The message catalogues used to translate program messages into other
|
||||
languages are in the "`po/`" directory, named "`xx.po`", where "`xx`"
|
||||
is the ISO 639-1 2-letter language code, such as "`fr`" for French.
|
||||
|
||||
Each of these files contains lines like this:
|
||||
|
||||
#: src/pv/cursor.c:85
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "erro ao ler o nome do terminal"
|
||||
|
||||
The comment line, starting "`#`", shows the source filename and line number
|
||||
at which this message can be found. The "`msgid`" is the original message
|
||||
in the program, in English. The "`msgstr`" is the translated text.
|
||||
|
||||
It is the "`msgstr`" lines which need to be updated by translators.
|
||||
|
||||
Message catalogue files should all be encoded as UTF-8.
|
||||
|
||||
_FIXME: The test below doesn't work on Debian with only en_GB installed, and
|
||||
also it looks like the compiled-in LOCALEDIR is overriding LOCPATH._
|
||||
|
||||
After making a change to a "`.po`" file, test it by compiling it and installing
|
||||
to a temporary location, like this:
|
||||
|
||||
make install DESTDIR=/tmp/yourtest
|
||||
localedef -f UTF-8 -i de_DE /tmp/yourtest/usr/local/share/locale/de_DE.UTF-8
|
||||
LOCPATH=/tmp/yourtest/usr/local/share/locale \
|
||||
LC_ALL=de_DE.UTF-8 ./pv --help
|
||||
|
||||
Replace "`--help`" with whatever is appropriate for your test. In this
|
||||
example, the language being tested is "`de`" (German), on a system which is
|
||||
running with UTF-8 support.
|
||||
|
||||
To add a new language, create the new message catalogue file under "`po/`"
|
||||
by copying "`po/pv.pot`" to "`po/xx.po`", where "`xx`" is the language code,
|
||||
and adjusting it. The "`.pot`" file is generated automatically by "`make`".
|
||||
|
||||
Next, add the language code to "`po/LINGUAS`" - this is a list of the
|
||||
2-letter codes of the supported languages.
|
||||
|
||||
Finally, run "`./config.status`" and "`make -C po update-po`".
|
||||
|
||||
When the source code is updated, running "`make -C po update-po`" will
|
||||
update the "`pv.pot`" file so that it lists where all the messages are in
|
||||
the source. It will also use _msgmerge_ to update all of the "`.po`" files
|
||||
from the updated "`pv.pot`" file. After doing this, look for missing
|
||||
translations (empty "`msgstr`" lines) or translations marked as "fuzzy", as
|
||||
these will need to be corrected by translators.
|
||||
|
||||
|
||||
## Release checklist
|
||||
|
||||
The package maintainer should run through these steps for a new release:
|
||||
|
||||
* Check for patches and bug reports at https://tracker.debian.org/pkg/pv
|
||||
* Run "`make indent; make indent indentclean check`"
|
||||
* Run "`make -C po update-po`"
|
||||
* Run "`make analyse`" and see whether remaining warnings can be addressed
|
||||
* Version bump and documentation checks:
|
||||
* Update the version in `configure.ac` and `docs/NEWS.md`
|
||||
* Check that `docs/NEWS.md` is up to date
|
||||
* Check that `docs/TODO.md` is up to date
|
||||
* Check that the manual `docs/pv.1` is up to date
|
||||
* Run "`make docs/pv.1.md`" and, if using VPATH, copy the result to the source directory
|
||||
* Ensure everything has been committed to the repository
|
||||
* Run "`autoreconf`" in the source directory
|
||||
* Consistency and build checks:
|
||||
* Wipe the build directory, and run "`configure`" there
|
||||
* Run "`make distcheck`"
|
||||
* Run "`./configure && make check`" on all test systems including Cygwin, using the `tar.gz` that was just created
|
||||
* Run "`make release MAINTAINER=<signing-user>`"
|
||||
* Update the project web site:
|
||||
* Copy the release `.tar.gz`, `.txt`, and `.asc` files to the web site
|
||||
* Use "`pandoc --from markdown --to html`" to convert the TODO, news, and manual to HTML
|
||||
* Update the TODO, news, and manual on the web site
|
||||
* Update the version numbers on the web site
|
||||
* Update the package index on the web site
|
||||
* Create a new release in the repository, and apply the associated tag
|
||||
|
||||
+472
@@ -0,0 +1,472 @@
|
||||
### 1.8.0 - 24 September 2023
|
||||
|
||||
#### Features
|
||||
|
||||
* feature: new "`--discard`" option to discard input as if writing to */dev/null* ([#42](https://codeberg.org/a-j-wood/pv/issues/42))
|
||||
* feature: new "`--error-skip-block`" option to make "`--skip-errors`" skip whole blocks ([#37](https://codeberg.org/a-j-wood/pv/issues/37))
|
||||
* feature: use `posix_fadvise()` like `cat`(1) does, to improve efficiency ([#39](https://codeberg.org/a-j-wood/pv/issues/39))
|
||||
* feature: new "`--enable-static`" option to "`configure`" for static builds ([#75](https://codeberg.org/a-j-wood/pv/pull/75))
|
||||
|
||||
#### Security
|
||||
|
||||
* security: with "`--pidfile`", write to a temporary file and rename it into place, to improve security
|
||||
* security: keep self-contained copies of name and format string in PV internal state for memory safety
|
||||
* security: ignore _TMP_ / _TMPDIR_ environment variables when using a terminal lock file
|
||||
|
||||
#### Fixes
|
||||
|
||||
* fix: only report errors about missing files when starting to transfer from them, not while calculating size, and behave more like `cat`(1) by skipping them and moving on
|
||||
* fix: auto-calculate total line count with "`--line-mode`" when all inputs are regular files
|
||||
* fix: use `clock_gettime()` in ETA calculation to cope with machine suspend/resume ([#13](https://codeberg.org/a-j-wood/pv/issues/13))
|
||||
* fix: if "`--width`" or "`--height`" were provided, do not change them when the window size changes ([#36](https://codeberg.org/a-j-wood/pv/issues/36))
|
||||
* fix: when a file descriptor position in "`--watchfd`" moves backwards, show the rate using the correct prefix ([#41](https://codeberg.org/a-j-wood/pv/issues/41))
|
||||
* fix: rewrite terminal state save/restore so state is not intermittently garbled on exit when using "`--cursor`" ([#20](https://codeberg.org/a-j-wood/pv/issues/20)), ([#24](https://codeberg.org/a-j-wood/pv/issues/24))
|
||||
|
||||
#### Cleanups
|
||||
|
||||
* cleanup: addressed many potential issues highlighted by the software auditing tools "`splint`" and "`flawfinder`" (see new target "`make analyse`")
|
||||
* cleanup: switched the build system to GNU Automake
|
||||
* cleanup: replaced the test harness with the one native to GNU Automake
|
||||
* cleanup: added a test for terminal width detection to "`make check`"
|
||||
* cleanup: added a test to "`make check`" to ensure that "`make install`" installs everything expected
|
||||
* cleanup: replaced *AC_HEADER_TIOCGWINSZ* with *AC_CHECK_HEADERS(sys/ioctl.h)* for better MacOS compatibility ([#74](https://codeberg.org/a-j-wood/pv/issues/74))
|
||||
* cleanup: with "`--sync`", call `fsync()` instead of `fdatasync()` on incapable systems ([#73](https://codeberg.org/a-j-wood/pv/issues/73))
|
||||
* cleanup: the manual is now a static file instead of needing to be built with "`configure`"
|
||||
|
||||
#### Dropped items
|
||||
|
||||
* dropped: dropped support for "`--enable-static-nls`"
|
||||
* dropped: removed the Linux Software Map file, as the LSM project appears to be long dead
|
||||
* dropped: will no longer publish to SourceForge as it has a chequered history and is unnecessary
|
||||
* dropped: removed project from GitHub and moved to Codeberg - see "[Give Up GitHub](https://giveupgithub.org/)"
|
||||
|
||||
#### Other items
|
||||
|
||||
* licensing change from Artistic 2.0 to GPLv3+
|
||||
|
||||
### 1.7.24 - 30 July 2023
|
||||
|
||||
* fix: correct terminal size detection, broken in 1.7.17 by the configuration script rewrite ([#72](https://codeberg.org/a-j-wood/pv/issues/72))
|
||||
* security: removed *DEBUG* environment variable in debug mode, added "`--debug`" instead
|
||||
* cleanup: added "`make analyse`" to run "`splint`" and "`flawfinder`" on all source files
|
||||
* cleanup: corrected detection of boolean capability
|
||||
* cleanup: word wrapping of "`--help`" output is now multi-byte locale aware
|
||||
* cleanup: adjusted "`indent`" rules to line length of 120 and reformatted code
|
||||
|
||||
### 1.7.18 - 28 July 2023
|
||||
|
||||
* fix: language file installation had been broken by the configuration script rewrite
|
||||
|
||||
### 1.7.17 - 27 July 2023
|
||||
|
||||
* feature: new "`--sync`" option to flush cache to disk after every write (related to [#6](https://codeberg.org/a-j-wood/pv/issues/6), to improve accuracy when writing to slow disks)
|
||||
* feature: new "`--direct-io`" option to bypass cache - implements [#29 "Option to enable *O_DIRECT*"](https://codeberg.org/a-j-wood/pv/issues/29) - requested by Romain Kang, Jacek Wielemborek
|
||||
* fix: correct byte prefix size to 2 spaces in rate display, so progress display size remains constant at low transfer rates
|
||||
* cleanup: rewrote `configure.in` as per suggestions in newer "`autoconf`" manuals
|
||||
* cleanup: replaced `header.in` with one generated by "`autoheader`", moving custom logic to a separate header file "`config-aux.h`"
|
||||
* cleanup: added copyright notice to all source files as per GNU standards
|
||||
* cleanup: changed "`--version`" output to conform to GNU standards
|
||||
* cleanup: replaced backticks with `$()` in all shell scripts that did not come from elsewhere, as backticks are deprecated and harder to read
|
||||
* cleanup: improved the output formatting of "`make test`"
|
||||
* cleanup: extended the "`make test`" mechanism to allow certain tests to be skipped on platforms that cannot support them
|
||||
* cleanup: skip the "pipe" test (for *SIGPIPE*) if GNU "`head`" is not available, so that "`make test`" on stock OpenBSD 7.3 works
|
||||
* cleanup: added a lot more tests to "`make test`"
|
||||
* cleanup: replace all calls to `sprintf()` and `snprintf()` with a new wrapper function `pv_snprintf()` to improve security and compatibility
|
||||
* cleanup: replace all calls to `strcat()` with a wrapper `pv_strlcat()` to improve security and compatibility
|
||||
* cleanup: replace all `write()` calls to the terminal with a wrapper `pv_write_retry()` for consistency
|
||||
* cleanup: tidy up and fix compilation warning in "`--watchfd`" code
|
||||
* cleanup: rewrote all local shell scripts to pass analysis by [ShellCheck](https://www.shellcheck.net)
|
||||
|
||||
### 1.7.0 - 17 July 2023
|
||||
|
||||
* dropped: support for Red Hat Enterprise Linux and its derivatives has been dropped; removed the RPM spec file, and will no longer build binaries
|
||||
* feature: the "`--size`" option now accepts "`@filename`" to use the size of another file (pull request [#57](https://codeberg.org/a-j-wood/pv/pull/57) supplied by [Dave Beckett](https://github.com/dajobe))
|
||||
* feature: the "`--watchfd`" option is now available on OS X (pull request [#60](https://codeberg.org/a-j-wood/pv/pull/60) supplied by [christoph-zededa](https://github.com/christoph-zededa))
|
||||
* feature: new "`--bits`" option to show bit count instead of byte count (adapted from pull request [#63](https://codeberg.org/a-j-wood/pv/pull/63) supplied by [Nick Black](https://nick-black.com))
|
||||
* feature: new "`--average-rate-window`" option, to set the window over which the average rate is calculated, also used for ETA (modified from pull request [#65](https://codeberg.org/a-j-wood/pv/pull/65) supplied by [lemonsqueeze](https://github.com/lemonsqueeze))
|
||||
* feature: the "`--watchfd`" option will now show relative filenames, if they are under the current directory (pull request [#66](https://codeberg.org/a-j-wood/pv/pull/66) supplied by [ikasty](https://github.com/ikasty))
|
||||
* fix: correction to `pv_in_foreground()` to behave as its comment block says it should, when not on a terminal - corrects [#19 "No output in Arch Linux initcpio after 1.6.6"](https://codeberg.org/a-j-wood/pv/issues/19), [#31 "No output written from inside zsh <() construct"](https://codeberg.org/a-j-wood/pv/issues/31), [#55 "pv Stopped Working in the Background"](https://codeberg.org/a-j-wood/pv/issues/55) (pull request [#64](https://codeberg.org/a-j-wood/pv/pull/64) supplied by [Michael Weiß](https://github.com/quitschbo))
|
||||
* fix: workaround for OS X 11 behaviour in configure script regarding stat64 at compile time (pull request [#57](https://codeberg.org/a-j-wood/pv/pull/57) supplied by [Dave Beckett](https://github.com/dajobe))
|
||||
* fix: workaround for macOS equivalence of stat to stat64 - patches from [Filippo Valsorda](https://github.com/FiloSottile) and [Demitri Muna](https://github.com/demitri), correcting [#33 "Fix compilation problems due to `stat64()` on Apple Silicon"](https://codeberg.org/a-j-wood/pv/issues/33)
|
||||
* fix: add burst rate limit to transfer, so rate limits are not broken by bursty traffic (pull request [#62](https://codeberg.org/a-j-wood/pv/pull/62) supplied by [Volodymyr Bychkovyak](https://github.com/vbychkoviak))
|
||||
* fix: corrected "`--force`" option so it will still output progress when not in the same process group as the owner of the terminal - corrects [#23 "No output with "`-f`" when run in background after 1.6.6"](https://codeberg.org/a-j-wood/pv/issues/23) and helps to correct [#31 "No output written from inside zsh <() construct"](https://codeberg.org/a-j-wood/pv/issues/31)
|
||||
* fix: corrected elapsed time display to show as D:HH:MM:SS after 1 day, like the ETA does - corrects [#16 "Show days in same format in ETA as in elapsed time"](https://codeberg.org/a-j-wood/pv/issues/16)
|
||||
* fix: corrected bug where percentages went down after 100% when in "`--numeric`" mode with a "`--size`" that was too small - corrects [#26 "Correct "`-n`" behaviour when going past 100% of "`-s`" size"](https://codeberg.org/a-j-wood/pv/issues/26)
|
||||
* i18n: recoded Polish translation file to UTF-8
|
||||
* i18n: removed inaccurate fuzzy translation matches
|
||||
* docs: moved all open issues into GitHub and updated the TODO list
|
||||
* docs: renamed README to README.md and altered it to Markdown format
|
||||
* docs: moved contributors from the README to docs/ACKNOWLEDGEMENTS.md
|
||||
* docs: moved TODO to TODO.md and altered it to Markdown format
|
||||
* docs: moved NEWS to NEWS.md, converted it to UTF-8, and altered it to Markdown format
|
||||
|
||||
### 1.6.20 - 12 September 2021
|
||||
|
||||
* fix: add missing `stddef.h` include to `number.c` (Sam James)
|
||||
|
||||
### 1.6.19 - 5 September 2021
|
||||
|
||||
* fix: starting pv in the background no longer immediately stops unless the transfer is to/from the terminal (Andriy Gapon, Jonathan Elchison)
|
||||
* fix: using "`-B`", "`-A`", or "`-T`" now switches on "`-C`" implicitly (Johannes Gerer, André Stapf)
|
||||
* fix: AIX build fixes (Peter Korsgaard)
|
||||
* i18n: updated German "`--help`" translations (Richard Fonfara)
|
||||
* i18n: switched to UTF-8 encoding, added missing translations (de,fr,pt)
|
||||
* docs: new "common switches" manual section (Jacek Wielemborek)
|
||||
* docs: use placeholder instead of `/dev/sda` in the manual (Pranav Peshwe)
|
||||
* docs: mention MacOS pipes and "`-B 1024`" in the manual (Jan Venekamp)
|
||||
* docs: correct shell in `autoconf/scripts/index.sh` (Juan Picca)
|
||||
* cleanup: various compiler warnings cleaned up
|
||||
|
||||
Full changelog is below:
|
||||
|
||||
* (r181) added common switches section to manual (Jacek Wielemborek)
|
||||
* (r184) use placeholder instead of /dev/sda in the manual (Pranav Peshwe)
|
||||
* (r185) replace ash with sh in autoconf/scripts/index.sh (Juan Picca)
|
||||
* (r185) added note to manual about "`-B 1024`" in MacOS pipes (Jan Venekamp)
|
||||
* (r185) fix AIX config check when the CWD contains "yes" (Peter Korsgaard)
|
||||
* (r189) (#1556) updated German "`--help`" translations (Richard Fonfara)
|
||||
* (r189) updated missing German translations and changed to UTF-8 encoding
|
||||
* (r191) updated missing French translations and changed to UTF-8 encoding
|
||||
* (r193) updated missing Portuguese translations, changed to UTF-8 encoding
|
||||
* (r196) (#1563) using "`-B`", "`-A`", or "`-T`" now switches on "`-C`" implicitly (Johannes Gerer, André Stapf)
|
||||
* (r199) fixed numerous compiler warnings in newer GCC versions
|
||||
* (r200,205) fixed bug where "`pv /dev/zero >/dev/null &`" stopped immediately (Jonathan Elchison, Andriy Gapon)
|
||||
* (r203,205) marked unused arguments with GCC unused attribute, started using boolean data type for flags, corrected more compiler warnings
|
||||
|
||||
### 1.6.6 - 30 June 2017
|
||||
|
||||
* (r161) use `%llu` instead of `%Lu` for better compatibility (Eric A. Borisch)
|
||||
* (r162) (#1532) fix target buffer size ("`-B`") being ignored (AndCycle, Ilya Basin, Antoine Beaupré)
|
||||
* (r164) cap read/write sizes, and check elapsed time during read/write cycles, to avoid display hangs with large buffers or slow media; also remove `select()` call from repeated_write function as it slows the transfer down and the wrapping `alarm()` means it is unnecessary
|
||||
* (r169) (#1477) use alternate form for transfer counter, such that 13GB is shown as 13.0GB so it's the same width as 13.1GB (André Stapf)
|
||||
* (r171) cleanup: units corrections in man page, of the form kb -> KiB
|
||||
* (r175) report error in "`-d`" if process fd directory is unreadable, or if process disappears before we start the main loop (Jacek Wielemborek)
|
||||
|
||||
### 1.6.0 - 15 March 2015
|
||||
|
||||
* fix lstat64 support when unavailable - separate patches supplied by Ganael Laplanche and Peter Korsgaard
|
||||
* (#1506) new option "`-D`" / "`--delay-start`" to only show bar after N seconds (Damon Harper)
|
||||
* new option "`--fineta`" / "`-I`" to show ETA as time of day rather than time remaining - patch supplied by Erkki Seppälä (r147)
|
||||
* (#1509) change ETA ("`--eta`" / "`-e`") so that days are given if the hours remaining are 24 or more (Jacek Wielemborek)
|
||||
* (#1499) repeat read and write attempts on partial buffer fill/empty to work around post-signal transfer rate drop reported by Ralf Ramsauer
|
||||
* (#1507) do not try to calculate total size in line mode, due to bug reported by Jacek Wielemborek and Michiel Van Herwegen
|
||||
* cleanup: removed defunct RATS comments and unnecessary copyright notices
|
||||
* clean up displayed lines when using "`--watchfd PID`", when PID exits
|
||||
* output errors on a new line to avoid overwriting transfer bar
|
||||
|
||||
### 1.5.7 - 26 August 2014
|
||||
|
||||
* show KiB instead of incorrect kiB (Debian bug #706175)
|
||||
* (#1284) do not gzip man page, for non-Linux OSes (Bob Friesenhahn)
|
||||
* work around "awk" bug in `tests/016-numeric-timer` in decimal "," locales
|
||||
* fix "`make rpm`" and "`make srpm`", extend "`make release`" to sign releases
|
||||
|
||||
### 1.5.3 - 4 May 2014
|
||||
|
||||
* remove *SPLICE_F_NONBLOCK* to fix problem with slow `splice()` (Jan Seda)
|
||||
|
||||
### 1.5.2 - 10 February 2014
|
||||
|
||||
* allow "`--watchfd`" to look at block devices
|
||||
* let "`--watchfd PID:FD`" work with "`--size N`"
|
||||
* moved contributors out of the manual as the list was too long (NB everyone is still listed in the README and always will be)
|
||||
|
||||
### 1.5.1 - 23 January 2014
|
||||
|
||||
* new option "`--watchfd`" - suggested by Jacek Wielemborek and "fdwatch"
|
||||
* use non-block flag with `splice()`
|
||||
* new display option "`--buffer-percent`", suggested by Kim Krecht
|
||||
* new display option "`--last-written`", suggested by Kim Krecht
|
||||
* new transfer option "`--no-splice`"
|
||||
* fix for minor bug which dropped display elements after one empty one
|
||||
* fix for single fd leak on exit (Cristian Ciupitu)
|
||||
|
||||
### 1.4.12 - 5 August 2013
|
||||
|
||||
* new option "`--null`" - patch supplied by Zing Shishak
|
||||
* AIX build fix (add "`-lc128`") - with help from Pawel Piatek
|
||||
* AIX "`-c`" fixes - with help from Pawel Piatek
|
||||
* SCO build fix (`po2table.sh`) - reported by Wouter Pronk
|
||||
* test scripts fix for older distributions - patch from Bryan Dongray
|
||||
* fix for `splice()` not using stdin - patch from Zev Weiss
|
||||
|
||||
### 1.4.6 - 22 January 2013
|
||||
|
||||
* added patch from Pawel Piatek to omit *O_NOFOLLOW* in AIX
|
||||
|
||||
### 1.4.5 - 10 January 2013
|
||||
|
||||
* updated manual page to show known problem with "`-R`" on Cygwin
|
||||
|
||||
### 1.4.4 - 11 December 2012
|
||||
|
||||
* added debugging, see "`pv -h`" when `configure` is run with "`--enable-debugging`"
|
||||
* rewrote cursor positioning code used when IPC is unavailable (Cygwin)
|
||||
* fixed cursor positioning cursor read answerback problem (Cygwin/Solaris)
|
||||
* fixed bug causing crash when progress displayed with too-small terminal
|
||||
|
||||
### 1.4.0 - 6 December 2012
|
||||
|
||||
* new option "`--skip-errors`" commissioned by Jim Salter
|
||||
* if stdout is a block device, and we don't know the total size, use the size of that block device as the total (Peter Samuelson)
|
||||
* new option "`--stop-at-size`" to stop after "`--size`" bytes
|
||||
* report correct filename on read errors
|
||||
* fix use-after-free bug in remote PID cleanup code
|
||||
* refactored large chunks of code to make it more readable and to replace most static variables with a state structure
|
||||
|
||||
### 1.3.9 - 5 November 2012
|
||||
|
||||
* allow "`--format`" parameters to be sent with "`--remote`"
|
||||
* configure option "`--disable-ipc`"
|
||||
* added tests for "`--numeric`" with "`--timer`" and "`--bytes`"
|
||||
* added tests for "`--remote`"
|
||||
|
||||
### 1.3.8 - 29 October 2012
|
||||
|
||||
* new "`--pidfile`" option to save process ID to a file
|
||||
* integrated patch for "`--numeric`" with "`--timer`" and "`--bytes`" (Sami Liedes)
|
||||
* removed signalling from "`--remote`" to prevent accidental process kills
|
||||
* new "`--format`" option (originally Vladimir Pal / Vladimir Ermakov)
|
||||
|
||||
### 1.3.4 - 27 June 2012
|
||||
|
||||
* new "`--disable-splice`" configure script option
|
||||
* fixed line mode size count with multiple files (Moritz Barsnick)
|
||||
* fixes for AIX core dumps (Pawel Piatek)
|
||||
|
||||
### 1.3.1 - 9 June 2012
|
||||
|
||||
* do not use `splice()` if the write buffer is not empty (Thomas Rachel)
|
||||
* added test 15 (pipe transfers), and new test script
|
||||
|
||||
### 1.3.0 - 5 June 2012
|
||||
|
||||
* added Tiger build patch from Olle Jonsson
|
||||
* fix 1024-boundary display garble (Debian bug #586763)
|
||||
* use `splice`(2) where available (Debian bug #601683)
|
||||
* added known bugs section of the manual page
|
||||
* fixed average rate test, 12 (Andrew Macheret)
|
||||
* use IEEE1541 units (Thomas Rachel)
|
||||
* bug with rate limit under 10 fixed (Henry Precheur)
|
||||
* speed up PV line mode (patch: Guillaume Marcais)
|
||||
* remove `LD=ld` from `vars.mk` to fix cross-compilation (paintitgray/PV#1291)
|
||||
|
||||
### 1.2.0 - 14 December 2010
|
||||
|
||||
* integrated improved SI prefixes and "`--average-rate`" (Henry Gebhardt)
|
||||
* return nonzero if exiting due to *SIGTERM* (Martin Baum)
|
||||
* patch from Phil Rutschman to restore terminal properly on exit
|
||||
* fix i18n especially for "`--help`" (Sebastian Kayser)
|
||||
* refactored `pv_display`
|
||||
* we now have a coherent, documented, exit status
|
||||
* modified pipe test and new cksum test from Sebastian Kayser
|
||||
* default *CFLAGS* to just "`-O`" for non-GCC (Kjetil Torgrim Homme)
|
||||
* LFS compile fix for OS X 10.4 (Alexandre de Verteuil)
|
||||
* remove *DESTDIR* `/` suffix (Sam Nelson, Daniel Pape)
|
||||
* fixed potential NULL deref in transfer (Elias Pipping / LLVM/Clang)
|
||||
|
||||
### 1.1.4 - 6 March 2008
|
||||
|
||||
* patch from Elias Pipping correcting compilation failure on Darwin 9
|
||||
* patch from Patrick Collison correcting similar problems on OS X
|
||||
* trap *SIGINT* / *SIGHUP* / *SIGTERM* so we clean up IPCs on exit (Laszlo Ersek)
|
||||
* abort if numeric option, eg "`-L`", has non-numeric value (Boris Lohner)
|
||||
|
||||
### 1.1.0 - 30 August 2007
|
||||
|
||||
* new option "`--remote`" ("`-R`") to control an already-running process
|
||||
* new option "`--line-mode`" ("`-l`") to count lines instead of bytes
|
||||
* fix for "`-L`" to be less resource intensive
|
||||
* fix for input/output equivalence check on Mac OS X
|
||||
* fix for size calculation in pipelines on Mac OS X
|
||||
* fixed "`make uninstall`"
|
||||
* removed "`/debian`" directory at request of new Debian maintainer
|
||||
|
||||
### 1.0.1 - 4 August 2007
|
||||
|
||||
* licensing change from Artistic to Artistic 2.0
|
||||
* removed the "`-l`" / "`--license`" option
|
||||
|
||||
### 1.0.0 - 2 August 2007
|
||||
|
||||
* act more like "`cat`" - just skip unreadable files, don't abort
|
||||
* removed text version of manual page, and obsolete Info file generation
|
||||
* code cleanup and separation of PV internals from CLI front-end
|
||||
|
||||
### 0.9.9 - 5 February 2007
|
||||
|
||||
* new option "`--buffer-size`" ("`-B`") suggested by Mark Tomich
|
||||
* build fix: HP/UX largefile compile fix from Timo Savinen
|
||||
* maintain better buffer filling during transfers
|
||||
* workaround: "`pv /dev/zero | dd bs=1M count=1k`" bug (reported by Gert Menke)
|
||||
* dropped support for the Texinfo manual
|
||||
|
||||
### 0.9.6 - 27 February 2006
|
||||
|
||||
* bugfix: `key_t` incompatibility with Cygwin
|
||||
* bugfix: interval ("`-i`") parameter parses numbers after decimal point
|
||||
* build fix: use static NLS if `msgfmt` is unavailable
|
||||
* on the final update, blank out the now-zero ETA
|
||||
|
||||
### 0.9.2 - 1 September 2005
|
||||
|
||||
* Daniel Roethlisberger patch: use lockfiles if terminal locking fails
|
||||
|
||||
### 0.9.1 - 16 June 2005
|
||||
|
||||
* minor RPM spec file fix for Fedora Core 4
|
||||
|
||||
### 0.9.0 - 15 November 2004
|
||||
|
||||
* minor NLS bugfix
|
||||
|
||||
### 0.8.9 - 6 November 2004
|
||||
|
||||
* decimal values now accepted for rate and size, eg "`-L 1.23M`"
|
||||
* code cleanup
|
||||
* developers: "`make help`" now lists Makefile targets
|
||||
|
||||
### 0.8.6 - 29 June 2004
|
||||
|
||||
* use `uu_lock()` for terminal locking on FreeBSD
|
||||
|
||||
### 0.8.5 - 2 May 2004
|
||||
|
||||
* cursor positioning ("`-c`") reliability improved on systems with IPC
|
||||
* minor fix: made test 005 more reliable
|
||||
* new option "`--height`" ("`-H`")
|
||||
|
||||
### 0.8.2 - 24 April 2004
|
||||
|
||||
* allow k,m,g,t suffixes on numbers
|
||||
* added "`srpm`" and "`release`" Makefile targets
|
||||
|
||||
### 0.8.1 - 19 April 2004
|
||||
|
||||
* bugfix in cursor positioning ("`-c`")
|
||||
|
||||
### 0.8.0 - 12 February 2004
|
||||
|
||||
* replaced GNU getopt with my library code
|
||||
* replaced GNU gettext with my very minimal replacement
|
||||
* use *DESTDIR* instead of *RPM_BUILD_ROOT* for optional installation prefix
|
||||
* looked for flaws using RATS, cleaned up code
|
||||
|
||||
### 0.7.0 - 8 February 2004
|
||||
|
||||
* display buffer management fixes (thanks Cédric Delfosse)
|
||||
* replaced "`--enable-debug`" with "`--enable-debugging`" and "`--enable-profiling`"
|
||||
|
||||
### 0.6.4 - 14 January 2004
|
||||
|
||||
* fixed minor bug in RPM installation
|
||||
* bugfix in "`make index`" (only of interest to developers)
|
||||
|
||||
### 0.6.3 - 22 December 2003
|
||||
|
||||
* fixed transient bug that reported "resource unavailable" occasionally
|
||||
|
||||
### 0.6.2 - 6 August 2003
|
||||
|
||||
* block devices now have their size read correctly, so "`pv /dev/hda1`" works
|
||||
* minor code cleanups (mainly removal of CVS "Id" tags)
|
||||
|
||||
### 0.6.0 - 3 August 2003
|
||||
|
||||
* doing *^Z* then "`bg`" then "`fg`" now continues displaying
|
||||
|
||||
### 0.5.9 - 23 July 2003
|
||||
|
||||
* fix for test 007 when not in C locale
|
||||
* fix for build process to use *CPPFLAGS*
|
||||
* fix for build process to use correct i18n libraries
|
||||
* fix for build process - more portable sed in dependency generator
|
||||
* fix for install process - remember to `mkinstalldirs` before installing
|
||||
* fixes for building on Mac OS X
|
||||
|
||||
### 0.5.3 - 4 May 2003
|
||||
|
||||
* added Polish translation thanks to Bartosz Feński <fenio@o2.pl> <http://skawina.eu.org/> and Krystian Zubel
|
||||
* moved `doc/debian` to `./debian` at insistence of common sense
|
||||
* minor Solaris 8 compatibility fixes
|
||||
* seems to compile and test OK on Mac OS X
|
||||
|
||||
### 0.5.0 - 15 April 2003
|
||||
|
||||
* added French translation thanks to Stéphane Lacasse <stephane@gorfou.ca>
|
||||
* added German translation thanks to Marcos Kreinacke <public@kreinacke.com>
|
||||
* switched LGPL reference from "Library" to "Lesser"
|
||||
|
||||
### 0.4.9 - 18 February 2003
|
||||
|
||||
* support for >2GB files added where available (Debian bug #180986)
|
||||
* added `doc/debian` dir (from Cédric Delfosse)
|
||||
* added "`make rpm`" and "`make deb`" targets to build RPM and Debian packages
|
||||
* added a "`make pv-static`" rule to build a statically linked version
|
||||
|
||||
### 0.4.5 - 13 December 2002
|
||||
|
||||
* added Portuguese (Brazilian) translation thanks to Eduardo Aguiar
|
||||
|
||||
### 0.4.4 - 7 December 2002
|
||||
|
||||
* pause/resume support - don't count time while stopped
|
||||
* stop output when resumed in the background
|
||||
* terminal size change support
|
||||
* bugfix: "`<=>`" indicator no longer sticks at right hand edge
|
||||
|
||||
### 0.4.0 - 27 November 2002
|
||||
|
||||
* allow decimal interval values, eg 0.1, 0.5, etc
|
||||
* some simple tests added ("`make check`")
|
||||
* smoother throughput limiting ("`--rate-limit`"), now done in 0.1sec chunks
|
||||
* bounds-check interval values ("`-i`") - max update interval now 10 minutes
|
||||
* more reliable non-blocking output to keep display updated
|
||||
* no longer rely on `atoll()`
|
||||
* don't output final blank line if "`--numeric`"
|
||||
* use `fcntl()` instead of `flock()` for Solaris compatibility
|
||||
|
||||
### 0.3.0 - 25 November 2002
|
||||
|
||||
* handle broken output pipe gracefully
|
||||
* continue updating display even when output pipe is blocking
|
||||
|
||||
### 0.2.6 - 21 October 2002
|
||||
|
||||
* we now ignore *EINTR* on `select()`
|
||||
* variable-size buffer (still need to add code to change size)
|
||||
* added (tentative) support for internationalisation
|
||||
* removed superfluous "`--no-progress`", etc options
|
||||
* optimised transfer by using bigger buffers, based on `st_blksize`
|
||||
* added "`--wait`" option to wait until transfer begins before showing progress
|
||||
* added "`--rate-limit`" option to limit rate to a maximum throughput
|
||||
* added "`--quiet`" option (no output at all) to be used with "`--rate-limit`"
|
||||
|
||||
### 0.2.5 - 23 July 2002
|
||||
|
||||
* added *[FILE]...* arguments, like "`cat`"
|
||||
* function separation in code
|
||||
* some bug fixes related to numeric overflow
|
||||
|
||||
### 0.2.3 - 19 July 2002
|
||||
|
||||
* Texinfo manual written, man page updated
|
||||
* byte counter added
|
||||
|
||||
### 0.2.0 - 18 July 2002
|
||||
|
||||
* ETA counter added
|
||||
* screen width estimation added
|
||||
* progress bar added
|
||||
|
||||
### 0.1.0 - 17 July 2002
|
||||
|
||||
* main loop created
|
||||
* rate counter added
|
||||
* elapsed time counter added
|
||||
* percentage calculation added
|
||||
|
||||
### 0.0.1 - 16 July 2002
|
||||
|
||||
* package created
|
||||
* first draft of man page written
|
||||
@@ -0,0 +1,31 @@
|
||||
Things still to do. (#n) indicates the issue tracker number.
|
||||
|
||||
* ([#3](https://codeberg.org/a-j-wood/pv/issues/3)) Option ("`-x`"?) to use xterm title line for status (Joachim Haga)
|
||||
* ([#4](https://codeberg.org/a-j-wood/pv/issues/4)) Option for process title (Martin Sarsale) as "`pv - name:FooProcess -xyz - transferred: 1.3GB - 500KB/s - running: 10:15:30s`"
|
||||
* ([#6](https://codeberg.org/a-j-wood/pv/issues/6)) Look at effect of *O_SYNC* or `fsync` on performance; update counters during buffer flush
|
||||
* ([#9](https://codeberg.org/a-j-wood/pv/issues/9)) Option to switch rate to per minute if really slow
|
||||
* ([#10](https://codeberg.org/a-j-wood/pv/issues/10)) Add watchfd tests
|
||||
* ([#11](https://codeberg.org/a-j-wood/pv/issues/11)) Option "`--progress-from FILE`", read last number and use it as bytes read (Jacek Wielemborek)
|
||||
* ([#12](https://codeberg.org/a-j-wood/pv/issues/12)) Allow multiple "`-d`" options (Linus Heckemann for multiple PID:FD; Jacek Wielemborek)
|
||||
* ([#15](https://codeberg.org/a-j-wood/pv/issues/15)) Use Unicode for more granular progress bar (Alexander Petrossian)
|
||||
* ([#17](https://codeberg.org/a-j-wood/pv/issues/17)) Allow "`-r`" with "`-l`" and "`-n`" to output lines/sec (Roland Kletzing)
|
||||
* ([#22](https://codeberg.org/a-j-wood/pv/issues/22)) Options to skip input and seek on output (Jason A. Pfeil, Feb 2022)
|
||||
* ([#25](https://codeberg.org/a-j-wood/pv/issues/25)) Normalise progress to 100% on overrun (Andrej Gantvorg)
|
||||
* ([#34](https://codeberg.org/a-j-wood/pv/issues/34)) Continue timer even if input or output is blocking (Martin Probst - Jun 2017)
|
||||
* ([#35](https://codeberg.org/a-j-wood/pv/issues/35)) Allow decimal values for "`-s`", "`-L`", "`-B`" (Thomas Watson - Aug 2020)
|
||||
* ([#38](https://codeberg.org/a-j-wood/pv/issues/38)) Reset ETA on *SIGUSR1* (Jacek Wielemborek - Jan 2019)
|
||||
* ([#40](https://codeberg.org/a-j-wood/pv/issues/40)) Permit "`-c`" with "`-d PID:FD`", reject "`-N`" with "`-d PID`" (Norman Rasmussen - Nov 2020)
|
||||
* ([#43](https://codeberg.org/a-j-wood/pv/issues/43)) Differentiate between "`--eta`" and "`--fineta`" in display (André Stapf - Apr 2017)
|
||||
* ([#45](https://codeberg.org/a-j-wood/pv/issues/45)) Option "`--sparse`" (with block size option) to write sparse output (Andriy Galetski - Apr 2019)
|
||||
* ([#46](https://codeberg.org/a-j-wood/pv/issues/46)) Option to show speed gauge (% max speed) if progress not known (Ryan Cooley - Jun 2019)
|
||||
* ([#47](https://codeberg.org/a-j-wood/pv/issues/47)) Analyse splice and buffer usage to improve performance
|
||||
* ([#48](https://codeberg.org/a-j-wood/pv/issues/48)) Option to show multiple files with individual sizes and a cumulative total (Zach Riggle - Jul 2021)
|
||||
* ([#49](https://codeberg.org/a-j-wood/pv/issues/49)) Option to provide stats for avg/min/max/stddev throughput (Venky.N.Iyer)
|
||||
* ([#50](https://codeberg.org/a-j-wood/pv/issues/50)) Allow pv to report on a whole pipeline at once (Will Entriken - Feb 2011)
|
||||
* ([#54](https://codeberg.org/a-j-wood/pv/issues/54)) Run command every n percent ([haarp](https://github.com/haarp))
|
||||
* ([#56](https://codeberg.org/a-j-wood/pv/issues/56)) Support for backgrounding pv, and allowing it to be monitored separately ([jimbobmcgee](https://github.com/jimbobmcgee))
|
||||
* ([#67](https://codeberg.org/a-j-wood/pv/issues/67)) Wrap another process to monitor its stdin & stdout ([Alex Mason](https://github.com/axman6))
|
||||
* ([#76](https://codeberg.org/a-j-wood/pv/issues/76)) Provide a way to test translations without installing
|
||||
* ([#77](https://codeberg.org/a-j-wood/pv/issues/77)) Eliminate all warnings from "splint" and "flawfinder"
|
||||
|
||||
Any assistance would be appreciated.
|
||||
@@ -5,32 +5,32 @@
|
||||
# time, as suggested by Ville Herva <Ville.Herva@iki.fi>.
|
||||
#
|
||||
|
||||
test_input=`mktemp /tmp/pvbench1XXXXXX`
|
||||
strace_output=`mktemp /tmp/pvbench2XXXXXX`
|
||||
test_input=$(mktemp /tmp/pvbench1XXXXXX)
|
||||
strace_output=$(mktemp /tmp/pvbench2XXXXXX)
|
||||
|
||||
trap "rm -f ${test_input} ${strace_output}" 0
|
||||
trap 'rm -f ${test_input} ${strace_output}' EXIT
|
||||
|
||||
pv=${pv:-./pv}
|
||||
test -x ${pv} || pv=pv
|
||||
test -x "${pv}" || pv="pv"
|
||||
|
||||
dd if=/dev/zero of=${test_input} bs=1k count=1k >/dev/null 2>&1
|
||||
dd if=/dev/zero of="${test_input}" bs=1k count=1k >/dev/null 2>&1
|
||||
|
||||
echo -e "Buf(k)\tRate(k)\tReads\tRsize\tWrites\tWsize"
|
||||
|
||||
for ((buffer=100; buffer<=1000; buffer+=100)); do
|
||||
for ((rate=0; rate<=1000; rate+=100)); do
|
||||
for ((rate=100; rate<=1000; rate+=100)); do
|
||||
rateparm="-L ${rate}k"
|
||||
test ${rate} -eq 0 && rateparm=""
|
||||
strace -tt -o ${strace_output} \
|
||||
${pv} ${rateparm} -B ${buffer}k \
|
||||
-f < ${test_input} > /dev/null 2>&1
|
||||
strace -tt -o "${strace_output}" \
|
||||
"${pv}" "${rateparm}" -B "${buffer}k" \
|
||||
-f < "${test_input}" > /dev/null 2>&1
|
||||
rdata=$(
|
||||
awk '$2~/^read\(0,/{c++;t+=$NF}END{print c "\t" t/c}' \
|
||||
${strace_output}
|
||||
"${strace_output}"
|
||||
)
|
||||
wdata=$(
|
||||
awk '$2~/^write\(1,/{c++;t+=$NF}END{print c "\t" t/c}' \
|
||||
${strace_output}
|
||||
"${strace_output}"
|
||||
)
|
||||
echo -e "${buffer}\t${rate}\t${rdata}\t${wdata}"
|
||||
done
|
||||
+211
-101
@@ -1,17 +1,17 @@
|
||||
.TH @UCPACKAGE@ 1 "September 2021" Linux "User Manuals"
|
||||
.TH PV 1 "September 2023" Linux "User Manuals"
|
||||
.SH NAME
|
||||
@PACKAGE@ \- monitor the progress of data through a pipe
|
||||
pv \- monitor the progress of data through a pipe
|
||||
.SH SYNOPSIS
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
[\fIOPTION\fR]
|
||||
[\fIFILE\fR]...
|
||||
.br
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
[\fI\-h\fR|\fI\-V\fR]
|
||||
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
shows the progress of data through a pipeline by giving information such as
|
||||
time elapsed, percentage completed (with progress bar), current throughput
|
||||
rate, total data transferred, and ETA.
|
||||
@@ -20,13 +20,13 @@ To use it, insert it in a pipeline between two processes, with the
|
||||
appropriate options. Its standard input will be passed through to its
|
||||
standard output and progress will be shown on standard error.
|
||||
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
will copy each supplied
|
||||
.B FILE
|
||||
.I FILE
|
||||
in turn to standard output
|
||||
.BR "" "(" -
|
||||
means standard input), or if no
|
||||
.BR FILE s
|
||||
.IR FILE s
|
||||
are specified just standard input is copied. This is the same behaviour
|
||||
as
|
||||
.BR cat (1).
|
||||
@@ -35,15 +35,15 @@ A simple example to watch how quickly a file is transferred using
|
||||
.BR nc (1):
|
||||
|
||||
.RS
|
||||
.B @PACKAGE@ file | nc -w 1 somewhere.com 3000
|
||||
.B pv file | nc -w 1 somewhere.com 3000
|
||||
.RE
|
||||
|
||||
A similar example, transferring a file from another process and passing the
|
||||
expected size to
|
||||
.BR @PACKAGE@ :
|
||||
.BR pv :
|
||||
|
||||
.RS
|
||||
.B cat file | @PACKAGE@ -s 12345 | nc -w 1 somewhere.com 3000
|
||||
.B cat file | pv -s 12345 | nc -w 1 somewhere.com 3000
|
||||
.RE
|
||||
|
||||
A more complicated example using numeric output to feed into the
|
||||
@@ -53,7 +53,7 @@ program for a full-screen progress display:
|
||||
.RS
|
||||
.B (tar cf - . \e
|
||||
.br
|
||||
.B " | @PACKAGE@ -n -s $(du -sb . | awk '{print $1}') \e"
|
||||
.B " | pv -n -s $(du -sb . | awk '{print $1}') \e"
|
||||
.br
|
||||
.B " | gzip -9 > out.tgz) 2>&1 \e"
|
||||
.br
|
||||
@@ -63,24 +63,24 @@ program for a full-screen progress display:
|
||||
Taking an image of a disk, skipping errors:
|
||||
|
||||
.RS
|
||||
.B @PACKAGE@ -EE /dev/your/disk/device > disk-image.img
|
||||
.B pv -EE /dev/your/disk/device > disk-image.img
|
||||
.RE
|
||||
|
||||
Writing an image back to a disk:
|
||||
|
||||
.RS
|
||||
.B @PACKAGE@ disk-image.img > /dev/your/disk/device
|
||||
.B pv disk-image.img > /dev/your/disk/device
|
||||
.RE
|
||||
|
||||
Zeroing a disk:
|
||||
|
||||
.RS
|
||||
.B @PACKAGE@ < /dev/zero > /dev/your/disk/device
|
||||
.B pv < /dev/zero > /dev/your/disk/device
|
||||
.RE
|
||||
|
||||
Note that if the input size cannot be calculated, and the output is a block
|
||||
device, then the size of the block device will be used and
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
will automatically stop at that size as if
|
||||
.B \-S
|
||||
had been given.
|
||||
@@ -88,25 +88,25 @@ had been given.
|
||||
(Linux only): Watching file descriptor 3 opened by another process 1234:
|
||||
|
||||
.RS
|
||||
.B @PACKAGE@ -d 1234:3
|
||||
.B pv -d 1234:3
|
||||
.RE
|
||||
|
||||
(Linux only): Watching all file descriptors used by process 1234:
|
||||
|
||||
.RS
|
||||
.B @PACKAGE@ -d 1234
|
||||
.B pv -d 1234
|
||||
.RE
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
takes many options, which are divided into display switches, output
|
||||
modifiers, and general options.
|
||||
|
||||
|
||||
.SH DISPLAY SWITCHES
|
||||
If no display switches are specified,
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
behaves as if
|
||||
.BR \-p ", " \-t ", " \-e ", " \-r ", and " \-b
|
||||
had been given (i.e. everything except average rate is switched on).
|
||||
@@ -114,8 +114,8 @@ Otherwise, only those display types that are explicitly switched on will be
|
||||
shown.
|
||||
.TP
|
||||
.B \-p, \-\-progress
|
||||
Turn the progress bar on. If standard input is not a file and no
|
||||
size was given (with the
|
||||
Turn the progress bar on. If any inputs are not files, or are
|
||||
unreadable, and no size was explicitly given (with the
|
||||
.B \-s
|
||||
modifier), the progress bar cannot indicate how close to completion the
|
||||
transfer is, so it will just move left and right to indicate that data is
|
||||
@@ -123,11 +123,11 @@ moving.
|
||||
.TP
|
||||
.B \-t, \-\-timer
|
||||
Turn the timer on. This will display the total elapsed time that
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
has been running for.
|
||||
.TP
|
||||
.B \-e, \-\-eta
|
||||
Turn the ETA timer on. This will attempt to guess, based on previous
|
||||
Turn the ETA timer on. This will attempt to guess, based on current
|
||||
transfer rates and the total data size, how long it will be before
|
||||
completion. This option will have no effect if the total data size cannot
|
||||
be determined.
|
||||
@@ -142,13 +142,18 @@ Turn the rate counter on. This will display the current rate of data
|
||||
transfer.
|
||||
.TP
|
||||
.B \-a, \-\-average\-rate
|
||||
Turn the average rate counter on. This will display the average rate of
|
||||
data transfer so far.
|
||||
Turn the average rate counter on. This will display the current average
|
||||
rate of data transfer (default: last 30s, see
|
||||
.BR \-m ).
|
||||
.TP
|
||||
.B \-b, \-\-bytes
|
||||
Turn the total byte counter on. This will display the total amount of
|
||||
data transferred so far.
|
||||
.TP
|
||||
.B \-8, \-\-bits
|
||||
Display the total bits instead of the total bytes. The output suffix will
|
||||
be "b" instead of "B".
|
||||
.TP
|
||||
.B \-T, \-\-buffer\-percent
|
||||
Turn on the transfer buffer percentage display. This will show the
|
||||
percentage of the transfer buffer in use - but see the caveat under
|
||||
@@ -158,9 +163,9 @@ in the
|
||||
section below. Implies
|
||||
.BR \-C .
|
||||
.TP
|
||||
.B \-A, \-\-last\-written NUM
|
||||
.BI \-A\ NUM \fR,\ \fB\-\-last\-written\ NUM
|
||||
Show the last
|
||||
.B NUM
|
||||
.I NUM
|
||||
bytes written - but see the caveat under
|
||||
.B %nA
|
||||
in the
|
||||
@@ -168,7 +173,7 @@ in the
|
||||
section below. Implies
|
||||
.BR \-C .
|
||||
.TP
|
||||
.B \-F, \-\-format FORMAT
|
||||
.BI \-F\ FORMAT \fR,\ \fB\-\-format\ FORMAT
|
||||
Ignore the options
|
||||
.BR \-p ,
|
||||
.BR \-t ,
|
||||
@@ -180,14 +185,14 @@ Ignore the options
|
||||
and
|
||||
.BR \-A ,
|
||||
and instead use the format string
|
||||
.B FORMAT
|
||||
.I FORMAT
|
||||
to determine the output format. See the
|
||||
.B FORMATTING
|
||||
section below.
|
||||
.TP
|
||||
.B \-n, \-\-numeric
|
||||
Numeric output. Instead of giving a visual indication of progress,
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
will give an integer percentage, one per line, on standard error, suitable
|
||||
for piping (via convoluted redirection) into
|
||||
.BR dialog (1).
|
||||
@@ -205,10 +210,16 @@ is in use, then adding
|
||||
will cause the number of bytes processed so far to be output instead of a
|
||||
percentage; if
|
||||
.B \-\-line\-mode
|
||||
is also in use, then instead of bytes or a percentage, the number of lines
|
||||
is also in use as well as
|
||||
.B \-\-bytes
|
||||
and
|
||||
.BR \-\-numeric ,
|
||||
then instead of bytes or a percentage, the number of lines
|
||||
so far is output. And finally, if
|
||||
.B \-\-timer
|
||||
is also in use, then each output line is prefixed with the elapsed time
|
||||
is added to
|
||||
.BR \-\-numeric ,
|
||||
then each output line is prefixed with the elapsed time
|
||||
so far, as a decimal number of seconds.
|
||||
.TP
|
||||
.B \-q, \-\-quiet
|
||||
@@ -228,23 +239,34 @@ or
|
||||
.BR mcrypt (1)
|
||||
which require a passphrase before data can be processed.
|
||||
.TP
|
||||
.B \-D, \-\-delay-start SEC
|
||||
.BI \-D\ SEC \fR,\ \fB\-\-delay\-start\ SEC
|
||||
Wait until
|
||||
.B SEC
|
||||
.I SEC
|
||||
seconds have passed before showing any progress information, for example in
|
||||
a script where you only want to show a progress bar if it starts taking a
|
||||
long time. Note that this can be a decimal such as 0.5.
|
||||
.TP
|
||||
.B \-s SIZE, \-\-size SIZE
|
||||
.BI \-s\ SIZE \fR,\ \fB\-\-size\ SIZE
|
||||
Assume the total amount of data to be transferred is
|
||||
.B SIZE
|
||||
.I SIZE
|
||||
bytes when calculating percentages and ETAs. The same suffixes of "k", "m"
|
||||
etc can be used as with
|
||||
.BR -L .
|
||||
.TP
|
||||
.B ""
|
||||
Has no effect if used with
|
||||
.B -d PID
|
||||
If
|
||||
.I SIZE
|
||||
starts with
|
||||
.BR "@" ,
|
||||
the size of file whose name follows the
|
||||
.B @
|
||||
will be used.
|
||||
.TP
|
||||
.B ""
|
||||
Note that
|
||||
.B \-\-size
|
||||
has no effect if used with
|
||||
.BI \-d\ PID
|
||||
to watch all file descriptors of a process, but will work with
|
||||
.BR "-d PID:FD" .
|
||||
.TP
|
||||
@@ -252,34 +274,49 @@ to watch all file descriptors of a process, but will work with
|
||||
Instead of counting bytes, count lines (newline characters). The progress
|
||||
bar will only move when a new line is found, and the value passed to the
|
||||
.B \-s
|
||||
option will be interpreted as a line count. Note that file sizes are not
|
||||
automatically calculated when this option is used, to avoid having to read
|
||||
all files twice.
|
||||
option will be interpreted as a line count.
|
||||
.TP
|
||||
.B ""
|
||||
If this option is used without
|
||||
.BR \-s ,
|
||||
the "total size" (in this case, total line count) is calculated by reading
|
||||
through all input files once before transfer starts. If any inputs are
|
||||
pipes or non-regular files, or are unreadable, the total size will not be
|
||||
calculated.
|
||||
.TP
|
||||
.B \-0, \-\-null
|
||||
Count lines as null terminated. This option implies \-\-line\-mode.
|
||||
Count lines as terminated with a zero byte instead of with a newline.
|
||||
This option implies \-\-line\-mode.
|
||||
.TP
|
||||
.B \-i SEC, \-\-interval SEC
|
||||
.BI \-i\ SEC \fR,\ \fB\-\-interval\ SEC
|
||||
Wait
|
||||
.B SEC
|
||||
.I SEC
|
||||
seconds between updates. The default is to update every second.
|
||||
Note that this can be a decimal such as 0.1.
|
||||
.TP
|
||||
.B \-w WIDTH, \-\-width WIDTH
|
||||
.BI \-m\ SEC \fR,\ \fB\-\-average-rate-window\ SEC
|
||||
Compute current average rate over a
|
||||
.I SEC
|
||||
seconds window for average rate and ETA calculations (default 30 seconds).
|
||||
.TP
|
||||
.BI \-w\ WIDTH \fR,\ \fB\-\-width\ WIDTH
|
||||
Assume the terminal is
|
||||
.B WIDTH
|
||||
.I WIDTH
|
||||
characters wide, instead of trying to work it out (or assuming 80 if it
|
||||
cannot be guessed).
|
||||
cannot be guessed). If this option is used, the output width will not be
|
||||
adjusted if the width of the terminal changes while the transfer is running.
|
||||
.TP
|
||||
.B \-H HEIGHT, \-\-height HEIGHT
|
||||
.BI \-H\ HEIGHT \fR,\ \fB\-\-height\ HEIGHT
|
||||
Assume the terminal is
|
||||
.B HEIGHT
|
||||
.I HEIGHT
|
||||
rows high, instead of trying to work it out (or assuming 25 if it
|
||||
cannot be guessed).
|
||||
cannot be guessed). If this option is used, the output height will not be
|
||||
adjusted if the height of the terminal changes while the transfer is
|
||||
running.
|
||||
.TP
|
||||
.B \-N NAME, \-\-name NAME
|
||||
.BI \-N\ NAME \fR,\ \fB\-\-name\ NAME
|
||||
Prefix the output information with
|
||||
.BR NAME .
|
||||
.IR NAME .
|
||||
Useful in conjunction with
|
||||
.B \-c
|
||||
if you have a complicated pipeline and you want to be able to tell different
|
||||
@@ -287,7 +324,7 @@ parts of it apart.
|
||||
.TP
|
||||
.B \-f, \-\-force
|
||||
Force output. Normally,
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
will not output any visual display if standard error is not a terminal.
|
||||
This option forces it to do so.
|
||||
.TP
|
||||
@@ -296,21 +333,21 @@ Use cursor positioning escape sequences instead of just using carriage
|
||||
returns. This is useful in conjunction with
|
||||
.B \-N
|
||||
(name) if you are using multiple
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
invocations in a single, long, pipeline.
|
||||
|
||||
|
||||
.SH DATA TRANSFER MODIFIERS
|
||||
.TP
|
||||
.B \-L RATE, \-\-rate-limit RATE
|
||||
.BI \-L\ RATE \fR,\ \fB\-\-rate-limit\ RATE
|
||||
Limit the transfer to a maximum of
|
||||
.B RATE
|
||||
.I RATE
|
||||
bytes per second. A suffix of "K", "M", "G", or "T" can be added to denote
|
||||
kibibytes (*1024), mebibytes, and so on.
|
||||
.TP
|
||||
.B \-B BYTES, \-\-buffer-size BYTES
|
||||
.BI \-B\ BYTES \fR,\ \fB\-\-buffer-size\ BYTES
|
||||
Use a transfer buffer size of
|
||||
.B BYTES
|
||||
.I BYTES
|
||||
bytes. A suffix of "K", "M", "G", or "T" can be added to denote
|
||||
kibibytes (*1024), mebibytes, and so on. The default buffer size is the
|
||||
block size of the input file's filesystem multiplied by 32 (512KiB max), or
|
||||
@@ -333,11 +370,14 @@ but means that the transfer buffer may not be used. This prevents
|
||||
.B \-A
|
||||
and
|
||||
.B \-T
|
||||
from working, and makes
|
||||
from working, cannot work with
|
||||
.BR \-X ,
|
||||
and makes
|
||||
.B \-B
|
||||
redundant, so using
|
||||
.BR \-A ,
|
||||
.BR \-T ,
|
||||
.BR \-X ,
|
||||
or
|
||||
.B \-B
|
||||
automatically switches on
|
||||
@@ -363,47 +403,92 @@ Specify
|
||||
twice to only report a read error once per file, instead of reporting each
|
||||
byte range skipped.
|
||||
.TP
|
||||
.BI \-Z\ BYTES \fR,\ \fB\-\-error\-skip\-block\ BYTES
|
||||
When ignoring read errors with
|
||||
.BR \-E ,
|
||||
instead of trying to adaptively skip by reading small amounts and skipping
|
||||
progressively larger sections until a read succeeds, move to the next file
|
||||
block of
|
||||
.I BYTES
|
||||
bytes as soon as an error occurs. There may still be some shorter skips
|
||||
where the block being skipped coincides with the end of the transfer buffer.
|
||||
.TP
|
||||
.B ""
|
||||
This option can only be used with
|
||||
.B \-E
|
||||
and is intended for use when reading from a block device, such as
|
||||
.B \-E\ \-Z\ 4K
|
||||
to skip in 4 kibibyte blocks. This will speed up reads from faulty media,
|
||||
at the expense of potentially losing more data.
|
||||
.TP
|
||||
.B \-S, \-\-stop-at-size
|
||||
If a size was specified with
|
||||
.BR \-s ,
|
||||
stop transferring data once that many bytes have been written, instead of
|
||||
continuing to the end of input.
|
||||
.TP
|
||||
.B \-d PID[:FD], \-\-watchfd PID[:FD]
|
||||
.B \-Y, \-\-sync
|
||||
After every write operation, synchronise the buffer caches to disk - see
|
||||
.BR fdatasync (2).
|
||||
This has no effect when the output is a pipe. Using
|
||||
.B \-Y
|
||||
may improve the accuracy of the progress bar when writing to a slow disk.
|
||||
.TP
|
||||
.B \-K, \-\-direct-io
|
||||
Set the
|
||||
.B O_DIRECT
|
||||
flag on all inputs and outputs, if it is available. This will minimise
|
||||
the effect of caches, at the cost of performance. Due to memory alignment
|
||||
requirements, it also may cause read or write failures with an error of
|
||||
"Invalid argument", especially if reading and writing files across a variety
|
||||
of filesystems in a single
|
||||
.B pv
|
||||
call. Use this option with caution.
|
||||
.TP
|
||||
.B \-X, \-\-discard
|
||||
Instead of transferring input data to standard output, discard it. This is
|
||||
equivalent to redirecting standard output to
|
||||
.IR /dev/null ,
|
||||
except that
|
||||
.BR write (2)
|
||||
is never called. Implies
|
||||
.BR \-C .
|
||||
.TP
|
||||
.BI \-d\ PID\fR[\fB:\fR\fIFD\fR],\ \fB\-\-watchfd\ PID\fR[\fB:\fR\fIFD\fR]
|
||||
Instead of transferring data, watch file descriptor
|
||||
.B FD
|
||||
.I FD
|
||||
of process
|
||||
.BR PID ,
|
||||
.IR PID ,
|
||||
and show its progress. The
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
process will exit when
|
||||
.B FD
|
||||
.I FD
|
||||
either changes to a different file, changes read/write mode, or is closed;
|
||||
other data transfer modifiers - and remote control - may not be used with
|
||||
this option.
|
||||
.TP
|
||||
.B ""
|
||||
If only a
|
||||
.B PID
|
||||
.I PID
|
||||
is specified, then that process will be watched, and all regular files and
|
||||
block devices it opens will be shown with a progress bar. The
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
process will exit when process
|
||||
.B PID
|
||||
.I PID
|
||||
exits.
|
||||
.TP
|
||||
.B \-R PID, \-\-remote PID
|
||||
.BI \-R\ PID \fR,\ \fB\-\-remote\ PID
|
||||
If
|
||||
.B PID
|
||||
.I PID
|
||||
is an instance of
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
that is already running,
|
||||
.B \-R PID
|
||||
.BI \-R\ PID
|
||||
will cause that instance to act as though it had been given
|
||||
this instance's command line instead. For example, if
|
||||
.B @PACKAGE@ -L 123K
|
||||
.B pv -L 123K
|
||||
is running with process ID 9876, then running
|
||||
.B @PACKAGE@ -R 9876 -L 321K
|
||||
.B pv -R 9876 -L 321K
|
||||
will cause it to start using a rate limit of 321KiB instead of 123KiB.
|
||||
Note that some options cannot be changed while running, such as
|
||||
.BR \-c ,
|
||||
@@ -416,17 +501,17 @@ and
|
||||
|
||||
.SH GENERAL OPTIONS
|
||||
.TP
|
||||
.B \-P FILE, \-\-pidfile FILE
|
||||
.BI \-P\ FILE \fR,\ \fB\-\-pidfile\ FILE
|
||||
Save the process ID of
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
in
|
||||
.BR FILE .
|
||||
The file will be truncated if it already exists, and will be removed when
|
||||
.B @PACKAGE@
|
||||
.IR FILE .
|
||||
The file will be replaced if it already exists, and will be removed when
|
||||
.B pv
|
||||
exits. While
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
is running, it will contain a single number - the process ID of
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
- followed by a newline.
|
||||
.TP
|
||||
.B \-h, \-\-help
|
||||
@@ -473,6 +558,11 @@ Bytes transferred so far (or lines if
|
||||
.B \-l
|
||||
was specified). Equivalent to
|
||||
.BR \-b .
|
||||
If
|
||||
.B \-\-bits
|
||||
was specified,
|
||||
.B %b
|
||||
shows the bits transferred so far, not bytes.
|
||||
.TP
|
||||
.B %T
|
||||
Percentage of the transfer buffer in use. Equivalent to
|
||||
@@ -498,6 +588,7 @@ Padded to 9 characters with spaces, and suffixed with :.
|
||||
.TP
|
||||
.B %%
|
||||
A single %.
|
||||
|
||||
.P
|
||||
The format string equivalent of turning on all display switches is
|
||||
.BR "\`%N %b %T %t %r %a %p %e'" .
|
||||
@@ -507,19 +598,19 @@ The format string equivalent of turning on all display switches is
|
||||
Some suggested common switch combinations:
|
||||
|
||||
.TP
|
||||
.B @PACKAGE@ -ptebar
|
||||
.B pv -ptebar
|
||||
Show a progress bar, elapsed time, estimated completion time, byte counter,
|
||||
average rate, and current rate.
|
||||
.TP
|
||||
.B @PACKAGE@ -betlap
|
||||
.B pv -betlap
|
||||
Show a progress bar, elapsed time, estimated completion time, line counter,
|
||||
and average rate, counting lines instead of bytes.
|
||||
.TP
|
||||
.B @PACKAGE@ -t
|
||||
.B pv -t
|
||||
Show only the elapsed time - useful as a simple timer, e.g.
|
||||
.BR "sleep 10m | pv -t" .
|
||||
.TP
|
||||
.B @PACKAGE@ -pterb
|
||||
.B pv -pterb
|
||||
The default behaviour: progress bar, elapsed time, estimated completion
|
||||
time, current rate, and byte counter.
|
||||
|
||||
@@ -565,14 +656,26 @@ A zero exit status indicates no problems.
|
||||
|
||||
.SH AUTHOR
|
||||
Written by Andrew Wood, with patches submitted by various other people.
|
||||
Please see the package README for a complete list of contributors.
|
||||
Please see the package's ACKNOWLEDGEMENTS file for a complete list of
|
||||
contributors.
|
||||
|
||||
|
||||
.SH KNOWN PROBLEMS
|
||||
The following problems are known to exist in
|
||||
.BR @PACKAGE@ :
|
||||
.TP
|
||||
.B *
|
||||
.BR pv :
|
||||
.IP \(bu 3
|
||||
In some versions of
|
||||
.BR bash (1)
|
||||
and
|
||||
.BR zsh (1),
|
||||
the construct
|
||||
.B <(pv filename)
|
||||
will not output any progress to the terminal when run from an interactive
|
||||
shell, due to the subprocess being run in a separate process group from the
|
||||
one that owns the terminal. In these cases, use
|
||||
.BR \-\-force .
|
||||
.P
|
||||
.IP \(bu 3
|
||||
The
|
||||
.B -c
|
||||
option does not work properly on Cygwin without
|
||||
@@ -581,10 +684,9 @@ running, if started near the bottom of the screen (IPC is needed to handle
|
||||
the terminal scrolling). To fix this, start
|
||||
.B cygserver
|
||||
before using
|
||||
.BR "@PACKAGE@ -c" .
|
||||
.BR "pv -c" .
|
||||
.P
|
||||
.TP
|
||||
.B *
|
||||
.IP \(bu 3
|
||||
The
|
||||
.B -R
|
||||
option is not available on Cygwin without
|
||||
@@ -592,25 +694,33 @@ option is not available on Cygwin without
|
||||
running (SYSV IPC is needed). To fix this, start
|
||||
.B cygserver
|
||||
before running the instance of
|
||||
.B @PACKAGE@
|
||||
.B pv
|
||||
you want, at runtime, to change the parameters of.
|
||||
.P
|
||||
If you find any other problems, please report them.
|
||||
|
||||
|
||||
.SH REPORTING BUGS
|
||||
Report bugs in
|
||||
.B @PACKAGE@
|
||||
to pv@ivarch.com or use the contact form linked from the
|
||||
.B @PACKAGE@
|
||||
home page: <http://www.ivarch.com/programs/pv.shtml>
|
||||
Please report any bugs to
|
||||
.BR pv@ivarch.com .
|
||||
|
||||
Alternatively, use the issue tracker linked from the
|
||||
.B pv
|
||||
home page: <https://www.ivarch.com/programs/pv.shtml>
|
||||
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR cat (1),
|
||||
.BR dialog (1),
|
||||
.BR splice (2)
|
||||
.BR splice (2),
|
||||
.BR open (2)
|
||||
(for
|
||||
.BR O_DIRECT )
|
||||
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood.
|
||||
|
||||
.SH LICENSE
|
||||
This is free software, distributed under the ARTISTIC 2.0 license.
|
||||
License GPLv3+: GNU GPL version 3 or later <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||
|
||||
This is free software: you are free to change and redistribute it. There is
|
||||
NO WARRANTY, to the extent permitted by law.
|
||||
+546
@@ -0,0 +1,546 @@
|
||||
# NAME
|
||||
|
||||
pv - monitor the progress of data through a pipe
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
**pv** \[*OPTION*\] \[*FILE*\]\...\
|
||||
**pv** \[*-h*\|*-V*\]
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
**pv** shows the progress of data through a pipeline by giving
|
||||
information such as time elapsed, percentage completed (with progress
|
||||
bar), current throughput rate, total data transferred, and ETA.
|
||||
|
||||
To use it, insert it in a pipeline between two processes, with the
|
||||
appropriate options. Its standard input will be passed through to its
|
||||
standard output and progress will be shown on standard error.
|
||||
|
||||
**pv** will copy each supplied *FILE* in turn to standard output (**-**
|
||||
means standard input), or if no *FILE*s are specified just standard
|
||||
input is copied. This is the same behaviour as **cat**(1).
|
||||
|
||||
A simple example to watch how quickly a file is transferred using
|
||||
**nc**(1):
|
||||
|
||||
> **pv file \| nc -w 1 somewhere.com 3000**
|
||||
|
||||
A similar example, transferring a file from another process and passing
|
||||
the expected size to **pv**:
|
||||
|
||||
> **cat file \| pv -s 12345 \| nc -w 1 somewhere.com 3000**
|
||||
|
||||
A more complicated example using numeric output to feed into the
|
||||
**dialog**(1) program for a full-screen progress display:
|
||||
|
||||
> **(tar cf - . \\**\
|
||||
> ** \| pv -n -s \$(du -sb . \| awk \'{print \$1}\') \\**\
|
||||
> ** \| gzip -9 \> out.tgz) 2\>&1 \\**\
|
||||
> **\| dialog \--gauge \'Progress\' 7 70**
|
||||
|
||||
Taking an image of a disk, skipping errors:
|
||||
|
||||
> **pv -EE /dev/your/disk/device \> disk-image.img**
|
||||
|
||||
Writing an image back to a disk:
|
||||
|
||||
> **pv disk-image.img \> /dev/your/disk/device**
|
||||
|
||||
Zeroing a disk:
|
||||
|
||||
> **pv \< /dev/zero \> /dev/your/disk/device**
|
||||
|
||||
Note that if the input size cannot be calculated, and the output is a
|
||||
block device, then the size of the block device will be used and **pv**
|
||||
will automatically stop at that size as if **-S** had been given.
|
||||
|
||||
(Linux only): Watching file descriptor 3 opened by another process 1234:
|
||||
|
||||
> **pv -d 1234:3**
|
||||
|
||||
(Linux only): Watching all file descriptors used by process 1234:
|
||||
|
||||
> **pv -d 1234**
|
||||
|
||||
# OPTIONS
|
||||
|
||||
**pv** takes many options, which are divided into display switches,
|
||||
output modifiers, and general options.
|
||||
|
||||
# DISPLAY SWITCHES
|
||||
|
||||
If no display switches are specified, **pv** behaves as if **-p**,
|
||||
**-t**, **-e**, **-r**, and **-b** had been given (i.e. everything
|
||||
except average rate is switched on). Otherwise, only those display types
|
||||
that are explicitly switched on will be shown.
|
||||
|
||||
**-p, \--progress**
|
||||
|
||||
: Turn the progress bar on. If any inputs are not files, or are
|
||||
unreadable, and no size was explicitly given (with the **-s**
|
||||
modifier), the progress bar cannot indicate how close to completion
|
||||
the transfer is, so it will just move left and right to indicate
|
||||
that data is moving.
|
||||
|
||||
**-t, \--timer**
|
||||
|
||||
: Turn the timer on. This will display the total elapsed time that
|
||||
**pv** has been running for.
|
||||
|
||||
**-e, \--eta**
|
||||
|
||||
: Turn the ETA timer on. This will attempt to guess, based on current
|
||||
transfer rates and the total data size, how long it will be before
|
||||
completion. This option will have no effect if the total data size
|
||||
cannot be determined.
|
||||
|
||||
**-I, \--fineta**
|
||||
|
||||
: Turn the ETA timer on, but display the estimated local time of
|
||||
arrival instead of time left. When the estimated time is more than 6
|
||||
hours in the future, the date is shown as well.
|
||||
|
||||
**-r, \--rate**
|
||||
|
||||
: Turn the rate counter on. This will display the current rate of data
|
||||
transfer.
|
||||
|
||||
**-a, \--average-rate**
|
||||
|
||||
: Turn the average rate counter on. This will display the current
|
||||
average rate of data transfer (default: last 30s, see **-m**).
|
||||
|
||||
**-b, \--bytes**
|
||||
|
||||
: Turn the total byte counter on. This will display the total amount
|
||||
of data transferred so far.
|
||||
|
||||
**-8, \--bits**
|
||||
|
||||
: Display the total bits instead of the total bytes. The output suffix
|
||||
will be \"b\" instead of \"B\".
|
||||
|
||||
**-T, \--buffer-percent**
|
||||
|
||||
: Turn on the transfer buffer percentage display. This will show the
|
||||
percentage of the transfer buffer in use - but see the caveat under
|
||||
**%T** in the **FORMATTING** section below. Implies **-C**.
|
||||
|
||||
**-A NUM, \--last-written NUM**
|
||||
|
||||
: Show the last *NUM* bytes written - but see the caveat under **%nA**
|
||||
in the **FORMATTING** section below. Implies **-C**.
|
||||
|
||||
**-F FORMAT, \--format FORMAT**
|
||||
|
||||
: Ignore the options **-p**, **-t**, **-e**, **-r**, **-a**, **-b**,
|
||||
**-T**, and **-A**, and instead use the format string *FORMAT* to
|
||||
determine the output format. See the **FORMATTING** section below.
|
||||
|
||||
**-n, \--numeric**
|
||||
|
||||
: Numeric output. Instead of giving a visual indication of progress,
|
||||
**pv** will give an integer percentage, one per line, on standard
|
||||
error, suitable for piping (via convoluted redirection) into
|
||||
**dialog**(1). Note that **-f** is not required if **-n** is being
|
||||
used.
|
||||
|
||||
: Note that if **\--numeric** is in use, then adding **\--bytes** will
|
||||
cause the number of bytes processed so far to be output instead of a
|
||||
percentage; if **\--line-mode** is also in use as well as
|
||||
**\--bytes** and **\--numeric**, then instead of bytes or a
|
||||
percentage, the number of lines so far is output. And finally, if
|
||||
**\--timer** is added to **\--numeric**, then each output line is
|
||||
prefixed with the elapsed time so far, as a decimal number of
|
||||
seconds.
|
||||
|
||||
**-q, \--quiet**
|
||||
|
||||
: No output. Useful if the **-L** option is being used on its own to
|
||||
just limit the transfer rate of a pipe.
|
||||
|
||||
# OUTPUT MODIFIERS
|
||||
|
||||
**-W, \--wait**
|
||||
|
||||
: Wait until the first byte has been transferred before showing any
|
||||
progress information or calculating any ETAs. Useful if the program
|
||||
you are piping to or from requires extra information before it
|
||||
starts, eg piping data into **gpg**(1) or **mcrypt**(1) which
|
||||
require a passphrase before data can be processed.
|
||||
|
||||
**-D SEC, \--delay-start SEC**
|
||||
|
||||
: Wait until *SEC* seconds have passed before showing any progress
|
||||
information, for example in a script where you only want to show a
|
||||
progress bar if it starts taking a long time. Note that this can be
|
||||
a decimal such as 0.5.
|
||||
|
||||
**-s SIZE, \--size SIZE**
|
||||
|
||||
: Assume the total amount of data to be transferred is *SIZE* bytes
|
||||
when calculating percentages and ETAs. The same suffixes of \"k\",
|
||||
\"m\" etc can be used as with **-L**.
|
||||
|
||||
: If *SIZE* starts with **@**, the size of file whose name follows the
|
||||
**@** will be used.
|
||||
|
||||
: Note that **\--size** has no effect if used with **-d ***PID* to
|
||||
watch all file descriptors of a process, but will work with **-d
|
||||
PID:FD**.
|
||||
|
||||
**-l, \--line-mode**
|
||||
|
||||
: Instead of counting bytes, count lines (newline characters). The
|
||||
progress bar will only move when a new line is found, and the value
|
||||
passed to the **-s** option will be interpreted as a line count.
|
||||
|
||||
: If this option is used without **-s**, the \"total size\" (in this
|
||||
case, total line count) is calculated by reading through all input
|
||||
files once before transfer starts. If any inputs are pipes or
|
||||
non-regular files, or are unreadable, the total size will not be
|
||||
calculated.
|
||||
|
||||
**-0, \--null**
|
||||
|
||||
: Count lines as terminated with a zero byte instead of with a
|
||||
newline. This option implies \--line-mode.
|
||||
|
||||
**-i SEC, \--interval SEC**
|
||||
|
||||
: Wait *SEC* seconds between updates. The default is to update every
|
||||
second. Note that this can be a decimal such as 0.1.
|
||||
|
||||
**-m SEC, \--average-rate-window SEC**
|
||||
|
||||
: Compute current average rate over a *SEC* seconds window for average
|
||||
rate and ETA calculations (default 30 seconds).
|
||||
|
||||
**-w WIDTH, \--width WIDTH**
|
||||
|
||||
: Assume the terminal is *WIDTH* characters wide, instead of trying to
|
||||
work it out (or assuming 80 if it cannot be guessed). If this option
|
||||
is used, the output width will not be adjusted if the width of the
|
||||
terminal changes while the transfer is running.
|
||||
|
||||
**-H HEIGHT, \--height HEIGHT**
|
||||
|
||||
: Assume the terminal is *HEIGHT* rows high, instead of trying to work
|
||||
it out (or assuming 25 if it cannot be guessed). If this option is
|
||||
used, the output height will not be adjusted if the height of the
|
||||
terminal changes while the transfer is running.
|
||||
|
||||
**-N NAME, \--name NAME**
|
||||
|
||||
: Prefix the output information with *NAME*. Useful in conjunction
|
||||
with **-c** if you have a complicated pipeline and you want to be
|
||||
able to tell different parts of it apart.
|
||||
|
||||
**-f, \--force**
|
||||
|
||||
: Force output. Normally, **pv** will not output any visual display if
|
||||
standard error is not a terminal. This option forces it to do so.
|
||||
|
||||
**-c, \--cursor**
|
||||
|
||||
: Use cursor positioning escape sequences instead of just using
|
||||
carriage returns. This is useful in conjunction with **-N** (name)
|
||||
if you are using multiple **pv** invocations in a single, long,
|
||||
pipeline.
|
||||
|
||||
# DATA TRANSFER MODIFIERS
|
||||
|
||||
**-L RATE, \--rate-limit RATE**
|
||||
|
||||
: Limit the transfer to a maximum of *RATE* bytes per second. A suffix
|
||||
of \"K\", \"M\", \"G\", or \"T\" can be added to denote kibibytes
|
||||
(\*1024), mebibytes, and so on.
|
||||
|
||||
**-B BYTES, \--buffer-size BYTES**
|
||||
|
||||
: Use a transfer buffer size of *BYTES* bytes. A suffix of \"K\",
|
||||
\"M\", \"G\", or \"T\" can be added to denote kibibytes (\*1024),
|
||||
mebibytes, and so on. The default buffer size is the block size of
|
||||
the input file\'s filesystem multiplied by 32 (512KiB max), or
|
||||
400KiB if the block size cannot be determined. This can be useful on
|
||||
platforms like MacOS which perform better in pipelines with specific
|
||||
buffer sizes such as 1024. Implies **-C**.
|
||||
|
||||
**-C, \--no-splice**
|
||||
|
||||
: Never use **splice**(2), even if it would normally be possible. The
|
||||
**splice**(2) system call is a more efficient way of transferring
|
||||
data from or to a pipe than regular **read**(2) and **write**(2),
|
||||
but means that the transfer buffer may not be used. This prevents
|
||||
**-A** and **-T** from working, cannot work with **-X**, and makes
|
||||
**-B** redundant, so using **-A**, **-T**, **-X**, or **-B**
|
||||
automatically switches on **-C**. Switching on **-C** results in a
|
||||
small loss of transfer efficiency. (This option has no effect on
|
||||
systems where **splice**(2) is unavailable).
|
||||
|
||||
**-E, \--skip-errors**
|
||||
|
||||
: Ignore read errors by attempting to skip past the offending
|
||||
sections. The corresponding parts of the output will be null bytes.
|
||||
At first only a few bytes will be skipped, but if there are many
|
||||
errors in a row then the skips will move up to chunks of 512. This
|
||||
is intended to be similar to **dd conv=sync,noerror** but has not
|
||||
been as thoroughly tested.
|
||||
|
||||
: Specify **-E** twice to only report a read error once per file,
|
||||
instead of reporting each byte range skipped.
|
||||
|
||||
**-Z BYTES, \--error-skip-block BYTES**
|
||||
|
||||
: When ignoring read errors with **-E**, instead of trying to
|
||||
adaptively skip by reading small amounts and skipping progressively
|
||||
larger sections until a read succeeds, move to the next file block
|
||||
of *BYTES* bytes as soon as an error occurs. There may still be some
|
||||
shorter skips where the block being skipped coincides with the end
|
||||
of the transfer buffer.
|
||||
|
||||
: This option can only be used with **-E** and is intended for use
|
||||
when reading from a block device, such as **-E -Z 4K** to skip in 4
|
||||
kibibyte blocks. This will speed up reads from faulty media, at the
|
||||
expense of potentially losing more data.
|
||||
|
||||
**-S, \--stop-at-size**
|
||||
|
||||
: If a size was specified with **-s**, stop transferring data once
|
||||
that many bytes have been written, instead of continuing to the end
|
||||
of input.
|
||||
|
||||
**-Y, \--sync**
|
||||
|
||||
: After every write operation, synchronise the buffer caches to disk -
|
||||
see **fdatasync**(2). This has no effect when the output is a pipe.
|
||||
Using **-Y** may improve the accuracy of the progress bar when
|
||||
writing to a slow disk.
|
||||
|
||||
**-K, \--direct-io**
|
||||
|
||||
: Set the **O_DIRECT** flag on all inputs and outputs, if it is
|
||||
available. This will minimise the effect of caches, at the cost of
|
||||
performance. Due to memory alignment requirements, it also may cause
|
||||
read or write failures with an error of \"Invalid argument\",
|
||||
especially if reading and writing files across a variety of
|
||||
filesystems in a single **pv** call. Use this option with caution.
|
||||
|
||||
**-X, \--discard**
|
||||
|
||||
: Instead of transferring input data to standard output, discard it.
|
||||
This is equivalent to redirecting standard output to */dev/null*,
|
||||
except that **write**(2) is never called. Implies **-C**.
|
||||
|
||||
**-d PID\[:FD\], \--watchfd PID\[:FD\]**
|
||||
|
||||
: Instead of transferring data, watch file descriptor *FD* of process
|
||||
*PID*, and show its progress. The **pv** process will exit when *FD*
|
||||
either changes to a different file, changes read/write mode, or is
|
||||
closed; other data transfer modifiers - and remote control - may not
|
||||
be used with this option.
|
||||
|
||||
: If only a *PID* is specified, then that process will be watched, and
|
||||
all regular files and block devices it opens will be shown with a
|
||||
progress bar. The **pv** process will exit when process *PID* exits.
|
||||
|
||||
**-R PID, \--remote PID**
|
||||
|
||||
: If *PID* is an instance of **pv** that is already running, **-R
|
||||
***PID* will cause that instance to act as though it had been given
|
||||
this instance\'s command line instead. For example, if **pv -L
|
||||
123K** is running with process ID 9876, then running **pv -R 9876 -L
|
||||
321K** will cause it to start using a rate limit of 321KiB instead
|
||||
of 123KiB. Note that some options cannot be changed while running,
|
||||
such as **-c**, **-l**, **-f**, **-D**, **-E**, and **-S**.
|
||||
|
||||
# GENERAL OPTIONS
|
||||
|
||||
**-P FILE, \--pidfile FILE**
|
||||
|
||||
: Save the process ID of **pv** in *FILE*. The file will be replaced
|
||||
if it already exists, and will be removed when **pv** exits. While
|
||||
**pv** is running, it will contain a single number - the process ID
|
||||
of **pv** - followed by a newline.
|
||||
|
||||
**-h, \--help**
|
||||
|
||||
: Print a usage message on standard output and exit successfully.
|
||||
|
||||
**-V, \--version**
|
||||
|
||||
: Print version information on standard output and exit successfully.
|
||||
|
||||
# FORMATTING
|
||||
|
||||
If the **-F** option is given, then the output format is determined by
|
||||
the given format string. Within that string, the following sequences can
|
||||
be used:
|
||||
|
||||
**%p**
|
||||
|
||||
: Progress bar. Expands to fill the remaining space. Should only be
|
||||
specified once. Equivalent to **-p**.
|
||||
|
||||
**%t**
|
||||
|
||||
: Elapsed time. Equivalent to **-t**.
|
||||
|
||||
**%e**
|
||||
|
||||
: ETA as time remaining. Equivalent to **-e**.
|
||||
|
||||
**%I**
|
||||
|
||||
: ETA as local time of completion. Equivalent to **-I**.
|
||||
|
||||
**%r**
|
||||
|
||||
: Current data transfer rate. Equivalent to **-r**.
|
||||
|
||||
**%a**
|
||||
|
||||
: Average data transfer rate. Equivalent to **-a**.
|
||||
|
||||
**%b**
|
||||
|
||||
: Bytes transferred so far (or lines if **-l** was specified).
|
||||
Equivalent to **-b**. If **\--bits** was specified, **%b** shows the
|
||||
bits transferred so far, not bytes.
|
||||
|
||||
**%T**
|
||||
|
||||
: Percentage of the transfer buffer in use. Equivalent to **-T**.
|
||||
Shows \"{\-\-\--}\" if the transfer is being done with
|
||||
**splice**(2), since splicing to or from pipes does not use the
|
||||
buffer.
|
||||
|
||||
**%nA**
|
||||
|
||||
: Show the last **n** bytes written (e.g. **%16A** for the last 16
|
||||
bytes). Shows only dots if the transfer is being done with
|
||||
**splice**(2), since splicing to or from pipes does not use the
|
||||
buffer.
|
||||
|
||||
**%N**
|
||||
|
||||
: Name prefix given by **-N**. Padded to 9 characters with spaces, and
|
||||
suffixed with :.
|
||||
|
||||
**%%**
|
||||
|
||||
: A single %.
|
||||
|
||||
The format string equivalent of turning on all display switches is
|
||||
**\`%N %b %T %t %r %a %p %e\'**.
|
||||
|
||||
# COMMON SWITCHES
|
||||
|
||||
Some suggested common switch combinations:
|
||||
|
||||
**pv -ptebar**
|
||||
|
||||
: Show a progress bar, elapsed time, estimated completion time, byte
|
||||
counter, average rate, and current rate.
|
||||
|
||||
**pv -betlap**
|
||||
|
||||
: Show a progress bar, elapsed time, estimated completion time, line
|
||||
counter, and average rate, counting lines instead of bytes.
|
||||
|
||||
**pv -t**
|
||||
|
||||
: Show only the elapsed time - useful as a simple timer, e.g. **sleep
|
||||
10m \| pv -t**.
|
||||
|
||||
**pv -pterb**
|
||||
|
||||
: The default behaviour: progress bar, elapsed time, estimated
|
||||
completion time, current rate, and byte counter.
|
||||
|
||||
On MacOS, it may be useful to specify **-B 1024** in a pipeline, as this
|
||||
may improve performance.
|
||||
|
||||
# EXIT STATUS
|
||||
|
||||
An exit status of 1 indicates a problem with the **-R** or **-P**
|
||||
options.
|
||||
|
||||
Any other exit status is a bitmask of the following:
|
||||
|
||||
**2**
|
||||
|
||||
: One or more files could not be accessed, **stat**(2)ed, or opened.
|
||||
|
||||
**4**
|
||||
|
||||
: An input file was the same as the output file.
|
||||
|
||||
**8**
|
||||
|
||||
: Internal error with closing a file or moving to the next file.
|
||||
|
||||
**16**
|
||||
|
||||
: There was an error while transferring data from one or more input
|
||||
files.
|
||||
|
||||
**32**
|
||||
|
||||
: A signal was caught that caused an early exit.
|
||||
|
||||
**64**
|
||||
|
||||
: Memory allocation failed.
|
||||
|
||||
A zero exit status indicates no problems.
|
||||
|
||||
# AUTHOR
|
||||
|
||||
Written by Andrew Wood, with patches submitted by various other people.
|
||||
Please see the package\'s ACKNOWLEDGEMENTS file for a complete list of
|
||||
contributors.
|
||||
|
||||
# KNOWN PROBLEMS
|
||||
|
||||
The following problems are known to exist in **pv**:
|
||||
|
||||
- In some versions of **bash**(1) and **zsh**(1), the construct
|
||||
**\<(pv filename)** will not output any progress to the terminal
|
||||
when run from an interactive shell, due to the subprocess being run
|
||||
in a separate process group from the one that owns the terminal. In
|
||||
these cases, use **\--force**.
|
||||
|
||||
- The **-c** option does not work properly on Cygwin without
|
||||
**cygserver** running, if started near the bottom of the screen (IPC
|
||||
is needed to handle the terminal scrolling). To fix this, start
|
||||
**cygserver** before using **pv -c**.
|
||||
|
||||
- The **-R** option is not available on Cygwin without **cygserver**
|
||||
running (SYSV IPC is needed). To fix this, start **cygserver**
|
||||
before running the instance of **pv** you want, at runtime, to
|
||||
change the parameters of.
|
||||
|
||||
If you find any other problems, please report them.
|
||||
|
||||
# REPORTING BUGS
|
||||
|
||||
Please report any bugs to **pv@ivarch.com**.
|
||||
|
||||
Alternatively, use the issue tracker linked from the **pv** home page:
|
||||
\<https://www.ivarch.com/programs/pv.shtml\>
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
**cat**(1), **dialog**(1), **splice**(2), **open**(2) (for **O_DIRECT**)
|
||||
|
||||
# COPYRIGHT
|
||||
|
||||
Copyright © 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood.
|
||||
|
||||
License GPLv3+: GNU GPL version 3 or later
|
||||
\<https://www.gnu.org/licenses/gpl-3.0.html\>.
|
||||
|
||||
This is free software: you are free to change and redistribute it. There
|
||||
is NO WARRANTY, to the extent permitted by law.
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Script to autogenerate the `configure' script, and rebuild the dependency
|
||||
# list.
|
||||
|
||||
set -e
|
||||
|
||||
cd `dirname $0`
|
||||
|
||||
cd autoconf
|
||||
autoconf configure.in > ../configure
|
||||
cd ..
|
||||
chmod 755 configure
|
||||
|
||||
echo > autoconf/make/depend.mk~
|
||||
echo > autoconf/make/filelist.mk~
|
||||
echo > autoconf/make/modules.mk~
|
||||
|
||||
MAKE=make
|
||||
which gmake >/dev/null 2>&1 && MAKE=gmake
|
||||
|
||||
rm -rf .gen
|
||||
mkdir .gen
|
||||
cd .gen
|
||||
sh ../configure
|
||||
$MAKE make
|
||||
$MAKE dep
|
||||
cd ..
|
||||
rm -rf .gen
|
||||
rm -rf autoconf/autom4te.cache
|
||||
|
||||
# EOF
|
||||
@@ -0,0 +1,9 @@
|
||||
Makevars.template
|
||||
*.sed
|
||||
*.gmo
|
||||
*.header
|
||||
*.sin
|
||||
*.pot
|
||||
Rules-quot
|
||||
stamp-po
|
||||
*~
|
||||
@@ -0,0 +1,4 @@
|
||||
de
|
||||
fr
|
||||
pl
|
||||
pt
|
||||
@@ -0,0 +1,510 @@
|
||||
# Makefile for PO directory in any package using GNU gettext.
|
||||
# Copyright (C) 1995-2000 Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||
# Copyright (C) 2000-2020 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# are permitted in any medium without royalty provided the copyright
|
||||
# notice and this notice are preserved. This file is offered as-is,
|
||||
# without any warranty.
|
||||
#
|
||||
# Origin: gettext-0.21
|
||||
GETTEXT_MACRO_VERSION = 0.20
|
||||
|
||||
PACKAGE = @PACKAGE@
|
||||
VERSION = @VERSION@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
|
||||
SED = @SED@
|
||||
SHELL = /bin/sh
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
datarootdir = @datarootdir@
|
||||
datadir = @datadir@
|
||||
localedir = @localedir@
|
||||
gettextsrcdir = $(datadir)/gettext/po
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
# We use $(mkdir_p).
|
||||
# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as
|
||||
# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions,
|
||||
# @install_sh@ does not start with $(SHELL), so we add it.
|
||||
# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined
|
||||
# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake
|
||||
# versions, $(mkinstalldirs) and $(install_sh) are unused.
|
||||
mkinstalldirs = $(SHELL) @install_sh@ -d
|
||||
install_sh = $(SHELL) @install_sh@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
mkdir_p = @mkdir_p@
|
||||
|
||||
# When building gettext-tools, we prefer to use the built programs
|
||||
# rather than installed programs. However, we can't do that when we
|
||||
# are cross compiling.
|
||||
CROSS_COMPILING = @CROSS_COMPILING@
|
||||
|
||||
GMSGFMT_ = @GMSGFMT@
|
||||
GMSGFMT_no = @GMSGFMT@
|
||||
GMSGFMT_yes = @GMSGFMT_015@
|
||||
GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT))
|
||||
XGETTEXT_ = @XGETTEXT@
|
||||
XGETTEXT_no = @XGETTEXT@
|
||||
XGETTEXT_yes = @XGETTEXT_015@
|
||||
XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
|
||||
MSGMERGE = @MSGMERGE@
|
||||
MSGMERGE_UPDATE = @MSGMERGE@ --update
|
||||
MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
|
||||
MSGINIT = msginit
|
||||
MSGCONV = msgconv
|
||||
MSGFILTER = msgfilter
|
||||
|
||||
POFILES = @POFILES@
|
||||
GMOFILES = @GMOFILES@
|
||||
UPDATEPOFILES = @UPDATEPOFILES@
|
||||
DUMMYPOFILES = @DUMMYPOFILES@
|
||||
DISTFILES.common = Makefile.in.in remove-potcdate.sin \
|
||||
$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
|
||||
DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \
|
||||
$(POFILES) $(GMOFILES) \
|
||||
$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
|
||||
|
||||
POTFILES = \
|
||||
|
||||
CATALOGS = @CATALOGS@
|
||||
|
||||
POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot
|
||||
POFILESDEPS_yes = $(POFILESDEPS_)
|
||||
POFILESDEPS_no =
|
||||
POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT))
|
||||
|
||||
DISTFILESDEPS_ = update-po
|
||||
DISTFILESDEPS_yes = $(DISTFILESDEPS_)
|
||||
DISTFILESDEPS_no =
|
||||
DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO))
|
||||
|
||||
# Makevars gets inserted here. (Don't remove this line!)
|
||||
|
||||
all: all-@USE_NLS@
|
||||
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .po .gmo .sed .sin .nop .po-create .po-update
|
||||
|
||||
# The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
|
||||
# The GNU Coding Standards say in
|
||||
# <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
|
||||
# "GNU distributions usually contain some files which are not source files
|
||||
# ... . Since these files normally appear in the source directory, they
|
||||
# should always appear in the source directory, not in the build directory.
|
||||
# So Makefile rules to update them should put the updated files in the
|
||||
# source directory."
|
||||
# Therefore we put these files in the source directory, not the build directory.
|
||||
|
||||
# During .po -> .gmo conversion, take into account the most recent changes to
|
||||
# the .pot file. This eliminates the need to update the .po files when the
|
||||
# .pot file has changed, which would be troublesome if the .po files are put
|
||||
# under version control.
|
||||
$(GMOFILES): $(srcdir)/$(DOMAIN).pot
|
||||
.po.gmo:
|
||||
@lang=`echo $* | sed -e 's,.*/,,'`; \
|
||||
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||
echo "$${cdcmd}rm -f $${lang}.gmo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) -o $${lang}.1po $${lang}.po $(DOMAIN).pot && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.1po && rm -f $${lang}.1po"; \
|
||||
cd $(srcdir) && \
|
||||
rm -f $${lang}.gmo && \
|
||||
$(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) -o $${lang}.1po $${lang}.po $(DOMAIN).pot && \
|
||||
$(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.1po && \
|
||||
mv t-$${lang}.gmo $${lang}.gmo && \
|
||||
rm -f $${lang}.1po
|
||||
|
||||
.sin.sed:
|
||||
sed -e '/^#/d' $< > t-$@
|
||||
mv t-$@ $@
|
||||
|
||||
|
||||
all-yes: $(srcdir)/stamp-po
|
||||
all-no:
|
||||
|
||||
# Ensure that the gettext macros and this Makefile.in.in are in sync.
|
||||
CHECK_MACRO_VERSION = \
|
||||
test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \
|
||||
|| { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \
|
||||
exit 1; \
|
||||
}
|
||||
|
||||
# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no
|
||||
# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because
|
||||
# we don't want to bother translators with empty POT files). We assume that
|
||||
# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty.
|
||||
# In this case, $(srcdir)/stamp-po is a nop (i.e. a phony target).
|
||||
|
||||
# $(srcdir)/stamp-po is a timestamp denoting the last time at which the CATALOGS
|
||||
# have been loosely updated. Its purpose is that when a developer or translator
|
||||
# checks out the package from a version control system, and the $(DOMAIN).pot
|
||||
# file is not under version control, "make" will update the $(DOMAIN).pot and
|
||||
# the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
|
||||
# timestamp would not be necessary if updating the $(CATALOGS) would always
|
||||
# touch them; however, the rule for $(POFILES) has been designed to not touch
|
||||
# files that don't need to be changed.
|
||||
$(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
|
||||
@$(CHECK_MACRO_VERSION)
|
||||
test ! -f $(srcdir)/$(DOMAIN).pot || \
|
||||
test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
|
||||
@test ! -f $(srcdir)/$(DOMAIN).pot || { \
|
||||
echo "touch $(srcdir)/stamp-po" && \
|
||||
echo timestamp > $(srcdir)/stamp-poT && \
|
||||
mv $(srcdir)/stamp-poT $(srcdir)/stamp-po; \
|
||||
}
|
||||
|
||||
# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
|
||||
# otherwise packages like GCC can not be built if only parts of the source
|
||||
# have been downloaded.
|
||||
|
||||
# This target rebuilds $(DOMAIN).pot; it is an expensive operation.
|
||||
# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed.
|
||||
# The determination of whether the package xyz is a GNU one is based on the
|
||||
# heuristic whether some file in the top level directory mentions "GNU xyz".
|
||||
# If GNU 'find' is available, we avoid grepping through monster files.
|
||||
$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
|
||||
package_gnu="$(PACKAGE_GNU)"; \
|
||||
test -n "$$package_gnu" || { \
|
||||
if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \
|
||||
LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f -size -10000000c -exec grep -i 'GNU @PACKAGE@' /dev/null '{}' ';' 2>/dev/null; \
|
||||
else \
|
||||
LC_ALL=C grep -i 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \
|
||||
fi; \
|
||||
} | grep -v 'libtool:' >/dev/null; then \
|
||||
package_gnu=yes; \
|
||||
else \
|
||||
package_gnu=no; \
|
||||
fi; \
|
||||
}; \
|
||||
if test "$$package_gnu" = "yes"; then \
|
||||
package_prefix='GNU '; \
|
||||
else \
|
||||
package_prefix=''; \
|
||||
fi; \
|
||||
if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \
|
||||
msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \
|
||||
else \
|
||||
msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \
|
||||
fi; \
|
||||
case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
|
||||
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
|
||||
--add-comments=TRANSLATORS: \
|
||||
--files-from=$(srcdir)/POTFILES.in \
|
||||
--copyright-holder='$(COPYRIGHT_HOLDER)' \
|
||||
--msgid-bugs-address="$$msgid_bugs_address" \
|
||||
$(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
|
||||
;; \
|
||||
*) \
|
||||
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
|
||||
--add-comments=TRANSLATORS: \
|
||||
--files-from=$(srcdir)/POTFILES.in \
|
||||
--copyright-holder='$(COPYRIGHT_HOLDER)' \
|
||||
--package-name="$${package_prefix}@PACKAGE@" \
|
||||
--package-version='@VERSION@' \
|
||||
--msgid-bugs-address="$$msgid_bugs_address" \
|
||||
$(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
|
||||
;; \
|
||||
esac
|
||||
test ! -f $(DOMAIN).po || { \
|
||||
if test -f $(srcdir)/$(DOMAIN).pot-header; then \
|
||||
sed -e '1,/^#$$/d' < $(DOMAIN).po > $(DOMAIN).1po && \
|
||||
cat $(srcdir)/$(DOMAIN).pot-header $(DOMAIN).1po > $(DOMAIN).po && \
|
||||
rm -f $(DOMAIN).1po \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||
sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
|
||||
sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \
|
||||
if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \
|
||||
rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \
|
||||
else \
|
||||
rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \
|
||||
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
|
||||
fi; \
|
||||
else \
|
||||
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
|
||||
fi; \
|
||||
}
|
||||
|
||||
# This rule has no dependencies: we don't need to update $(DOMAIN).pot at
|
||||
# every "make" invocation, only create it when it is missing.
|
||||
# Only "make $(DOMAIN).pot-update" or "make dist" will force an update.
|
||||
$(srcdir)/$(DOMAIN).pot:
|
||||
$(MAKE) $(DOMAIN).pot-update
|
||||
|
||||
# This target rebuilds a PO file if $(DOMAIN).pot has changed.
|
||||
# Note that a PO file is not touched if it doesn't need to be changed.
|
||||
$(POFILES): $(POFILESDEPS)
|
||||
@test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot
|
||||
@lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
|
||||
if test -f "$(srcdir)/$${lang}.po"; then \
|
||||
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||
echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
|
||||
cd $(srcdir) \
|
||||
&& { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].*) \
|
||||
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
|
||||
0.1[6-7] | 0.1[6-7].*) \
|
||||
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
|
||||
*) \
|
||||
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
|
||||
esac; \
|
||||
}; \
|
||||
else \
|
||||
$(MAKE) $${lang}.po-create; \
|
||||
fi
|
||||
|
||||
|
||||
install: install-exec install-data
|
||||
install-exec:
|
||||
install-data: install-data-@USE_NLS@
|
||||
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
|
||||
for file in $(DISTFILES.common) Makevars.template; do \
|
||||
$(INSTALL_DATA) $(srcdir)/$$file \
|
||||
$(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||
done; \
|
||||
for file in Makevars; do \
|
||||
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||
done; \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
install-data-no: all
|
||||
install-data-yes: all
|
||||
@catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||
$(mkdir_p) $(DESTDIR)$$dir; \
|
||||
if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \
|
||||
$(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \
|
||||
echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \
|
||||
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
|
||||
if test -n "$$lc"; then \
|
||||
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
|
||||
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
|
||||
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
|
||||
for file in *; do \
|
||||
if test -f $$file; then \
|
||||
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
|
||||
fi; \
|
||||
done); \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||
else \
|
||||
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
|
||||
:; \
|
||||
else \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
fi; \
|
||||
fi; \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||
ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
|
||||
ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
|
||||
cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||
echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \
|
||||
fi; \
|
||||
done; \
|
||||
done
|
||||
|
||||
install-strip: install
|
||||
|
||||
installdirs: installdirs-exec installdirs-data
|
||||
installdirs-exec:
|
||||
installdirs-data: installdirs-data-@USE_NLS@
|
||||
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
installdirs-data-no:
|
||||
installdirs-data-yes:
|
||||
@catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||
$(mkdir_p) $(DESTDIR)$$dir; \
|
||||
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
|
||||
if test -n "$$lc"; then \
|
||||
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
|
||||
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
|
||||
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
|
||||
for file in *; do \
|
||||
if test -f $$file; then \
|
||||
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
|
||||
fi; \
|
||||
done); \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||
else \
|
||||
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
|
||||
:; \
|
||||
else \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
fi; \
|
||||
fi; \
|
||||
fi; \
|
||||
done; \
|
||||
done
|
||||
|
||||
# Define this as empty until I found a useful application.
|
||||
installcheck:
|
||||
|
||||
uninstall: uninstall-exec uninstall-data
|
||||
uninstall-exec:
|
||||
uninstall-data: uninstall-data-@USE_NLS@
|
||||
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||
for file in $(DISTFILES.common) Makevars.template; do \
|
||||
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||
done; \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
uninstall-data-no:
|
||||
uninstall-data-yes:
|
||||
catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||
for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||
done; \
|
||||
done
|
||||
|
||||
check: all
|
||||
|
||||
info dvi ps pdf html tags TAGS ctags CTAGS ID:
|
||||
|
||||
install-dvi install-ps install-pdf install-html:
|
||||
|
||||
mostlyclean:
|
||||
rm -f remove-potcdate.sed
|
||||
rm -f $(srcdir)/stamp-poT
|
||||
rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
|
||||
rm -fr *.o
|
||||
|
||||
clean: mostlyclean
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile Makefile.in POTFILES
|
||||
|
||||
maintainer-clean: distclean
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
rm -f $(srcdir)/$(DOMAIN).pot $(srcdir)/stamp-po $(GMOFILES)
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
dist distdir:
|
||||
test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS)
|
||||
@$(MAKE) dist2
|
||||
# This is a separate target because 'update-po' must be executed before.
|
||||
dist2: $(srcdir)/stamp-po $(DISTFILES)
|
||||
@dists="$(DISTFILES)"; \
|
||||
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||
dists="$$dists Makevars.template"; \
|
||||
fi; \
|
||||
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||
dists="$$dists $(DOMAIN).pot stamp-po"; \
|
||||
else \
|
||||
case $(XGETTEXT) in \
|
||||
:) echo "Warning: Creating a tarball without '$(DOMAIN).pot', because a suitable 'xgettext' program was not found in PATH." 1>&2;; \
|
||||
*) echo "Warning: Creating a tarball without '$(DOMAIN).pot', because 'xgettext' found no strings to extract. Check the contents of the POTFILES.in file and the XGETTEXT_OPTIONS in the Makevars file." 1>&2;; \
|
||||
esac; \
|
||||
fi; \
|
||||
if test -f $(srcdir)/ChangeLog; then \
|
||||
dists="$$dists ChangeLog"; \
|
||||
fi; \
|
||||
for i in 0 1 2 3 4 5 6 7 8 9; do \
|
||||
if test -f $(srcdir)/ChangeLog.$$i; then \
|
||||
dists="$$dists ChangeLog.$$i"; \
|
||||
fi; \
|
||||
done; \
|
||||
if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \
|
||||
for file in $$dists; do \
|
||||
if test -f $$file; then \
|
||||
cp -p $$file $(distdir) || exit 1; \
|
||||
else \
|
||||
cp -p $(srcdir)/$$file $(distdir) || exit 1; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
update-po: Makefile
|
||||
$(MAKE) $(DOMAIN).pot-update
|
||||
test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
|
||||
$(MAKE) update-gmo
|
||||
|
||||
# General rule for creating PO files.
|
||||
|
||||
.nop.po-create:
|
||||
@lang=`echo $@ | sed -e 's/\.po-create$$//'`; \
|
||||
echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
|
||||
exit 1
|
||||
|
||||
# General rule for updating PO files.
|
||||
|
||||
.nop.po-update:
|
||||
@lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
|
||||
if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; fi; \
|
||||
tmpdir=`pwd`; \
|
||||
echo "$$lang:"; \
|
||||
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||
echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
|
||||
cd $(srcdir); \
|
||||
if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].*) \
|
||||
$(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
|
||||
0.1[6-7] | 0.1[6-7].*) \
|
||||
$(MSGMERGE) $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
|
||||
*) \
|
||||
$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
|
||||
esac; \
|
||||
}; then \
|
||||
if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
|
||||
rm -f $$tmpdir/$$lang.new.po; \
|
||||
else \
|
||||
if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
|
||||
:; \
|
||||
else \
|
||||
echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
fi; \
|
||||
else \
|
||||
echo "msgmerge for $$lang.po failed!" 1>&2; \
|
||||
rm -f $$tmpdir/$$lang.new.po; \
|
||||
fi
|
||||
|
||||
$(DUMMYPOFILES):
|
||||
|
||||
update-gmo: Makefile $(GMOFILES)
|
||||
@:
|
||||
|
||||
# Recreate Makefile by invoking config.status. Explicitly invoke the shell,
|
||||
# because execution permission bits may not work on the current file system.
|
||||
# Use @SHELL@, which is the shell determined by autoconf for the use by its
|
||||
# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient.
|
||||
Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@
|
||||
cd $(top_builddir) \
|
||||
&& @SHELL@ ./config.status $(subdir)/$@.in po-directories
|
||||
|
||||
force:
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make not to export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
# Makefile variables for PO directory in any package using GNU gettext.
|
||||
#
|
||||
# Copyright (C) 2003-2019 Free Software Foundation, Inc.
|
||||
# This file is free software; the Free Software Foundation gives
|
||||
# unlimited permission to use, copy, distribute, and modify it.
|
||||
|
||||
# Usually the message domain is the same as the package name.
|
||||
DOMAIN = $(PACKAGE)
|
||||
|
||||
# These two variables depend on the location of this directory.
|
||||
subdir = po
|
||||
top_builddir = ..
|
||||
|
||||
# These options get passed to xgettext.
|
||||
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
|
||||
|
||||
# This is the copyright holder that gets inserted into the header of the
|
||||
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
|
||||
# package. (Note that the msgstr strings, extracted from the package's
|
||||
# sources, belong to the copyright holder of the package.) Translators are
|
||||
# expected to transfer the copyright for their translations to this person
|
||||
# or entity, or to disclaim their copyright. The empty string stands for
|
||||
# the public domain; in this case the translators are expected to disclaim
|
||||
# their copyright.
|
||||
COPYRIGHT_HOLDER = Andrew Wood
|
||||
|
||||
# This tells whether or not to prepend "GNU " prefix to the package
|
||||
# name that gets inserted into the header of the $(DOMAIN).pot file.
|
||||
# Possible values are "yes", "no", or empty. If it is empty, try to
|
||||
# detect it automatically by scanning the files in $(top_srcdir) for
|
||||
# "GNU packagename" string.
|
||||
PACKAGE_GNU =
|
||||
|
||||
# This is the email address or URL to which the translators shall report
|
||||
# bugs in the untranslated strings:
|
||||
# - Strings which are not entire sentences, see the maintainer guidelines
|
||||
# in the GNU gettext documentation, section 'Preparing Strings'.
|
||||
# - Strings which use unclear terms or require additional context to be
|
||||
# understood.
|
||||
# - Strings which make invalid assumptions about notation of date, time or
|
||||
# money.
|
||||
# - Pluralisation problems.
|
||||
# - Incorrect English spelling.
|
||||
# - Incorrect formatting.
|
||||
# It can be your email address, or a mailing list address where translators
|
||||
# can write to without being subscribed, or the URL of a web page through
|
||||
# which the translators can contact you.
|
||||
MSGID_BUGS_ADDRESS =
|
||||
|
||||
# This is the list of locale categories, beyond LC_MESSAGES, for which the
|
||||
# message catalogs shall be used. It is usually empty.
|
||||
EXTRA_LOCALE_CATEGORIES =
|
||||
|
||||
# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt'
|
||||
# context. Possible values are "yes" and "no". Set this to yes if the
|
||||
# package uses functions taking also a message context, like pgettext(), or
|
||||
# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument.
|
||||
USE_MSGCTXT = no
|
||||
|
||||
# These options get passed to msgmerge.
|
||||
# Useful options are in particular:
|
||||
# --previous to keep previous msgids of translated messages,
|
||||
# --quiet to reduce the verbosity.
|
||||
MSGMERGE_OPTIONS =
|
||||
|
||||
# These options get passed to msginit.
|
||||
# If you want to disable line wrapping when writing PO files, add
|
||||
# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and
|
||||
# MSGINIT_OPTIONS.
|
||||
MSGINIT_OPTIONS =
|
||||
|
||||
# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
|
||||
# has changed. Possible values are "yes" and "no". Set this to no if
|
||||
# the POT file is checked in the repository and the version control
|
||||
# program ignores timestamps.
|
||||
PO_DEPENDS_ON_POT = yes
|
||||
|
||||
# This tells whether or not to forcibly update $(DOMAIN).pot and
|
||||
# regenerate PO files on "make dist". Possible values are "yes" and
|
||||
# "no". Set this to no if the POT file and PO files are maintained
|
||||
# externally.
|
||||
DIST_DEPENDS_ON_UPDATE_PO = yes
|
||||
@@ -0,0 +1,16 @@
|
||||
src/main/debug.c
|
||||
src/main/help.c
|
||||
src/main/main.c
|
||||
src/main/options.c
|
||||
src/main/remote.c
|
||||
src/main/version.c
|
||||
src/pv/cursor.c
|
||||
src/pv/display.c
|
||||
src/pv/file.c
|
||||
src/pv/loop.c
|
||||
src/pv/number.c
|
||||
src/pv/signal.c
|
||||
src/pv/state.c
|
||||
src/pv/string.c
|
||||
src/pv/transfer.c
|
||||
src/pv/watchpid.c
|
||||
+288
-254
@@ -1,7 +1,8 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-05 19:25+0100\n"
|
||||
"Report-Msgid-Bugs-To: pv@ivarch.com\n"
|
||||
"POT-Creation-Date: 2023-09-24 21:33+0100\n"
|
||||
"Language: de\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Date: 1999-06-01 15:18:29+0100\n"
|
||||
"From: Andrew Wood <ivarch@ubik>\n"
|
||||
@@ -19,399 +20,275 @@ msgstr ""
|
||||
"nls/intl/textdomain.c src/nls/intl-cat/cat-compat.c src/nls/intl-gett/intl-"
|
||||
"compat.c\n"
|
||||
|
||||
#: src/pv/cursor.c:80
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "Terminalname konnte nicht gelesen werden"
|
||||
|
||||
#: src/pv/cursor.c:125
|
||||
msgid "failed to open lock file"
|
||||
msgstr "Sperrdatei konnte nicht geöffnet werden"
|
||||
|
||||
#: src/pv/cursor.c:159
|
||||
msgid "lock attempt failed"
|
||||
msgstr "Sperrversuch fehlgeschlagen"
|
||||
|
||||
#: src/pv/cursor.c:409
|
||||
msgid "failed to open terminal"
|
||||
msgstr "Terminal konnte nicht geöffnet werden"
|
||||
|
||||
#: src/pv/display.c:138
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:143
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:558 src/pv/transfer.c:679
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "Puffer konnte nicht allokiert werden"
|
||||
|
||||
#: src/pv/display.c:618 src/pv/transfer.c:458
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:697 src/pv/display.c:702 src/pv/display.c:764
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/file.c:119
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "Konnte nicht versuchen, die Ausgabe zu starten"
|
||||
|
||||
#: src/pv/file.c:215
|
||||
msgid "failed to close file"
|
||||
msgstr "Datei konnte nicht geschlossen werden"
|
||||
|
||||
#: src/pv/file.c:238
|
||||
msgid "failed to read file"
|
||||
msgstr "Datei konnte nicht gelesen werden"
|
||||
|
||||
#: src/pv/file.c:248
|
||||
msgid "failed to stat file"
|
||||
msgstr "Dateiinformationen konnten nicht gelesen werden"
|
||||
|
||||
#: src/pv/file.c:257
|
||||
msgid "failed to stat output file"
|
||||
msgstr "Dateiinformationen für Ausgabe-Datei konnten nicht gelesen werden"
|
||||
|
||||
#: src/pv/file.c:280
|
||||
msgid "input file is output file"
|
||||
msgstr "Eingabe-Datei ist Ausgabe-Datei"
|
||||
|
||||
#: src/pv/loop.c:520 src/pv/loop.c:590 src/pv/loop.c:642 src/pv/watchpid.c:51
|
||||
#: src/pv/watchpid.c:74 src/pv/watchpid.c:84 src/pv/watchpid.c:115
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:33
|
||||
msgid "none"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:341
|
||||
msgid "read failed"
|
||||
msgstr "read-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:359
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "warnung: lesefehler erkannt"
|
||||
|
||||
#: src/pv/transfer.c:374
|
||||
msgid "file is not seekable"
|
||||
msgstr "datei ist nicht durchsuchbar"
|
||||
|
||||
#: src/pv/transfer.c:437
|
||||
msgid "failed to seek past error"
|
||||
msgstr "konnte den Fehler nicht überwinden"
|
||||
|
||||
#: src/pv/transfer.c:456
|
||||
msgid "skipped past read error"
|
||||
msgstr "über den Lesefehler hinaus verschoben"
|
||||
|
||||
#: src/pv/transfer.c:631
|
||||
msgid "write failed"
|
||||
msgstr "write-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
msgid "select call failed"
|
||||
msgstr "select-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/watchpid.c:76 src/pv/watchpid.c:86 src/pv/watchpid.c:117
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:120
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "keine normale Datei oder Blockgerät"
|
||||
|
||||
#: src/main/version.c:17
|
||||
#, c-format
|
||||
msgid "%s %s - Copyright %s %s"
|
||||
msgstr "%s %s - Copyright(C) %s %s"
|
||||
|
||||
#: src/main/version.c:20
|
||||
#, c-format
|
||||
msgid "Web site: %s"
|
||||
msgstr "Web-Site: %s"
|
||||
|
||||
#: src/main/version.c:23
|
||||
msgid ""
|
||||
"This program is free software, and is being distributed under the\n"
|
||||
"terms of the Artistic License 2.0."
|
||||
msgstr ""
|
||||
"Dieses Programm ist freie Software und wird unter den Bedingungen\n"
|
||||
"der Artistic License verbreitet."
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid ""
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
msgstr ""
|
||||
"Dieses Programm wird in der Hoffnung verbreitet, dass es nützlich sein "
|
||||
"wird,\n"
|
||||
"aber OHNE JEGLICHE GARANTIE; ohne die implizite Garantie von\n"
|
||||
"MARKTGÄNGIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK."
|
||||
|
||||
#: src/main/help.c:31
|
||||
#: src/main/help.c:283
|
||||
msgid "show progress bar"
|
||||
msgstr "Fortschritts-Anzeige"
|
||||
|
||||
#: src/main/help.c:33
|
||||
#: src/main/help.c:286
|
||||
msgid "show elapsed time"
|
||||
msgstr "zeige die verstrichene Zeit an"
|
||||
|
||||
#: src/main/help.c:35
|
||||
#: src/main/help.c:289
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "zeige die erwartete Zeit bis zum Ende an"
|
||||
|
||||
#: src/main/help.c:38
|
||||
#: src/main/help.c:292
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "zeige die absolute geschätzte Zeit bis zur Fertigstellung"
|
||||
|
||||
#: src/main/help.c:40
|
||||
#: src/main/help.c:295
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "zeige die Datentransferrate an"
|
||||
|
||||
#: src/main/help.c:42
|
||||
#: src/main/help.c:298
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:44
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "zeige die Anzahl von Bytes, die transferiert worden sind"
|
||||
|
||||
#: src/main/help.c:46
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "zeige, wie viel Prozent des Übertragungsbuffers in Benutzung sind"
|
||||
|
||||
#: src/main/help.c:47
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:48
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "NUM zeige die zuletzt geschriebenen NUM Bytes"
|
||||
|
||||
#: src/main/help.c:49
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:50
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "setze das Ausgabeformat auf FORMAT"
|
||||
|
||||
#: src/main/help.c:52
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "Ausgabe von Prozent-Angaben statt visueller Darstellung"
|
||||
|
||||
#: src/main/help.c:54
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "sämtliche Transferinformationen unterdrücken"
|
||||
|
||||
#: src/main/help.c:57
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "keine Ausgabe bevor das erste Byte übertragen wurde"
|
||||
|
||||
#: src/main/help.c:58 src/main/help.c:66
|
||||
#: src/main/help.c:300 src/main/help.c:328 src/main/help.c:340
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:59
|
||||
#: src/main/help.c:301
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:304
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "zeige die Anzahl von Bytes, die transferiert worden sind"
|
||||
|
||||
#: src/main/help.c:307
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:310
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "zeige, wie viel Prozent des Übertragungsbuffers in Benutzung sind"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:313
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "NUM zeige die zuletzt geschriebenen NUM Bytes"
|
||||
|
||||
#: src/main/help.c:315
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:316
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "setze das Ausgabeformat auf FORMAT"
|
||||
|
||||
#: src/main/help.c:319
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "Ausgabe von Prozent-Angaben statt visueller Darstellung"
|
||||
|
||||
#: src/main/help.c:322
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "sämtliche Transferinformationen unterdrücken"
|
||||
|
||||
#: src/main/help.c:326
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "keine Ausgabe bevor das erste Byte übertragen wurde"
|
||||
|
||||
#: src/main/help.c:329
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "SEC nichts anzeigen, bis SEC Sekunden vergangen sind"
|
||||
|
||||
#: src/main/help.c:60
|
||||
#: src/main/help.c:331
|
||||
msgid "SIZE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:61
|
||||
#: src/main/help.c:332
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "setze erwartete Datenlänge auf SIZE Byte"
|
||||
|
||||
#: src/main/help.c:63
|
||||
#: src/main/help.c:335
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "zähle Zeilen anstelle von Bytes"
|
||||
|
||||
#: src/main/help.c:65
|
||||
#: src/main/help.c:338
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "Zeilen sind nullterminiert"
|
||||
|
||||
#: src/main/help.c:67
|
||||
#: src/main/help.c:341
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aktualisiere Ausgabe nach SEC Sekunden Intervall"
|
||||
|
||||
#: src/main/help.c:68
|
||||
#: src/main/help.c:343
|
||||
msgid "WIDTH"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:69
|
||||
#: src/main/help.c:344
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "setze Terminal-Breite auf WIDTH Zeichen"
|
||||
|
||||
#: src/main/help.c:70
|
||||
#: src/main/help.c:346
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:71
|
||||
#: src/main/help.c:347
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "setze Terminal-Höhe auf HEIGHT Zeichen"
|
||||
|
||||
#: src/main/help.c:72
|
||||
#: src/main/help.c:349
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:73
|
||||
#: src/main/help.c:350
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "setze den NAMEn für visuelle Darstellung"
|
||||
|
||||
#: src/main/help.c:75
|
||||
#: src/main/help.c:353
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr ""
|
||||
"Ausgabe auch dann erzwingen, wenn der Fehlerausgabe-Kanal kein Terminal ist"
|
||||
|
||||
#: src/main/help.c:77
|
||||
#: src/main/help.c:356
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "benutze Escape-Sequenzen zur Cursor-Positionierung"
|
||||
|
||||
#: src/main/help.c:79
|
||||
#: src/main/help.c:359
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:80
|
||||
#: src/main/help.c:360
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "beschränke die Transferrate auf RATE Byte pro Sekunde"
|
||||
|
||||
#: src/main/help.c:81
|
||||
#: src/main/help.c:362 src/main/help.c:371
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:82
|
||||
#: src/main/help.c:363
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "BYTES benutze einen Puffer in der Größe von BYTES"
|
||||
|
||||
#: src/main/help.c:84
|
||||
#: src/main/help.c:366
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "anstelle von splice() immer read/write benutzen"
|
||||
|
||||
#: src/main/help.c:86
|
||||
#: src/main/help.c:369
|
||||
msgid "skip read errors in input"
|
||||
msgstr "Lesefehler in der Eingabe nicht beachten"
|
||||
|
||||
#: src/main/help.c:88
|
||||
#: src/main/help.c:372
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:375
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "anhalten, nachdem --size Bytes übertragen wurden"
|
||||
|
||||
#: src/main/help.c:90
|
||||
#: src/main/help.c:378
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:381
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:384
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:91
|
||||
#: src/main/help.c:388
|
||||
msgid "update settings of process PID"
|
||||
msgstr "Einstellungen der Prozess-PID updaten"
|
||||
|
||||
#: src/main/help.c:94
|
||||
#: src/main/help.c:392 src/main/help.c:407
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:95
|
||||
#: src/main/help.c:393
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "Prozess-ID in FILE speichern"
|
||||
|
||||
#: src/main/help.c:97
|
||||
#: src/main/help.c:396
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:98
|
||||
#: src/main/help.c:397
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "die vom Prozess PID geöffnete Datei FD beobachten"
|
||||
|
||||
#: src/main/help.c:101
|
||||
#: src/main/help.c:401
|
||||
msgid "show this help and exit"
|
||||
msgstr "zeige diese Hilfe und beende"
|
||||
|
||||
#: src/main/help.c:103
|
||||
#: src/main/help.c:404
|
||||
msgid "show version information and exit"
|
||||
msgstr "zeige Versionsinformationen und beende"
|
||||
|
||||
#: src/main/help.c:109
|
||||
#: src/main/help.c:408
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:433
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Syntax: %s [OPTION] [DATEI]..."
|
||||
|
||||
#: src/main/help.c:112
|
||||
#: src/main/help.c:444
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output,\n"
|
||||
"with monitoring."
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Verbindet DATEI(en) oder den Standard-Eingabe-Kanal mit dem\n"
|
||||
"Standard-Ausgabe-Kanal und misst den Datenstrom."
|
||||
"Verbindet DATEI(en) oder den Standard-Eingabe-Kanal mit dem Standard-Ausgabe-"
|
||||
"Kanal und misst den Datenstrom."
|
||||
|
||||
#: src/main/help.c:207
|
||||
msgid ""
|
||||
"Debugging is enabled; export the DEBUG environment variable to define the\n"
|
||||
"output filename.\n"
|
||||
msgstr ""
|
||||
"Das Debuggen ist aktiviert. Exportieren Sie die Umgebungsvariable DEBUG,\n"
|
||||
"um den Ausgabedateinamen zu definieren.\n"
|
||||
|
||||
#: src/main/help.c:211
|
||||
#: src/main/help.c:581
|
||||
#, c-format
|
||||
msgid "Please report any bugs to %s."
|
||||
msgstr "Bitte senden Sie Fehlerberichte an %s."
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Bitte senden Sie Fehlerberichte an %s"
|
||||
|
||||
#: src/main/main.c:74
|
||||
#: src/main/main.c:83
|
||||
msgid "state allocation failed"
|
||||
msgstr "Zustandszuweisung fehlgeschlagen"
|
||||
|
||||
#: src/main/main.c:246
|
||||
#, fuzzy
|
||||
msgid "failed to read terminal attributes"
|
||||
msgstr "Terminalname konnte nicht gelesen werden"
|
||||
|
||||
#: src/main/options.c:98
|
||||
#: src/main/options.c:173
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "`option' konnte nicht allokiert werden"
|
||||
|
||||
#: src/main/options.c:112
|
||||
#: src/main/options.c:192
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "`option' (argv) konnte nicht allokiert werden"
|
||||
|
||||
#: src/main/options.c:151
|
||||
#: src/main/options.c:254
|
||||
msgid "integer argument expected"
|
||||
msgstr "Ganzzahliges Argument erwartet"
|
||||
|
||||
#: src/main/options.c:162
|
||||
#: src/main/options.c:265
|
||||
msgid "numeric argument expected"
|
||||
msgstr "numerisches Argument erwartet"
|
||||
|
||||
#: src/main/options.c:173
|
||||
#: src/main/options.c:276
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "Prozess-ID oder PID:FD-Paar erwartet"
|
||||
|
||||
#: src/main/options.c:180
|
||||
#: src/main/options.c:283
|
||||
msgid "invalid process ID"
|
||||
msgstr "ungültige Prozess-ID"
|
||||
|
||||
#: src/main/options.c:316
|
||||
#: src/main/options.c:384 src/pv/file.c:323
|
||||
msgid "failed to stat file"
|
||||
msgstr "Dateiinformationen konnten nicht gelesen werden"
|
||||
|
||||
#: src/main/options.c:487
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "`%s --help' zeigt weitere Informationen an."
|
||||
|
||||
#: src/main/options.c:320
|
||||
#: src/main/options.c:489
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "`%s -h' zeigt weitere Informationen an."
|
||||
|
||||
#: src/main/options.c:336
|
||||
#: src/main/options.c:520
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -419,30 +296,187 @@ msgstr ""
|
||||
"Beim Anzeigen von Dateideskriptoren können keine Optionen für den "
|
||||
"Zeilenmodus oder den Übertragungsmodifikator verwendet werden"
|
||||
|
||||
#: src/main/options.c:344
|
||||
#: src/main/options.c:529
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"Beim Anzeigen von Dateideskriptoren können keine Zeilenmodus- oder "
|
||||
"Übertragungsmodifikatoroptionen verwendet werden."
|
||||
|
||||
#: src/main/options.c:352
|
||||
#: src/main/options.c:538
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
"kann keine Fernbedienung verwenden, wenn Dateideskriptoren angezeigt werden"
|
||||
|
||||
#: src/main/options.c:360
|
||||
#: src/main/options.c:547
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
"Dateien können beim Betrachten von Dateideskriptoren nicht übertragen werden"
|
||||
|
||||
#: src/main/options.c:368
|
||||
#: src/main/options.c:562
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "Nicht verfügbar auf Systemen ohne /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:221
|
||||
#: src/main/remote.c:242
|
||||
msgid "message not received"
|
||||
msgstr "Nachricht nicht empfangen"
|
||||
|
||||
#: src/main/remote.c:328
|
||||
#: src/main/remote.c:351
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr "IPC wird auf diesem System nicht unterstützt"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:29
|
||||
msgid "This is free software: you are free to change and redistribute it."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:30
|
||||
msgid "There is NO WARRANTY, to the extent permitted by law."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:32
|
||||
msgid "Project web site"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:87
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "Terminalname konnte nicht gelesen werden"
|
||||
|
||||
#: src/pv/cursor.c:130
|
||||
msgid "failed to open lock file"
|
||||
msgstr "Sperrdatei konnte nicht geöffnet werden"
|
||||
|
||||
#: src/pv/cursor.c:163
|
||||
msgid "lock attempt failed"
|
||||
msgstr "Sperrversuch fehlgeschlagen"
|
||||
|
||||
#: src/pv/cursor.c:424
|
||||
msgid "failed to open terminal"
|
||||
msgstr "Terminal konnte nicht geöffnet werden"
|
||||
|
||||
#: src/pv/display.c:187
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:199
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:701 src/pv/transfer.c:894
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "Puffer konnte nicht allokiert werden"
|
||||
|
||||
#: src/pv/display.c:763
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:768 src/pv/transfer.c:584
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/display.c:820 src/pv/display.c:833
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/file.c:148
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "Konnte nicht versuchen, die Ausgabe zu starten"
|
||||
|
||||
#: src/pv/file.c:293
|
||||
msgid "failed to close file"
|
||||
msgstr "Datei konnte nicht geschlossen werden"
|
||||
|
||||
#: src/pv/file.c:316
|
||||
msgid "failed to read file"
|
||||
msgstr "Datei konnte nicht gelesen werden"
|
||||
|
||||
#: src/pv/file.c:331
|
||||
msgid "failed to stat output file"
|
||||
msgstr "Dateiinformationen für Ausgabe-Datei konnten nicht gelesen werden"
|
||||
|
||||
#: src/pv/file.c:353
|
||||
msgid "input file is output file"
|
||||
msgstr "Eingabe-Datei ist Ausgabe-Datei"
|
||||
|
||||
#: src/pv/file.c:411
|
||||
msgid "(none)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:413
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:541 src/pv/loop.c:595 src/pv/loop.c:637 src/pv/watchpid.c:73
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102
|
||||
#: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158
|
||||
#: src/pv/watchpid.c:169 src/pv/watchpid.c:255 src/pv/watchpid.c:263
|
||||
#: src/pv/watchpid.c:294 src/pv/watchpid.c:314
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:36
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:385 src/pv/state.c:395
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:446
|
||||
msgid "read failed"
|
||||
msgstr "read-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:469
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "warnung: lesefehler erkannt"
|
||||
|
||||
#: src/pv/transfer.c:485
|
||||
msgid "file is not seekable"
|
||||
msgstr "datei ist nicht durchsuchbar"
|
||||
|
||||
#: src/pv/transfer.c:563
|
||||
msgid "failed to seek past error"
|
||||
msgstr "konnte den Fehler nicht überwinden"
|
||||
|
||||
#: src/pv/transfer.c:583
|
||||
msgid "skipped past read error"
|
||||
msgstr "über den Lesefehler hinaus verschoben"
|
||||
|
||||
#: src/pv/transfer.c:623
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:636
|
||||
msgid "failed to set alarm signal handler"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:759
|
||||
msgid "write failed"
|
||||
msgstr "write-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:985
|
||||
msgid "select call failed"
|
||||
msgstr "select-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:95 src/pv/watchpid.c:104
|
||||
#: src/pv/watchpid.c:150 src/pv/watchpid.c:159 src/pv/watchpid.c:171
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:104 src/pv/watchpid.c:171
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "keine normale Datei oder Blockgerät"
|
||||
+288
-254
@@ -1,7 +1,8 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-05 19:25+0100\n"
|
||||
"Report-Msgid-Bugs-To: pv@ivarch.com\n"
|
||||
"POT-Creation-Date: 2023-09-24 21:33+0100\n"
|
||||
"Language: fr\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Date: 1999-06-01 15:18:29+0100\n"
|
||||
"From: Andrew Wood <ivarch@ubik>\n"
|
||||
@@ -19,398 +20,274 @@ msgstr ""
|
||||
"nls/intl/textdomain.c src/nls/intl-cat/cat-compat.c src/nls/intl-gett/intl-"
|
||||
"compat.c\n"
|
||||
|
||||
#: src/pv/cursor.c:80
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "échec de lecture du nom du terminal"
|
||||
|
||||
#: src/pv/cursor.c:125
|
||||
msgid "failed to open lock file"
|
||||
msgstr "échec de l'ouverture du fichier de verrouillage"
|
||||
|
||||
#: src/pv/cursor.c:159
|
||||
msgid "lock attempt failed"
|
||||
msgstr "tentative de verrouillage échoué"
|
||||
|
||||
#: src/pv/cursor.c:409
|
||||
msgid "failed to open terminal"
|
||||
msgstr "l'ouverture du terminal a échoué"
|
||||
|
||||
#: src/pv/display.c:138
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:143
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:558 src/pv/transfer.c:679
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "l'allocation de mémoire tampon a échoué"
|
||||
|
||||
#: src/pv/display.c:618 src/pv/transfer.c:458
|
||||
msgid "B"
|
||||
msgstr "O"
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "B/s"
|
||||
msgstr "O/s"
|
||||
|
||||
#: src/pv/display.c:697 src/pv/display.c:702 src/pv/display.c:764
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/file.c:119
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "ne peut pas passer au début de la sortie"
|
||||
|
||||
#: src/pv/file.c:215
|
||||
msgid "failed to close file"
|
||||
msgstr "la fermeture du fichier a échoué"
|
||||
|
||||
#: src/pv/file.c:238
|
||||
msgid "failed to read file"
|
||||
msgstr "la lecture du fichier a échoué"
|
||||
|
||||
#: src/pv/file.c:248
|
||||
msgid "failed to stat file"
|
||||
msgstr "échec à statuer sur le fichier"
|
||||
|
||||
#: src/pv/file.c:257
|
||||
msgid "failed to stat output file"
|
||||
msgstr "échec à statuer sur le fichier de sortie"
|
||||
|
||||
#: src/pv/file.c:280
|
||||
msgid "input file is output file"
|
||||
msgstr "fichiers d'entré et de sortie sont les mêmes"
|
||||
|
||||
#: src/pv/loop.c:520 src/pv/loop.c:590 src/pv/loop.c:642 src/pv/watchpid.c:51
|
||||
#: src/pv/watchpid.c:74 src/pv/watchpid.c:84 src/pv/watchpid.c:115
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:33
|
||||
msgid "none"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:341
|
||||
msgid "read failed"
|
||||
msgstr "la lecture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:359
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "avertissement: erreurs de lecture détectées"
|
||||
|
||||
#: src/pv/transfer.c:374
|
||||
msgid "file is not seekable"
|
||||
msgstr "ne peut pas se déplacer dans le fichier"
|
||||
|
||||
#: src/pv/transfer.c:437
|
||||
msgid "failed to seek past error"
|
||||
msgstr "n'a pas réussi à dépasser l'erreur"
|
||||
|
||||
#: src/pv/transfer.c:456
|
||||
msgid "skipped past read error"
|
||||
msgstr "erreur de lecture dépassée"
|
||||
|
||||
#: src/pv/transfer.c:631
|
||||
msgid "write failed"
|
||||
msgstr "l'écriture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
msgid "select call failed"
|
||||
msgstr "appel de sélection a échoué"
|
||||
|
||||
#: src/pv/watchpid.c:76 src/pv/watchpid.c:86 src/pv/watchpid.c:117
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:120
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "pas un fichier ordinaire ou un périphérique de bloc"
|
||||
|
||||
#: src/main/version.c:17
|
||||
#, c-format
|
||||
msgid "%s %s - Copyright %s %s"
|
||||
msgstr "%s %s - Copyright(C) %s %s"
|
||||
|
||||
#: src/main/version.c:20
|
||||
#, c-format
|
||||
msgid "Web site: %s"
|
||||
msgstr "Site Web: %s"
|
||||
|
||||
#: src/main/version.c:23
|
||||
msgid ""
|
||||
"This program is free software, and is being distributed under the\n"
|
||||
"terms of the Artistic License 2.0."
|
||||
msgstr ""
|
||||
"Ce programme est un logiciel libre et est distribué sous les termes\n"
|
||||
"anglophone de la Licence Artistique 2.0 (Artistic License 2.0)."
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid ""
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
msgstr ""
|
||||
"Ce programme est distribué dans l'espoir qu'il sera utile, mais\n"
|
||||
"SANS GARANTIE AUCUNE; ni même de garantie sous-entendu que le\n"
|
||||
"programme soit COMMERCIALISABLE ou APPLICABLE À UNE TÂCHE\n"
|
||||
"PARTICULIÈRE."
|
||||
|
||||
#: src/main/help.c:31
|
||||
#: src/main/help.c:283
|
||||
msgid "show progress bar"
|
||||
msgstr "affiche la barre de progression"
|
||||
|
||||
#: src/main/help.c:33
|
||||
#: src/main/help.c:286
|
||||
msgid "show elapsed time"
|
||||
msgstr "affiche le temps écoulé"
|
||||
|
||||
#: src/main/help.c:35
|
||||
#: src/main/help.c:289
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "affiche l'heure approximative de l'achèvement de la tâche"
|
||||
|
||||
#: src/main/help.c:38
|
||||
#: src/main/help.c:292
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "affiche l'heure absolute de l'achèvement de la tâche"
|
||||
|
||||
#: src/main/help.c:40
|
||||
#: src/main/help.c:295
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "affiche le taux de tranfert des données"
|
||||
|
||||
#: src/main/help.c:42
|
||||
#: src/main/help.c:298
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "afficher le compteur de taux moyen de transfert de données"
|
||||
|
||||
#: src/main/help.c:44
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "affiche le nombre d'octets transférés"
|
||||
|
||||
#: src/main/help.c:46
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "afficher le pourcentage de tampon de transfert utilisé"
|
||||
|
||||
#: src/main/help.c:47
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:48
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "affiche NUM octets pour la dernière fois écrits"
|
||||
|
||||
#: src/main/help.c:49
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:50
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "définir le format de sortie sur FORMAT"
|
||||
|
||||
#: src/main/help.c:52
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "imprime en pourcentage, pas les informations visuelles"
|
||||
|
||||
#: src/main/help.c:54
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "n'afficher aucune information de transfert"
|
||||
|
||||
#: src/main/help.c:57
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "ne rien afficher avant qu'au moins un octet soit tranféré"
|
||||
|
||||
#: src/main/help.c:58 src/main/help.c:66
|
||||
#: src/main/help.c:300 src/main/help.c:328 src/main/help.c:340
|
||||
msgid "SEC"
|
||||
msgstr "SEC"
|
||||
|
||||
#: src/main/help.c:59
|
||||
#: src/main/help.c:301
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:304
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "affiche le nombre d'octets transférés"
|
||||
|
||||
#: src/main/help.c:307
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:310
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "afficher le pourcentage de tampon de transfert utilisé"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:313
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "affiche NUM octets pour la dernière fois écrits"
|
||||
|
||||
#: src/main/help.c:315
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:316
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "définir le format de sortie sur FORMAT"
|
||||
|
||||
#: src/main/help.c:319
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "imprime en pourcentage, pas les informations visuelles"
|
||||
|
||||
#: src/main/help.c:322
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "n'afficher aucune information de transfert"
|
||||
|
||||
#: src/main/help.c:326
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "ne rien afficher avant qu'au moins un octet soit tranféré"
|
||||
|
||||
#: src/main/help.c:329
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "n'afficher rien jusqu'à ce que SEC secondes se soient écoulées"
|
||||
|
||||
#: src/main/help.c:60
|
||||
#: src/main/help.c:331
|
||||
msgid "SIZE"
|
||||
msgstr "TAILLE"
|
||||
|
||||
#: src/main/help.c:61
|
||||
#: src/main/help.c:332
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "ajuste la taille estimée des données à TAILLE octets"
|
||||
|
||||
#: src/main/help.c:63
|
||||
#: src/main/help.c:335
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "compte les lignes au lieu des octets"
|
||||
|
||||
#: src/main/help.c:65
|
||||
#: src/main/help.c:338
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "les lignes sont terminées par un nul"
|
||||
|
||||
#: src/main/help.c:67
|
||||
#: src/main/help.c:341
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "mise-à-jour toute les SEC secondes"
|
||||
|
||||
#: src/main/help.c:68
|
||||
#: src/main/help.c:343
|
||||
msgid "WIDTH"
|
||||
msgstr "LARGEUR"
|
||||
|
||||
#: src/main/help.c:69
|
||||
#: src/main/help.c:344
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "présumer la largeur du terminal à LARGEUR caractères"
|
||||
|
||||
#: src/main/help.c:70
|
||||
#: src/main/help.c:346
|
||||
msgid "HEIGHT"
|
||||
msgstr "HAUTEUR"
|
||||
|
||||
#: src/main/help.c:71
|
||||
#: src/main/help.c:347
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "présumer la hauteur du terminal à HAUTEUR lignes"
|
||||
|
||||
#: src/main/help.c:72
|
||||
#: src/main/help.c:349
|
||||
msgid "NAME"
|
||||
msgstr "NOM"
|
||||
|
||||
#: src/main/help.c:73
|
||||
#: src/main/help.c:350
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "préfixer les informations visuelles avec NOM"
|
||||
|
||||
#: src/main/help.c:75
|
||||
#: src/main/help.c:353
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "imprime vers la sortie d'erreur même si ce n'est pas un terminal"
|
||||
|
||||
#: src/main/help.c:77
|
||||
#: src/main/help.c:356
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "utiliser les séquences d'échappements de positionnement de curseur"
|
||||
|
||||
#: src/main/help.c:79
|
||||
#: src/main/help.c:359
|
||||
msgid "RATE"
|
||||
msgstr "TAUX"
|
||||
|
||||
#: src/main/help.c:80
|
||||
#: src/main/help.c:360
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "limite le taux de transfer à TAUX octets par seconde"
|
||||
|
||||
#: src/main/help.c:81
|
||||
#: src/main/help.c:362 src/main/help.c:371
|
||||
msgid "BYTES"
|
||||
msgstr "OCTETS"
|
||||
|
||||
#: src/main/help.c:82
|
||||
#: src/main/help.c:363
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "Utiliser une mémoire tampon de OCTETS octets"
|
||||
|
||||
#: src/main/help.c:84
|
||||
#: src/main/help.c:366
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "n'utilisez jamais splice(), utilisez toujours read/write"
|
||||
|
||||
#: src/main/help.c:86
|
||||
#: src/main/help.c:369
|
||||
msgid "skip read errors in input"
|
||||
msgstr "ignorer les erreurs de lecture dans l'entrée"
|
||||
|
||||
#: src/main/help.c:88
|
||||
#: src/main/help.c:372
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:375
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "arrêter après le transfert de --size octets"
|
||||
|
||||
#: src/main/help.c:90
|
||||
#: src/main/help.c:378
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:381
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:384
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:91
|
||||
#: src/main/help.c:388
|
||||
msgid "update settings of process PID"
|
||||
msgstr "mettre-à-jour la configuration du processus PID"
|
||||
|
||||
#: src/main/help.c:94
|
||||
#: src/main/help.c:392 src/main/help.c:407
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:95
|
||||
#: src/main/help.c:393
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "enregistrer l'ID de processus dans FILE"
|
||||
|
||||
#: src/main/help.c:97
|
||||
#: src/main/help.c:396
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:98
|
||||
#: src/main/help.c:397
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "regarder le fichier FD ouvert par le processus PID"
|
||||
|
||||
#: src/main/help.c:101
|
||||
#: src/main/help.c:401
|
||||
msgid "show this help and exit"
|
||||
msgstr "afficher cette aide puis quitter"
|
||||
|
||||
#: src/main/help.c:103
|
||||
#: src/main/help.c:404
|
||||
msgid "show version information and exit"
|
||||
msgstr "afficher la version puis quitter"
|
||||
|
||||
#: src/main/help.c:109
|
||||
#: src/main/help.c:408
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:433
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Utilisation : %s [OPTIONS] [FICHIER]..."
|
||||
|
||||
#: src/main/help.c:112
|
||||
#: src/main/help.c:444
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output,\n"
|
||||
"with monitoring."
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Concatène FICHIER(s), ou l'entrée standard, sur la sortie standard\n"
|
||||
"avec monitorage."
|
||||
"Concatène FICHIER(s), ou l'entrée standard, sur la sortie standard avec "
|
||||
"monitorage."
|
||||
|
||||
#: src/main/help.c:207
|
||||
msgid ""
|
||||
"Debugging is enabled; export the DEBUG environment variable to define the\n"
|
||||
"output filename.\n"
|
||||
msgstr ""
|
||||
"Le débogage est activé; exportez la variable d'environnement DEBUG pour\n"
|
||||
"définir le nom du fichier de sortie.\n"
|
||||
|
||||
#: src/main/help.c:211
|
||||
#: src/main/help.c:581
|
||||
#, c-format
|
||||
msgid "Please report any bugs to %s."
|
||||
msgstr "SVP rapporter touts bogues à %s."
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "SVP rapporter touts bogues à %s"
|
||||
|
||||
#: src/main/main.c:74
|
||||
#: src/main/main.c:83
|
||||
msgid "state allocation failed"
|
||||
msgstr "échec de l'allocation de mémoire de condition"
|
||||
|
||||
#: src/main/main.c:246
|
||||
#, fuzzy
|
||||
msgid "failed to read terminal attributes"
|
||||
msgstr "échec de lecture du nom du terminal"
|
||||
|
||||
#: src/main/options.c:98
|
||||
#: src/main/options.c:173
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "l'allocation pour la structure d'une option a echoué"
|
||||
|
||||
#: src/main/options.c:112
|
||||
#: src/main/options.c:192
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "l'allocation pour la structure de l'option argv a echoué"
|
||||
|
||||
#: src/main/options.c:151
|
||||
#: src/main/options.c:254
|
||||
msgid "integer argument expected"
|
||||
msgstr "Valeur entière attendue"
|
||||
|
||||
#: src/main/options.c:162
|
||||
#: src/main/options.c:265
|
||||
msgid "numeric argument expected"
|
||||
msgstr "Valeur numérique attendue"
|
||||
|
||||
#: src/main/options.c:173
|
||||
#: src/main/options.c:276
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "ID de processus ou paire pid:fd attendue"
|
||||
|
||||
#: src/main/options.c:180
|
||||
#: src/main/options.c:283
|
||||
msgid "invalid process ID"
|
||||
msgstr "ID de processus non valide"
|
||||
|
||||
#: src/main/options.c:316
|
||||
#: src/main/options.c:384 src/pv/file.c:323
|
||||
msgid "failed to stat file"
|
||||
msgstr "échec à statuer sur le fichier"
|
||||
|
||||
#: src/main/options.c:487
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Essayez `%s --help' pour plus d'information."
|
||||
|
||||
#: src/main/options.c:320
|
||||
#: src/main/options.c:489
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Essayez `%s -h' pour plus d'information."
|
||||
|
||||
#: src/main/options.c:336
|
||||
#: src/main/options.c:520
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -418,32 +295,189 @@ msgstr ""
|
||||
"impossible d'utiliser le mode ligne ou les options de modificateur de "
|
||||
"transfert lors de la visualisation des descripteurs de fichiers"
|
||||
|
||||
#: src/main/options.c:344
|
||||
#: src/main/options.c:529
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"impossible d'utiliser le positionnement du curseur lors de la visualisation "
|
||||
"des descripteurs de fichier"
|
||||
|
||||
#: src/main/options.c:352
|
||||
#: src/main/options.c:538
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
"impossible d'utiliser la télécommande lors de la visualisation des "
|
||||
"descripteurs de fichiers"
|
||||
|
||||
#: src/main/options.c:360
|
||||
#: src/main/options.c:547
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
"impossible de transférer des fichiers lorsque vous regardez des descripteurs "
|
||||
"de fichiers"
|
||||
|
||||
#: src/main/options.c:368
|
||||
#: src/main/options.c:562
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "non disponible sur les systèmes sans /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:221
|
||||
#: src/main/remote.c:242
|
||||
msgid "message not received"
|
||||
msgstr "message non reçu"
|
||||
|
||||
#: src/main/remote.c:328
|
||||
#: src/main/remote.c:351
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr "IPC non pris en charge sur ce système"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:29
|
||||
msgid "This is free software: you are free to change and redistribute it."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:30
|
||||
msgid "There is NO WARRANTY, to the extent permitted by law."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:32
|
||||
msgid "Project web site"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:87
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "échec de lecture du nom du terminal"
|
||||
|
||||
#: src/pv/cursor.c:130
|
||||
msgid "failed to open lock file"
|
||||
msgstr "échec de l'ouverture du fichier de verrouillage"
|
||||
|
||||
#: src/pv/cursor.c:163
|
||||
msgid "lock attempt failed"
|
||||
msgstr "tentative de verrouillage échoué"
|
||||
|
||||
#: src/pv/cursor.c:424
|
||||
msgid "failed to open terminal"
|
||||
msgstr "l'ouverture du terminal a échoué"
|
||||
|
||||
#: src/pv/display.c:187
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:199
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:701 src/pv/transfer.c:894
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "l'allocation de mémoire tampon a échoué"
|
||||
|
||||
#: src/pv/display.c:763
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:768 src/pv/transfer.c:584
|
||||
msgid "B"
|
||||
msgstr "O"
|
||||
|
||||
#: src/pv/display.c:820 src/pv/display.c:833
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
msgid "B/s"
|
||||
msgstr "O/s"
|
||||
|
||||
#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/file.c:148
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "ne peut pas passer au début de la sortie"
|
||||
|
||||
#: src/pv/file.c:293
|
||||
msgid "failed to close file"
|
||||
msgstr "la fermeture du fichier a échoué"
|
||||
|
||||
#: src/pv/file.c:316
|
||||
msgid "failed to read file"
|
||||
msgstr "la lecture du fichier a échoué"
|
||||
|
||||
#: src/pv/file.c:331
|
||||
msgid "failed to stat output file"
|
||||
msgstr "échec à statuer sur le fichier de sortie"
|
||||
|
||||
#: src/pv/file.c:353
|
||||
msgid "input file is output file"
|
||||
msgstr "fichiers d'entré et de sortie sont les mêmes"
|
||||
|
||||
#: src/pv/file.c:411
|
||||
msgid "(none)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:413
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:541 src/pv/loop.c:595 src/pv/loop.c:637 src/pv/watchpid.c:73
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102
|
||||
#: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158
|
||||
#: src/pv/watchpid.c:169 src/pv/watchpid.c:255 src/pv/watchpid.c:263
|
||||
#: src/pv/watchpid.c:294 src/pv/watchpid.c:314
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:36
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:385 src/pv/state.c:395
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:446
|
||||
msgid "read failed"
|
||||
msgstr "la lecture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:469
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "avertissement: erreurs de lecture détectées"
|
||||
|
||||
#: src/pv/transfer.c:485
|
||||
msgid "file is not seekable"
|
||||
msgstr "ne peut pas se déplacer dans le fichier"
|
||||
|
||||
#: src/pv/transfer.c:563
|
||||
msgid "failed to seek past error"
|
||||
msgstr "n'a pas réussi à dépasser l'erreur"
|
||||
|
||||
#: src/pv/transfer.c:583
|
||||
msgid "skipped past read error"
|
||||
msgstr "erreur de lecture dépassée"
|
||||
|
||||
#: src/pv/transfer.c:623
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:636
|
||||
msgid "failed to set alarm signal handler"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:759
|
||||
msgid "write failed"
|
||||
msgstr "l'écriture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:985
|
||||
msgid "select call failed"
|
||||
msgstr "appel de sélection a échoué"
|
||||
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:95 src/pv/watchpid.c:104
|
||||
#: src/pv/watchpid.c:150 src/pv/watchpid.c:159 src/pv/watchpid.c:171
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:104 src/pv/watchpid.c:171
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "pas un fichier ordinaire ou un périphérique de bloc"
|
||||
@@ -0,0 +1,472 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR Free Software Foundation, Inc.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: pv@ivarch.com\n"
|
||||
"POT-Creation-Date: 2023-09-24 21:33+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/main/help.c:283
|
||||
msgid "show progress bar"
|
||||
msgstr "pokaż pasek postępu"
|
||||
|
||||
#: src/main/help.c:286
|
||||
msgid "show elapsed time"
|
||||
msgstr "pokaż upływający czas"
|
||||
|
||||
#: src/main/help.c:289
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "pokaż szacowany czas ukończenia"
|
||||
|
||||
#: src/main/help.c:292
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:295
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "pokaż licznik prędkości przesyłania"
|
||||
|
||||
#: src/main/help.c:298
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:300 src/main/help.c:328 src/main/help.c:340
|
||||
msgid "SEC"
|
||||
msgstr "WARTOŚĆ"
|
||||
|
||||
#: src/main/help.c:301
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:304
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "pokaż ilość przesłanych bajtów"
|
||||
|
||||
#: src/main/help.c:307
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:310
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:313
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:315
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:316
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:319
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "wświetl wyjście procentowo, bez graficznej prezentacji"
|
||||
|
||||
#: src/main/help.c:322
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "nie wyświetlaj żadnych informacji o przesyłaniu"
|
||||
|
||||
#: src/main/help.c:326
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "nie wyświetlaj nic aż do pierwszego przesłanego bajtu"
|
||||
|
||||
#: src/main/help.c:329
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:331
|
||||
msgid "SIZE"
|
||||
msgstr "WARTOŚĆ"
|
||||
|
||||
#: src/main/help.c:332
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "ustaw oczekiwany rozmiar danych na WARTOŚĆ bajtów"
|
||||
|
||||
#: src/main/help.c:335
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:338
|
||||
msgid "lines are null-terminated"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:341
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aktualizuj co każde WARTOŚĆ sekund"
|
||||
|
||||
#: src/main/help.c:343
|
||||
msgid "WIDTH"
|
||||
msgstr "WARTOŚĆ"
|
||||
|
||||
#: src/main/help.c:344
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "przyjmij, że terminal ma szerokość WARTOŚĆ znaków"
|
||||
|
||||
#: src/main/help.c:346
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:347
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "przyjmij, że terminal ma szerokość WARTOŚĆ znaków"
|
||||
|
||||
#: src/main/help.c:349
|
||||
msgid "NAME"
|
||||
msgstr "NAZWA"
|
||||
|
||||
#: src/main/help.c:350
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "poprzedź informacje prefiksem NAZWA"
|
||||
|
||||
#: src/main/help.c:353
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "pokaż wyjście nawet gdy błędy nie są typu terminal"
|
||||
|
||||
#: src/main/help.c:356
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "używaj sekwencji escape do pozycjonowania"
|
||||
|
||||
#: src/main/help.c:359
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:360
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "ogranicz przesyłane dane do RATE bajtów na sekundę"
|
||||
|
||||
#: src/main/help.c:362 src/main/help.c:371
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:363
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:366
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:369
|
||||
msgid "skip read errors in input"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:372
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:375
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:378
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:381
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:384
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:388
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:392 src/main/help.c:407
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:393
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:396
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:397
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:401
|
||||
msgid "show this help and exit"
|
||||
msgstr "wyświetl te informacje z pomocą i wyjdź"
|
||||
|
||||
#: src/main/help.c:404
|
||||
msgid "show version information and exit"
|
||||
msgstr "wyświetl informacje o wersji i wyjdź"
|
||||
|
||||
#: src/main/help.c:408
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:433
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Sposób użycia: %s [OPCJA] [PLIK]..."
|
||||
|
||||
#: src/main/help.c:444
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Łączenie PLIK(ów) lub wejścia standardowego, do wyjścia standardowego z "
|
||||
"monitoringiem."
|
||||
|
||||
#: src/main/help.c:581
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Proszę przesyłać zgłoszenia błędów do %s"
|
||||
|
||||
#: src/main/main.c:83
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:173
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "nie udało się zaalokować struktur opcji"
|
||||
|
||||
#: src/main/options.c:192
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "nie udało się zaalokować struktur opcji argv"
|
||||
|
||||
#: src/main/options.c:254
|
||||
msgid "integer argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:265
|
||||
msgid "numeric argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:276
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:283
|
||||
msgid "invalid process ID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:384 src/pv/file.c:323
|
||||
msgid "failed to stat file"
|
||||
msgstr "nie udało się wykonać operacji stat na pliku"
|
||||
|
||||
#: src/main/options.c:487
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Spróbuj `%s --help' by uzyskać więcej informacji"
|
||||
|
||||
#: src/main/options.c:489
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Spróbuj `%s -h' by uzyskać więcej informacji"
|
||||
|
||||
#: src/main/options.c:520
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:529
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:538
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:547
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:562
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:242
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:351
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:29
|
||||
msgid "This is free software: you are free to change and redistribute it."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:30
|
||||
msgid "There is NO WARRANTY, to the extent permitted by law."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:32
|
||||
msgid "Project web site"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:87
|
||||
msgid "failed to get terminal name"
|
||||
msgstr ""
|
||||
|
||||
# "Przewidywany czas ukończenia" for ETA is too long
|
||||
#: src/pv/cursor.c:130
|
||||
msgid "failed to open lock file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:163
|
||||
msgid "lock attempt failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:424
|
||||
msgid "failed to open terminal"
|
||||
msgstr "nie udało się otworzyć terminala"
|
||||
|
||||
#: src/pv/display.c:187
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:199
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:701 src/pv/transfer.c:894
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "nie udało się zaalokować bufora"
|
||||
|
||||
#: src/pv/display.c:763
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:768 src/pv/transfer.c:584
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/display.c:820 src/pv/display.c:833
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/file.c:148
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr ""
|
||||
|
||||
# "Przewidywany czas ukończenia" for ETA is too long
|
||||
#: src/pv/file.c:293
|
||||
msgid "failed to close file"
|
||||
msgstr "nie udało się zamknąć pliku"
|
||||
|
||||
#: src/pv/file.c:316
|
||||
msgid "failed to read file"
|
||||
msgstr "nie udało się odczytać pliku"
|
||||
|
||||
#: src/pv/file.c:331
|
||||
msgid "failed to stat output file"
|
||||
msgstr "nie udało się wykonać operacji stat na pliku wyjściowym"
|
||||
|
||||
#: src/pv/file.c:353
|
||||
msgid "input file is output file"
|
||||
msgstr "plik wejściowy jest zarazem plikiem wyjściowym"
|
||||
|
||||
#: src/pv/file.c:411
|
||||
msgid "(none)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:413
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:541 src/pv/loop.c:595 src/pv/loop.c:637 src/pv/watchpid.c:73
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102
|
||||
#: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158
|
||||
#: src/pv/watchpid.c:169 src/pv/watchpid.c:255 src/pv/watchpid.c:263
|
||||
#: src/pv/watchpid.c:294 src/pv/watchpid.c:314
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:36
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:385 src/pv/state.c:395
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:446
|
||||
msgid "read failed"
|
||||
msgstr "błąd odczytu"
|
||||
|
||||
#: src/pv/transfer.c:469
|
||||
msgid "warning: read errors detected"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:485
|
||||
msgid "file is not seekable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:563
|
||||
msgid "failed to seek past error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:583
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:623
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:636
|
||||
msgid "failed to set alarm signal handler"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:759
|
||||
msgid "write failed"
|
||||
msgstr "błąd zapisu"
|
||||
|
||||
#: src/pv/transfer.c:985
|
||||
msgid "select call failed"
|
||||
msgstr "nie udało się wywołać funkcji select"
|
||||
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:95 src/pv/watchpid.c:104
|
||||
#: src/pv/watchpid.c:150 src/pv/watchpid.c:159 src/pv/watchpid.c:171
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:104 src/pv/watchpid.c:171
|
||||
msgid "not a regular file or block device"
|
||||
msgstr ""
|
||||
+288
-253
@@ -5,406 +5,284 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-05 19:25+0100\n"
|
||||
"Report-Msgid-Bugs-To: pv@ivarch.com\n"
|
||||
"POT-Creation-Date: 2023-09-24 21:33+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: pt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/pv/cursor.c:80
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "erro ao ler o nome do terminal"
|
||||
|
||||
#: src/pv/cursor.c:125
|
||||
msgid "failed to open lock file"
|
||||
msgstr "erro ao abrir arquivo de bloqueio"
|
||||
|
||||
#: src/pv/cursor.c:159
|
||||
msgid "lock attempt failed"
|
||||
msgstr "tentativa de bloqueio falhou"
|
||||
|
||||
#: src/pv/cursor.c:409
|
||||
msgid "failed to open terminal"
|
||||
msgstr "erro abrindo o terminal"
|
||||
|
||||
#: src/pv/display.c:138
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:143
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:558 src/pv/transfer.c:679
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "erro alocando o buffer"
|
||||
|
||||
#: src/pv/display.c:618 src/pv/transfer.c:458
|
||||
msgid "B"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
#: src/pv/display.c:697 src/pv/display.c:702 src/pv/display.c:764
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/file.c:119
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "não pode mover para o início da produção"
|
||||
|
||||
#: src/pv/file.c:215
|
||||
msgid "failed to close file"
|
||||
msgstr "erro fechando o arquivo"
|
||||
|
||||
#: src/pv/file.c:238
|
||||
msgid "failed to read file"
|
||||
msgstr "erro lendo o arquivo"
|
||||
|
||||
#: src/pv/file.c:248
|
||||
msgid "failed to stat file"
|
||||
msgstr "erro obtendo informações do arquivo"
|
||||
|
||||
#: src/pv/file.c:257
|
||||
msgid "failed to stat output file"
|
||||
msgstr "erro obtendo informações do arquivo de saída"
|
||||
|
||||
#: src/pv/file.c:280
|
||||
msgid "input file is output file"
|
||||
msgstr "os arquivos de entrada e saída são o mesmo"
|
||||
|
||||
#: src/pv/loop.c:520 src/pv/loop.c:590 src/pv/loop.c:642 src/pv/watchpid.c:51
|
||||
#: src/pv/watchpid.c:74 src/pv/watchpid.c:84 src/pv/watchpid.c:115
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:33
|
||||
msgid "none"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:341
|
||||
msgid "read failed"
|
||||
msgstr "erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:359
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "aviso: erros de leitura detectados"
|
||||
|
||||
#: src/pv/transfer.c:374
|
||||
msgid "file is not seekable"
|
||||
msgstr "não pode mover dentro do arquivo"
|
||||
|
||||
#: src/pv/transfer.c:437
|
||||
msgid "failed to seek past error"
|
||||
msgstr "não pode ir além do erro"
|
||||
|
||||
#: src/pv/transfer.c:456
|
||||
msgid "skipped past read error"
|
||||
msgstr "ignorado erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:631
|
||||
msgid "write failed"
|
||||
msgstr "erro de gravação"
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
msgid "select call failed"
|
||||
msgstr "erro na chamada da função select"
|
||||
|
||||
#: src/pv/watchpid.c:76 src/pv/watchpid.c:86 src/pv/watchpid.c:117
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:120
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "não é um arquivo regular ou dispositivo de bloqueio"
|
||||
|
||||
#: src/main/version.c:17
|
||||
#, c-format
|
||||
msgid "%s %s - Copyright %s %s"
|
||||
msgstr "%s %s - Copyright(C) %s %s"
|
||||
|
||||
#: src/main/version.c:20
|
||||
#, c-format
|
||||
msgid "Web site: %s"
|
||||
msgstr "Site: %s"
|
||||
|
||||
#: src/main/version.c:23
|
||||
msgid ""
|
||||
"This program is free software, and is being distributed under the\n"
|
||||
"terms of the Artistic License 2.0."
|
||||
msgstr ""
|
||||
"Este programa é um software livre, distribuído sob os termos da\n"
|
||||
"Licença Artística."
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid ""
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
msgstr ""
|
||||
"Este programa é distribuído com o intuito de que seja útil,\n"
|
||||
"porém SEM QUAISQUER GARANTIAS; sem inclusive as garantias implícitas de\n"
|
||||
"COMERCIALIZAÇÃO e ADEQUAÇÃO A OBJETIVOS PARTICULARES."
|
||||
|
||||
#: src/main/help.c:31
|
||||
#: src/main/help.c:283
|
||||
msgid "show progress bar"
|
||||
msgstr "exibe barra de progressão"
|
||||
|
||||
#: src/main/help.c:33
|
||||
#: src/main/help.c:286
|
||||
msgid "show elapsed time"
|
||||
msgstr "exibe tempo passado"
|
||||
|
||||
#: src/main/help.c:35
|
||||
#: src/main/help.c:289
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "exibe o tempo estimado de término"
|
||||
|
||||
#: src/main/help.c:38
|
||||
#: src/main/help.c:292
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "exibe o tempo absoluto estimado de término"
|
||||
|
||||
#: src/main/help.c:40
|
||||
#: src/main/help.c:295
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "exibe a taxa de transferência"
|
||||
|
||||
#: src/main/help.c:42
|
||||
#: src/main/help.c:298
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "exibe o contador da taxa média de transferência de dados"
|
||||
|
||||
#: src/main/help.c:44
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "exibe a quantidade de bytes transferidos"
|
||||
|
||||
#: src/main/help.c:46
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "exibe a porcentagem de buffer de transferência em uso"
|
||||
|
||||
#: src/main/help.c:47
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:48
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "exibe NUM bytes gravados pela última vez"
|
||||
|
||||
#: src/main/help.c:49
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:50
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "definir o formato de saída para FORMAT"
|
||||
|
||||
#: src/main/help.c:52
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "exibe apenas as porcentagens, sem informações visuais"
|
||||
|
||||
#: src/main/help.c:54
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "executa programa sem exibir quaisquer informações"
|
||||
|
||||
#: src/main/help.c:57
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "não exibe nada até iniciar o processamento"
|
||||
|
||||
#: src/main/help.c:58 src/main/help.c:66
|
||||
#: src/main/help.c:300 src/main/help.c:328 src/main/help.c:340
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:59
|
||||
#: src/main/help.c:301
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:304
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "exibe a quantidade de bytes transferidos"
|
||||
|
||||
#: src/main/help.c:307
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:310
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "exibe a porcentagem de buffer de transferência em uso"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:313
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "exibe NUM bytes gravados pela última vez"
|
||||
|
||||
#: src/main/help.c:315
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:316
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "definir o formato de saída para FORMAT"
|
||||
|
||||
#: src/main/help.c:319
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "exibe apenas as porcentagens, sem informações visuais"
|
||||
|
||||
#: src/main/help.c:322
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "executa programa sem exibir quaisquer informações"
|
||||
|
||||
#: src/main/help.c:326
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "não exibe nada até iniciar o processamento"
|
||||
|
||||
#: src/main/help.c:329
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "não exibir nada até que os segundos SEC tenham passado"
|
||||
|
||||
#: src/main/help.c:60
|
||||
#: src/main/help.c:331
|
||||
msgid "SIZE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:61
|
||||
#: src/main/help.c:332
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "seta a quantidade estimada de dados em SIZE bytes"
|
||||
|
||||
#: src/main/help.c:63
|
||||
#: src/main/help.c:335
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "contar linhas em vez de bytes"
|
||||
|
||||
#: src/main/help.c:65
|
||||
#: src/main/help.c:338
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "linhas são terminadas em nulo"
|
||||
|
||||
#: src/main/help.c:67
|
||||
#: src/main/help.c:341
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "atualiza informações a cada SEC segundos"
|
||||
|
||||
#: src/main/help.c:68
|
||||
#: src/main/help.c:343
|
||||
msgid "WIDTH"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:69
|
||||
#: src/main/help.c:344
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "presuma que o terminal tem WIDTH caracteres de largura"
|
||||
|
||||
#: src/main/help.c:70
|
||||
#: src/main/help.c:346
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:71
|
||||
#: src/main/help.c:347
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "presuma que o terminal tem HEIGHT caracteres de altura"
|
||||
|
||||
#: src/main/help.c:72
|
||||
#: src/main/help.c:349
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:73
|
||||
#: src/main/help.c:350
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "exibe NAME antes das demais informações"
|
||||
|
||||
#: src/main/help.c:75
|
||||
#: src/main/help.c:353
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "gera dados mesmo que a saída de erro seja redirecionada"
|
||||
|
||||
#: src/main/help.c:77
|
||||
#: src/main/help.c:356
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "utiliza caracteres de escape para posicionar o cursor"
|
||||
|
||||
#: src/main/help.c:79
|
||||
#: src/main/help.c:359
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:80
|
||||
#: src/main/help.c:360
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "limita a transferência a RATE bytes por segundo"
|
||||
|
||||
#: src/main/help.c:81
|
||||
#: src/main/help.c:362 src/main/help.c:371
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:82
|
||||
#: src/main/help.c:363
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "use um tamanho de buffer de BYTES"
|
||||
|
||||
#: src/main/help.c:84
|
||||
#: src/main/help.c:366
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "nunca use splice(), sempre use read/write"
|
||||
|
||||
#: src/main/help.c:86
|
||||
#: src/main/help.c:369
|
||||
msgid "skip read errors in input"
|
||||
msgstr "ignorar erros de leitura em entrada"
|
||||
|
||||
#: src/main/help.c:88
|
||||
#: src/main/help.c:372
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:375
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "parar após --size bytes terem sido transferidos"
|
||||
|
||||
#: src/main/help.c:90
|
||||
#: src/main/help.c:378
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:381
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:384
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:91
|
||||
#: src/main/help.c:388
|
||||
msgid "update settings of process PID"
|
||||
msgstr "atualizar as configurações do processo PID"
|
||||
|
||||
#: src/main/help.c:94
|
||||
#: src/main/help.c:392 src/main/help.c:407
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:95
|
||||
#: src/main/help.c:393
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "salvar ID do processo em FILE"
|
||||
|
||||
#: src/main/help.c:97
|
||||
#: src/main/help.c:396
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:98
|
||||
#: src/main/help.c:397
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "assistir arquivo FD aberto pelo processo PID"
|
||||
|
||||
#: src/main/help.c:101
|
||||
#: src/main/help.c:401
|
||||
msgid "show this help and exit"
|
||||
msgstr "exibe esta tela de ajuda e termina"
|
||||
|
||||
#: src/main/help.c:103
|
||||
#: src/main/help.c:404
|
||||
msgid "show version information and exit"
|
||||
msgstr "exibe a versão e termina"
|
||||
|
||||
#: src/main/help.c:109
|
||||
#: src/main/help.c:408
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:433
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Uso: %s [OPÇÕES] [ARQUIVOS]..."
|
||||
|
||||
#: src/main/help.c:112
|
||||
#: src/main/help.c:444
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output,\n"
|
||||
"with monitoring."
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Concatena ARQUIVO(s) ou a entrada padrão e grava na saída padrão,\n"
|
||||
"com monitoramento."
|
||||
"Concatena ARQUIVO(s) ou a entrada padrão e grava na saída padrão, com "
|
||||
"monitoramento."
|
||||
|
||||
#: src/main/help.c:207
|
||||
msgid ""
|
||||
"Debugging is enabled; export the DEBUG environment variable to define the\n"
|
||||
"output filename.\n"
|
||||
msgstr ""
|
||||
"A depuração está habilitada; exporte a variável de ambiente DEBUG para\n"
|
||||
"definir o nome do arquivo de saída.\n"
|
||||
|
||||
#: src/main/help.c:211
|
||||
#: src/main/help.c:581
|
||||
#, c-format
|
||||
msgid "Please report any bugs to %s."
|
||||
msgstr "Por favor, reporte quaisquer defeitos para %s."
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Por favor, reporte quaisquer defeitos para %s"
|
||||
|
||||
#: src/main/main.c:74
|
||||
#: src/main/main.c:83
|
||||
msgid "state allocation failed"
|
||||
msgstr "alocação de memória de status falhou"
|
||||
|
||||
#: src/main/main.c:246
|
||||
#, fuzzy
|
||||
msgid "failed to read terminal attributes"
|
||||
msgstr "erro ao ler o nome do terminal"
|
||||
|
||||
#: src/main/options.c:98
|
||||
#: src/main/options.c:173
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "erro na alocação da estrutura de opções"
|
||||
|
||||
#: src/main/options.c:112
|
||||
#: src/main/options.c:192
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "erro na alocação da estrutura de opções argv"
|
||||
|
||||
#: src/main/options.c:151
|
||||
#: src/main/options.c:254
|
||||
msgid "integer argument expected"
|
||||
msgstr "argumento inteiro esperado"
|
||||
|
||||
#: src/main/options.c:162
|
||||
#: src/main/options.c:265
|
||||
msgid "numeric argument expected"
|
||||
msgstr "argumento numérico esperado"
|
||||
|
||||
#: src/main/options.c:173
|
||||
#: src/main/options.c:276
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "ID do processo ou par pid:fd esperado"
|
||||
|
||||
#: src/main/options.c:180
|
||||
#: src/main/options.c:283
|
||||
msgid "invalid process ID"
|
||||
msgstr "ID de processo inválido"
|
||||
|
||||
#: src/main/options.c:316
|
||||
#: src/main/options.c:384 src/pv/file.c:323
|
||||
msgid "failed to stat file"
|
||||
msgstr "erro obtendo informações do arquivo"
|
||||
|
||||
#: src/main/options.c:487
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Tente `%s --help' para maiores informações."
|
||||
|
||||
#: src/main/options.c:320
|
||||
#: src/main/options.c:489
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Tente `%s -h' para maiores informações."
|
||||
|
||||
#: src/main/options.c:336
|
||||
#: src/main/options.c:520
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -412,28 +290,185 @@ msgstr ""
|
||||
"não pode usar o modo de linha ou opções de modificador de transferência ao "
|
||||
"assistir os descritores de arquivo"
|
||||
|
||||
#: src/main/options.c:344
|
||||
#: src/main/options.c:529
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"não pode usar o posicionamento do cursor ao observar os descritores de "
|
||||
"arquivo"
|
||||
|
||||
#: src/main/options.c:352
|
||||
#: src/main/options.c:538
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr "não pode usar o controle remoto ao assistir os descritores de arquivo"
|
||||
|
||||
#: src/main/options.c:360
|
||||
#: src/main/options.c:547
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "não pode transferir arquivos ao assistir descritores de arquivo"
|
||||
|
||||
#: src/main/options.c:368
|
||||
#: src/main/options.c:562
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "não disponível em sistemas sem /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:221
|
||||
#: src/main/remote.c:242
|
||||
msgid "message not received"
|
||||
msgstr "mensagem não recebida"
|
||||
|
||||
#: src/main/remote.c:328
|
||||
#: src/main/remote.c:351
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr "IPC não suportado neste sistema"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:29
|
||||
msgid "This is free software: you are free to change and redistribute it."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:30
|
||||
msgid "There is NO WARRANTY, to the extent permitted by law."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:32
|
||||
msgid "Project web site"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:87
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "erro ao ler o nome do terminal"
|
||||
|
||||
#: src/pv/cursor.c:130
|
||||
msgid "failed to open lock file"
|
||||
msgstr "erro ao abrir arquivo de bloqueio"
|
||||
|
||||
#: src/pv/cursor.c:163
|
||||
msgid "lock attempt failed"
|
||||
msgstr "tentativa de bloqueio falhou"
|
||||
|
||||
#: src/pv/cursor.c:424
|
||||
msgid "failed to open terminal"
|
||||
msgstr "erro abrindo o terminal"
|
||||
|
||||
#: src/pv/display.c:187
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:199
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:701 src/pv/transfer.c:894
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "erro alocando o buffer"
|
||||
|
||||
#: src/pv/display.c:763
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:768 src/pv/transfer.c:584
|
||||
msgid "B"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:820 src/pv/display.c:833
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/file.c:148
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "não pode mover para o início da produção"
|
||||
|
||||
#: src/pv/file.c:293
|
||||
msgid "failed to close file"
|
||||
msgstr "erro fechando o arquivo"
|
||||
|
||||
#: src/pv/file.c:316
|
||||
msgid "failed to read file"
|
||||
msgstr "erro lendo o arquivo"
|
||||
|
||||
#: src/pv/file.c:331
|
||||
msgid "failed to stat output file"
|
||||
msgstr "erro obtendo informações do arquivo de saída"
|
||||
|
||||
#: src/pv/file.c:353
|
||||
msgid "input file is output file"
|
||||
msgstr "os arquivos de entrada e saída são o mesmo"
|
||||
|
||||
#: src/pv/file.c:411
|
||||
msgid "(none)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:413
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:541 src/pv/loop.c:595 src/pv/loop.c:637 src/pv/watchpid.c:73
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102
|
||||
#: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158
|
||||
#: src/pv/watchpid.c:169 src/pv/watchpid.c:255 src/pv/watchpid.c:263
|
||||
#: src/pv/watchpid.c:294 src/pv/watchpid.c:314
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:36
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:385 src/pv/state.c:395
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:446
|
||||
msgid "read failed"
|
||||
msgstr "erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:469
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "aviso: erros de leitura detectados"
|
||||
|
||||
#: src/pv/transfer.c:485
|
||||
msgid "file is not seekable"
|
||||
msgstr "não pode mover dentro do arquivo"
|
||||
|
||||
#: src/pv/transfer.c:563
|
||||
msgid "failed to seek past error"
|
||||
msgstr "não pode ir além do erro"
|
||||
|
||||
#: src/pv/transfer.c:583
|
||||
msgid "skipped past read error"
|
||||
msgstr "ignorado erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:623
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:636
|
||||
msgid "failed to set alarm signal handler"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:759
|
||||
msgid "write failed"
|
||||
msgstr "erro de gravação"
|
||||
|
||||
#: src/pv/transfer.c:985
|
||||
msgid "select call failed"
|
||||
msgstr "erro na chamada da função select"
|
||||
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:95 src/pv/watchpid.c:104
|
||||
#: src/pv/watchpid.c:150 src/pv/watchpid.c:159 src/pv/watchpid.c:171
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:104 src/pv/watchpid.c:171
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "não é um arquivo regular ou dispositivo de bloqueio"
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Standard definitions to make use of the config.h values set by the
|
||||
* `configure' script. Include this after config.h and before anything
|
||||
* else.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#if ENABLE_NLS
|
||||
# ifdef HAVE_LIBINTL_H
|
||||
# include <libintl.h>
|
||||
# endif
|
||||
# ifdef HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
# endif
|
||||
# define _(String) gettext (String)
|
||||
# define N_(String) (String)
|
||||
#else
|
||||
# define _(String) (String)
|
||||
# define N_(String) (String)
|
||||
#endif
|
||||
|
||||
#undef CURSOR_ANSWERBACK_BYTE_BY_BYTE
|
||||
#ifndef _AIX
|
||||
#define CURSOR_ANSWERBACK_BYTE_BY_BYTE 1
|
||||
#endif
|
||||
|
||||
/* Boolean type support */
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#else
|
||||
# ifndef HAVE__BOOL
|
||||
# ifdef __cplusplus
|
||||
typedef bool _Bool;
|
||||
# else
|
||||
# define _Bool signed char
|
||||
# endif
|
||||
# endif
|
||||
# define bool _Bool
|
||||
# define false 0
|
||||
# define true 1
|
||||
# define __bool_true_false_are_defined 1
|
||||
#endif
|
||||
|
||||
/* EOF */
|
||||
@@ -0,0 +1,344 @@
|
||||
/* src/include/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Debugging support enabled */
|
||||
#undef ENABLE_DEBUGGING
|
||||
|
||||
/* Define to 1 if translation of program messages to the user's native
|
||||
language is requested. */
|
||||
#undef ENABLE_NLS
|
||||
|
||||
/* Define to 1 if you have the `alarm' function. */
|
||||
#undef HAVE_ALARM
|
||||
|
||||
/* Define to 1 if you have the `basename' function. */
|
||||
#undef HAVE_BASENAME
|
||||
|
||||
/* Define to 1 if you have the Mac OS X function
|
||||
CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */
|
||||
#undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES
|
||||
|
||||
/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
|
||||
the CoreFoundation framework. */
|
||||
#undef HAVE_CFPREFERENCESCOPYAPPVALUE
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define if the GNU dcgettext() function is already present or preinstalled.
|
||||
*/
|
||||
#undef HAVE_DCGETTEXT
|
||||
|
||||
/* Define to 1 if you have the `dup2' function. */
|
||||
#undef HAVE_DUP2
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `fdatasync' function. */
|
||||
#undef HAVE_FDATASYNC
|
||||
|
||||
/* Define to 1 if you have the `fpathconf' function. */
|
||||
#undef HAVE_FPATHCONF
|
||||
|
||||
/* Define to 1 if you have the `getcwd' function. */
|
||||
#undef HAVE_GETCWD
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
#undef HAVE_GETOPT_H
|
||||
|
||||
/* Define to 1 if you have the `getopt_long' function. */
|
||||
#undef HAVE_GETOPT_LONG
|
||||
|
||||
/* Define if the GNU gettext() function is already present or preinstalled. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define if you have the iconv() function and it works. */
|
||||
#undef HAVE_ICONV
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* IPC support enabled */
|
||||
#undef HAVE_IPC
|
||||
|
||||
/* Define to 1 if you have the <libgen.h> header file. */
|
||||
#undef HAVE_LIBGEN_H
|
||||
|
||||
/* Define to 1 if you have the <libintl.h> header file. */
|
||||
#undef HAVE_LIBINTL_H
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#undef HAVE_MEMCPY
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#undef HAVE_MEMMOVE
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#undef HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||
#undef HAVE_MINIX_CONFIG_H
|
||||
|
||||
/* Define to 1 if you have the `msgget' function. */
|
||||
#undef HAVE_MSGGET
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
#undef HAVE_NANOSLEEP
|
||||
|
||||
/* Define to 1 if you have the `posix_fadvise' function. */
|
||||
#undef HAVE_POSIX_FADVISE
|
||||
|
||||
/* Define to 1 if you have the `posix_memalign' function. */
|
||||
#undef HAVE_POSIX_MEMALIGN
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#undef HAVE_SELECT
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* Define to 1 if you have the `splice' function. */
|
||||
#undef HAVE_SPLICE
|
||||
|
||||
/* Define to 1 if stdbool.h conforms to C99. */
|
||||
#undef HAVE_STDBOOL_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#undef HAVE_STRCHR
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#undef HAVE_STRERROR
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strlcat' function. */
|
||||
#undef HAVE_STRLCAT
|
||||
|
||||
/* Define to 1 if you have the `strrchr' function. */
|
||||
#undef HAVE_STRRCHR
|
||||
|
||||
/* Define to 1 if you have the `strstr' function. */
|
||||
#undef HAVE_STRSTR
|
||||
|
||||
/* Define to 1 if you have the `strtoul' function. */
|
||||
#undef HAVE_STRTOUL
|
||||
|
||||
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
|
||||
/* Define to 1 if you have the `sysconf' function. */
|
||||
#undef HAVE_SYSCONF
|
||||
|
||||
/* Define to 1 if you have the <sys/file.h> header file. */
|
||||
#undef HAVE_SYS_FILE_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||
#undef HAVE_SYS_IPC_H
|
||||
|
||||
/* Define to 1 if you have the <sys/msg.h> header file. */
|
||||
#undef HAVE_SYS_MSG_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#undef HAVE_TERMIOS_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `vsnprintf' function. */
|
||||
#undef HAVE_VSNPRINTF
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#undef HAVE_WCHAR_H
|
||||
|
||||
/* Define to 1 if you have the <wctype.h> header file. */
|
||||
#undef HAVE_WCTYPE_H
|
||||
|
||||
/* Define to 1 if the system has the type `_Bool'. */
|
||||
#undef HAVE__BOOL
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on macOS. */
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
# undef _DARWIN_C_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable X/Open compliant socket functions that do not require linking
|
||||
with -lxnet on HP-UX 11.11. */
|
||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
# undef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
#endif
|
||||
/* Identify the host operating system as Minix.
|
||||
This macro does not affect the system headers' behavior.
|
||||
A future release of Autoconf may stop defining this macro. */
|
||||
#ifndef _MINIX
|
||||
# undef _MINIX
|
||||
#endif
|
||||
/* Enable general extensions on NetBSD.
|
||||
Enable NetBSD compatibility extensions on Minix. */
|
||||
#ifndef _NETBSD_SOURCE
|
||||
# undef _NETBSD_SOURCE
|
||||
#endif
|
||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
||||
Oddly enough, this does nothing on OpenBSD. */
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
# undef _OPENBSD_SOURCE
|
||||
#endif
|
||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_SOURCE
|
||||
# undef _POSIX_SOURCE
|
||||
#endif
|
||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_1_SOURCE
|
||||
# undef _POSIX_1_SOURCE
|
||||
#endif
|
||||
/* Enable POSIX-compatible threading on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
||||
#ifndef __STDC_WANT_LIB_EXT2__
|
||||
# undef __STDC_WANT_LIB_EXT2__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
# undef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
||||
to make mbstate_t available. */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
# undef _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef gid_t
|
||||
|
||||
/* Define to the type of a signed integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef int32_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef mode_t
|
||||
|
||||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
#undef off_t
|
||||
|
||||
/* Define as a signed integer type capable of holding a process identifier. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef ssize_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef uid_t
|
||||
|
||||
#include "config-aux.h"
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Replacement getopt function's header file. Include this AFTER config.h.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRARY_GETOPT_H
|
||||
#define _LIBRARY_GETOPT_H 1
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETOPT
|
||||
|
||||
int minigetopt(int, char **, char *);
|
||||
extern char *minioptarg;
|
||||
extern int minioptind, miniopterr, minioptopt;
|
||||
|
||||
#define getopt minigetopt /* Flawfinder: ignore */
|
||||
#define optarg minioptarg
|
||||
#define optind minioptind
|
||||
#define opterr miniopterr
|
||||
#define optopt minioptopt
|
||||
|
||||
#endif /* !HAVE_GETOPT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBRARY_GETOPT_H */
|
||||
|
||||
/* EOF */
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Replacement gettext library header file. Include this within config.h,
|
||||
* like this:
|
||||
*
|
||||
* #ifdef ENABLE_NLS
|
||||
* # include "library/gettext.h"
|
||||
* #else
|
||||
* # define _(String) (String)
|
||||
* # define N_(String) (String)
|
||||
* #endif
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LIBRARY_GETTEXT_H
|
||||
#define _LIBRARY_GETTEXT_H 1
|
||||
|
||||
#ifdef HAVE_GETTEXT
|
||||
# ifdef HAVE_LIBINTL_H
|
||||
# include <libintl.h>
|
||||
# endif
|
||||
# ifdef HAVE_LOCALE_H
|
||||
# include <locale.h>
|
||||
# endif
|
||||
# define _(String) gettext (String)
|
||||
# define N_(String) (String)
|
||||
#else
|
||||
# define _(String) minigettext (String)
|
||||
# define N_(String) (String)
|
||||
# define setlocale minisetlocale
|
||||
# define bindtextdomain minibindtextdomain
|
||||
# define textdomain minitextdomain
|
||||
# ifndef LC_ALL
|
||||
# define LC_ALL ""
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *minisetlocale(char *, char *);
|
||||
char *minibindtextdomain(char *, char *);
|
||||
char *minitextdomain(char *);
|
||||
char *minigettext(char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBRARY_GETTEXT_H */
|
||||
|
||||
/* EOF */
|
||||
+38
-15
@@ -1,10 +1,21 @@
|
||||
/*
|
||||
* Global program option structure and the parsing function prototype.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifndef _OPTIONS_H
|
||||
#define _OPTIONS_H 1
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -13,7 +24,7 @@ struct opts_s;
|
||||
typedef struct opts_s *opts_t;
|
||||
|
||||
struct opts_s { /* structure describing run-time options */
|
||||
char *program_name; /* name the program is running as */
|
||||
/*@keep@*/ const char *program_name; /* name the program is running as */
|
||||
bool do_nothing; /* exit-without-doing-anything flag */
|
||||
bool progress; /* progress bar flag */
|
||||
bool timer; /* timer flag */
|
||||
@@ -22,38 +33,50 @@ struct opts_s { /* structure describing run-time options */
|
||||
bool rate; /* rate counter flag */
|
||||
bool average_rate; /* average rate counter flag */
|
||||
bool bytes; /* bytes transferred flag */
|
||||
bool bits; /* report transfer size in bits */
|
||||
bool bufpercent; /* transfer buffer percentage flag */
|
||||
unsigned int lastwritten; /* show N bytes last written */
|
||||
size_t lastwritten; /* show N bytes last written */
|
||||
bool force; /* force-if-not-terminal flag */
|
||||
bool cursor; /* whether to use cursor positioning */
|
||||
bool numeric; /* numeric output only */
|
||||
bool wait; /* wait for transfer before display */
|
||||
bool linemode; /* count lines instead of bytes */
|
||||
bool null; /* lines are null-terminated */
|
||||
bool no_op; /* do nothing other than pipe data */
|
||||
unsigned long long rate_limit; /* rate limit, in bytes per second */
|
||||
unsigned long long buffer_size;/* buffer size, in bytes (0=default) */
|
||||
bool null_terminated_lines; /* lines are null-terminated */
|
||||
bool no_display; /* do nothing other than pipe data */
|
||||
off_t rate_limit; /* rate limit, in bytes per second */
|
||||
size_t buffer_size; /* buffer size, in bytes (0=default) */
|
||||
unsigned int remote; /* PID of pv to update settings of */
|
||||
unsigned long long size; /* total size of data */
|
||||
off_t size; /* total size of data */
|
||||
bool no_splice; /* flag set if never to use splice */
|
||||
unsigned int skip_errors; /* skip read errors counter */
|
||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||
bool stop_at_size; /* set if we stop at "size" bytes */
|
||||
bool sync_after_write; /* set if we sync after every write */
|
||||
bool direct_io; /* set if O_DIRECT is to be used */
|
||||
bool discard_input; /* set to write nothing to stdout */
|
||||
double interval; /* interval between updates */
|
||||
double delay_start; /* delay before first display */
|
||||
unsigned int watch_pid; /* process to watch fds of */
|
||||
pid_t watch_pid; /* process to watch fds of */
|
||||
int watch_fd; /* fd to watch */
|
||||
unsigned int average_rate_window; /* time window in seconds for average rate calculations */
|
||||
unsigned int width; /* screen width */
|
||||
unsigned int height; /* screen height */
|
||||
char *name; /* process name, if any */
|
||||
char *format; /* output format, if any */
|
||||
char *pidfile; /* PID file, if any */
|
||||
int argc; /* number of non-option arguments */
|
||||
char **argv; /* array of non-option arguments */
|
||||
bool width_set_manually; /* width was set manually, not detected */
|
||||
bool height_set_manually; /* height was set manually, not detected */
|
||||
/*@keep@*/ /*@null@*/ char *name; /* display name, if any */
|
||||
/*@keep@*/ /*@null@*/ char *format; /* output format, if any */
|
||||
/*@keep@*/ /*@null@*/ char *pidfile; /* PID file, if any */
|
||||
unsigned int argc; /* number of non-option arguments */
|
||||
/*@keep@*/ /*@null@*/ const char **argv; /* array of non-option arguments */
|
||||
unsigned int argv_length; /* allocated array size */
|
||||
};
|
||||
|
||||
extern opts_t opts_parse(int, char **);
|
||||
extern void opts_free(opts_t);
|
||||
/*@-exportlocal@*/
|
||||
/* splint thinks opts_free is exported but not used - it is used. */
|
||||
|
||||
extern /*@null@*/ /*@only@*/ opts_t opts_parse(unsigned int, char **);
|
||||
extern void opts_free(/*@only@*/ opts_t);
|
||||
extern bool opts_add_file(opts_t, const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+139
-80
@@ -1,19 +1,17 @@
|
||||
/*
|
||||
* Functions internal to the PV library.
|
||||
* Functions internal to the PV library. Include "config.h" first.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifndef _PV_INTERNAL_H
|
||||
#define _PV_INTERNAL_H 1
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef _PV_H
|
||||
#include "pv.h"
|
||||
#endif /* _PV_H */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -33,18 +31,55 @@ extern "C" {
|
||||
#define PV_DISPLAY_OUTPUTBUF 256
|
||||
#define PV_DISPLAY_FINETA 512
|
||||
|
||||
#define RATE_GRANULARITY 100000 /* usec between -L rate chunks */
|
||||
#define REMOTE_INTERVAL 100000 /* usec between checks for -R */
|
||||
#define BUFFER_SIZE 409600 /* default transfer buffer size */
|
||||
#define BUFFER_SIZE_MAX 524288 /* max auto transfer buffer size */
|
||||
#define MAX_READ_AT_ONCE 524288 /* max to read() in one go */
|
||||
#define MAX_WRITE_AT_ONCE 524288 /* max to write() in one go */
|
||||
#define TRANSFER_READ_TIMEOUT 90000 /* usec to time reads out at */
|
||||
#define TRANSFER_WRITE_TIMEOUT 900000 /* usec to time writes out at */
|
||||
#define RATE_GRANULARITY 100000000 /* nsec between -L rate chunks */
|
||||
#define RATE_BURST_WINDOW 5 /* rate burst window (multiples of rate) */
|
||||
#define REMOTE_INTERVAL 100000000 /* nsec between checks for -R */
|
||||
#define BUFFER_SIZE (size_t) 409600 /* default transfer buffer size */
|
||||
#define BUFFER_SIZE_MAX (size_t) 524288 /* max auto transfer buffer size */
|
||||
#define MAX_READ_AT_ONCE (size_t) 524288 /* max to read() in one go */
|
||||
#define MAX_WRITE_AT_ONCE (size_t) 524288 /* max to write() in one go */
|
||||
#define TRANSFER_READ_TIMEOUT 0.09L /* seconds to time reads out at */
|
||||
#define TRANSFER_WRITE_TIMEOUT 0.9L /* seconds to time writes out at */
|
||||
|
||||
#define MAXIMISE_BUFFER_FILL 1
|
||||
|
||||
|
||||
typedef struct pvhistory {
|
||||
off_t total_bytes;
|
||||
long double elapsed_sec;
|
||||
} pvhistory_t;
|
||||
|
||||
#define PV_SIZEOF_DEFAULT_FORMAT 512
|
||||
#define PV_SIZEOF_CWD 4096
|
||||
#define PV_SIZEOF_LASTOUTPUT_BUFFER 256
|
||||
#define PV_SIZEOF_STR_NAME 512
|
||||
#define PV_SIZEOF_STR_TRANSFERRED 128
|
||||
#define PV_SIZEOF_STR_BUFPERCENT 128
|
||||
#define PV_SIZEOF_STR_TIMER 128
|
||||
#define PV_SIZEOF_STR_RATE 128
|
||||
#define PV_SIZEOF_STR_AVERAGE_RATE 128
|
||||
#define PV_SIZEOF_STR_PROGRESS 1024
|
||||
#define PV_SIZEOF_STR_LASTOUTPUT 512
|
||||
#define PV_SIZEOF_STR_ETA 128
|
||||
#define PV_SIZEOF_STR_FINETA 128
|
||||
#define PV_FORMAT_ARRAY_MAX 100
|
||||
#define PV_SIZEOF_CRS_LOCK_FILE 1024
|
||||
|
||||
#define PV_SIZEOF_FILE_FDINFO 4096
|
||||
#define PV_SIZEOF_FILE_FD 4096
|
||||
#define PV_SIZEOF_FILE_FDPATH 4096
|
||||
#define PV_SIZEOF_DISPLAY_NAME 512
|
||||
|
||||
|
||||
/*
|
||||
* Structure for data shared between multiple "pv -c" instances.
|
||||
*/
|
||||
struct pvcursorstate_s {
|
||||
int y_topmost; /* terminal row of topmost "pv" instance */
|
||||
bool tty_tostop_added; /* whether any instance had to set TOSTOP on the terminal */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Structure for holding PV internal state. Opaque outside the PV library.
|
||||
*/
|
||||
@@ -52,8 +87,8 @@ struct pvstate_s {
|
||||
/***************
|
||||
* Input files *
|
||||
***************/
|
||||
int input_file_count; /* number of input files */
|
||||
const char **input_files; /* input files (0=first) */
|
||||
unsigned int input_file_count; /* number of input files */
|
||||
/*@only@*/ /*@null@*/ char **input_files; /* input files */
|
||||
|
||||
/*******************
|
||||
* Program control *
|
||||
@@ -63,37 +98,47 @@ struct pvstate_s {
|
||||
bool numeric; /* numeric output only */
|
||||
bool wait; /* wait for data before display */
|
||||
bool linemode; /* count lines instead of bytes */
|
||||
bool null; /* lines are null-terminated */
|
||||
bool no_op; /* do nothing other than pipe data */
|
||||
bool bits; /* report bits instead of bytes */
|
||||
bool null_terminated_lines; /* lines are null-terminated */
|
||||
bool no_display; /* do nothing other than pipe data */
|
||||
unsigned int skip_errors; /* skip read errors counter */
|
||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||
bool stop_at_size; /* set if we stop at "size" bytes */
|
||||
bool sync_after_write; /* set if we sync after every write */
|
||||
bool direct_io; /* set if O_DIRECT is to be used */
|
||||
bool direct_io_changed; /* set when direct_io is changed */
|
||||
bool no_splice; /* never use splice() */
|
||||
unsigned long long rate_limit; /* rate limit, in bytes per second */
|
||||
unsigned long long target_buffer_size; /* buffer size (0=default) */
|
||||
unsigned long long size; /* total size of data */
|
||||
bool discard_input; /* write nothing to stdout */
|
||||
off_t rate_limit; /* rate limit, in bytes per second */
|
||||
size_t target_buffer_size; /* buffer size (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
double interval; /* interval between updates */
|
||||
double delay_start; /* delay before first display */
|
||||
unsigned int watch_pid; /* process to watch fds of */
|
||||
pid_t watch_pid; /* process to watch fds of */
|
||||
int watch_fd; /* fd to watch */
|
||||
unsigned int width; /* screen width */
|
||||
unsigned int height; /* screen height */
|
||||
const char *name; /* display name */
|
||||
char default_format[512]; /* default format string */
|
||||
const char *format_string; /* output format string */
|
||||
bool width_set_manually; /* width was set manually, not detected */
|
||||
bool height_set_manually; /* height was set manually, not detected */
|
||||
/*@only@*/ /*@null@*/ char *name; /* display name */
|
||||
char default_format[PV_SIZEOF_DEFAULT_FORMAT]; /* default format string */
|
||||
/*@only@*/ /*@null@*/ char *format_string; /* output format string */
|
||||
|
||||
/******************
|
||||
* Program status *
|
||||
******************/
|
||||
const char *program_name; /* program name for error reporting */
|
||||
const char *current_file; /* current file being read */
|
||||
/*@only@*/ char *program_name; /* program name for error reporting */
|
||||
char cwd[PV_SIZEOF_CWD]; /* current working directory for relative path */
|
||||
int current_input_file; /* index of current file being read */
|
||||
int exit_status; /* exit status to give (0=OK) */
|
||||
|
||||
/*******************
|
||||
* Signal handling *
|
||||
*******************/
|
||||
int pv_sig_old_stderr; /* see pv_sig_ttou() */
|
||||
struct timeval pv_sig_tstp_time; /* see pv_sig_tstp() / __cont() */
|
||||
struct timeval pv_sig_toffset; /* total time spent stopped */
|
||||
bool pv_tty_tostop_added; /* whether we had to set TOSTOP on the terminal */
|
||||
struct timespec pv_sig_tstp_time; /* see pv_sig_tstp() / __cont() */
|
||||
struct timespec pv_sig_toffset; /* total time spent stopped */
|
||||
volatile sig_atomic_t pv_sig_newsize; /* whether we need to get term size again */
|
||||
volatile sig_atomic_t pv_sig_abort; /* whether we need to abort right now */
|
||||
volatile sig_atomic_t reparse_display; /* whether to re-check format string */
|
||||
@@ -113,28 +158,37 @@ struct pvstate_s {
|
||||
long double prev_elapsed_sec;
|
||||
long double prev_rate;
|
||||
long double prev_trans;
|
||||
unsigned long long initial_offset;
|
||||
char *display_buffer;
|
||||
|
||||
/* Keep track of progress over last intervals to compute current average rate. */
|
||||
/*@null@*/ pvhistory_t *history; /* state at previous intervals (circular buffer) */
|
||||
unsigned int history_len; /* total size */
|
||||
int history_interval; /* seconds between each history entry */
|
||||
int history_first;
|
||||
int history_last;
|
||||
long double current_avg_rate; /* current average rate over last history intervals */
|
||||
|
||||
off_t initial_offset;
|
||||
/*@only@*/ char *display_buffer;
|
||||
long display_buffer_size;
|
||||
int lastoutput_length; /* number of last-output bytes to show */
|
||||
unsigned char lastoutput_buffer[256];
|
||||
size_t lastoutput_length; /* number of last-output bytes to show */
|
||||
char lastoutput_buffer[PV_SIZEOF_LASTOUTPUT_BUFFER];
|
||||
int prev_width; /* screen width last time we were called */
|
||||
int prev_length; /* length of last string we output */
|
||||
char str_name[512];
|
||||
char str_transferred[128];
|
||||
char str_bufpercent[128];
|
||||
char str_timer[128];
|
||||
char str_rate[128];
|
||||
char str_average_rate[128];
|
||||
char str_progress[1024];
|
||||
char str_lastoutput[512];
|
||||
char str_eta[128];
|
||||
char str_fineta[128];
|
||||
char str_name[PV_SIZEOF_STR_NAME];
|
||||
char str_transferred[PV_SIZEOF_STR_TRANSFERRED];
|
||||
char str_bufpercent[PV_SIZEOF_STR_BUFPERCENT];
|
||||
char str_timer[PV_SIZEOF_STR_TIMER];
|
||||
char str_rate[PV_SIZEOF_STR_RATE];
|
||||
char str_average_rate[PV_SIZEOF_STR_AVERAGE_RATE];
|
||||
char str_progress[PV_SIZEOF_STR_PROGRESS];
|
||||
char str_lastoutput[PV_SIZEOF_STR_LASTOUTPUT];
|
||||
char str_eta[PV_SIZEOF_STR_ETA];
|
||||
char str_fineta[PV_SIZEOF_STR_FINETA];
|
||||
unsigned long components_used; /* bitmask of components used */
|
||||
struct {
|
||||
const char *string;
|
||||
int length;
|
||||
} format[100];
|
||||
} format[PV_FORMAT_ARRAY_MAX];
|
||||
bool display_visible; /* set once anything written to terminal */
|
||||
|
||||
/********************
|
||||
@@ -144,14 +198,14 @@ struct pvstate_s {
|
||||
int crs_shmid; /* ID of our shared memory segment */
|
||||
int crs_pvcount; /* number of `pv' processes in total */
|
||||
int crs_pvmax; /* highest number of `pv's seen */
|
||||
int *crs_y_top; /* pointer to Y coord of topmost `pv' */
|
||||
/*@keep@*/ /*@null@*/ struct pvcursorstate_s *crs_shared; /* data shared between instances */
|
||||
int crs_y_lastread; /* last value of _y_top seen */
|
||||
int crs_y_offset; /* our Y offset from this top position */
|
||||
int crs_needreinit; /* counter if we need to reinit cursor pos */
|
||||
bool crs_noipc; /* set if we can't use IPC */
|
||||
#endif /* HAVE_IPC */
|
||||
int crs_lock_fd; /* fd of lockfile, -1 if none open */
|
||||
char crs_lock_file[1024];
|
||||
char crs_lock_file[PV_SIZEOF_CRS_LOCK_FILE];
|
||||
int crs_y_start; /* our initial Y coordinate */
|
||||
|
||||
/*******************
|
||||
@@ -172,10 +226,10 @@ struct pvstate_s {
|
||||
* is the offset in the buffer that we've written data up to. It
|
||||
* will always be less than or equal to read_position.
|
||||
*/
|
||||
unsigned char *transfer_buffer; /* data transfer buffer */
|
||||
unsigned long long buffer_size; /* size of buffer */
|
||||
unsigned long read_position; /* amount of data in buffer */
|
||||
unsigned long write_position; /* buffered data written */
|
||||
/*@keep@*/ /*@null@*/ char *transfer_buffer; /* data transfer buffer */
|
||||
size_t buffer_size; /* size of buffer */
|
||||
size_t read_position; /* amount of data in buffer */
|
||||
size_t write_position; /* buffered data written */
|
||||
|
||||
/*
|
||||
* While reading from a file descriptor we keep track of how many
|
||||
@@ -184,57 +238,62 @@ struct pvstate_s {
|
||||
* on this fd (read_error_warning_shown).
|
||||
*
|
||||
* Whenever the active file descriptor changes from
|
||||
* last_read_skip_fd, we reset read_errors_in_a_row and
|
||||
* read_error_warning_shown to 0 for the new file descriptor and set
|
||||
* last_read_skip_fd to the new fd number.
|
||||
* last_read_skip_fd, we reset read_errors_in_a_row to 0 and
|
||||
* read_error_warning_shown to false for the new file descriptor and
|
||||
* set last_read_skip_fd to the new fd number.
|
||||
*
|
||||
* This way, we're treating each input file separately.
|
||||
*/
|
||||
int last_read_skip_fd;
|
||||
unsigned long read_errors_in_a_row;
|
||||
int read_error_warning_shown;
|
||||
off_t read_errors_in_a_row;
|
||||
bool read_error_warning_shown;
|
||||
#ifdef HAVE_SPLICE
|
||||
/*
|
||||
* These variables are used to keep track of whether splice() was
|
||||
* used; splice_failed_fd is the file descriptor that splice() last
|
||||
* failed on, so that we don't keep trying to use it on an fd that
|
||||
* doesn't support it, and splice_used is set to 1 if splice() was
|
||||
* used this time within pv_transfer().
|
||||
* doesn't support it, and splice_used is set to true if splice()
|
||||
* was used this time within pv_transfer().
|
||||
*/
|
||||
int splice_failed_fd;
|
||||
int splice_used;
|
||||
bool splice_used;
|
||||
#endif
|
||||
long to_write; /* max to write this time around */
|
||||
long written; /* bytes sent to stdout this time */
|
||||
ssize_t to_write; /* max to write this time around */
|
||||
ssize_t written; /* bytes sent to stdout this time */
|
||||
};
|
||||
|
||||
|
||||
struct pvwatchfd_s {
|
||||
unsigned int watch_pid; /* PID to watch */
|
||||
pid_t watch_pid; /* PID to watch */
|
||||
int watch_fd; /* fd to watch, -1 = not displayed */
|
||||
char file_fdinfo[4096]; /* path to /proc fdinfo file */
|
||||
char file_fd[4096]; /* path to /proc fd symlink */
|
||||
char file_fdpath[4096]; /* path to file that was opened */
|
||||
char display_name[512]; /* name to show on progress bar */
|
||||
struct stat64 sb_fd; /* stat of fd symlink */
|
||||
struct stat64 sb_fd_link; /* lstat of fd symlink */
|
||||
unsigned long long size; /* size of whole file, 0 if unknown */
|
||||
long long position; /* position last seen at */
|
||||
struct timeval start_time; /* time we started watching the fd */
|
||||
#ifdef __APPLE__
|
||||
#else
|
||||
char file_fdinfo[PV_SIZEOF_FILE_FDINFO]; /* path to /proc fdinfo file */
|
||||
char file_fd[PV_SIZEOF_FILE_FD]; /* path to /proc fd symlink */
|
||||
#endif
|
||||
char file_fdpath[PV_SIZEOF_FILE_FDPATH]; /* path to file that was opened */
|
||||
char display_name[PV_SIZEOF_DISPLAY_NAME]; /* name to show on progress bar */
|
||||
struct stat sb_fd; /* stat of fd symlink */
|
||||
struct stat sb_fd_link; /* lstat of fd symlink */
|
||||
off_t size; /* size of whole file, 0 if unknown */
|
||||
off_t position; /* position last seen at */
|
||||
struct timespec start_time; /* time we started watching the fd */
|
||||
};
|
||||
typedef struct pvwatchfd_s *pvwatchfd_t;
|
||||
|
||||
void pv_error(pvstate_t, char *, ...);
|
||||
|
||||
int pv_main_loop(pvstate_t);
|
||||
void pv_display(pvstate_t, long double, long long, long long);
|
||||
long pv_transfer(pvstate_t, int, int *, int *, unsigned long long, long *);
|
||||
void pv_set_buffer_size(unsigned long long, int);
|
||||
int pv_next_file(pvstate_t, int, int);
|
||||
void pv_display(pvstate_t, long double, off_t, off_t);
|
||||
ssize_t pv_transfer(pvstate_t, int, bool *, bool *, off_t, long *);
|
||||
int pv_next_file(pvstate_t, unsigned int, int);
|
||||
/*@out@*/ const char *pv_current_file_name(pvstate_t);
|
||||
|
||||
void pv_write_retry(int, const char *, size_t);
|
||||
|
||||
void pv_crs_fini(pvstate_t);
|
||||
void pv_crs_init(pvstate_t);
|
||||
void pv_crs_update(pvstate_t, char *);
|
||||
void pv_crs_update(pvstate_t, const char *);
|
||||
#ifdef HAVE_IPC
|
||||
void pv_crs_needreinit(pvstate_t);
|
||||
#endif
|
||||
@@ -248,9 +307,9 @@ void pv_remote_check(pvstate_t);
|
||||
void pv_remote_fini(pvstate_t);
|
||||
int pv_remote_set(pvstate_t);
|
||||
|
||||
int pv_watchfd_info(pvstate_t, pvwatchfd_t, int);
|
||||
int pv_watchfd_info(pvstate_t, pvwatchfd_t, bool);
|
||||
int pv_watchfd_changed(pvwatchfd_t);
|
||||
long long pv_watchfd_position(pvwatchfd_t);
|
||||
off_t pv_watchfd_position(pvwatchfd_t);
|
||||
int pv_watchpid_scanfds(pvstate_t, pvstate_t, unsigned int, int *, pvwatchfd_t *, pvstate_t *, int *);
|
||||
void pv_watchpid_setname(pvstate_t, pvwatchfd_t);
|
||||
|
||||
|
||||
+115
-26
@@ -1,10 +1,23 @@
|
||||
/*
|
||||
* Functions used across the program.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifndef _PV_H
|
||||
#define _PV_H 1
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -21,7 +34,7 @@ typedef struct pvstate_s *pvstate_t;
|
||||
typedef enum {
|
||||
PV_NUMTYPE_INTEGER,
|
||||
PV_NUMTYPE_DOUBLE
|
||||
} pv_numtype_t;
|
||||
} pv_numtype;
|
||||
|
||||
|
||||
/*
|
||||
@@ -29,26 +42,91 @@ typedef enum {
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return the given string converted to a double.
|
||||
* Return the given string converted to a double, for use as a time
|
||||
* interval.
|
||||
*/
|
||||
extern double pv_getnum_d(const char *);
|
||||
extern double pv_getnum_interval(const char *);
|
||||
|
||||
/*
|
||||
* Return the given string converted to an unsigned integer.
|
||||
* Return the given string converted to an off_t, for use as a size.
|
||||
*/
|
||||
extern unsigned int pv_getnum_ui(const char *);
|
||||
extern off_t pv_getnum_size(const char *);
|
||||
|
||||
/*
|
||||
* Return the given string converted to an unsigned long long.
|
||||
* Return the given string converted to an unsigned integer, for use as a
|
||||
* count such as screen width.
|
||||
*/
|
||||
extern unsigned long long pv_getnum_ull(const char *);
|
||||
extern unsigned int pv_getnum_count(const char *);
|
||||
|
||||
/*
|
||||
* Return zero if the given string is a number of the given type. NB an
|
||||
* Return true if the given string is a number of the given type. NB an
|
||||
* integer is both a valid integer and a valid double.
|
||||
*/
|
||||
extern int pv_getnum_check(const char *, pv_numtype_t);
|
||||
extern bool pv_getnum_check(const char *, pv_numtype);
|
||||
|
||||
/*
|
||||
* String handling wrappers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Wrapper for sprintf(), falling back to sprintf() on systems without that
|
||||
* function.
|
||||
*/
|
||||
extern int pv_snprintf(char *, size_t, const char *, ...);
|
||||
|
||||
/*
|
||||
* Implementation of strlcat() where it is unavailable: append a string to a
|
||||
* buffer, constraining the buffer to a particular size and ensuring
|
||||
* termination with '\0'.
|
||||
*/
|
||||
extern size_t pv_strlcat(char *, const char *, size_t);
|
||||
|
||||
/*
|
||||
* Allocate and return a duplicate of a \0-terminated string, ensuring that
|
||||
* the duplicate is also \0-terminated. Returns NULL on error.
|
||||
*/
|
||||
/*@null@ */ /*@only@ */ extern char *pv_strdup(const char *);
|
||||
|
||||
/*
|
||||
* Functions relating to elapsed time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Read the current elapsed time, relative to an unspecified point in the
|
||||
* past, and store it in the given timespec buffer. The time is guaranteed
|
||||
* to not go backwards and does not count time when the system was
|
||||
* suspended. See clock_gettime(2) with CLOCK_MONOTONIC.
|
||||
*/
|
||||
void pv_elapsedtime_read(struct timespec *);
|
||||
|
||||
/* Set the time in the given timespec to zero. */
|
||||
void pv_elapsedtime_zero(struct timespec *);
|
||||
|
||||
/* Copy the second timespec into the first. Analogous to strcpy(3). */
|
||||
void pv_elapsedtime_copy(struct timespec *, const struct timespec *);
|
||||
|
||||
/*
|
||||
* Return -1, 0, or 1 depending on whether the first time is earlier than,
|
||||
* equal to, or later than the second time. Analogous to strcmp(3).
|
||||
*/
|
||||
int pv_elapsedtime_compare(const struct timespec *, const struct timespec *);
|
||||
|
||||
/* Add the latter two timespecs and store them in the first timespec. */
|
||||
void pv_elapsedtime_add(struct timespec *, const struct timespec *, const struct timespec *);
|
||||
|
||||
/* Add a number of nanoseconds to the given timespec. */
|
||||
void pv_elapsedtime_add_nsec(struct timespec *, long long);
|
||||
|
||||
/* Set the first timespec to the second minus the third. */
|
||||
void pv_elapsedtime_subtract(struct timespec *, const struct timespec *, const struct timespec *);
|
||||
|
||||
/* Convert a timespec to seconds. */
|
||||
long double pv_elapsedtime_seconds(const struct timespec *);
|
||||
|
||||
/* Sleep for a number of nanoseconds. */
|
||||
void pv_nanosleep(long long);
|
||||
|
||||
|
||||
/*
|
||||
* Main PV functions.
|
||||
*/
|
||||
@@ -56,7 +134,7 @@ extern int pv_getnum_check(const char *, pv_numtype_t);
|
||||
/*
|
||||
* Create a new state structure, and return it, or 0 (NULL) on error.
|
||||
*/
|
||||
extern pvstate_t pv_state_alloc(const char *);
|
||||
extern /*@null@*/ /*@only@*/ pvstate_t pv_state_alloc(const char *);
|
||||
|
||||
/*
|
||||
* Set the formatting string, given a set of old-style formatting options.
|
||||
@@ -66,8 +144,8 @@ extern void pv_state_set_format(pvstate_t state, bool progress,
|
||||
bool fineta, bool rate,
|
||||
bool average_rate, bool bytes,
|
||||
bool bufpercent,
|
||||
unsigned int lastwritten,
|
||||
const char *name);
|
||||
size_t lastwritten,
|
||||
/*@null@*/ const char *name);
|
||||
|
||||
/*
|
||||
* Set the various options.
|
||||
@@ -78,23 +156,29 @@ extern void pv_state_numeric_set(pvstate_t, bool);
|
||||
extern void pv_state_wait_set(pvstate_t, bool);
|
||||
extern void pv_state_delay_start_set(pvstate_t, double);
|
||||
extern void pv_state_linemode_set(pvstate_t, bool);
|
||||
extern void pv_state_null_set(pvstate_t, bool);
|
||||
extern void pv_state_no_op_set(pvstate_t, bool);
|
||||
extern void pv_state_bits_set(pvstate_t, bool);
|
||||
extern void pv_state_null_terminated_lines_set(pvstate_t, bool);
|
||||
extern void pv_state_no_display_set(pvstate_t, bool);
|
||||
extern void pv_state_skip_errors_set(pvstate_t, unsigned int);
|
||||
extern void pv_state_error_skip_block_set(pvstate_t, off_t);
|
||||
extern void pv_state_stop_at_size_set(pvstate_t, bool);
|
||||
extern void pv_state_rate_limit_set(pvstate_t, unsigned long long);
|
||||
extern void pv_state_target_buffer_size_set(pvstate_t, unsigned long long);
|
||||
extern void pv_state_sync_after_write_set(pvstate_t, bool);
|
||||
extern void pv_state_direct_io_set(pvstate_t, bool);
|
||||
extern void pv_state_rate_limit_set(pvstate_t, off_t);
|
||||
extern void pv_state_target_buffer_size_set(pvstate_t, size_t);
|
||||
extern void pv_state_no_splice_set(pvstate_t, bool);
|
||||
extern void pv_state_size_set(pvstate_t, unsigned long long);
|
||||
extern void pv_state_discard_input_set(pvstate_t, bool);
|
||||
extern void pv_state_size_set(pvstate_t, off_t);
|
||||
extern void pv_state_interval_set(pvstate_t, double);
|
||||
extern void pv_state_width_set(pvstate_t, unsigned int);
|
||||
extern void pv_state_height_set(pvstate_t, unsigned int);
|
||||
extern void pv_state_name_set(pvstate_t, const char *);
|
||||
extern void pv_state_format_string_set(pvstate_t, const char *);
|
||||
extern void pv_state_watch_pid_set(pvstate_t, unsigned int);
|
||||
extern void pv_state_width_set(pvstate_t, unsigned int, bool);
|
||||
extern void pv_state_height_set(pvstate_t, unsigned int, bool);
|
||||
extern void pv_state_name_set(pvstate_t, /*@null@*/ const char *);
|
||||
extern void pv_state_format_string_set(pvstate_t, /*@null@*/ const char *);
|
||||
extern void pv_state_watch_pid_set(pvstate_t, pid_t);
|
||||
extern void pv_state_watch_fd_set(pvstate_t, int);
|
||||
extern void pv_state_average_rate_window_set(pvstate_t, unsigned int);
|
||||
|
||||
extern void pv_state_inputfiles(pvstate_t, int, const char **);
|
||||
extern void pv_state_inputfiles(pvstate_t, unsigned int, const char **);
|
||||
|
||||
/*
|
||||
* Work out whether we are in the foreground.
|
||||
@@ -109,7 +193,7 @@ extern void pv_screensize(unsigned int *width, unsigned int *height);
|
||||
/*
|
||||
* Calculate the total size of all input files.
|
||||
*/
|
||||
extern unsigned long long pv_calc_total_size(pvstate_t);
|
||||
extern off_t pv_calc_total_size(pvstate_t);
|
||||
|
||||
/*
|
||||
* Set up signal handlers ready for running the main loop.
|
||||
@@ -139,11 +223,11 @@ extern void pv_sig_fini(pvstate_t);
|
||||
/*
|
||||
* Free a state structure, after which it can no longer be used.
|
||||
*/
|
||||
extern void pv_state_free(pvstate_t);
|
||||
extern void pv_state_free(/*@only@*/ pvstate_t);
|
||||
|
||||
|
||||
#ifdef ENABLE_DEBUGGING
|
||||
# if __STDC_VERSION__ < 199901L
|
||||
# if __STDC_VERSION__ < 199901L && !defined(__func__)
|
||||
# if __GNUC__ >= 2
|
||||
# define __func__ __FUNCTION__
|
||||
# else
|
||||
@@ -155,6 +239,11 @@ extern void pv_state_free(pvstate_t);
|
||||
# define debug(x,...) do { } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the debugging destination file, if debugging is enabled.
|
||||
*/
|
||||
void debugging_output_destination(const char *);
|
||||
|
||||
/*
|
||||
* Output debugging information, if debugging is enabled.
|
||||
*/
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Small reimplementation of getopt().
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef HAVE_GETOPT
|
||||
|
||||
char *minioptarg = NULL;
|
||||
int minioptind = 0;
|
||||
int miniopterr = 1;
|
||||
int minioptopt = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Minimalist getopt() clone, which handles short options only and doesn't
|
||||
* permute argv[].
|
||||
*/
|
||||
int minigetopt(int argc, char **argv, char *optstring)
|
||||
{
|
||||
static int nextchar = 0;
|
||||
int optchar;
|
||||
int i;
|
||||
|
||||
if ((0 == minioptind) && (argc > 0))
|
||||
minioptind++;
|
||||
|
||||
if ((nextchar > 0) && (0 == argv[minioptind][nextchar])) {
|
||||
minioptind++;
|
||||
nextchar = 0;
|
||||
}
|
||||
|
||||
if (minioptind >= argc)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* End of options if arg doesn't start with "-"
|
||||
*/
|
||||
if (argv[minioptind][0] != '-')
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* End of options if arg is just "-"
|
||||
*/
|
||||
if (0 == argv[minioptind][1])
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* End of options if arg is "--", but don't include the "--" in the
|
||||
* non-option arguments
|
||||
*/
|
||||
if (('-' == argv[minioptind][1]) && (0 == argv[minioptind][2])) {
|
||||
minioptind++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == nextchar)
|
||||
nextchar = 1;
|
||||
|
||||
optchar = argv[minioptind][nextchar++];
|
||||
|
||||
for (i = 0; optstring[i] != 0 && optstring[i] != optchar; i++) {
|
||||
}
|
||||
|
||||
if (0 == optstring[i]) {
|
||||
minioptopt = optchar;
|
||||
if (miniopterr)
|
||||
fprintf(stderr, "%s: invalid option -- %c\n",
|
||||
argv[0], optchar);
|
||||
return '?';
|
||||
}
|
||||
|
||||
if (optstring[i + 1] != ':') {
|
||||
minioptarg = NULL;
|
||||
return optchar;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point we've got an option that takes an argument.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Next character isn't 0, so the argument is within this array
|
||||
* element (i.e. "-dFOO").
|
||||
*/
|
||||
if (argv[minioptind][nextchar] != 0) {
|
||||
minioptarg = &(argv[minioptind][nextchar]);
|
||||
nextchar = 0;
|
||||
minioptind++;
|
||||
return optchar;
|
||||
}
|
||||
|
||||
/*
|
||||
* Argument is in the next array element (i.e. "-d FOO").
|
||||
*/
|
||||
nextchar = 0;
|
||||
minioptind++;
|
||||
if (minioptind >= argc) {
|
||||
fprintf(stderr, "%s: option `-%c' requires an argument\n",
|
||||
argv[0], optchar);
|
||||
return ':';
|
||||
}
|
||||
minioptarg = argv[minioptind++];
|
||||
|
||||
return optchar;
|
||||
}
|
||||
|
||||
#endif /* HAVE_GETOPT */
|
||||
|
||||
/* EOF */
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Very minimal (and stupid) implementation of gettext, with a fixed lookup
|
||||
* table.
|
||||
*
|
||||
* This library ONLY handles gettext(), and that only for the basic form (it
|
||||
* translates strings to other strings with no other modification, so %2$d
|
||||
* style constructs are not dealt with). The setlocale(), bindtextdomain(),
|
||||
* and textdomain() functions are ignored.
|
||||
*
|
||||
* To use this library, create a function that, given a language string,
|
||||
* returns a struct msg_table_s[] of msgid and msgstr pairs, with the end
|
||||
* of the table being marked by a NULL msgid. The po2table.sh script will do
|
||||
* this.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef HAVE_GETTEXT
|
||||
|
||||
struct msgtable_s {
|
||||
char *msgid;
|
||||
char *msgstr;
|
||||
};
|
||||
|
||||
#if ENABLE_NLS
|
||||
struct msgtable_s *minigettext__gettable(char *);
|
||||
#else /* ENABLE_NLS */
|
||||
struct msgtable_s *minigettext__gettable(char *a)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* ENABLE_NLS */
|
||||
|
||||
char *minisetlocale(char *a, char *b)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *minibindtextdomain(char *a, char *b)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *minitextdomain(char *a)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *minigettext(char *msgid)
|
||||
{
|
||||
static struct msgtable_s *table = NULL;
|
||||
static int tried_lang = 0;
|
||||
char *lang;
|
||||
int i;
|
||||
|
||||
if (NULL == msgid)
|
||||
return msgid;
|
||||
|
||||
if (0 == tried_lang) {
|
||||
lang = getenv("LANGUAGE");
|
||||
if (lang)
|
||||
table = minigettext__gettable(lang);
|
||||
|
||||
if (NULL == table) {
|
||||
lang = getenv("LANG");
|
||||
if (lang)
|
||||
table = minigettext__gettable(lang);
|
||||
}
|
||||
|
||||
if (NULL == table) {
|
||||
lang = getenv("LC_ALL");
|
||||
if (lang)
|
||||
table = minigettext__gettable(lang);
|
||||
}
|
||||
|
||||
if (NULL == table) {
|
||||
lang = getenv("LC_MESSAGES");
|
||||
if (lang)
|
||||
table = minigettext__gettable(lang);
|
||||
}
|
||||
|
||||
tried_lang = 1;
|
||||
}
|
||||
|
||||
if (NULL == table)
|
||||
return msgid;
|
||||
|
||||
for (i = 0; table[i].msgid; i++) {
|
||||
if (0 == strcmp(table[i].msgid, msgid)) {
|
||||
if (0 == table[i].msgstr)
|
||||
return msgid;
|
||||
if (0 == table[i].msgstr[0])
|
||||
return msgid;
|
||||
return table[i].msgstr;
|
||||
}
|
||||
}
|
||||
|
||||
return msgid;
|
||||
}
|
||||
|
||||
#endif /* HAVE_GETTEXT */
|
||||
|
||||
/* EOF */
|
||||
+56
-20
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Output debugging information.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "pv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -16,57 +18,91 @@
|
||||
|
||||
|
||||
#ifdef ENABLE_DEBUGGING
|
||||
/*@null@*/ static const char *debug_filename = NULL;
|
||||
|
||||
/*
|
||||
* Output debugging information to the file given in the DEBUG environment
|
||||
* variable, if it is defined.
|
||||
* Set the destination for debugging information.
|
||||
*/
|
||||
void debugging_output(const char *function, const char *file, int line,
|
||||
const char *format, ...)
|
||||
void debugging_output_destination(const char *filename)
|
||||
{
|
||||
debug_filename = filename;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output debugging information to the file specified earlier by a call to
|
||||
* debugging_output_destination(), if any.
|
||||
*/
|
||||
void debugging_output(const char *function, const char *file, int line, const char *format, ...)
|
||||
{
|
||||
static bool tried_open = false;
|
||||
static FILE *debugfptr = NULL;
|
||||
char *debugfile;
|
||||
va_list ap;
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
char tbuf[128];
|
||||
char tbuf[128]; /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder note: tbuf is only written to by strftime() which
|
||||
* takes its size, and we enforce string termination.
|
||||
*/
|
||||
|
||||
if (false == tried_open) {
|
||||
debugfile = getenv("DEBUG");
|
||||
if (NULL != debugfile)
|
||||
debugfptr = fopen(debugfile, "a");
|
||||
if (NULL != debug_filename) {
|
||||
debugfptr = fopen(debug_filename, "a"); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder note: caller directly controls
|
||||
* filename, the safest we can manage is to use
|
||||
* append mode.
|
||||
*/
|
||||
}
|
||||
tried_open = true;
|
||||
}
|
||||
|
||||
if (NULL == debugfptr)
|
||||
if (NULL == debugfptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void) time(&t);
|
||||
tm = localtime(&t);
|
||||
tbuf[0] = '\0';
|
||||
if (0 == strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", tm))
|
||||
if (0 == strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", tm)) {
|
||||
tbuf[0] = '\0';
|
||||
}
|
||||
tbuf[sizeof(tbuf) - 1] = '\0'; /* enforce termination */
|
||||
|
||||
(void) fprintf(debugfptr, "[%s] (%d) %s (%s:%d): ", tbuf, getpid(),
|
||||
function, file, line);
|
||||
(void) fprintf(debugfptr, "[%s] (%d) %s (%s:%d): ", tbuf, getpid(), function, file, line);
|
||||
|
||||
va_start(ap, format);
|
||||
(void) vfprintf(debugfptr, format, ap);
|
||||
(void) vfprintf(debugfptr, format, ap); /* flawfinder: ignore */
|
||||
va_end(ap);
|
||||
|
||||
/*
|
||||
* flawfinder note: vfprintf format is explicitly controlled by the
|
||||
* caller of this function - no mitigation possible or desirable.
|
||||
*/
|
||||
|
||||
(void) fprintf(debugfptr, "\n");
|
||||
(void) fflush(debugfptr);
|
||||
}
|
||||
|
||||
#else /* ! ENABLE_DEBUGGING */
|
||||
|
||||
/*
|
||||
* Stub debugging destination function.
|
||||
*/
|
||||
void debugging_output_destination( __attribute__((unused))
|
||||
const char *filename)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Stub debugging output function.
|
||||
*/
|
||||
void debugging_output( __attribute__ ((unused))
|
||||
const char *function, __attribute__ ((unused))
|
||||
const char *file, __attribute__ ((unused))
|
||||
int line, __attribute__ ((unused))
|
||||
void debugging_output( __attribute__((unused))
|
||||
const char *function, __attribute__((unused))
|
||||
const char *file, __attribute__((unused))
|
||||
int line, __attribute__((unused))
|
||||
const char *format, ...)
|
||||
{
|
||||
}
|
||||
|
||||
+566
-186
@@ -1,23 +1,275 @@
|
||||
/*
|
||||
* Output command-line help to stdout.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "pv.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#if defined(ENABLE_NLS) && defined(HAVE_WCHAR_H)
|
||||
#include <wchar.h>
|
||||
#if defined(HAVE_WCTYPE_H)
|
||||
#include <wctype.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define N_(String) (String)
|
||||
|
||||
struct optdesc_s {
|
||||
char *optshort;
|
||||
char *optlong;
|
||||
char *param;
|
||||
char *description;
|
||||
/*
|
||||
* Return the number of display columns needed to show the given string.
|
||||
*
|
||||
* To do this, we convert it to a wide character string, and use the wide
|
||||
* character display width function "wcswidth()" on it.
|
||||
*
|
||||
* If NLS is disabled, or the string cannot be converted, this is just the
|
||||
* same as "strlen()".
|
||||
*/
|
||||
static size_t display_width(const char *string)
|
||||
{
|
||||
size_t width;
|
||||
|
||||
#if defined(ENABLE_NLS) && defined(HAVE_WCHAR_H)
|
||||
size_t wide_char_count;
|
||||
size_t wide_string_buffer_size;
|
||||
wchar_t *wide_string;
|
||||
|
||||
if (NULL == string)
|
||||
return 0;
|
||||
|
||||
/*@-nullpass@ */
|
||||
/*
|
||||
* splint note: mbstowcs() manual page on Linux explicitly says it
|
||||
* takes NULL.
|
||||
*/
|
||||
wide_char_count = mbstowcs(NULL, string, 0);
|
||||
/*@+nullpass@ */
|
||||
if (wide_char_count == (size_t) -1) {
|
||||
debug("%s: %s: %s", "mbstowcs", string, strerror(errno));
|
||||
return strlen(string); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: we have already checked for NULL,
|
||||
* and we don't know the size of the originating buffer so
|
||||
* can't use strnlen(); it is up to the caller to provide a
|
||||
* terminated string.
|
||||
*/
|
||||
}
|
||||
|
||||
wide_string_buffer_size = sizeof(*wide_string) * (1 + wide_char_count);
|
||||
wide_string = malloc(wide_string_buffer_size);
|
||||
if (NULL == wide_string) {
|
||||
perror("malloc");
|
||||
return strlen(string); /* flawfinder: ignore */
|
||||
/* flawfinder rationale: see above. */
|
||||
}
|
||||
memset(wide_string, 0, wide_string_buffer_size);
|
||||
|
||||
if (mbstowcs(wide_string, string, 1 + wide_char_count) == (size_t) -1) {
|
||||
debug("%s: %s: %s", "mbstowcs", string, strerror(errno));
|
||||
width = strlen(string); /* flawfinder: ignore */
|
||||
/* flawfinder rationale: see above. */
|
||||
} else if (NULL != wide_string) {
|
||||
/*@-unrecog @ */
|
||||
/* splint seems unable to see the prototype. */
|
||||
width = wcswidth(wide_string, wide_char_count);
|
||||
/*@+unrecog @ */
|
||||
} else {
|
||||
width = 0;
|
||||
}
|
||||
|
||||
free(wide_string);
|
||||
|
||||
#else /* ! defined(ENABLE_NLS) && defined(HAVE_WCHAR_H) */
|
||||
if (NULL == string)
|
||||
return 0;
|
||||
|
||||
width = strlen(string); /* flawfinder: ignore */
|
||||
/* flawfinder rationale: see above. */
|
||||
#endif /* defined(ENABLE_NLS) && defined(HAVE_WCHAR_H) */
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The 7-bit ASCII version of display_word_wrap() below - does not
|
||||
* understand multi-byte characters.
|
||||
*/
|
||||
static void display_word_wrap_7bit(const char *string, size_t display_width, size_t left_margin)
|
||||
{
|
||||
const char *start;
|
||||
const char *end;
|
||||
|
||||
if (NULL == string)
|
||||
return;
|
||||
|
||||
start = string;
|
||||
|
||||
while (strlen(start) > display_width) { /* flawfinder: ignore */
|
||||
/* flawfinder rationale: see above. */
|
||||
|
||||
end = start + display_width;
|
||||
while ((end > start) && (end[0] != ' '))
|
||||
end--;
|
||||
if (end == start) {
|
||||
end = start + display_width;
|
||||
} else {
|
||||
end++;
|
||||
}
|
||||
printf("%.*s", (int) (end - start), start);
|
||||
if (end == start)
|
||||
end++;
|
||||
start = end;
|
||||
if (start[0] != '\0')
|
||||
printf("\n%*s", (int) left_margin, "");
|
||||
}
|
||||
|
||||
printf("%s", start);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output a string to standard output, word wrapping to "display_width"
|
||||
* display character positions, and left-padding any new lines after the
|
||||
* first one with "left_margin" spaces.
|
||||
*
|
||||
* Wide characters are handled if NLS is enabled, but if they can't be, this
|
||||
* falls back to a version which just counts bytes as characters.
|
||||
*/
|
||||
static void display_word_wrap(const char *string, size_t display_width, size_t left_margin)
|
||||
{
|
||||
#if defined(ENABLE_NLS) && defined(HAVE_WCHAR_H)
|
||||
size_t wide_char_count;
|
||||
size_t wide_string_buffer_size;
|
||||
wchar_t *wide_string;
|
||||
size_t start_idx, end_idx, chars_remaining;
|
||||
|
||||
if (NULL == string)
|
||||
return;
|
||||
|
||||
/*@-nullpass@ */
|
||||
/* splint note: see earlier mbstowcs() call. */
|
||||
wide_char_count = mbstowcs(NULL, string, 0);
|
||||
/*@+nullpass@ */
|
||||
if (wide_char_count == (size_t) -1) {
|
||||
debug("%s: %s: %s", "mbstowcs", string, strerror(errno));
|
||||
display_word_wrap_7bit(string, display_width, left_margin);
|
||||
return;
|
||||
}
|
||||
|
||||
wide_string_buffer_size = sizeof(*wide_string) * (1 + wide_char_count);
|
||||
wide_string = malloc(wide_string_buffer_size);
|
||||
if (NULL == wide_string) {
|
||||
perror("malloc");
|
||||
display_word_wrap_7bit(string, display_width, left_margin);
|
||||
return;
|
||||
}
|
||||
memset(wide_string, 0, wide_string_buffer_size);
|
||||
|
||||
if (mbstowcs(wide_string, string, 1 + wide_char_count) == (size_t) -1) {
|
||||
debug("%s: %s: %s", "mbstowcs", string, strerror(errno));
|
||||
free(wide_string);
|
||||
display_word_wrap_7bit(string, display_width, left_margin);
|
||||
return;
|
||||
}
|
||||
|
||||
start_idx = 0;
|
||||
chars_remaining = wide_char_count;
|
||||
|
||||
while (chars_remaining > 0 && wcswidth(&(wide_string[start_idx]), chars_remaining) > display_width) {
|
||||
size_t next_idx;
|
||||
|
||||
end_idx = start_idx + display_width;
|
||||
while ((end_idx > start_idx) && (!iswspace(wide_string[end_idx])))
|
||||
end_idx--;
|
||||
if (end_idx == start_idx) {
|
||||
end_idx = start_idx + display_width;
|
||||
} else {
|
||||
end_idx++;
|
||||
}
|
||||
|
||||
next_idx = end_idx;
|
||||
if (end_idx == start_idx)
|
||||
next_idx++;
|
||||
|
||||
while (start_idx < end_idx && start_idx < wide_char_count) {
|
||||
char multi_byte_string[MB_CUR_MAX + 1]; /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: array is explicitly
|
||||
* cleared, large enough according to the wctomb()
|
||||
* manual, and we explicitly terminate the string.
|
||||
*/
|
||||
memset(multi_byte_string, 0, MB_CUR_MAX + 1);
|
||||
if (wctomb(multi_byte_string, wide_string[start_idx]) >= 0) {
|
||||
multi_byte_string[MB_CUR_MAX] = '\0';
|
||||
printf("%s", multi_byte_string);
|
||||
}
|
||||
start_idx++;
|
||||
}
|
||||
|
||||
start_idx = next_idx;
|
||||
if (start_idx < wide_char_count)
|
||||
printf("\n%*s", (int) left_margin, "");
|
||||
|
||||
chars_remaining = wide_char_count - start_idx;
|
||||
}
|
||||
|
||||
while (start_idx < wide_char_count) {
|
||||
char multi_byte_string[MB_CUR_MAX + 1]; /* flawfinder: ignore */
|
||||
/* flawfinder rationale as above. */
|
||||
memset(multi_byte_string, 0, MB_CUR_MAX + 1);
|
||||
if (wctomb(multi_byte_string, wide_string[start_idx]) >= 0) {
|
||||
multi_byte_string[MB_CUR_MAX] = '\0';
|
||||
printf("%s", multi_byte_string);
|
||||
}
|
||||
start_idx++;
|
||||
}
|
||||
|
||||
free(wide_string);
|
||||
|
||||
#else /* ! defined(ENABLE_NLS) && defined(HAVE_WCHAR_H) */
|
||||
display_word_wrap_7bit(string, display_width, left_margin);
|
||||
#endif /* defined(ENABLE_NLS) && defined(HAVE_WCHAR_H) */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Structure holding the displayed descriptions of each option - the short
|
||||
* option such as "-s", its long counterpart such as "--size", the name of
|
||||
* its argument such as "SIZE", and the description of what the option does.
|
||||
* Any of them may be NULL.
|
||||
*
|
||||
* In the initialiser for this structure, translatable strings are wrapped
|
||||
* with N_() to indicate that they are to be translated into the operator's
|
||||
* language by this function at run-time.
|
||||
*
|
||||
* Note that "opt_short" and "opt_long" should never be marked as
|
||||
* translatable, as they must remain consistent across all locales.
|
||||
*
|
||||
* The list is terminated with a NULL opt_short value - to leave a gap, set
|
||||
* opt_short to an empty string instead.
|
||||
*/
|
||||
struct option_definition_s {
|
||||
/*@null@ */ const char *opt_short;
|
||||
/*@null@ */ const char *opt_long;
|
||||
/*@null@ *//*@observer@ */ const char *opt_argument;
|
||||
/*@null@ *//*@observer@ */ const char *opt_description;
|
||||
struct {
|
||||
/*
|
||||
* Structure holding the width, in display character
|
||||
* positions, of the individual parts of the description of
|
||||
* each option - calculated after initialisation, so that
|
||||
* translation can be performed.
|
||||
*/
|
||||
size_t opt_short;
|
||||
size_t opt_long;
|
||||
size_t opt_argument;
|
||||
size_t opt_description;
|
||||
} width;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,189 +278,317 @@ struct optdesc_s {
|
||||
*/
|
||||
void display_help(void)
|
||||
{
|
||||
struct optdesc_s optlist[] = {
|
||||
{"-p", "--progress", 0,
|
||||
N_("show progress bar")},
|
||||
{"-t", "--timer", 0,
|
||||
N_("show elapsed time")},
|
||||
{"-e", "--eta", 0,
|
||||
N_("show estimated time of arrival (completion)")},
|
||||
{"-I", "--fineta", 0,
|
||||
N_
|
||||
("show absolute estimated time of arrival (completion)")},
|
||||
{"-r", "--rate", 0,
|
||||
N_("show data transfer rate counter")},
|
||||
{"-a", "--average-rate", 0,
|
||||
N_("show data transfer average rate counter")},
|
||||
{"-b", "--bytes", 0,
|
||||
N_("show number of bytes transferred")},
|
||||
{"-T", "--buffer-percent", 0,
|
||||
N_("show percentage of transfer buffer in use")},
|
||||
{"-A", "--last-written", _("NUM"),
|
||||
N_("show NUM bytes last written")},
|
||||
{"-F", "--format", N_("FORMAT"),
|
||||
N_("set output format to FORMAT")},
|
||||
{"-n", "--numeric", 0,
|
||||
N_("output percentages, not visual information")},
|
||||
{"-q", "--quiet", 0,
|
||||
N_("do not output any transfer information at all")},
|
||||
{"", 0, 0, 0},
|
||||
{"-W", "--wait", 0,
|
||||
N_("display nothing until first byte transferred")},
|
||||
{"-D", "--delay-start", N_("SEC"),
|
||||
N_("display nothing until SEC seconds have passed")},
|
||||
{"-s", "--size", N_("SIZE"),
|
||||
N_("set estimated data size to SIZE bytes")},
|
||||
{"-l", "--line-mode", 0,
|
||||
N_("count lines instead of bytes")},
|
||||
{"-0", "--null", 0,
|
||||
N_("lines are null-terminated")},
|
||||
{"-i", "--interval", N_("SEC"),
|
||||
N_("update every SEC seconds")},
|
||||
{"-w", "--width", N_("WIDTH"),
|
||||
N_("assume terminal is WIDTH characters wide")},
|
||||
{"-H", "--height", N_("HEIGHT"),
|
||||
N_("assume terminal is HEIGHT rows high")},
|
||||
{"-N", "--name", N_("NAME"),
|
||||
N_("prefix visual information with NAME")},
|
||||
{"-f", "--force", 0,
|
||||
N_("output even if standard error is not a terminal")},
|
||||
{"-c", "--cursor", 0,
|
||||
N_("use cursor positioning escape sequences")},
|
||||
{"", 0, 0, 0},
|
||||
{"-L", "--rate-limit", N_("RATE"),
|
||||
N_("limit transfer to RATE bytes per second")},
|
||||
{"-B", "--buffer-size", N_("BYTES"),
|
||||
N_("use a buffer size of BYTES")},
|
||||
{"-C", "--no-splice", 0,
|
||||
N_("never use splice(), always use read/write")},
|
||||
{"-E", "--skip-errors", 0,
|
||||
N_("skip read errors in input")},
|
||||
{"-S", "--stop-at-size", 0,
|
||||
N_("stop after --size bytes have been transferred")},
|
||||
struct option_definition_s option_definitions[] = {
|
||||
{ "-p", "--progress", NULL,
|
||||
N_("show progress bar"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-t", "--timer", NULL,
|
||||
N_("show elapsed time"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-e", "--eta", NULL,
|
||||
N_("show estimated time of arrival (completion)"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-I", "--fineta", NULL,
|
||||
N_("show absolute estimated time of arrival (completion)"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-r", "--rate", NULL,
|
||||
N_("show data transfer rate counter"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-a", "--average-rate", NULL,
|
||||
N_("show data transfer average rate counter"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-m", "--average-rate-window", N_("SEC"),
|
||||
N_("compute average rate over past SEC seconds (default 30s)"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-b", "--bytes", NULL,
|
||||
N_("show number of bytes transferred"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-8", "--bits", NULL,
|
||||
N_("show number of bits transferred"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-T", "--buffer-percent", NULL,
|
||||
N_("show percentage of transfer buffer in use"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-A", "--last-written", _("NUM"),
|
||||
N_("show NUM bytes last written"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-F", "--format", N_("FORMAT"),
|
||||
N_("set output format to FORMAT"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-n", "--numeric", NULL,
|
||||
N_("output percentages, not visual information"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-q", "--quiet", NULL,
|
||||
N_("do not output any transfer information at all"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-W", "--wait", NULL,
|
||||
N_("display nothing until first byte transferred"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-D", "--delay-start", N_("SEC"),
|
||||
N_("display nothing until SEC seconds have passed"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-s", "--size", N_("SIZE"),
|
||||
N_("set estimated data size to SIZE bytes"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-l", "--line-mode", NULL,
|
||||
N_("count lines instead of bytes"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-0", "--null", NULL,
|
||||
N_("lines are null-terminated"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-i", "--interval", N_("SEC"),
|
||||
N_("update every SEC seconds"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-w", "--width", N_("WIDTH"),
|
||||
N_("assume terminal is WIDTH characters wide"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-H", "--height", N_("HEIGHT"),
|
||||
N_("assume terminal is HEIGHT rows high"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-N", "--name", N_("NAME"),
|
||||
N_("prefix visual information with NAME"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-f", "--force", NULL,
|
||||
N_("output even if standard error is not a terminal"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-c", "--cursor", NULL,
|
||||
N_("use cursor positioning escape sequences"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-L", "--rate-limit", N_("RATE"),
|
||||
N_("limit transfer to RATE bytes per second"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-B", "--buffer-size", N_("BYTES"),
|
||||
N_("use a buffer size of BYTES"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-C", "--no-splice", NULL,
|
||||
N_("never use splice(), always use read/write"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-E", "--skip-errors", NULL,
|
||||
N_("skip read errors in input"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-Z", "--error-skip-block", N_("BYTES"),
|
||||
N_("skip errors in BYTES blocks at a time"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-S", "--stop-at-size", NULL,
|
||||
N_("stop after --size bytes have been transferred"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-Y", "--sync", NULL,
|
||||
N_("flush cache to disk after every write"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-K", "--direct-io", NULL,
|
||||
N_("use direct I/O to bypass cache"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-X", "--discard", NULL,
|
||||
N_("discard input instead of writing to output"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#ifdef HAVE_IPC
|
||||
{"-R", "--remote", N_("PID"),
|
||||
N_("update settings of process PID")},
|
||||
{ "-R", "--remote", N_("PID"),
|
||||
N_("update settings of process PID"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#endif /* HAVE_IPC */
|
||||
{"", 0, 0, 0},
|
||||
{"-P", "--pidfile", N_("FILE"),
|
||||
N_("save process ID in FILE")},
|
||||
{"", 0, 0, 0},
|
||||
{"-d", "--watchfd", N_("PID[:FD]"),
|
||||
N_("watch file FD opened by process PID")},
|
||||
{"", 0, 0, 0},
|
||||
{"-h", "--help", 0,
|
||||
N_("show this help and exit")},
|
||||
{"-V", "--version", 0,
|
||||
N_("show version information and exit")},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
unsigned int i, col1max = 0, tw = 77;
|
||||
char *optbuf;
|
||||
|
||||
printf(_("Usage: %s [OPTION] [FILE]..."), PROGRAM_NAME);
|
||||
printf("\n%s\n\n",
|
||||
_
|
||||
("Concatenate FILE(s), or standard input, to standard output,\n"
|
||||
"with monitoring."));
|
||||
|
||||
for (i = 0; optlist[i].optshort; i++) {
|
||||
unsigned int width = 0;
|
||||
char *param;
|
||||
|
||||
width = 2 + (unsigned int) strlen(optlist[i].optshort);
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
if (optlist[i].optlong)
|
||||
width +=
|
||||
2 + (unsigned int) strlen(optlist[i].optlong);
|
||||
#endif
|
||||
param = optlist[i].param;
|
||||
if (param)
|
||||
param = _(param);
|
||||
if (param)
|
||||
width += 1 + strlen(param);
|
||||
|
||||
if (width > col1max)
|
||||
col1max = width;
|
||||
}
|
||||
|
||||
col1max++;
|
||||
|
||||
optbuf = malloc((size_t) (col1max + 16));
|
||||
if (NULL == optbuf) {
|
||||
fprintf(stderr, "%s: %s\n", PROGRAM_NAME, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; optlist[i].optshort; i++) {
|
||||
char *param;
|
||||
char *description;
|
||||
char *start;
|
||||
char *end;
|
||||
|
||||
if ('\0' == optlist[i].optshort[0]) {
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
param = optlist[i].param;
|
||||
if (param)
|
||||
param = _(param);
|
||||
description = optlist[i].description;
|
||||
if (description)
|
||||
description = _(description);
|
||||
|
||||
#ifdef HAVE_SNPRINTF
|
||||
(void) snprintf(optbuf, (size_t) (col1max + 15),
|
||||
"%s%s%s%s%s", optlist[i].optshort,
|
||||
#else
|
||||
sprintf(optbuf, "%s%s%s%s%s", optlist[i].optshort,
|
||||
#endif
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
optlist[i].optlong ? ", " : "",
|
||||
optlist[i].optlong ? optlist[i].optlong : "",
|
||||
#else
|
||||
"", "",
|
||||
#endif
|
||||
param ? " " : "", param ? param : "");
|
||||
|
||||
printf(" %-*s ", (int) (col1max - 2), optbuf);
|
||||
|
||||
if (NULL == description) {
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
start = description;
|
||||
|
||||
while ((unsigned int) strlen(start) > tw - col1max) {
|
||||
end = start + tw - col1max;
|
||||
while ((end > start) && (end[0] != ' '))
|
||||
end--;
|
||||
if (end == start) {
|
||||
end = start + tw - col1max;
|
||||
} else {
|
||||
end++;
|
||||
}
|
||||
printf("%.*s\n%*s ", (int) (end - start), start,
|
||||
(int) col1max, "");
|
||||
if (end == start)
|
||||
end++;
|
||||
start = end;
|
||||
}
|
||||
|
||||
printf("%s\n", start);
|
||||
}
|
||||
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-P", "--pidfile", N_("FILE"),
|
||||
N_("save process ID in FILE"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-d", "--watchfd", N_("PID[:FD]"),
|
||||
N_("watch file FD opened by process PID"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-h", "--help", NULL,
|
||||
N_("show this help and exit"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-V", "--version", NULL,
|
||||
N_("show version information and exit"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#ifdef ENABLE_DEBUGGING
|
||||
printf("\n");
|
||||
printf("%s",
|
||||
_
|
||||
("Debugging is enabled; export the DEBUG environment variable to define the\noutput filename.\n"));
|
||||
{ "-!", "--debug", N_("FILE"),
|
||||
N_("write debug logs to FILE"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#endif
|
||||
{ NULL, NULL, NULL, NULL, { 0, 0, 0, 0} }
|
||||
};
|
||||
unsigned int option_index;
|
||||
size_t widest_option_width = 0;
|
||||
size_t description_left_margin = 0;
|
||||
size_t min_description_width = 50;
|
||||
size_t right_margin = 77;
|
||||
const char *program_description;
|
||||
const char *bug_report_note;
|
||||
unsigned int terminal_width = 0, terminal_height = 0;
|
||||
|
||||
pv_screensize(&terminal_width, &terminal_height);
|
||||
if (terminal_width > 5) {
|
||||
right_margin = (size_t) (terminal_width - 3);
|
||||
}
|
||||
|
||||
/*@-formatconst@ */
|
||||
/*
|
||||
* splint note: unavoidable use of %s in translated string. Should
|
||||
* be hard to exploit - the message catalogue would have to be
|
||||
* replaced or forced to load from another location.
|
||||
*/
|
||||
printf(_("Usage: %s [OPTION] [FILE]..."), PACKAGE_NAME);
|
||||
/*@+formatconst@ */
|
||||
|
||||
printf("\n");
|
||||
printf(_("Please report any bugs to %s."), BUG_REPORTS_TO);
|
||||
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory leak
|
||||
* warnings, but in this case it's unavoidable, and mitigated by the
|
||||
* fact we only translate each string once.
|
||||
*/
|
||||
program_description = _("Concatenate FILE(s), or standard input, to standard output, with monitoring.");
|
||||
if (NULL != program_description) {
|
||||
display_word_wrap(program_description, right_margin, 0);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
/*
|
||||
* Translate the help text, and calculate the displayed width of
|
||||
* each part of each option definition. The total display width of
|
||||
* the short option, long option, and option argument together form
|
||||
* the "option" width - we look for the widest one to calculate the
|
||||
* left margin for all of the descriptions to start at.
|
||||
*/
|
||||
for (option_index = 0; NULL != option_definitions[option_index].opt_short; option_index++) {
|
||||
struct option_definition_s *definition;
|
||||
size_t option_width;
|
||||
|
||||
definition = &(option_definitions[option_index]);
|
||||
option_width = 0;
|
||||
|
||||
definition->width.opt_short = display_width(definition->opt_short);
|
||||
definition->width.opt_long = 0;
|
||||
definition->width.opt_argument = 0;
|
||||
definition->width.opt_description = 0;
|
||||
|
||||
if (NULL != definition->opt_long) {
|
||||
definition->width.opt_long = display_width(definition->opt_long);
|
||||
}
|
||||
|
||||
if (NULL != definition->opt_argument) {
|
||||
/*@observer@ */ const char *translated;
|
||||
translated = _(definition->opt_argument);
|
||||
if (NULL != translated) {
|
||||
definition->opt_argument = translated;
|
||||
}
|
||||
definition->width.opt_argument = display_width(definition->opt_argument);
|
||||
}
|
||||
|
||||
if (NULL != definition->opt_description) {
|
||||
/*@observer@ */ const char *translated;
|
||||
translated = _(definition->opt_description);
|
||||
if (NULL != translated) {
|
||||
definition->opt_description = translated;
|
||||
}
|
||||
definition->width.opt_description = display_width(definition->opt_description);
|
||||
}
|
||||
|
||||
/*
|
||||
* The option_width is padded with a left margin of 2
|
||||
* spaces, a ", " between the short and long options, a
|
||||
* space between the long option and the argument, and two
|
||||
* spaces after the argument:
|
||||
*
|
||||
* " <short>, <long> <arg> <description>"
|
||||
*
|
||||
* If we don't have getopt_long() then ", <long>" is omitted.
|
||||
*/
|
||||
option_width += 2 + definition->width.opt_short; /* " short" */
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
option_width += 2 + definition->width.opt_long; /* ", <long>" */
|
||||
#endif
|
||||
option_width += 1 + definition->width.opt_argument; /* " ARG" */
|
||||
option_width += 2; /* final 2 spaces */
|
||||
|
||||
if (option_width > widest_option_width) {
|
||||
widest_option_width = option_width;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the left margin for the option descriptions, based on the
|
||||
* widest option width, or (right margin - min_description_width),
|
||||
* whichever is less, so that there is always room for
|
||||
* "min_description_width" characters of description.
|
||||
*/
|
||||
description_left_margin = right_margin - min_description_width;
|
||||
if (widest_option_width < description_left_margin) {
|
||||
description_left_margin = widest_option_width;
|
||||
}
|
||||
|
||||
debug("%s: description_left_margin=%d, widest_option_width=%d, right_margin=%d", "help display",
|
||||
(int) description_left_margin, (int) widest_option_width, (int) right_margin);
|
||||
|
||||
/*
|
||||
* Display each of the option definitions, word wrapping the
|
||||
* descriptions.
|
||||
*/
|
||||
for (option_index = 0; NULL != option_definitions[option_index].opt_short; option_index++) {
|
||||
struct option_definition_s *definition;
|
||||
size_t option_width;
|
||||
|
||||
definition = &(option_definitions[option_index]);
|
||||
option_width = 0;
|
||||
|
||||
if (definition->width.opt_short > 0 && NULL != definition->opt_short) {
|
||||
printf(" %s", definition->opt_short);
|
||||
option_width += 2 + definition->width.opt_short;
|
||||
}
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
if (definition->width.opt_long > 0 && NULL != definition->opt_long) {
|
||||
printf(", %s", definition->opt_long);
|
||||
option_width += 2 + definition->width.opt_long;
|
||||
}
|
||||
#endif
|
||||
if (definition->width.opt_argument > 0 && NULL != definition->opt_argument) {
|
||||
printf(" %s", definition->opt_argument);
|
||||
option_width += 1 + definition->width.opt_argument;
|
||||
}
|
||||
|
||||
/* Just start a new line if there's no description. */
|
||||
if ((0 == definition->width.opt_description) || (NULL == definition->opt_description)) {
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the option is too wide, start a new line for the
|
||||
* description. In both cases, pad with spaces up to the
|
||||
* description left margin.
|
||||
*/
|
||||
if (option_width > description_left_margin) {
|
||||
printf("\n%*s", (int) description_left_margin, "");
|
||||
} else if (option_width < description_left_margin) {
|
||||
printf("%*s", (int) (description_left_margin - option_width), "");
|
||||
}
|
||||
|
||||
/* Output the description, word wrapped. */
|
||||
display_word_wrap(definition->opt_description, right_margin - description_left_margin,
|
||||
description_left_margin);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
bug_report_note = _("Please report any bugs to: %s");
|
||||
if (NULL != bug_report_note) {
|
||||
/*@-formatconst@ */
|
||||
/*
|
||||
* splint note: see earlier "formatconst" note.
|
||||
* flawfinder: same reason.
|
||||
*/
|
||||
printf(bug_report_note, PACKAGE_BUGREPORT); /* flawfinder: ignore */
|
||||
/*@+formatconst@ */
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
+143
-120
@@ -1,14 +1,17 @@
|
||||
/*
|
||||
* Main program entry point - read the command line options, then perform
|
||||
* the appropriate actions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "options.h"
|
||||
#include "pv.h"
|
||||
|
||||
/* We do not set this because it breaks "dd" - see below. */
|
||||
/* #undef MAKE_STDOUT_NONBLOCKING */
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -16,9 +19,9 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
int pv_remote_set(opts_t);
|
||||
@@ -32,24 +35,25 @@ void pv_remote_fini(void);
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct termios t, t_save;
|
||||
opts_t opts;
|
||||
pvstate_t state;
|
||||
bool t_saved, t_needs_reset;
|
||||
/*@only@ */ opts_t opts = NULL;
|
||||
/*@only@ */ pvstate_t state = NULL;
|
||||
int retcode = 0;
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
/* Initialise language translation. */
|
||||
(void) setlocale(LC_ALL, "");
|
||||
(void) bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
(void) textdomain(PACKAGE);
|
||||
#endif
|
||||
|
||||
opts = opts_parse(argc, argv);
|
||||
/* Parse the command line arguments. */
|
||||
opts = opts_parse(argc >= 0 ? (unsigned int) argc : 0, argv);
|
||||
if (NULL == opts) {
|
||||
debug("%s: %d", "exiting with status", 64);
|
||||
return 64;
|
||||
}
|
||||
|
||||
/* Early exit if necessary, such as with "-h". */
|
||||
if (opts->do_nothing) {
|
||||
debug("%s", "nothing to do - exiting with status 0");
|
||||
opts_free(opts);
|
||||
@@ -70,31 +74,97 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
state = pv_state_alloc(opts->program_name);
|
||||
if (NULL == state) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name,
|
||||
_("state allocation failed"), strerror(errno));
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory
|
||||
* leak warnings, but in this case it's unavoidable, and
|
||||
* mitigated by the fact we only translate each string once.
|
||||
*/
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, _("state allocation failed"), strerror(errno));
|
||||
opts_free(opts);
|
||||
debug("%s: %d", "exiting with status", 64);
|
||||
return 64;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a PID file if -P was specified.
|
||||
*/
|
||||
if (opts->pidfile != NULL) {
|
||||
FILE *pidfptr;
|
||||
pidfptr = fopen(opts->pidfile, "w");
|
||||
if (NULL == pidfptr) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name,
|
||||
opts->pidfile, strerror(errno));
|
||||
char *pidfile_tmp_name;
|
||||
size_t pidfile_tmp_bufsize;
|
||||
int pidfile_tmp_fd;
|
||||
FILE *pidfile_tmp_fptr;
|
||||
mode_t prev_umask;
|
||||
|
||||
pidfile_tmp_bufsize = 16 + strlen(opts->pidfile); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: pidfile was supplied as an argument
|
||||
* so we have to assume it is \0 terminated.
|
||||
*/
|
||||
pidfile_tmp_name = malloc(pidfile_tmp_bufsize);
|
||||
if (NULL == pidfile_tmp_name) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
return 1;
|
||||
}
|
||||
fprintf(pidfptr, "%d\n", getpid());
|
||||
if (0 != fclose(pidfptr)) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name,
|
||||
opts->pidfile, strerror(errno));
|
||||
memset(pidfile_tmp_name, 0, pidfile_tmp_bufsize);
|
||||
(void) pv_snprintf(pidfile_tmp_name, pidfile_tmp_bufsize, "%s.XXXXXX", opts->pidfile);
|
||||
|
||||
/*@-type@ *//* splint doesn't like mode_t */
|
||||
prev_umask = umask(0000); /* flawfinder: ignore */
|
||||
(void) umask(prev_umask | 0133); /* flawfinder: ignore */
|
||||
|
||||
/*@-unrecog@ *//* splint doesn't know mkstemp() */
|
||||
pidfile_tmp_fd = mkstemp(pidfile_tmp_name); /* flawfinder: ignore */
|
||||
/*@+unrecog@ */
|
||||
if (pidfile_tmp_fd < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, pidfile_tmp_name, strerror(errno));
|
||||
(void) umask(prev_umask); /* flawfinder: ignore */
|
||||
free(pidfile_tmp_name);
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
return 1;
|
||||
}
|
||||
|
||||
(void) umask(prev_umask); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale (umask, mkstemp) - flawfinder
|
||||
* recommends setting the most restrictive umask possible
|
||||
* when calling mkstemp(), so this is what we have done.
|
||||
*
|
||||
* We get the original umask and OR it with 0133 to make
|
||||
* sure new files will be at least chmod 644. Then we put
|
||||
* the umask back to what it was, after creating the
|
||||
* temporary file.
|
||||
*/
|
||||
|
||||
/*@+type@ */
|
||||
|
||||
pidfile_tmp_fptr = fdopen(pidfile_tmp_fd, "w");
|
||||
if (NULL == pidfile_tmp_fptr) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, pidfile_tmp_name, strerror(errno));
|
||||
(void) close(pidfile_tmp_fd);
|
||||
(void) remove(pidfile_tmp_name);
|
||||
free(pidfile_tmp_name);
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(pidfile_tmp_fptr, "%d\n", getpid());
|
||||
if (0 != fclose(pidfile_tmp_fptr)) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->pidfile, strerror(errno));
|
||||
}
|
||||
|
||||
if (rename(pidfile_tmp_name, opts->pidfile) < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->pidfile, strerror(errno));
|
||||
(void) remove(pidfile_tmp_name);
|
||||
}
|
||||
|
||||
free(pidfile_tmp_name);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -102,24 +172,30 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
if (0 == opts->argc) {
|
||||
debug("%s", "no files given - adding fake argument `-'");
|
||||
opts->argv[opts->argc++] = "-";
|
||||
if (!opts_add_file(opts, "-")) {
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
return 64;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put our list of files into the PV internal state.
|
||||
* Put our list of input files into the PV internal state.
|
||||
*/
|
||||
pv_state_inputfiles(state, opts->argc,
|
||||
(const char **) (opts->argv));
|
||||
if (NULL != opts->argv) {
|
||||
pv_state_inputfiles(state, opts->argc, (const char **) (opts->argv));
|
||||
}
|
||||
|
||||
/* Total size calculation, in normal transfer mode. */
|
||||
if (0 == opts->watch_pid) {
|
||||
/*
|
||||
* If no size was given, and we're not in line mode, try to
|
||||
* calculate the total size.
|
||||
* If no size was given, try to calculate the total size.
|
||||
*/
|
||||
if ((0 == opts->size) && (false == opts->linemode)) {
|
||||
if (0 == opts->size) {
|
||||
pv_state_linemode_set(state, opts->linemode);
|
||||
pv_state_null_terminated_lines_set(state, opts->null_terminated_lines);
|
||||
opts->size = pv_calc_total_size(state);
|
||||
debug("%s: %llu", "no size given - calculated",
|
||||
opts->size);
|
||||
debug("%s: %llu", "no size given - calculated", opts->size);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -138,8 +214,8 @@ int main(int argc, char **argv)
|
||||
if ((0 == isatty(STDERR_FILENO))
|
||||
&& (false == opts->force)
|
||||
&& (false == opts->numeric)) {
|
||||
opts->no_op = true;
|
||||
debug("%s", "nothing to display - setting no_op");
|
||||
opts->no_display = true;
|
||||
debug("%s", "nothing to display - setting no_display");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -152,13 +228,11 @@ int main(int argc, char **argv)
|
||||
pv_screensize(&width, &height);
|
||||
if (0 == opts->width) {
|
||||
opts->width = width;
|
||||
debug("%s: %u", "auto-detected terminal width",
|
||||
width);
|
||||
debug("%s: %u", "auto-detected terminal width", width);
|
||||
}
|
||||
if (0 == opts->height) {
|
||||
opts->height = height;
|
||||
debug("%s: %u", "auto-detected terminal height",
|
||||
height);
|
||||
debug("%s: %u", "auto-detected terminal height", height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,18 +260,23 @@ int main(int argc, char **argv)
|
||||
* Copy parameters from options into main state.
|
||||
*/
|
||||
pv_state_interval_set(state, opts->interval);
|
||||
pv_state_width_set(state, opts->width);
|
||||
pv_state_height_set(state, opts->height);
|
||||
pv_state_no_op_set(state, opts->no_op);
|
||||
pv_state_width_set(state, opts->width, opts->width_set_manually);
|
||||
pv_state_height_set(state, opts->height, opts->height_set_manually);
|
||||
pv_state_no_display_set(state, opts->no_display);
|
||||
pv_state_force_set(state, opts->force);
|
||||
pv_state_cursor_set(state, opts->cursor);
|
||||
pv_state_numeric_set(state, opts->numeric);
|
||||
pv_state_wait_set(state, opts->wait);
|
||||
pv_state_delay_start_set(state, opts->delay_start);
|
||||
pv_state_linemode_set(state, opts->linemode);
|
||||
pv_state_null_set(state, opts->null);
|
||||
pv_state_bits_set(state, opts->bits);
|
||||
pv_state_null_terminated_lines_set(state, opts->null_terminated_lines);
|
||||
pv_state_skip_errors_set(state, opts->skip_errors);
|
||||
pv_state_error_skip_block_set(state, opts->error_skip_block);
|
||||
pv_state_stop_at_size_set(state, opts->stop_at_size);
|
||||
pv_state_sync_after_write_set(state, opts->sync_after_write);
|
||||
pv_state_direct_io_set(state, opts->direct_io);
|
||||
pv_state_discard_input_set(state, opts->discard_input);
|
||||
pv_state_rate_limit_set(state, opts->rate_limit);
|
||||
pv_state_target_buffer_size_set(state, opts->buffer_size);
|
||||
pv_state_no_splice_set(state, opts->no_splice);
|
||||
@@ -206,11 +285,11 @@ int main(int argc, char **argv)
|
||||
pv_state_format_string_set(state, opts->format);
|
||||
pv_state_watch_pid_set(state, opts->watch_pid);
|
||||
pv_state_watch_fd_set(state, opts->watch_fd);
|
||||
pv_state_average_rate_window_set(state, opts->average_rate_window);
|
||||
|
||||
pv_state_set_format(state, opts->progress, opts->timer, opts->eta,
|
||||
opts->fineta, opts->rate, opts->average_rate,
|
||||
opts->bytes, opts->bufpercent,
|
||||
opts->lastwritten, opts->name);
|
||||
opts->bytes, opts->bufpercent, opts->lastwritten, opts->name);
|
||||
|
||||
#ifdef MAKE_STDOUT_NONBLOCKING
|
||||
/*
|
||||
@@ -219,96 +298,40 @@ int main(int argc, char **argv)
|
||||
* Note that this can cause problems with (broken) applications
|
||||
* such as dd.
|
||||
*/
|
||||
fcntl(STDOUT_FILENO, F_SETFL,
|
||||
O_NONBLOCK | fcntl(STDOUT_FILENO, F_GETFL));
|
||||
fcntl(STDOUT_FILENO, F_SETFL, O_NONBLOCK | fcntl(STDOUT_FILENO, F_GETFL));
|
||||
#endif /* MAKE_STDOUT_NONBLOCKING */
|
||||
|
||||
/*
|
||||
* Keep track of whether we've saved the terminal attributes and
|
||||
* whether we need to reset them at the end.
|
||||
*/
|
||||
t_saved = false;
|
||||
t_needs_reset = false;
|
||||
/* Initialise the signal handling. */
|
||||
pv_sig_init(state);
|
||||
|
||||
/*
|
||||
* Set terminal option TOSTOP so we get signal SIGTTOU if we try to
|
||||
* write to the terminal while backgrounded.
|
||||
*
|
||||
* Also, save the current terminal attributes for later restoration.
|
||||
*/
|
||||
memset(&t, 0, sizeof(t));
|
||||
if (0 != isatty(STDERR_FILENO)) {
|
||||
if (0 == tcgetattr(STDERR_FILENO, &t)) {
|
||||
debug("%s", "saved terminal attributes");
|
||||
t_saved = true;
|
||||
} else {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name,
|
||||
_("failed to read terminal attributes"),
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
t_save = t;
|
||||
if (t_saved && pv_in_foreground()) {
|
||||
t.c_lflag |= TOSTOP;
|
||||
(void) tcsetattr(STDERR_FILENO, TCSANOW, &t);
|
||||
t_needs_reset = true;
|
||||
debug("%s", "set terminal TOSTOP attribute");
|
||||
}
|
||||
|
||||
if (0 != opts->watch_pid) {
|
||||
if (0 <= opts->watch_fd) {
|
||||
pv_sig_init(state);
|
||||
retcode = pv_watchfd_loop(state);
|
||||
if (t_needs_reset && pv_in_foreground()) {
|
||||
(void) tcsetattr(STDERR_FILENO, TCSANOW,
|
||||
&t_save);
|
||||
}
|
||||
if (opts->pidfile != NULL) {
|
||||
if (0 != remove(opts->pidfile)) {
|
||||
fprintf(stderr, "%s: %s: %s\n",
|
||||
opts->program_name,
|
||||
opts->pidfile,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
pv_sig_fini(state);
|
||||
} else {
|
||||
pv_sig_init(state);
|
||||
retcode = pv_watchpid_loop(state);
|
||||
if (t_needs_reset && pv_in_foreground()) {
|
||||
(void) tcsetattr(STDERR_FILENO, TCSANOW,
|
||||
&t_save);
|
||||
}
|
||||
if (opts->pidfile != NULL) {
|
||||
if (0 != remove(opts->pidfile)) {
|
||||
fprintf(stderr, "%s: %s: %s\n",
|
||||
opts->program_name,
|
||||
opts->pidfile,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
pv_sig_fini(state);
|
||||
}
|
||||
} else {
|
||||
pv_sig_init(state);
|
||||
/* Run the appropriate main loop. */
|
||||
if (0 == opts->watch_pid) {
|
||||
/* Normal "transfer data" mode. */
|
||||
pv_remote_init();
|
||||
retcode = pv_main_loop(state);
|
||||
pv_remote_fini();
|
||||
if (t_needs_reset && pv_in_foreground()) {
|
||||
(void) tcsetattr(STDERR_FILENO, TCSANOW, &t_save);
|
||||
}
|
||||
if (opts->pidfile != NULL) {
|
||||
if (0 != remove(opts->pidfile)) {
|
||||
fprintf(stderr, "%s: %s: %s\n",
|
||||
opts->program_name, opts->pidfile,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
pv_sig_fini(state);
|
||||
} else if (0 != opts->watch_pid && -1 == opts->watch_fd) {
|
||||
/* "Watch all file descriptors of another process" mode. */
|
||||
retcode = pv_watchpid_loop(state);
|
||||
} else if (0 != opts->watch_pid && -1 != opts->watch_fd) {
|
||||
/* "Watch a specific file descriptor of another process" mode. */
|
||||
retcode = pv_watchfd_loop(state);
|
||||
}
|
||||
|
||||
/* Clear up the PID file, if one was written. */
|
||||
if (opts->pidfile != NULL) {
|
||||
if (0 != remove(opts->pidfile)) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->pidfile, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/* Close down the signal handling. */
|
||||
pv_sig_fini(state);
|
||||
|
||||
/* Free the internal PV state. */
|
||||
pv_state_free(state);
|
||||
|
||||
/* Free the data from parsing the command-line arguments. */
|
||||
opts_free(opts);
|
||||
|
||||
debug("%s: %d", "exiting with status", retcode);
|
||||
|
||||
+319
-116
@@ -1,19 +1,24 @@
|
||||
/*
|
||||
* Parse command-line options.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "options.h"
|
||||
#include "library/getopt.h"
|
||||
#include "pv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
|
||||
void display_help(void);
|
||||
@@ -23,97 +28,173 @@ void display_version(void);
|
||||
/*
|
||||
* Free an opts_t object.
|
||||
*/
|
||||
void opts_free(opts_t opts)
|
||||
void opts_free( /*@only@ */ opts_t opts)
|
||||
{
|
||||
if (!opts)
|
||||
return;
|
||||
/*@-keeptrans@ */
|
||||
/*
|
||||
* splint note: we're explicitly being handed the "opts" object to
|
||||
* free it, so the previously "kept" internally allocated buffers
|
||||
* are now ours to free.
|
||||
*/
|
||||
if (NULL != opts->name)
|
||||
free(opts->name);
|
||||
if (NULL != opts->format)
|
||||
free(opts->format);
|
||||
if (NULL != opts->pidfile)
|
||||
free(opts->pidfile);
|
||||
if (NULL != opts->argv)
|
||||
free(opts->argv);
|
||||
/*@+keeptrans@ */
|
||||
free(opts);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a filename to the list of non-option arguments, returning false on
|
||||
* error. The filename is not copied - the pointer is stored.
|
||||
*/
|
||||
bool opts_add_file(opts_t opts, const char *filename)
|
||||
{
|
||||
/*@-branchstate@ */
|
||||
if ((opts->argc >= opts->argv_length) || (NULL == opts->argv)) {
|
||||
opts->argv_length = opts->argc + 10;
|
||||
/*@-keeptrans@ */
|
||||
opts->argv = realloc(opts->argv, opts->argv_length * sizeof(char *));
|
||||
/*@+keeptrans@ */
|
||||
if (NULL == opts->argv) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
opts->argv_length = 0;
|
||||
opts->argc = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*@+branchstate@ */
|
||||
|
||||
/*
|
||||
* splint notes: we turned off "branchstate" above because depending
|
||||
* on whether we have to extend the array, we change argv from
|
||||
* "keep" to "only", which is also why we turned off "keeptrans";
|
||||
* there doesn't seem to be a clean way to tell splint that everyone
|
||||
* else should not touch argv but we're allowed to reallocate it and
|
||||
* so is opts_parse.
|
||||
*/
|
||||
|
||||
opts->argv[opts->argc++] = filename;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse the given command-line arguments into an opts_t object, handling
|
||||
* "help", "license" and "version" options internally.
|
||||
* "help" and "version" options internally.
|
||||
*
|
||||
* Returns an opts_t, or 0 on error.
|
||||
* Returns an opts_t, or NULL on error.
|
||||
*
|
||||
* Note that the contents of *argv[] (i.e. the command line parameters)
|
||||
* aren't copied anywhere, just the pointers are copied, so make sure the
|
||||
* command line data isn't overwritten or argv[1] free()d or whatever.
|
||||
*/
|
||||
opts_t opts_parse(int argc, char **argv)
|
||||
/*@null@ */
|
||||
/*@only@ */
|
||||
opts_t opts_parse(unsigned int argc, char **argv)
|
||||
{
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
/*@-nullassign@ */
|
||||
/* splint rationale: NULL is allowed for "flags" in long options. */
|
||||
struct option long_options[] = {
|
||||
{"help", 0, NULL, (int) 'h'},
|
||||
{"version", 0, NULL, (int) 'V'},
|
||||
{"progress", 0, NULL, (int) 'p'},
|
||||
{"timer", 0, NULL, (int) 't'},
|
||||
{"eta", 0, NULL, (int) 'e'},
|
||||
{"fineta", 0, NULL, (int) 'I'},
|
||||
{"rate", 0, NULL, (int) 'r'},
|
||||
{"average-rate", 0, NULL, (int) 'a'},
|
||||
{"bytes", 0, NULL, (int) 'b'},
|
||||
{"buffer-percent", 0, NULL, (int) 'T'},
|
||||
{"last-written", 1, NULL, (int) 'A'},
|
||||
{"force", 0, NULL, (int) 'f'},
|
||||
{"numeric", 0, NULL, (int) 'n'},
|
||||
{"quiet", 0, NULL, (int) 'q'},
|
||||
{"cursor", 0, NULL, (int) 'c'},
|
||||
{"wait", 0, NULL, (int) 'W'},
|
||||
{"delay-start", 1, NULL, (int) 'D'},
|
||||
{"size", 1, NULL, (int) 's'},
|
||||
{"line-mode", 0, NULL, (int) 'l'},
|
||||
{"null", 0, NULL, (int) '0'},
|
||||
{"interval", 1, NULL, (int) 'i'},
|
||||
{"width", 1, NULL, (int) 'w'},
|
||||
{"height", 1, NULL, (int) 'H'},
|
||||
{"name", 1, NULL, (int) 'N'},
|
||||
{"format", 1, NULL, (int) 'F'},
|
||||
{"rate-limit", 1, NULL, (int) 'L'},
|
||||
{"buffer-size", 1, NULL, (int) 'B'},
|
||||
{"no-splice", 0, NULL, (int) 'C'},
|
||||
{"skip-errors", 0, NULL, (int) 'E'},
|
||||
{"stop-at-size", 0, NULL, (int) 'S'},
|
||||
{"remote", 1, NULL, (int) 'R'},
|
||||
{"pidfile", 1, NULL, (int) 'P'},
|
||||
{"watchfd", 1, NULL, (int) 'd'},
|
||||
{NULL, 0, NULL, 0}
|
||||
{ "help", 0, NULL, (int) 'h' },
|
||||
{ "version", 0, NULL, (int) 'V' },
|
||||
{ "progress", 0, NULL, (int) 'p' },
|
||||
{ "timer", 0, NULL, (int) 't' },
|
||||
{ "eta", 0, NULL, (int) 'e' },
|
||||
{ "fineta", 0, NULL, (int) 'I' },
|
||||
{ "rate", 0, NULL, (int) 'r' },
|
||||
{ "average-rate", 0, NULL, (int) 'a' },
|
||||
{ "bytes", 0, NULL, (int) 'b' },
|
||||
{ "bits", 0, NULL, (int) '8' },
|
||||
{ "buffer-percent", 0, NULL, (int) 'T' },
|
||||
{ "last-written", 1, NULL, (int) 'A' },
|
||||
{ "force", 0, NULL, (int) 'f' },
|
||||
{ "numeric", 0, NULL, (int) 'n' },
|
||||
{ "quiet", 0, NULL, (int) 'q' },
|
||||
{ "cursor", 0, NULL, (int) 'c' },
|
||||
{ "wait", 0, NULL, (int) 'W' },
|
||||
{ "delay-start", 1, NULL, (int) 'D' },
|
||||
{ "size", 1, NULL, (int) 's' },
|
||||
{ "line-mode", 0, NULL, (int) 'l' },
|
||||
{ "null", 0, NULL, (int) '0' },
|
||||
{ "interval", 1, NULL, (int) 'i' },
|
||||
{ "width", 1, NULL, (int) 'w' },
|
||||
{ "height", 1, NULL, (int) 'H' },
|
||||
{ "name", 1, NULL, (int) 'N' },
|
||||
{ "format", 1, NULL, (int) 'F' },
|
||||
{ "rate-limit", 1, NULL, (int) 'L' },
|
||||
{ "buffer-size", 1, NULL, (int) 'B' },
|
||||
{ "no-splice", 0, NULL, (int) 'C' },
|
||||
{ "skip-errors", 0, NULL, (int) 'E' },
|
||||
{ "error-skip-block", 1, NULL, (int) 'Z' },
|
||||
{ "stop-at-size", 0, NULL, (int) 'S' },
|
||||
{ "sync", 0, NULL, (int) 'Y' },
|
||||
{ "direct-io", 0, NULL, (int) 'K' },
|
||||
{ "discard", 0, NULL, (int) 'X' },
|
||||
{ "remote", 1, NULL, (int) 'R' },
|
||||
{ "pidfile", 1, NULL, (int) 'P' },
|
||||
{ "watchfd", 1, NULL, (int) 'd' },
|
||||
{ "average-rate-window", 1, NULL, (int) 'm' },
|
||||
#ifdef ENABLE_DEBUGGING
|
||||
{ "debug", 1, NULL, (int) '!' },
|
||||
#endif /* ENABLE_DEBUGGING */
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
/*@+nullassign@ */
|
||||
int option_index = 0;
|
||||
#endif /* HAVE_GETOPT_LONG */
|
||||
char *short_options = "hVpteIrab8TA:fnqcWD:s:l0i:w:H:N:F:L:B:CEZ:SYKXR:P:d:m:"
|
||||
#ifdef ENABLE_DEBUGGING
|
||||
"!:"
|
||||
#endif
|
||||
char *short_options =
|
||||
"hVpteIrabTA:fnqcWD:s:l0i:w:H:N:F:L:B:CESR:P:d:";
|
||||
;
|
||||
int c, numopts;
|
||||
unsigned int check_pid;
|
||||
int check_fd;
|
||||
unsigned int check_pid, parse_pid;
|
||||
int check_fd, parse_fd;
|
||||
opts_t opts;
|
||||
char *ptr;
|
||||
char *leafptr;
|
||||
|
||||
opts = calloc(1, sizeof(*opts));
|
||||
if (!opts) {
|
||||
fprintf(stderr, "%s: %s: %s\n", argv[0],
|
||||
_("option structure allocation failed"),
|
||||
strerror(errno));
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory
|
||||
* leak warnings, but in this case it's unavoidable, and
|
||||
* mitigated by the fact we only translate each string once.
|
||||
*/
|
||||
fprintf(stderr, "%s: %s: %s\n", argv[0], _("option structure allocation failed"), strerror(errno));
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
opts->program_name = argv[0];
|
||||
ptr = strrchr(opts->program_name, '/');
|
||||
if (NULL != ptr)
|
||||
opts->program_name = 1 + ptr;
|
||||
leafptr = strrchr(argv[0], '/');
|
||||
if (NULL != leafptr) {
|
||||
opts->program_name = 1 + leafptr;
|
||||
} else {
|
||||
leafptr = argv[0]; /* avoid splint "keep" warnings */
|
||||
opts->program_name = leafptr;
|
||||
}
|
||||
|
||||
opts->argc = 0;
|
||||
opts->argv = calloc((size_t) (argc + 1), sizeof(char *));
|
||||
if (NULL == opts->argv) {
|
||||
/*@-mustfreefresh@ */
|
||||
/* splint note: as above. */
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name,
|
||||
_("option structure argv allocation failed"),
|
||||
strerror(errno));
|
||||
opts_free(opts);
|
||||
_("option structure argv allocation failed"), strerror(errno));
|
||||
free(opts); /* can't call opts_free as argv is not set */
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
opts->argv_length = 1 + argc;
|
||||
|
||||
numopts = 0;
|
||||
|
||||
@@ -121,15 +202,25 @@ opts_t opts_parse(int argc, char **argv)
|
||||
opts->delay_start = 0;
|
||||
opts->watch_pid = 0;
|
||||
opts->watch_fd = -1;
|
||||
opts->average_rate_window = 30;
|
||||
|
||||
opts->width_set_manually = false;
|
||||
opts->height_set_manually = false;
|
||||
|
||||
do {
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
c = getopt_long(argc, argv,
|
||||
short_options, long_options,
|
||||
&option_index);
|
||||
c = getopt_long((int) argc, argv, short_options, long_options, &option_index); /* flawfinder: ignore */
|
||||
#else
|
||||
c = getopt(argc, argv, short_options);
|
||||
c = getopt((int) argc, argv, short_options); /* flawfinder: ignore */
|
||||
#endif
|
||||
/*
|
||||
* flawfinder rationale: we have to pass argv to getopt, and
|
||||
* limiting the argument sizes would be impractical and
|
||||
* cumbersome (and likely lead to more bugs); so we have to
|
||||
* trust the system getopt to not have internal buffer
|
||||
* overflows.
|
||||
*/
|
||||
|
||||
if (c < 0)
|
||||
continue;
|
||||
|
||||
@@ -138,48 +229,61 @@ opts_t opts_parse(int argc, char **argv)
|
||||
*/
|
||||
switch (c) {
|
||||
case 's':
|
||||
/* "-s @" is valid, so allow it. */
|
||||
if ('@' == *optarg)
|
||||
break;
|
||||
/* falls through */
|
||||
/*@fallthrough@ */
|
||||
case 'A':
|
||||
/*@fallthrough@ */
|
||||
case 'w':
|
||||
/*@fallthrough@ */
|
||||
case 'H':
|
||||
/*@fallthrough@ */
|
||||
case 'L':
|
||||
/*@fallthrough@ */
|
||||
case 'B':
|
||||
/*@fallthrough@ */
|
||||
case 'R':
|
||||
if (pv_getnum_check(optarg, PV_NUMTYPE_INTEGER) !=
|
||||
0) {
|
||||
fprintf(stderr, "%s: -%c: %s\n",
|
||||
opts->program_name, c,
|
||||
_("integer argument expected"));
|
||||
/*@fallthrough@ */
|
||||
case 'm':
|
||||
/*@fallthrough@ */
|
||||
case 'Z':
|
||||
if (!pv_getnum_check(optarg, PV_NUMTYPE_INTEGER)) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: -%c: %s\n", opts->program_name, c, _("integer argument expected"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
/*@fallthrough@ */
|
||||
case 'D':
|
||||
if (pv_getnum_check(optarg, PV_NUMTYPE_DOUBLE) !=
|
||||
0) {
|
||||
fprintf(stderr, "%s: -%c: %s\n",
|
||||
opts->program_name, c,
|
||||
_("numeric argument expected"));
|
||||
if (!pv_getnum_check(optarg, PV_NUMTYPE_DOUBLE)) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: -%c: %s\n", opts->program_name, c, _("numeric argument expected"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (sscanf(optarg, "%u:%d", &check_pid, &check_fd)
|
||||
< 1) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: -%c: %s\n",
|
||||
opts->program_name, c,
|
||||
_
|
||||
("process ID or pid:fd pair expected"));
|
||||
opts->program_name, c, _("process ID or pid:fd pair expected"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
if (check_pid < 1) {
|
||||
fprintf(stderr, "%s: -%c: %s\n",
|
||||
opts->program_name, c,
|
||||
_("invalid process ID"));
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: -%c: %s\n", opts->program_name, c, _("invalid process ID"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -226,13 +330,18 @@ opts_t opts_parse(int argc, char **argv)
|
||||
opts->bytes = true;
|
||||
numopts++;
|
||||
break;
|
||||
case '8':
|
||||
opts->bytes = true;
|
||||
opts->bits = true;
|
||||
numopts++;
|
||||
break;
|
||||
case 'T':
|
||||
opts->bufpercent = true;
|
||||
numopts++;
|
||||
opts->no_splice = true;
|
||||
break;
|
||||
case 'A':
|
||||
opts->lastwritten = pv_getnum_ui(optarg);
|
||||
opts->lastwritten = (size_t) pv_getnum_count(optarg);
|
||||
numopts++;
|
||||
opts->no_splice = true;
|
||||
break;
|
||||
@@ -244,7 +353,7 @@ opts_t opts_parse(int argc, char **argv)
|
||||
numopts++;
|
||||
break;
|
||||
case 'q':
|
||||
opts->no_op = true;
|
||||
opts->no_display = true;
|
||||
numopts++;
|
||||
break;
|
||||
case 'c':
|
||||
@@ -254,35 +363,64 @@ opts_t opts_parse(int argc, char **argv)
|
||||
opts->wait = true;
|
||||
break;
|
||||
case 'D':
|
||||
opts->delay_start = pv_getnum_d(optarg);
|
||||
opts->delay_start = pv_getnum_interval(optarg);
|
||||
break;
|
||||
case 's':
|
||||
opts->size = pv_getnum_ull(optarg);
|
||||
/* Permit "@<filename>" as well as just a number. */
|
||||
if ('@' == *optarg) {
|
||||
const char *size_file = 1 + optarg;
|
||||
struct stat sb;
|
||||
int rc;
|
||||
|
||||
rc = 0;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
rc = stat(size_file, &sb);
|
||||
if (0 == rc) {
|
||||
opts->size = (off_t) (sb.st_size);
|
||||
} else {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: %s %s: %s\n",
|
||||
opts->program_name,
|
||||
_("failed to stat file"), size_file, strerror(errno));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
} else {
|
||||
opts->size = pv_getnum_size(optarg);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
opts->linemode = true;
|
||||
break;
|
||||
case '0':
|
||||
opts->null = true;
|
||||
opts->null_terminated_lines = true;
|
||||
opts->linemode = true;
|
||||
break;
|
||||
case 'i':
|
||||
opts->interval = pv_getnum_d(optarg);
|
||||
opts->interval = pv_getnum_interval(optarg);
|
||||
break;
|
||||
case 'w':
|
||||
opts->width = pv_getnum_ui(optarg);
|
||||
opts->width = pv_getnum_count(optarg);
|
||||
opts->width_set_manually = opts->width == 0 ? false : true;
|
||||
break;
|
||||
case 'H':
|
||||
opts->height = pv_getnum_ui(optarg);
|
||||
opts->height = pv_getnum_count(optarg);
|
||||
opts->height_set_manually = opts->height == 0 ? false : true;
|
||||
break;
|
||||
case 'N':
|
||||
opts->name = optarg;
|
||||
opts->name = pv_strdup(optarg);
|
||||
if (NULL == opts->name) {
|
||||
fprintf(stderr, "%s: -N: %s\n", opts->program_name, strerror(errno));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
opts->rate_limit = pv_getnum_ull(optarg);
|
||||
opts->rate_limit = pv_getnum_size(optarg);
|
||||
break;
|
||||
case 'B':
|
||||
opts->buffer_size = pv_getnum_ull(optarg);
|
||||
opts->buffer_size = (size_t) pv_getnum_size(optarg);
|
||||
opts->no_splice = true;
|
||||
break;
|
||||
case 'C':
|
||||
@@ -291,84 +429,142 @@ opts_t opts_parse(int argc, char **argv)
|
||||
case 'E':
|
||||
opts->skip_errors++;
|
||||
break;
|
||||
case 'Z':
|
||||
opts->error_skip_block = pv_getnum_size(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
opts->stop_at_size = true;
|
||||
break;
|
||||
case 'Y':
|
||||
opts->sync_after_write = true;
|
||||
break;
|
||||
case 'K':
|
||||
opts->direct_io = true;
|
||||
break;
|
||||
case 'X':
|
||||
opts->discard_input = true;
|
||||
opts->no_splice = true;
|
||||
break;
|
||||
case 'R':
|
||||
opts->remote = pv_getnum_ui(optarg);
|
||||
opts->remote = pv_getnum_count(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
opts->pidfile = optarg;
|
||||
opts->pidfile = pv_strdup(optarg);
|
||||
if (NULL == opts->pidfile) {
|
||||
fprintf(stderr, "%s: -P: %s\n", opts->program_name, strerror(errno));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
opts->format = optarg;
|
||||
opts->format = pv_strdup(optarg);
|
||||
if (NULL == opts->format) {
|
||||
fprintf(stderr, "%s: -F: %s\n", opts->program_name, strerror(errno));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
opts->watch_pid = 0;
|
||||
opts->watch_fd = -1;
|
||||
parse_pid = 0;
|
||||
parse_fd = -1;
|
||||
/* No syntax check here, already done earlier */
|
||||
(void) sscanf(optarg, "%u:%d", &(opts->watch_pid),
|
||||
&(opts->watch_fd));
|
||||
(void) sscanf(optarg, "%u:%d", &parse_pid, &parse_fd);
|
||||
opts->watch_pid = (pid_t) parse_pid;
|
||||
opts->watch_fd = parse_fd;
|
||||
break;
|
||||
case 'm':
|
||||
opts->average_rate_window = pv_getnum_count(optarg);
|
||||
break;
|
||||
#ifdef ENABLE_DEBUGGING
|
||||
case '!':
|
||||
debugging_output_destination(optarg);
|
||||
break;
|
||||
#endif /* ENABLE_DEBUGGING */
|
||||
default:
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
/*@-formatconst@ */
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
fprintf(stderr,
|
||||
_("Try `%s --help' for more information."),
|
||||
opts->program_name);
|
||||
fprintf(stderr, _("Try `%s --help' for more information."), opts->program_name);
|
||||
#else
|
||||
fprintf(stderr,
|
||||
_("Try `%s -h' for more information."),
|
||||
opts->program_name);
|
||||
fprintf(stderr, _("Try `%s -h' for more information."), opts->program_name);
|
||||
#endif
|
||||
/*@+formatconst@ */
|
||||
/*
|
||||
* splint note: formatconst is warning about the use
|
||||
* of a non constant (translatable) format string;
|
||||
* this is unavoidable here and the only attack
|
||||
* vector is through the message catalogue.
|
||||
*/
|
||||
fprintf(stderr, "\n");
|
||||
opts_free(opts);
|
||||
opts = NULL;
|
||||
return NULL; /* early return */
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
} while (c != -1);
|
||||
|
||||
/*
|
||||
* splint thinks we can reach here after opts_free() and opts=NULL
|
||||
* above, so explicitly return here if opts was set to NULL.
|
||||
*/
|
||||
if (NULL == opts)
|
||||
return NULL;
|
||||
|
||||
if (0 != opts->watch_pid) {
|
||||
if (opts->linemode || opts->null || opts->stop_at_size
|
||||
if (opts->linemode || opts->null_terminated_lines || opts->stop_at_size
|
||||
|| (opts->skip_errors > 0) || (opts->buffer_size > 0)
|
||||
|| (opts->rate_limit > 0)) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
_
|
||||
("cannot use line mode or transfer modifier options when watching file descriptors"));
|
||||
_("cannot use line mode or transfer modifier options when watching file descriptors"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
if (opts->cursor) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
_
|
||||
("cannot use cursor positioning when watching file descriptors"));
|
||||
_("cannot use cursor positioning when watching file descriptors"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
if (0 != opts->remote) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
_
|
||||
("cannot use remote control when watching file descriptors"));
|
||||
_("cannot use remote control when watching file descriptors"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
if (optind < (int) argc) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
_
|
||||
("cannot transfer files when watching file descriptors"));
|
||||
_("cannot transfer files when watching file descriptors"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
if (0 != access("/proc/self/fdinfo", X_OK)) {
|
||||
#ifndef __APPLE__
|
||||
if (0 != access("/proc/self/fdinfo", X_OK)) { /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: access() is used here as a
|
||||
* low cost stat() to see whether the path exists at
|
||||
* all, under a path only modifiable by root, so is
|
||||
* unlikely to be exploitable.
|
||||
*/
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: -d: %s\n", opts->program_name,
|
||||
_
|
||||
("not available on systems without /proc/self/fdinfo"));
|
||||
_("not available on systems without /proc/self/fdinfo"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -382,11 +578,18 @@ opts_t opts_parse(int argc, char **argv)
|
||||
opts->bytes = true;
|
||||
}
|
||||
|
||||
/* If -Z was given but not -E, pretend one -E was given too. */
|
||||
if (opts->error_skip_block > 0 && 0 == opts->skip_errors)
|
||||
opts->skip_errors = 1;
|
||||
|
||||
/*
|
||||
* Store remaining command-line arguments.
|
||||
*/
|
||||
while (optind < argc) {
|
||||
opts->argv[opts->argc++] = argv[optind++];
|
||||
while (optind < (int) argc) {
|
||||
if (!opts_add_file(opts, argv[optind++])) {
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return opts;
|
||||
|
||||
+58
-35
@@ -1,10 +1,12 @@
|
||||
/*
|
||||
* Remote-control functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "options.h"
|
||||
#include "pv.h"
|
||||
|
||||
@@ -33,17 +35,23 @@ struct remote_msg {
|
||||
bool average_rate; /* average rate counter flag */
|
||||
bool bytes; /* bytes transferred flag */
|
||||
bool bufpercent; /* transfer buffer percentage flag */
|
||||
unsigned int lastwritten; /* last-written bytes count */
|
||||
unsigned long long rate_limit; /* rate limit, in bytes per second */
|
||||
unsigned long long buffer_size; /* buffer size, in bytes (0=default) */
|
||||
unsigned long long size; /* total size of data */
|
||||
size_t lastwritten; /* last-written bytes count */
|
||||
off_t rate_limit; /* rate limit, in bytes per second */
|
||||
size_t buffer_size; /* buffer size, in bytes (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
double interval; /* interval between updates */
|
||||
unsigned int width; /* screen width */
|
||||
unsigned int height; /* screen height */
|
||||
char name[256];
|
||||
char format[256];
|
||||
bool width_set_manually; /* width was set manually, not detected */
|
||||
bool height_set_manually; /* height was set manually, not detected */
|
||||
char name[256]; /* flawfinder: ignore */
|
||||
char format[256]; /* flawfinder: ignore */
|
||||
};
|
||||
|
||||
/*
|
||||
* flawfinder rationale: name and format are always explicitly zeroed and
|
||||
* bounded to one less than their size so they are always \0 terminated.
|
||||
*/
|
||||
|
||||
static int remote__msgid = -1;
|
||||
|
||||
@@ -62,7 +70,9 @@ static key_t remote__genkey(void)
|
||||
uid_t uid;
|
||||
key_t key;
|
||||
|
||||
/*@-type@ *//* splint doesn't like uid_t */
|
||||
uid = geteuid();
|
||||
/*@+type@ */
|
||||
|
||||
key = ftok("/tmp", (int) 'P') | uid;
|
||||
|
||||
@@ -77,7 +87,9 @@ static key_t remote__genkey(void)
|
||||
static int remote__msgget(void)
|
||||
{
|
||||
/* Catch SIGSYS in case msgget() raises it, so we get ENOSYS */
|
||||
/*@-unrecog@ *//* splint doesn't see SIGSYS */
|
||||
(void) signal(SIGSYS, SIG_IGN);
|
||||
/*@+unrecog@ */
|
||||
return msgget(remote__genkey(), IPC_CREAT | 0600);
|
||||
}
|
||||
|
||||
@@ -101,8 +113,7 @@ int pv_remote_set(opts_t opts)
|
||||
* Check that the remote process exists.
|
||||
*/
|
||||
if (kill((pid_t) (opts->remote), 0) != 0) {
|
||||
fprintf(stderr, "%s: %u: %s\n", opts->program_name,
|
||||
opts->remote, strerror(errno));
|
||||
fprintf(stderr, "%s: %u: %s\n", opts->program_name, opts->remote, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -142,33 +153,38 @@ int pv_remote_set(opts_t opts)
|
||||
msgbuf.interval = opts->interval;
|
||||
msgbuf.width = opts->width;
|
||||
msgbuf.height = opts->height;
|
||||
msgbuf.width_set_manually = opts->width_set_manually;
|
||||
msgbuf.height_set_manually = opts->height_set_manually;
|
||||
|
||||
if (opts->name != NULL) {
|
||||
strncpy(msgbuf.name, opts->name, sizeof(msgbuf.name) - 1);
|
||||
strncpy(msgbuf.name, opts->name, sizeof(msgbuf.name) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
if (opts->format != NULL) {
|
||||
strncpy(msgbuf.format, opts->format,
|
||||
sizeof(msgbuf.format) - 1);
|
||||
strncpy(msgbuf.format, opts->format, sizeof(msgbuf.format) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
|
||||
/*
|
||||
* flawfinder rationale: both name and format are explicitly bounded
|
||||
* to 1 less than the size of their buffer and the buffer is \0
|
||||
* terminated by memset() earlier.
|
||||
*/
|
||||
|
||||
msgid = remote__msgget();
|
||||
if (msgid < 0) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
strerror(errno));
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&qbuf, 0, sizeof(qbuf));
|
||||
if (msgctl(msgid, IPC_STAT, &qbuf) < 0) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
strerror(errno));
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
initial_qnum = qbuf.msg_qnum;
|
||||
|
||||
if (msgsnd(msgid, &msgbuf, sizeof(msgbuf) - sizeof(long), 0) != 0) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
strerror(errno));
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -180,7 +196,9 @@ int pv_remote_set(opts_t opts)
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
/*@-nullpass@ *//* splint: NULL is OK with select() */
|
||||
(void) select(0, NULL, NULL, NULL, &tv);
|
||||
/*@+nullpass@ */
|
||||
timeout -= 10000;
|
||||
|
||||
/*
|
||||
@@ -204,9 +222,7 @@ int pv_remote_set(opts_t opts)
|
||||
*/
|
||||
memset(&qbuf, 0, sizeof(qbuf));
|
||||
if (msgctl(msgid, IPC_STAT, &qbuf) >= 0) {
|
||||
(void) msgrcv(msgid, &msgbuf,
|
||||
sizeof(msgbuf) - sizeof(long),
|
||||
(long) (opts->remote), IPC_NOWAIT);
|
||||
(void) msgrcv(msgid, &msgbuf, sizeof(msgbuf) - sizeof(long), (long) (opts->remote), IPC_NOWAIT);
|
||||
/*
|
||||
* If this leaves nothing on the queue, remove the
|
||||
* queue, in case we created one for no reason.
|
||||
@@ -217,9 +233,15 @@ int pv_remote_set(opts_t opts)
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: %u: %s\n", opts->program_name, opts->remote,
|
||||
_("message not received"));
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory leak
|
||||
* warnings, but in this case it's unavoidable, and mitigated by the
|
||||
* fact we only translate each string once.
|
||||
*/
|
||||
fprintf(stderr, "%s: %u: %s\n", opts->program_name, opts->remote, _("message not received"));
|
||||
return 1;
|
||||
/*@+mustfreefresh @ */
|
||||
}
|
||||
|
||||
|
||||
@@ -240,16 +262,16 @@ void pv_remote_check(pvstate_t state)
|
||||
|
||||
memset(&msgbuf, 0, sizeof(msgbuf));
|
||||
|
||||
got =
|
||||
msgrcv(remote__msgid, &msgbuf, sizeof(msgbuf) - sizeof(long),
|
||||
getpid(), IPC_NOWAIT);
|
||||
got = msgrcv(remote__msgid, &msgbuf, sizeof(msgbuf) - sizeof(long), getpid(), IPC_NOWAIT);
|
||||
if (got < 0) {
|
||||
/*
|
||||
* If our queue had been deleted, re-create it.
|
||||
*/
|
||||
/*@-unrecog@ *//* splint doesn't see ENOMSG */
|
||||
if (errno != EAGAIN && errno != ENOMSG) {
|
||||
remote__msgid = remote__msgget();
|
||||
}
|
||||
/*@+unrecog@ */
|
||||
}
|
||||
if (got < 1)
|
||||
return;
|
||||
@@ -259,13 +281,14 @@ void pv_remote_check(pvstate_t state)
|
||||
pv_state_format_string_set(state, NULL);
|
||||
pv_state_name_set(state, NULL);
|
||||
|
||||
msgbuf.name[sizeof(msgbuf.name) - 1] = '\0';
|
||||
msgbuf.format[sizeof(msgbuf.format) - 1] = '\0';
|
||||
|
||||
pv_state_set_format(state, msgbuf.progress, msgbuf.timer,
|
||||
msgbuf.eta, msgbuf.fineta, msgbuf.rate,
|
||||
msgbuf.average_rate,
|
||||
msgbuf.bytes, msgbuf.bufpercent,
|
||||
msgbuf.lastwritten,
|
||||
'\0' ==
|
||||
msgbuf.name[0] ? NULL : strdup(msgbuf.name));
|
||||
msgbuf.lastwritten, '\0' == msgbuf.name[0] ? NULL : msgbuf.name);
|
||||
|
||||
if (msgbuf.rate_limit > 0)
|
||||
pv_state_rate_limit_set(state, msgbuf.rate_limit);
|
||||
@@ -276,12 +299,12 @@ void pv_remote_check(pvstate_t state)
|
||||
pv_state_size_set(state, msgbuf.size);
|
||||
if (msgbuf.interval > 0)
|
||||
pv_state_interval_set(state, msgbuf.interval);
|
||||
if (msgbuf.width > 0)
|
||||
pv_state_width_set(state, msgbuf.width);
|
||||
if (msgbuf.height > 0)
|
||||
pv_state_height_set(state, msgbuf.height);
|
||||
if (msgbuf.width > 0 && msgbuf.width_set_manually)
|
||||
pv_state_width_set(state, msgbuf.width, msgbuf.width_set_manually);
|
||||
if (msgbuf.height > 0 && msgbuf.height_set_manually)
|
||||
pv_state_height_set(state, msgbuf.height, msgbuf.height_set_manually);
|
||||
if (msgbuf.format[0] != '\0')
|
||||
pv_state_format_string_set(state, strdup(msgbuf.format));
|
||||
pv_state_format_string_set(state, msgbuf.format);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+21
-20
@@ -1,34 +1,35 @@
|
||||
/*
|
||||
* Output version information to stdout.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/*
|
||||
* Display current package version.
|
||||
* Display current package version as per GNU standards.
|
||||
*/
|
||||
void display_version(void)
|
||||
{
|
||||
printf(_("%s %s - Copyright %s %s"),
|
||||
PROGRAM_NAME, VERSION, COPYRIGHT_YEAR, COPYRIGHT_HOLDER);
|
||||
printf("\n\n");
|
||||
printf(_("Web site: %s"), PROJECT_HOMEPAGE);
|
||||
printf("\n\n");
|
||||
printf("%s",
|
||||
_("This program is free software, and is being distributed "
|
||||
"under the\nterms of the Artistic License 2.0."));
|
||||
printf("\n\n");
|
||||
printf("%s",
|
||||
_
|
||||
("This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."));
|
||||
printf("\n\n");
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory leak
|
||||
* warnings, but in this case it's unavoidable, and mitigated by the
|
||||
* fact we only translate each string once.
|
||||
*/
|
||||
/* GNU standard first line format: program and version only */
|
||||
printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
/* GNU standard second line format - "Copyright" always in English */
|
||||
printf("Copyright %s %s\n", "2023", "Andrew Wood");
|
||||
/* GNU standard license line and free software notice */
|
||||
printf("%s\n", _("License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"));
|
||||
printf("%s\n", _("This is free software: you are free to change and redistribute it."));
|
||||
printf("%s\n", _("There is NO WARRANTY, to the extent permitted by law."));
|
||||
/* Project web site link */
|
||||
printf("\n%s: <%s>\n", _("Project web site"), PACKAGE_URL);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
-438
@@ -1,438 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR Free Software Foundation, Inc.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-05 19:25+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=ISO-8859-2\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/pv/cursor.c:80
|
||||
#, fuzzy
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "nie uda³o siê otworzyæ terminala"
|
||||
|
||||
# "Przewidywany czas ukoñczenia" for ETA is too long
|
||||
#: src/pv/cursor.c:125
|
||||
#, fuzzy
|
||||
msgid "failed to open lock file"
|
||||
msgstr "nie uda³o siê zamkn±æ pliku"
|
||||
|
||||
#: src/pv/cursor.c:159
|
||||
msgid "lock attempt failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:409
|
||||
msgid "failed to open terminal"
|
||||
msgstr "nie uda³o siê otworzyæ terminala"
|
||||
|
||||
#: src/pv/display.c:138
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:143
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:558 src/pv/transfer.c:679
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "nie uda³o siê zaalokowaæ bufora"
|
||||
|
||||
#: src/pv/display.c:618 src/pv/transfer.c:458
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
#: src/pv/display.c:697 src/pv/display.c:702 src/pv/display.c:764
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/file.c:119
|
||||
#, fuzzy
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "nie uda³o siê wykonaæ operacji stat na pliku wyj¶ciowym"
|
||||
|
||||
# "Przewidywany czas ukoñczenia" for ETA is too long
|
||||
#: src/pv/file.c:215
|
||||
msgid "failed to close file"
|
||||
msgstr "nie uda³o siê zamkn±æ pliku"
|
||||
|
||||
#: src/pv/file.c:238
|
||||
msgid "failed to read file"
|
||||
msgstr "nie uda³o siê odczytaæ pliku"
|
||||
|
||||
#: src/pv/file.c:248
|
||||
msgid "failed to stat file"
|
||||
msgstr "nie uda³o siê wykonaæ operacji stat na pliku"
|
||||
|
||||
#: src/pv/file.c:257
|
||||
msgid "failed to stat output file"
|
||||
msgstr "nie uda³o siê wykonaæ operacji stat na pliku wyj¶ciowym"
|
||||
|
||||
#: src/pv/file.c:280
|
||||
msgid "input file is output file"
|
||||
msgstr "plik wej¶ciowy jest zarazem plikiem wyj¶ciowym"
|
||||
|
||||
#: src/pv/loop.c:520 src/pv/loop.c:590 src/pv/loop.c:642 src/pv/watchpid.c:51
|
||||
#: src/pv/watchpid.c:74 src/pv/watchpid.c:84 src/pv/watchpid.c:115
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:33
|
||||
msgid "none"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:341
|
||||
msgid "read failed"
|
||||
msgstr "b³±d odczytu"
|
||||
|
||||
#: src/pv/transfer.c:359
|
||||
msgid "warning: read errors detected"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:374
|
||||
msgid "file is not seekable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:437
|
||||
#, fuzzy
|
||||
msgid "failed to seek past error"
|
||||
msgstr "nie uda³o siê wykonaæ operacji stat na pliku"
|
||||
|
||||
#: src/pv/transfer.c:456
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:631
|
||||
msgid "write failed"
|
||||
msgstr "b³±d zapisu"
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
msgid "select call failed"
|
||||
msgstr "nie uda³o siê wywo³aæ funkcji select"
|
||||
|
||||
#: src/pv/watchpid.c:76 src/pv/watchpid.c:86 src/pv/watchpid.c:117
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:120
|
||||
msgid "not a regular file or block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:17
|
||||
#, fuzzy, c-format
|
||||
msgid "%s %s - Copyright %s %s"
|
||||
msgstr "%s %s - Prawa autorskie (C) %s %s"
|
||||
|
||||
#: src/main/version.c:20
|
||||
#, c-format
|
||||
msgid "Web site: %s"
|
||||
msgstr "Strona WWW: %s"
|
||||
|
||||
#: src/main/version.c:23
|
||||
msgid ""
|
||||
"This program is free software, and is being distributed under the\n"
|
||||
"terms of the Artistic License 2.0."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid ""
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:31
|
||||
msgid "show progress bar"
|
||||
msgstr "poka¿ pasek postêpu"
|
||||
|
||||
#: src/main/help.c:33
|
||||
msgid "show elapsed time"
|
||||
msgstr "poka¿ up³ywaj±cy czas"
|
||||
|
||||
#: src/main/help.c:35
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "poka¿ szacowany czas ukoñczenia"
|
||||
|
||||
#: src/main/help.c:38
|
||||
#, fuzzy
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "poka¿ szacowany czas ukoñczenia"
|
||||
|
||||
#: src/main/help.c:40
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "poka¿ licznik prêdko¶ci przesy³ania"
|
||||
|
||||
#: src/main/help.c:42
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:44
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "poka¿ ilo¶æ przes³anych bajtów"
|
||||
|
||||
#: src/main/help.c:46
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:47
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:48
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:49
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:50
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:52
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "w¶wietl wyj¶cie procentowo, bez graficznej prezentacji"
|
||||
|
||||
#: src/main/help.c:54
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "nie wy¶wietlaj ¿adnych informacji o przesy³aniu"
|
||||
|
||||
#: src/main/help.c:57
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "nie wy¶wietlaj nic a¿ do pierwszego przes³anego bajtu"
|
||||
|
||||
#: src/main/help.c:58 src/main/help.c:66
|
||||
msgid "SEC"
|
||||
msgstr "WARTO¦Æ"
|
||||
|
||||
#: src/main/help.c:59
|
||||
#, fuzzy
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "nie wy¶wietlaj nic a¿ do pierwszego przes³anego bajtu"
|
||||
|
||||
#: src/main/help.c:60
|
||||
msgid "SIZE"
|
||||
msgstr "WARTO¦Æ"
|
||||
|
||||
#: src/main/help.c:61
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "ustaw oczekiwany rozmiar danych na WARTO¦Æ bajtów"
|
||||
|
||||
#: src/main/help.c:63
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:65
|
||||
msgid "lines are null-terminated"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:67
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aktualizuj co ka¿de WARTO¦Æ sekund"
|
||||
|
||||
#: src/main/help.c:68
|
||||
msgid "WIDTH"
|
||||
msgstr "WARTO¦Æ"
|
||||
|
||||
#: src/main/help.c:69
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "przyjmij, ¿e terminal ma szeroko¶æ WARTO¦Æ znaków"
|
||||
|
||||
#: src/main/help.c:70
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:71
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "przyjmij, ¿e terminal ma szeroko¶æ WARTO¦Æ znaków"
|
||||
|
||||
#: src/main/help.c:72
|
||||
msgid "NAME"
|
||||
msgstr "NAZWA"
|
||||
|
||||
#: src/main/help.c:73
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "poprzed¼ informacje prefiksem NAZWA"
|
||||
|
||||
#: src/main/help.c:75
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "poka¿ wyj¶cie nawet gdy b³êdy nie s± typu terminal"
|
||||
|
||||
#: src/main/help.c:77
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "u¿ywaj sekwencji escape do pozycjonowania"
|
||||
|
||||
#: src/main/help.c:79
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:80
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "ogranicz przesy³ane dane do RATE bajtów na sekundê"
|
||||
|
||||
#: src/main/help.c:81
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:82
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:84
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:86
|
||||
msgid "skip read errors in input"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:88
|
||||
#, fuzzy
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "poka¿ ilo¶æ przes³anych bajtów"
|
||||
|
||||
#: src/main/help.c:90
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:91
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:94
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:95
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:97
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:98
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:101
|
||||
msgid "show this help and exit"
|
||||
msgstr "wy¶wietl te informacje z pomoc± i wyjd¼"
|
||||
|
||||
#: src/main/help.c:103
|
||||
msgid "show version information and exit"
|
||||
msgstr "wy¶wietl informacje o wersji i wyjd¼"
|
||||
|
||||
#: src/main/help.c:109
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Sposób u¿ycia: %s [OPCJA] [PLIK]..."
|
||||
|
||||
#: src/main/help.c:112
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output,\n"
|
||||
"with monitoring."
|
||||
msgstr ""
|
||||
"£±czenie PLIK(ów) lub wej¶cia standardowego, do wyj¶cia standardowego\n"
|
||||
"z monitoringiem."
|
||||
|
||||
#: src/main/help.c:207
|
||||
msgid ""
|
||||
"Debugging is enabled; export the DEBUG environment variable to define the\n"
|
||||
"output filename.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:211
|
||||
#, c-format
|
||||
msgid "Please report any bugs to %s."
|
||||
msgstr "Proszê przesy³aæ zg³oszenia b³êdów do %s."
|
||||
|
||||
#: src/main/main.c:74
|
||||
#, fuzzy
|
||||
msgid "state allocation failed"
|
||||
msgstr "nie uda³o siê zaalokowaæ bufora"
|
||||
|
||||
#: src/main/main.c:246
|
||||
#, fuzzy
|
||||
msgid "failed to read terminal attributes"
|
||||
msgstr "nie uda³o siê otworzyæ terminala"
|
||||
|
||||
#: src/main/options.c:98
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "nie uda³o siê zaalokowaæ struktur opcji"
|
||||
|
||||
#: src/main/options.c:112
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "nie uda³o siê zaalokowaæ struktur opcji argv"
|
||||
|
||||
#: src/main/options.c:151
|
||||
msgid "integer argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:162
|
||||
msgid "numeric argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:173
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:180
|
||||
msgid "invalid process ID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:316
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Spróbuj `%s --help' by uzyskaæ wiêcej informacji"
|
||||
|
||||
#: src/main/options.c:320
|
||||
#, fuzzy, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Spróbuj `%s -h' by uzyskaæ wiêcej informacji"
|
||||
|
||||
#: src/main/options.c:336
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:344
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:352
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:360
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:368
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:221
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:328
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr ""
|
||||
-427
@@ -1,427 +0,0 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-05 19:25+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/pv/cursor.c:80
|
||||
msgid "failed to get terminal name"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:125
|
||||
msgid "failed to open lock file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:159
|
||||
msgid "lock attempt failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:409
|
||||
msgid "failed to open terminal"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:138
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:143
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:558 src/pv/transfer.c:679
|
||||
msgid "buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:618 src/pv/transfer.c:458
|
||||
msgid "B"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:654 src/pv/display.c:662
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:697 src/pv/display.c:702 src/pv/display.c:764
|
||||
msgid "ETA"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:119
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:215
|
||||
msgid "failed to close file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:238
|
||||
msgid "failed to read file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:248
|
||||
msgid "failed to stat file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:257
|
||||
msgid "failed to stat output file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:280
|
||||
msgid "input file is output file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:520 src/pv/loop.c:590 src/pv/loop.c:642 src/pv/watchpid.c:51
|
||||
#: src/pv/watchpid.c:74 src/pv/watchpid.c:84 src/pv/watchpid.c:115
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:33
|
||||
msgid "none"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:341
|
||||
msgid "read failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:359
|
||||
msgid "warning: read errors detected"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:374
|
||||
msgid "file is not seekable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:437
|
||||
msgid "failed to seek past error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:456
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:631
|
||||
msgid "write failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
msgid "select call failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:76 src/pv/watchpid.c:86 src/pv/watchpid.c:117
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:120
|
||||
msgid "not a regular file or block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:17
|
||||
#, c-format
|
||||
msgid "%s %s - Copyright %s %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:20
|
||||
#, c-format
|
||||
msgid "Web site: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:23
|
||||
msgid ""
|
||||
"This program is free software, and is being distributed under the\n"
|
||||
"terms of the Artistic License 2.0."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid ""
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:31
|
||||
msgid "show progress bar"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:33
|
||||
msgid "show elapsed time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:35
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:38
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:40
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:42
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:44
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:46
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:47
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:48
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:49
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:50
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:52
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:54
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:57
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:58 src/main/help.c:66
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:59
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:60
|
||||
msgid "SIZE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:61
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:63
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:65
|
||||
msgid "lines are null-terminated"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:67
|
||||
msgid "update every SEC seconds"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:68
|
||||
msgid "WIDTH"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:69
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:70
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:71
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:72
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:73
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:75
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:77
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:79
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:80
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:81
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:82
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:84
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:86
|
||||
msgid "skip read errors in input"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:88
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:90
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:91
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:94
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:95
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:97
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:98
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:101
|
||||
msgid "show this help and exit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:103
|
||||
msgid "show version information and exit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:109
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:112
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output,\n"
|
||||
"with monitoring."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:207
|
||||
msgid ""
|
||||
"Debugging is enabled; export the DEBUG environment variable to define the\n"
|
||||
"output filename.\n"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:211
|
||||
#, c-format
|
||||
msgid "Please report any bugs to %s."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:74
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:246
|
||||
msgid "failed to read terminal attributes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:98
|
||||
msgid "option structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:112
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:151
|
||||
msgid "integer argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:162
|
||||
msgid "numeric argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:173
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:180
|
||||
msgid "invalid process ID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:316
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:320
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:336
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:344
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:352
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:360
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:368
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:221
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:328
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr ""
|
||||
+165
-113
@@ -9,8 +9,14 @@
|
||||
* However, some OSes (FreeBSD and MacOS X so far) don't allow locking of a
|
||||
* terminal, so we try to use a lockfile if terminal locking doesn't work,
|
||||
* and finally abort if even that is unavailable.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -29,17 +35,19 @@
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
/* for basename() */
|
||||
#ifdef HAVE_LIBGEN_H
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
|
||||
/*
|
||||
* Write the given buffer to the given file descriptor, retrying until all
|
||||
* bytes have been written or an error has occurred.
|
||||
*/
|
||||
static void write_retry(int fd, const char *buf, size_t count)
|
||||
void pv_write_retry(int fd, const char *buf, size_t count)
|
||||
{
|
||||
while (count > 0) {
|
||||
ssize_t nwritten;
|
||||
@@ -76,41 +84,32 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd)
|
||||
ttydev = ttyname(fd);
|
||||
if (!ttydev) {
|
||||
if (!state->force) {
|
||||
pv_error(state, "%s: %s",
|
||||
_("failed to get terminal name"),
|
||||
strerror(errno));
|
||||
pv_error(state, "%s: %s", _("failed to get terminal name"), strerror(errno));
|
||||
}
|
||||
/*
|
||||
* If we don't know our terminal name, we can neither do IPC
|
||||
* nor make a lock file, so turn off cursor positioning.
|
||||
*/
|
||||
state->cursor = 0;
|
||||
debug("%s",
|
||||
"ttyname failed - cursor positioning disabled");
|
||||
debug("%s", "ttyname failed - cursor positioning disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
tmpdir = (char *) getenv("TMPDIR");
|
||||
if (!tmpdir)
|
||||
tmpdir = (char *) getenv("TMP");
|
||||
if (!tmpdir)
|
||||
tmpdir = "/tmp";
|
||||
/*
|
||||
* We used to look at the TMPDIR or TMP environment variables to
|
||||
* override the temporary directory, but this leads to less
|
||||
* predictable behaviour, and flawfinder points out that relying on
|
||||
* environment variables in this way is not safe. So the lock
|
||||
* directory is hard-coded to "/tmp" now (Sep 2023).
|
||||
*/
|
||||
tmpdir = "/tmp";
|
||||
|
||||
memset(state->crs_lock_file, 0, sizeof(state->crs_lock_file));
|
||||
#ifdef HAVE_SNPRINTF
|
||||
(void) snprintf(state->crs_lock_file,
|
||||
sizeof(state->crs_lock_file) - 1,
|
||||
"%s/pv-%s-%i.lock", tmpdir, basename(ttydev),
|
||||
(int) geteuid());
|
||||
#else
|
||||
(void) sprintf(state->crs_lock_file,
|
||||
"%.*s/pv-%8s-%i.lock",
|
||||
sizeof(state->crs_lock_file) - 64, tmpdir,
|
||||
basename(ttydev), (int) geteuid());
|
||||
#endif
|
||||
memset(state->crs_lock_file, 0, PV_SIZEOF_CRS_LOCK_FILE);
|
||||
(void) pv_snprintf(state->crs_lock_file,
|
||||
PV_SIZEOF_CRS_LOCK_FILE, "%s/pv-%s-%i.lock", tmpdir, basename(ttydev), (int) geteuid());
|
||||
|
||||
/*
|
||||
* Pawel Piatek - not everyone has O_NOFOLLOW, e.g. AIX doesn't
|
||||
* Pawel Piatek - not everyone has O_NOFOLLOW, e.g. AIX doesn't.
|
||||
*/
|
||||
#ifdef O_NOFOLLOW
|
||||
openflags = O_RDWR | O_CREAT | O_NOFOLLOW;
|
||||
@@ -118,11 +117,17 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd)
|
||||
openflags = O_RDWR | O_CREAT;
|
||||
#endif
|
||||
|
||||
state->crs_lock_fd = open(state->crs_lock_file, openflags, 0600);
|
||||
state->crs_lock_fd = open(state->crs_lock_file, openflags, 0600); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: we aren't truncating the lock file, we
|
||||
* don't change its contents, and we are attempting to use
|
||||
* O_NOFOLLOW where possible to avoid symlink attacks, so this
|
||||
* open() is as safe as we can make it.
|
||||
*/
|
||||
|
||||
if (state->crs_lock_fd < 0) {
|
||||
pv_error(state, "%s: %s: %s",
|
||||
state->crs_lock_file,
|
||||
_("failed to open lock file"), strerror(errno));
|
||||
pv_error(state, "%s: %s: %s", state->crs_lock_file, _("failed to open lock file"), strerror(errno));
|
||||
state->cursor = 0;
|
||||
return;
|
||||
}
|
||||
@@ -155,17 +160,14 @@ static void pv_crs_lock(pvstate_t state, int fd)
|
||||
lock_fd = state->crs_lock_fd;
|
||||
}
|
||||
} else {
|
||||
pv_error(state, "%s: %s",
|
||||
_("lock attempt failed"),
|
||||
strerror(errno));
|
||||
pv_error(state, "%s: %s", _("lock attempt failed"), strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state->crs_lock_fd >= 0) {
|
||||
debug("%s: %s", state->crs_lock_file,
|
||||
"terminal lockfile acquired");
|
||||
debug("%s: %s", state->crs_lock_file, "terminal lockfile acquired");
|
||||
} else {
|
||||
debug("%s", "terminal lock acquired");
|
||||
}
|
||||
@@ -193,8 +195,7 @@ static void pv_crs_unlock(pvstate_t state, int fd)
|
||||
(void) fcntl(lock_fd, F_SETLK, &lock);
|
||||
|
||||
if (state->crs_lock_fd >= 0) {
|
||||
debug("%s: %s", state->crs_lock_file,
|
||||
"terminal lockfile released");
|
||||
debug("%s: %s", state->crs_lock_file, "terminal lockfile released");
|
||||
} else {
|
||||
debug("%s", "terminal lock released");
|
||||
}
|
||||
@@ -229,12 +230,17 @@ static void pv_crs_ipccount(pvstate_t state)
|
||||
/*
|
||||
* Get the current cursor Y co-ordinate by sending the ECMA-48 CPR code to
|
||||
* the terminal connected to the given file descriptor.
|
||||
*
|
||||
* This should only be called while the terminal is locked, to avoid
|
||||
* confusing other "pv -c" instances about the current terminal attributes,
|
||||
* since this function temporarily changes the terminal attributes and then
|
||||
* puts them back.
|
||||
*/
|
||||
static int pv_crs_get_ypos(int terminalfd)
|
||||
{
|
||||
struct termios tty;
|
||||
struct termios old_tty;
|
||||
char cpr[32];
|
||||
char cpr[32]; /* flawfinder: ignore - bounded, zeroed */
|
||||
int ypos;
|
||||
ssize_t r;
|
||||
#ifdef CURSOR_ANSWERBACK_BYTE_BY_BYTE
|
||||
@@ -252,14 +258,15 @@ static int pv_crs_get_ypos(int terminalfd)
|
||||
debug("%s: %s", "tcsetattr (1) failed", strerror(errno));
|
||||
}
|
||||
|
||||
write_retry(terminalfd, "\033[6n", 4);
|
||||
pv_write_retry(terminalfd, "\033[6n", 4);
|
||||
|
||||
memset(cpr, 0, sizeof(cpr));
|
||||
|
||||
#ifdef CURSOR_ANSWERBACK_BYTE_BY_BYTE
|
||||
/* Read answerback byte by byte - fails on AIX */
|
||||
for (got = 0, r = 0; got < (int) (sizeof(cpr) - 2); got += r) {
|
||||
r = read(terminalfd, cpr + got, 1);
|
||||
r = read(terminalfd, cpr + got, 1); /* flawfinder: ignore */
|
||||
/* flawfinder rationale: bounded to buffer size by "for" */
|
||||
if (r <= 0) {
|
||||
debug("got=%d, r=%d: %s", got, r, strerror(errno));
|
||||
break;
|
||||
@@ -270,24 +277,23 @@ static int pv_crs_get_ypos(int terminalfd)
|
||||
|
||||
debug
|
||||
("read answerback message from fd %d, length %d - buf = %02X %02X %02X %02X %02X %02X",
|
||||
terminalfd, got, cpr[0], cpr[1], cpr[2], cpr[3], cpr[4],
|
||||
cpr[5]);
|
||||
terminalfd, got, cpr[0], cpr[1], cpr[2], cpr[3], cpr[4], cpr[5]);
|
||||
|
||||
#else /* !CURSOR_ANSWERBACK_BYTE_BY_BYTE */
|
||||
/* Read answerback in one big lump - may fail on Solaris */
|
||||
r = read(terminalfd, cpr, sizeof(cpr));
|
||||
r = read(terminalfd, cpr, sizeof(cpr) - 2); /* flawfinder: ignore */
|
||||
/* flawfinder rationale: bounded to buffer size */
|
||||
if (r <= 0) {
|
||||
debug("r=%d: %s", r, strerror(errno));
|
||||
} else {
|
||||
debug
|
||||
("read answerback message from fd %d, length %d - buf = %02X %02X %02X %02X %02X %02X",
|
||||
terminalfd, r, cpr[0], cpr[1], cpr[2], cpr[3], cpr[4],
|
||||
cpr[5]);
|
||||
terminalfd, r, cpr[0], cpr[1], cpr[2], cpr[3], cpr[4], cpr[5]);
|
||||
|
||||
}
|
||||
#endif /* CURSOR_ANSWERBACK_BYTE_BY_BYTE */
|
||||
#endif /* !CURSOR_ANSWERBACK_BYTE_BY_BYTE */
|
||||
|
||||
ypos = (int) pv_getnum_ui(cpr + 2);
|
||||
ypos = (int) pv_getnum_count(cpr + 2);
|
||||
|
||||
if (0 != tcsetattr(terminalfd, TCSANOW | TCSAFLUSH, &old_tty)) {
|
||||
debug("%s: %s", "tcsetattr (2) failed", strerror(errno));
|
||||
@@ -333,25 +339,30 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
state->crs_shmid = shmget(key, sizeof(int), 0600 | IPC_CREAT);
|
||||
state->crs_shmid = shmget(key, sizeof(struct pvcursorstate_s), 0600 | IPC_CREAT);
|
||||
if (state->crs_shmid < 0) {
|
||||
debug("%s: %s", "shmget failed", strerror(errno));
|
||||
pv_crs_unlock(state, terminalfd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
state->crs_y_top = shmat(state->crs_shmid, NULL, 0);
|
||||
/*@-nullpass@ */
|
||||
/* splint doesn't know shmaddr can be NULL */
|
||||
state->crs_shared = shmat(state->crs_shmid, NULL, 0);
|
||||
/*@+nullpass@ */
|
||||
|
||||
pv_crs_ipccount(state);
|
||||
|
||||
/*
|
||||
* If nobody else is attached to the shared memory segment, we're
|
||||
* the first, so we need to initialise the shared memory with our
|
||||
* current Y cursor co-ordinate.
|
||||
* current Y cursor co-ordinate and with an initial false value for
|
||||
* the TOSTOP-added flag.
|
||||
*/
|
||||
if (state->crs_pvcount < 2) {
|
||||
state->crs_y_start = pv_crs_get_ypos(terminalfd);
|
||||
*(state->crs_y_top) = state->crs_y_start;
|
||||
state->crs_shared->y_topmost = state->crs_y_start;
|
||||
state->crs_shared->tty_tostop_added = false;
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
debug("%s", "we are the first to attach");
|
||||
}
|
||||
@@ -365,10 +376,9 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd)
|
||||
* to read the top Y co-ordinate from it.
|
||||
*/
|
||||
if (state->crs_pvcount > 1) {
|
||||
state->crs_y_start = *(state->crs_y_top);
|
||||
state->crs_y_start = state->crs_shared->y_topmost;
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
debug("%s: %d", "not the first to attach - got top y",
|
||||
state->crs_y_start);
|
||||
debug("%s: %d", "not the first to attach - got top y", state->crs_y_start);
|
||||
}
|
||||
|
||||
pv_crs_unlock(state, terminalfd);
|
||||
@@ -384,7 +394,7 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd)
|
||||
void pv_crs_init(pvstate_t state)
|
||||
{
|
||||
char *ttyfile;
|
||||
int fd;
|
||||
int terminalfd;
|
||||
|
||||
state->crs_lock_fd = -2;
|
||||
state->crs_lock_file[0] = '\0';
|
||||
@@ -395,28 +405,41 @@ void pv_crs_init(pvstate_t state)
|
||||
debug("%s", "init");
|
||||
|
||||
ttyfile = ttyname(STDERR_FILENO);
|
||||
if (!ttyfile) {
|
||||
debug("%s: %s",
|
||||
"disabling cursor positioning because ttyname failed",
|
||||
strerror(errno));
|
||||
state->cursor = 0;
|
||||
if (NULL == ttyfile) {
|
||||
debug("%s: %s", "disabling cursor positioning because ttyname failed", strerror(errno));
|
||||
state->cursor = false;
|
||||
return;
|
||||
}
|
||||
|
||||
fd = open(ttyfile, O_RDWR);
|
||||
if (fd < 0) {
|
||||
pv_error(state, "%s: %s: %s",
|
||||
_("failed to open terminal"), ttyfile,
|
||||
strerror(errno));
|
||||
terminalfd = open(ttyfile, O_RDWR); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: the file we open won't be truncated but
|
||||
* could be corrupted by writes attempting to get the current Y
|
||||
* position; but we get the filename from ttyname() and it could be
|
||||
* a symbolic link, so we can't do much more than trust it.
|
||||
*/
|
||||
|
||||
if (terminalfd < 0) {
|
||||
pv_error(state, "%s: %s: %s", _("failed to open terminal"), ttyfile, strerror(errno));
|
||||
state->cursor = false;
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_IPC
|
||||
if (pv_crs_ipcinit(state, ttyfile, fd) != 0) {
|
||||
if (pv_crs_ipcinit(state, ttyfile, terminalfd) != 0) {
|
||||
debug("%s", "ipcinit failed, setting noipc flag");
|
||||
state->crs_noipc = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have already set the terminal TOSTOP attribute, set the
|
||||
* flag in shared memory to let the other instances know.
|
||||
*/
|
||||
if ((!state->crs_noipc) && state->pv_tty_tostop_added && (NULL != state->crs_shared)) {
|
||||
debug("%s", "propagating local pv_tty_tostop_added true value to shared flag");
|
||||
state->crs_shared->tty_tostop_added = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are not using IPC, then we need to get the current Y
|
||||
* co-ordinate. If we are using IPC, then the pv_crs_ipcinit()
|
||||
@@ -429,22 +452,22 @@ void pv_crs_init(pvstate_t state)
|
||||
/*
|
||||
* Get current cursor position + 1.
|
||||
*/
|
||||
pv_crs_lock(state, fd);
|
||||
state->crs_y_start = pv_crs_get_ypos(fd);
|
||||
pv_crs_lock(state, terminalfd);
|
||||
state->crs_y_start = pv_crs_get_ypos(terminalfd);
|
||||
/*
|
||||
* Move down a line while the terminal is locked, so that
|
||||
* other processes in the pipeline will get a different
|
||||
* initial ypos.
|
||||
*/
|
||||
if (state->crs_y_start > 0)
|
||||
write_retry(STDERR_FILENO, "\n", 1);
|
||||
pv_crs_unlock(state, fd);
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
pv_crs_unlock(state, terminalfd);
|
||||
|
||||
if (state->crs_y_start < 1)
|
||||
state->cursor = 0;
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
(void) close(terminalfd);
|
||||
}
|
||||
|
||||
|
||||
@@ -466,7 +489,7 @@ void pv_crs_needreinit(pvstate_t state)
|
||||
* Reinitialise the cursor positioning code (called if we are backgrounded
|
||||
* then foregrounded again).
|
||||
*/
|
||||
void pv_crs_reinit(pvstate_t state)
|
||||
static void pv_crs_reinit(pvstate_t state)
|
||||
{
|
||||
debug("%s", "reinit");
|
||||
|
||||
@@ -485,8 +508,9 @@ void pv_crs_reinit(pvstate_t state)
|
||||
|
||||
state->crs_y_start = pv_crs_get_ypos(STDERR_FILENO);
|
||||
|
||||
if (state->crs_y_offset < 1)
|
||||
*(state->crs_y_top) = state->crs_y_start;
|
||||
if ((state->crs_y_offset < 1) && (NULL != state->crs_shared)) {
|
||||
state->crs_shared->y_topmost = state->crs_y_start;
|
||||
}
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
|
||||
pv_crs_unlock(state, STDERR_FILENO);
|
||||
@@ -495,23 +519,36 @@ void pv_crs_reinit(pvstate_t state)
|
||||
|
||||
|
||||
/*
|
||||
* Output a single-line update, moving the cursor to the correct position to
|
||||
* do so.
|
||||
* Output a single-line update (\0-terminated), using the ECMA-48 CSI "CUP"
|
||||
* sequence to move the cursor to the correct position to do so.
|
||||
*/
|
||||
void pv_crs_update(pvstate_t state, char *str)
|
||||
void pv_crs_update(pvstate_t state, const char *output_line)
|
||||
{
|
||||
char pos[32];
|
||||
char cup_cmd[32]; /* flawfinder: ignore */
|
||||
size_t cup_cmd_length, output_line_length;
|
||||
int y;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: the "cup_cmd" buffer is always zeroed
|
||||
* before each use, and is only written to by pv_snprintf() bounded
|
||||
* by its size; also, that function explictly zero-terminates the
|
||||
* string it writes. The write() call is also bounded.
|
||||
*/
|
||||
|
||||
output_line_length = strlen(output_line); /* flawfinder: ignore */
|
||||
/* flawfinder - output_line is explictly expected to be \0-terminated. */
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
if (!state->crs_noipc) {
|
||||
if (state->crs_needreinit > 0)
|
||||
pv_crs_reinit(state);
|
||||
|
||||
pv_crs_ipccount(state);
|
||||
if (state->crs_y_lastread != *(state->crs_y_top)) {
|
||||
state->crs_y_start = *(state->crs_y_top);
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
if (NULL != state->crs_shared) {
|
||||
if (state->crs_y_lastread != state->crs_shared->y_topmost) {
|
||||
state->crs_y_start = state->crs_shared->y_topmost;
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
}
|
||||
}
|
||||
|
||||
if (state->crs_needreinit > 0)
|
||||
@@ -528,15 +565,12 @@ void pv_crs_update(pvstate_t state, char *str)
|
||||
* scroll the screen (only if we're the first `pv'), and then move
|
||||
* our initial Y co-ordinate up.
|
||||
*/
|
||||
if (((state->crs_y_start + state->crs_pvmax) >
|
||||
(int) (state->height))
|
||||
if (((state->crs_y_start + state->crs_pvmax) > (int) (state->height))
|
||||
&& (!state->crs_noipc)
|
||||
) {
|
||||
int offs;
|
||||
|
||||
offs =
|
||||
((state->crs_y_start + state->crs_pvmax) -
|
||||
state->height);
|
||||
offs = ((state->crs_y_start + state->crs_pvmax) - state->height);
|
||||
|
||||
state->crs_y_start -= offs;
|
||||
if (state->crs_y_start < 1)
|
||||
@@ -550,16 +584,12 @@ void pv_crs_update(pvstate_t state, char *str)
|
||||
if (0 == state->crs_y_offset) {
|
||||
pv_crs_lock(state, STDERR_FILENO);
|
||||
|
||||
memset(pos, 0, sizeof(pos));
|
||||
# ifdef HAVE_SNPRINTF
|
||||
(void) snprintf(pos, sizeof(pos) - 1, "\033[%u;1H",
|
||||
state->height);
|
||||
# else
|
||||
(void) sprintf(pos, "\033[%u;1H", state->height);
|
||||
# endif
|
||||
write_retry(STDERR_FILENO, pos, strlen(pos));
|
||||
memset(cup_cmd, 0, sizeof(cup_cmd));
|
||||
(void) pv_snprintf(cup_cmd, sizeof(cup_cmd), "\033[%u;1H", state->height);
|
||||
cup_cmd_length = strlen(cup_cmd); /* flawfinder: ignore */
|
||||
pv_write_retry(STDERR_FILENO, cup_cmd, cup_cmd_length);
|
||||
for (; offs > 0; offs--) {
|
||||
write_retry(STDERR_FILENO, "\n", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
pv_crs_unlock(state, STDERR_FILENO);
|
||||
@@ -574,22 +604,26 @@ void pv_crs_update(pvstate_t state, char *str)
|
||||
|
||||
/*
|
||||
* Keep the Y co-ordinate within sensible bounds, so we can never
|
||||
* overflow the "pos" buffer.
|
||||
* overflow the "cup_cmd" buffer.
|
||||
*/
|
||||
if ((y < 1) || (y > 999999))
|
||||
y = 1;
|
||||
|
||||
memset(pos, 0, sizeof(pos));
|
||||
#ifdef HAVE_SNPRINTF
|
||||
(void) snprintf(pos, sizeof(pos) - 1, "\033[%d;1H", y);
|
||||
#else
|
||||
(void) sprintf(pos, "\033[%d;1H", y);
|
||||
#endif
|
||||
memset(cup_cmd, 0, sizeof(cup_cmd));
|
||||
(void) pv_snprintf(cup_cmd, sizeof(cup_cmd), "\033[%d;1H", y);
|
||||
cup_cmd_length = strlen(cup_cmd); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: "cup_cmd" is only written to by
|
||||
* pv_snprintf(), which explicitly ensures that the string will be
|
||||
* \0-terminated, and the buffer is zeroed beforehand so if
|
||||
* pv_snprintf() fails to run the string will be of zero length.
|
||||
*/
|
||||
|
||||
pv_crs_lock(state, STDERR_FILENO);
|
||||
|
||||
write_retry(STDERR_FILENO, pos, strlen(pos));
|
||||
write_retry(STDERR_FILENO, str, strlen(str));
|
||||
pv_write_retry(STDERR_FILENO, cup_cmd, cup_cmd_length);
|
||||
pv_write_retry(STDERR_FILENO, output_line, output_line_length);
|
||||
|
||||
pv_crs_unlock(state, STDERR_FILENO);
|
||||
}
|
||||
@@ -600,8 +634,13 @@ void pv_crs_update(pvstate_t state, char *str)
|
||||
*/
|
||||
void pv_crs_fini(pvstate_t state)
|
||||
{
|
||||
char pos[32];
|
||||
char cup_cmd[32]; /* flawfinder: ignore */
|
||||
unsigned int y;
|
||||
struct shmid_ds shm_buf;
|
||||
|
||||
/* flawfinder - "cup_cmd" is zeroed, and only written by pv_snprintf() */
|
||||
|
||||
memset(&shm_buf, 0, sizeof(shm_buf));
|
||||
|
||||
debug("%s", "fini");
|
||||
|
||||
@@ -621,27 +660,40 @@ void pv_crs_fini(pvstate_t state)
|
||||
if ((y < 1) || (y > 999999))
|
||||
y = 1;
|
||||
|
||||
memset(pos, 0, sizeof(pos));
|
||||
#ifdef HAVE_SNPRINTF
|
||||
(void) snprintf(pos, sizeof(pos) - 1, "\033[%u;1H\n", y);
|
||||
#else
|
||||
(void) sprintf(pos, "\033[%u;1H\n", y);
|
||||
#endif
|
||||
memset(cup_cmd, 0, sizeof(cup_cmd));
|
||||
(void) pv_snprintf(cup_cmd, sizeof(cup_cmd), "\033[%u;1H\n", y);
|
||||
|
||||
pv_crs_lock(state, STDERR_FILENO);
|
||||
|
||||
write_retry(STDERR_FILENO, pos, strlen(pos));
|
||||
pv_write_retry(STDERR_FILENO, cup_cmd, strlen(cup_cmd)); /* flawfinder: ignore */
|
||||
/* flawfinder - pv_snprintf() always \0-terminates (see above). */
|
||||
|
||||
/*
|
||||
* If any other "pv -c" instances have set the terminal TOSTOP
|
||||
* attribute, set our local flag so pv_sig_fini() will know about
|
||||
* it.
|
||||
*/
|
||||
if ((!state->crs_noipc) && (NULL != state->crs_shared) && state->crs_shared->tty_tostop_added) {
|
||||
if (!state->pv_tty_tostop_added) {
|
||||
debug("%s", "propagating shared tty_tostop_added true value to local flag");
|
||||
state->pv_tty_tostop_added = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
pv_crs_ipccount(state);
|
||||
(void) shmdt((void *) state->crs_y_top);
|
||||
if (NULL != state->crs_shared) {
|
||||
(void) shmdt(state->crs_shared);
|
||||
}
|
||||
state->crs_shared = NULL;
|
||||
|
||||
/*
|
||||
* If we are the last instance detaching from the shared memory,
|
||||
* delete it so it's not left lying around.
|
||||
*/
|
||||
if (state->crs_pvcount < 2)
|
||||
(void) shmctl(state->crs_shmid, IPC_RMID, NULL);
|
||||
(void) shmctl(state->crs_shmid, IPC_RMID, &shm_buf);
|
||||
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
|
||||
+419
-268
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Functions relating to elapsed time.
|
||||
*
|
||||
* Copyright 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/*
|
||||
* Read the current elapsed time, relative to an unspecified point in the
|
||||
* past, and store it in the given timespec buffer. The time is guaranteed
|
||||
* to not go backwards and does not count time when the system was
|
||||
* suspended. See clock_gettime(2) with CLOCK_MONOTONIC.
|
||||
*
|
||||
* The read should not fail; if it does, the program is aborted with exit
|
||||
* status 16.
|
||||
*/
|
||||
void pv_elapsedtime_read(struct timespec *return_time)
|
||||
{
|
||||
/*@-unrecog@ *//* splint doesn't know clock_gettime */
|
||||
if (0 != clock_gettime(CLOCK_MONOTONIC, return_time)) {
|
||||
fprintf(stderr, "%s: %s: %s\n", PACKAGE_NAME, "clock_gettime", strerror(errno));
|
||||
/*@-exitarg@ *//* we explicitly want a special exit status */
|
||||
exit(16);
|
||||
/*@+exitarg@ */
|
||||
}
|
||||
/*@+unrecog@ */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the time in the given timespec to zero.
|
||||
*/
|
||||
void pv_elapsedtime_zero(struct timespec *zero_time)
|
||||
{
|
||||
if (NULL == zero_time)
|
||||
return;
|
||||
zero_time->tv_sec = 0;
|
||||
zero_time->tv_nsec = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Copy source_time into dest_time. Analogous to strcpy(3).
|
||||
*/
|
||||
void pv_elapsedtime_copy(struct timespec *dest_time, const struct timespec *source_time)
|
||||
{
|
||||
if (NULL == dest_time)
|
||||
return;
|
||||
if (NULL == source_time)
|
||||
return;
|
||||
dest_time->tv_sec = source_time->tv_sec;
|
||||
dest_time->tv_nsec = source_time->tv_nsec;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return -1, 0, or 1 depending on whether the first time is earlier than,
|
||||
* equal to, or later than the second time. Analogous to strcmp(3).
|
||||
*/
|
||||
int pv_elapsedtime_compare(const struct timespec *first_time, const struct timespec *second_time)
|
||||
{
|
||||
/* Treat NULL as a zero time. */
|
||||
if ((NULL == first_time) && (NULL == second_time))
|
||||
return 0;
|
||||
if ((NULL == first_time) && (NULL != second_time))
|
||||
return -1;
|
||||
if ((NULL != first_time) && (NULL == second_time))
|
||||
return 1;
|
||||
|
||||
/* These should never happen, but check just in case. */
|
||||
if (NULL == first_time)
|
||||
return 0;
|
||||
if (NULL == second_time)
|
||||
return 0;
|
||||
|
||||
/* Check the seconds part, first */
|
||||
if (first_time->tv_sec < second_time->tv_sec)
|
||||
return -1;
|
||||
if (first_time->tv_sec > second_time->tv_sec)
|
||||
return 1;
|
||||
|
||||
/* Seconds are equal - compare nanoseconds. */
|
||||
if (first_time->tv_nsec < second_time->tv_nsec)
|
||||
return -1;
|
||||
if (first_time->tv_nsec > second_time->tv_nsec)
|
||||
return 1;
|
||||
|
||||
/* Nanoseconds are also equal - times are equal. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add first_time and second_time, writing the result to return_time.
|
||||
*/
|
||||
void pv_elapsedtime_add(struct timespec *return_time, const struct timespec *first_time,
|
||||
const struct timespec *second_time)
|
||||
{
|
||||
long long seconds, nanoseconds;
|
||||
|
||||
if (NULL == return_time)
|
||||
return;
|
||||
|
||||
seconds = 0;
|
||||
nanoseconds = 0;
|
||||
|
||||
if (NULL != first_time) {
|
||||
seconds += first_time->tv_sec;
|
||||
nanoseconds += first_time->tv_nsec;
|
||||
}
|
||||
|
||||
if (NULL != second_time) {
|
||||
seconds += second_time->tv_sec;
|
||||
nanoseconds += second_time->tv_nsec;
|
||||
}
|
||||
|
||||
seconds += nanoseconds / 1000000000;
|
||||
nanoseconds = nanoseconds % 1000000000;
|
||||
|
||||
/*@-type@ */
|
||||
return_time->tv_sec = seconds;
|
||||
return_time->tv_nsec = nanoseconds;
|
||||
/*@+type@ */
|
||||
|
||||
/*
|
||||
* splint rationale: we know the types are different but should be
|
||||
* large enough and are relying on the compiler to do the casting
|
||||
* correctly, since the manual for timespec(3) states the types are
|
||||
* implementation-defined.
|
||||
*
|
||||
* TODO: review this to make sure that this isn't just an elaborate
|
||||
* excuse for "it's hard to fix and I don't know how".
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a number of nanoseconds to the given timespec.
|
||||
*/
|
||||
void pv_elapsedtime_add_nsec(struct timespec *return_time, long long add_nanoseconds)
|
||||
{
|
||||
long long seconds, nanoseconds;
|
||||
|
||||
if (NULL == return_time)
|
||||
return;
|
||||
|
||||
seconds = return_time->tv_sec;
|
||||
nanoseconds = return_time->tv_nsec + add_nanoseconds;
|
||||
|
||||
seconds += nanoseconds / 1000000000;
|
||||
nanoseconds = nanoseconds % 1000000000;
|
||||
|
||||
/*@-type@ *//* see above */
|
||||
return_time->tv_sec = seconds;
|
||||
return_time->tv_nsec = nanoseconds;
|
||||
/*@+type@ */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the return timespec to the first time minus the second time.
|
||||
*/
|
||||
void pv_elapsedtime_subtract(struct timespec *return_time, const struct timespec *first_time,
|
||||
const struct timespec *second_time)
|
||||
{
|
||||
long long seconds, nanoseconds;
|
||||
|
||||
if (NULL == return_time)
|
||||
return;
|
||||
|
||||
seconds = 0;
|
||||
nanoseconds = 0;
|
||||
|
||||
if (NULL != first_time) {
|
||||
seconds += first_time->tv_sec;
|
||||
nanoseconds += first_time->tv_nsec;
|
||||
}
|
||||
|
||||
if (NULL != second_time) {
|
||||
seconds -= second_time->tv_sec;
|
||||
nanoseconds -= second_time->tv_nsec;
|
||||
}
|
||||
|
||||
seconds += nanoseconds / 1000000000;
|
||||
nanoseconds = nanoseconds % 1000000000;
|
||||
|
||||
if (nanoseconds < 0) {
|
||||
seconds--;
|
||||
nanoseconds = 1000000000 + nanoseconds;
|
||||
}
|
||||
|
||||
/*@-type@ *//* see above */
|
||||
return_time->tv_sec = seconds;
|
||||
return_time->tv_nsec = nanoseconds;
|
||||
/*@+type@ */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a timespec to seconds.
|
||||
*/
|
||||
long double pv_elapsedtime_seconds(const struct timespec *elapsed_time)
|
||||
{
|
||||
long double seconds;
|
||||
|
||||
if (NULL == elapsed_time)
|
||||
return 0.0;
|
||||
|
||||
seconds = (long double) elapsed_time->tv_sec;
|
||||
seconds += (long double) (elapsed_time->tv_nsec) / 1000000000.0L;
|
||||
|
||||
return seconds;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sleep for a number of nanoseconds.
|
||||
*/
|
||||
void pv_nanosleep(long long nanoseconds)
|
||||
{
|
||||
#if HAVE_NANOSLEEP
|
||||
struct timespec sleep_for, time_remaining;
|
||||
|
||||
memset(&sleep_for, 0, sizeof(sleep_for));
|
||||
memset(&time_remaining, 0, sizeof(time_remaining));
|
||||
|
||||
sleep_for.tv_sec = 0;
|
||||
/*@-type@ */
|
||||
sleep_for.tv_nsec = nanoseconds;
|
||||
/*@+type@ *//* splint rationale - best effort */
|
||||
/*@-unrecog@ */
|
||||
(void) nanosleep(&sleep_for, &time_remaining);
|
||||
/*@+unrecog@ *//* splint rationale - doesn't know of nanosleep() */
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
/*@-type@ */
|
||||
tv.tv_usec = nanoseconds / 1000;
|
||||
/*@+type@ *//* splint rationale - best effort */
|
||||
/*@-null@ */
|
||||
(void) select(0, NULL, NULL, NULL, &tv);
|
||||
/*@+null@ *//* splint doesn't know about select() */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
+274
-118
@@ -1,7 +1,13 @@
|
||||
/*
|
||||
* Functions for opening and closing files.
|
||||
* Functions for opening and closing files, and calculating their size.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -14,84 +20,100 @@
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
/*@-type@*/
|
||||
/* splint has trouble with off_t and mode_t throughout this file. */
|
||||
|
||||
/*
|
||||
* Try to work out the total size of all data by adding up the sizes of all
|
||||
* input files. If any of the input files are of indeterminate size (i.e.
|
||||
* they are a pipe), the total size is set to zero.
|
||||
* Calculate the total number of bytes to be transferred by adding up the
|
||||
* sizes of all input files. If any of the input files are of indeterminate
|
||||
* size (such as if they are a pipe), the total size is set to zero.
|
||||
*
|
||||
* Any files that cannot be stat()ed or that access() says we can't read
|
||||
* will cause a warning to be output and will be removed from the list.
|
||||
*
|
||||
* In line mode, any files that pass the above checks will then be read to
|
||||
* determine how many lines they contain, and the total size will be set to
|
||||
* the total line count. Only regular files will be read.
|
||||
* will be skipped, and the total size will be set to zero.
|
||||
*
|
||||
* Returns the total size, or 0 if it is unknown.
|
||||
*/
|
||||
unsigned long long pv_calc_total_size(pvstate_t state)
|
||||
static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
{
|
||||
unsigned long long total;
|
||||
struct stat64 sb;
|
||||
int rc, i, j, fd;
|
||||
off_t total;
|
||||
struct stat sb;
|
||||
unsigned int file_idx;
|
||||
|
||||
total = 0;
|
||||
rc = 0;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
|
||||
/*
|
||||
* No files specified - check stdin.
|
||||
*/
|
||||
if (state->input_file_count < 1) {
|
||||
if (0 == fstat64(STDIN_FILENO, &sb))
|
||||
if ((state->input_file_count < 1) || (NULL == state->input_files)) {
|
||||
if (0 == fstat(STDIN_FILENO, &sb))
|
||||
total = sb.st_size;
|
||||
return total;
|
||||
}
|
||||
|
||||
for (i = 0; i < state->input_file_count; i++) {
|
||||
if (0 == strcmp(state->input_files[i], "-")) {
|
||||
rc = fstat64(STDIN_FILENO, &sb);
|
||||
for (file_idx = 0; file_idx < state->input_file_count; file_idx++) {
|
||||
int rc;
|
||||
|
||||
if (0 == strcmp(state->input_files[file_idx], "-")) {
|
||||
rc = fstat(STDIN_FILENO, &sb);
|
||||
if (rc != 0) {
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
} else {
|
||||
rc = stat64(state->input_files[i], &sb);
|
||||
if (0 == rc)
|
||||
rc = access(state->input_files[i], R_OK);
|
||||
rc = stat(state->input_files[file_idx], &sb);
|
||||
if (0 == rc) {
|
||||
rc = access(state->input_files[file_idx], R_OK); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: we're not really
|
||||
* using access() to do permissions checks,
|
||||
* but to zero the total if we might be
|
||||
* unable to read the file later, so if an
|
||||
* attacker redirected one of the input
|
||||
* files in between this part and the actual
|
||||
* reading, the outcome would be that the
|
||||
* total byte count would be wrong or
|
||||
* missing, nothing useful.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
pv_error(state, "%s: %s",
|
||||
state->input_files[i], strerror(errno));
|
||||
for (j = i; j < state->input_file_count - 1; j++) {
|
||||
state->input_files[j] =
|
||||
state->input_files[j + 1];
|
||||
}
|
||||
state->input_file_count--;
|
||||
i--;
|
||||
state->exit_status |= 2;
|
||||
continue;
|
||||
debug("%s: %s", state->input_files[file_idx], strerror(errno));
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
|
||||
if (S_ISBLK(sb.st_mode)) {
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Get the size of block devices by opening
|
||||
* them and seeking to the end.
|
||||
*/
|
||||
if (0 == strcmp(state->input_files[i], "-")) {
|
||||
fd = open64("/dev/stdin", O_RDONLY);
|
||||
if (0 == strcmp(state->input_files[file_idx], "-")) {
|
||||
fd = open("/dev/stdin", O_RDONLY); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: "/dev/stdin" may be
|
||||
* a symlink, so can't use O_NOFOLLOW, and
|
||||
* so we have to assume that it being under
|
||||
* "/dev" means the path is less likely to
|
||||
* be under the control of someone else.
|
||||
*/
|
||||
} else {
|
||||
fd = open64(state->input_files[i],
|
||||
O_RDONLY);
|
||||
fd = open(state->input_files[file_idx], O_RDONLY); /* flawfinder: ignore */
|
||||
/* flawfinder - see last open() below. */
|
||||
}
|
||||
if (fd >= 0) {
|
||||
total += lseek64(fd, 0, SEEK_END);
|
||||
close(fd);
|
||||
off_t end_position;
|
||||
end_position = lseek(fd, 0, SEEK_END);
|
||||
if (end_position > 0) {
|
||||
total += end_position;
|
||||
}
|
||||
(void) close(fd);
|
||||
} else {
|
||||
pv_error(state, "%s: %s",
|
||||
state->input_files[i],
|
||||
strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
} else if (S_ISREG(sb.st_mode)) {
|
||||
total += sb.st_size;
|
||||
@@ -108,16 +130,22 @@ unsigned long long pv_calc_total_size(pvstate_t state)
|
||||
* Further modified to check that stdout is not in append-only mode
|
||||
* and that we can seek back to the start after getting the size.
|
||||
*/
|
||||
if (total <= 0) {
|
||||
rc = fstat64(STDOUT_FILENO, &sb);
|
||||
if (total < 1) {
|
||||
int rc;
|
||||
|
||||
rc = fstat(STDOUT_FILENO, &sb);
|
||||
|
||||
if ((0 == rc) && S_ISBLK(sb.st_mode)
|
||||
&& (0 == (fcntl(STDOUT_FILENO, F_GETFL) & O_APPEND))) {
|
||||
total = lseek64(STDOUT_FILENO, 0, SEEK_END);
|
||||
if (lseek64(STDOUT_FILENO, 0, SEEK_SET) != 0) {
|
||||
off_t end_position;
|
||||
end_position = lseek(STDOUT_FILENO, 0, SEEK_END);
|
||||
total = 0;
|
||||
if (end_position > 0) {
|
||||
total = end_position;
|
||||
}
|
||||
if (lseek(STDOUT_FILENO, 0, SEEK_SET) != 0) {
|
||||
pv_error(state, "%s: %s: %s", "(stdout)",
|
||||
_
|
||||
("failed to seek to start of output"),
|
||||
strerror(errno));
|
||||
_("failed to seek to start of output"), strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
}
|
||||
/*
|
||||
@@ -127,135 +155,181 @@ unsigned long long pv_calc_total_size(pvstate_t state)
|
||||
* device.
|
||||
*/
|
||||
if (total > 0) {
|
||||
state->stop_at_size = 1;
|
||||
state->stop_at_size = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!state->linemode)
|
||||
return total;
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Count the total number of lines to be transferred by reading through all
|
||||
* input files. If any of the inputs are not regular files (such as if they
|
||||
* are a pipe or a block device), the total size is set to zero.
|
||||
*
|
||||
* Any files that cannot be stat()ed or that access() says we can't read
|
||||
* will be skipped, and the total size will be set to zero.
|
||||
*
|
||||
* Returns the total size, or 0 if it is unknown.
|
||||
*/
|
||||
static off_t pv_calc_total_lines(pvstate_t state)
|
||||
{
|
||||
off_t total;
|
||||
struct stat sb;
|
||||
unsigned int file_idx;
|
||||
|
||||
/*
|
||||
* In line mode, we count input lines to work out the total size.
|
||||
*/
|
||||
total = 0;
|
||||
|
||||
for (i = 0; i < state->input_file_count; i++) {
|
||||
fd = -1;
|
||||
for (file_idx = 0; file_idx < state->input_file_count && NULL != state->input_files; file_idx++) {
|
||||
int fd = -1;
|
||||
int rc = 0;
|
||||
|
||||
if (0 == strcmp(state->input_files[i], "-")) {
|
||||
rc = fstat64(STDIN_FILENO, &sb);
|
||||
if (0 == strcmp(state->input_files[file_idx], "-")) {
|
||||
rc = fstat(STDIN_FILENO, &sb);
|
||||
if ((rc != 0) || (!S_ISREG(sb.st_mode))) {
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
fd = dup(STDIN_FILENO);
|
||||
} else {
|
||||
rc = stat64(state->input_files[i], &sb);
|
||||
rc = stat(state->input_files[file_idx], &sb);
|
||||
if ((rc != 0) || (!S_ISREG(sb.st_mode))) {
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
fd = open64(state->input_files[i], O_RDONLY);
|
||||
fd = open(state->input_files[file_idx], O_RDONLY); /* flawfinder: ignore */
|
||||
/* flawfinder - see last open() below. */
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
pv_error(state, "%s: %s", state->input_files[i],
|
||||
strerror(errno));
|
||||
debug("%s: %s", state->input_files[file_idx], strerror(errno));
|
||||
total = 0;
|
||||
state->exit_status |= 2;
|
||||
return total;
|
||||
}
|
||||
#if HAVE_POSIX_FADVISE
|
||||
/* Advise the OS that we will only be reading sequentially. */
|
||||
(void) posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
unsigned char scanbuf[1024];
|
||||
int numread, j;
|
||||
while (true) {
|
||||
char scanbuf[1024]; /* flawfinder: ignore */
|
||||
ssize_t numread, buf_idx;
|
||||
|
||||
numread = read(fd, scanbuf, sizeof(scanbuf));
|
||||
/* flawfinder - always bounded, below. */
|
||||
|
||||
numread = read(fd, scanbuf, sizeof(scanbuf)); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: each time around the loop
|
||||
* we are always reading into the start of the
|
||||
* buffer, not moving along it, so the bounding is
|
||||
* OK.
|
||||
*/
|
||||
if (numread < 0) {
|
||||
pv_error(state, "%s: %s",
|
||||
state->input_files[i],
|
||||
strerror(errno));
|
||||
pv_error(state, "%s: %s", state->input_files[file_idx], strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
break;
|
||||
} else if (0 == numread) {
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < numread; j++) {
|
||||
if ('\n' == scanbuf[j])
|
||||
total++;
|
||||
for (buf_idx = 0; buf_idx < numread; buf_idx++) {
|
||||
if (state->null_terminated_lines) {
|
||||
if ('\0' == scanbuf[buf_idx])
|
||||
total++;
|
||||
} else {
|
||||
if ('\n' == scanbuf[buf_idx])
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lseek64(fd, 0, SEEK_SET);
|
||||
close(fd);
|
||||
if (0 != lseek(fd, 0, SEEK_SET)) {
|
||||
pv_error(state, "%s: %s", state->input_files[file_idx], strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Work out the total size of all data by adding up the sizes of all input
|
||||
* files, using either pv_calc_total_bytes() or pv_calc_total_lines()
|
||||
* depending on whether state->linemode is true.
|
||||
*
|
||||
* Returns the total size, or 0 if it is unknown.
|
||||
*/
|
||||
off_t pv_calc_total_size(pvstate_t state)
|
||||
{
|
||||
if (state->linemode) {
|
||||
return pv_calc_total_lines(state);
|
||||
} else {
|
||||
return pv_calc_total_bytes(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Close the given file descriptor and open the next one, whose number in
|
||||
* the list is "filenum", returning the new file descriptor (or negative on
|
||||
* error). It is an error if the next input file is the same as the file
|
||||
* stdout is pointing to.
|
||||
*
|
||||
* Updates state->current_file in the process.
|
||||
* Updates state->current_input_file in the process.
|
||||
*/
|
||||
int pv_next_file(pvstate_t state, int filenum, int oldfd)
|
||||
int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
{
|
||||
struct stat64 isb;
|
||||
struct stat64 osb;
|
||||
int fd, input_file_is_stdout;
|
||||
struct stat isb;
|
||||
struct stat osb;
|
||||
int fd;
|
||||
bool input_file_is_stdout;
|
||||
|
||||
if (oldfd > 0) {
|
||||
if (close(oldfd)) {
|
||||
pv_error(state, "%s: %s",
|
||||
_("failed to close file"),
|
||||
strerror(errno));
|
||||
if (oldfd >= 0) {
|
||||
if (0 != close(oldfd)) {
|
||||
pv_error(state, "%s: %s", _("failed to close file"), strerror(errno));
|
||||
state->exit_status |= 8;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (filenum >= state->input_file_count) {
|
||||
debug("%s: %d >= %d", "filenum too large", filenum, state->input_file_count);
|
||||
state->exit_status |= 8;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (filenum < 0) {
|
||||
state->exit_status |= 8;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == strcmp(state->input_files[filenum], "-")) {
|
||||
if ((NULL == state->input_files) || (0 == strcmp(state->input_files[filenum], "-"))) {
|
||||
fd = STDIN_FILENO;
|
||||
} else {
|
||||
fd = open64(state->input_files[filenum], O_RDONLY);
|
||||
fd = open(state->input_files[filenum], O_RDONLY); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: the input file list is under the
|
||||
* control of the operator by its nature, so we can't refuse
|
||||
* to open symlinks etc as that would be counterintuitive.
|
||||
*/
|
||||
if (fd < 0) {
|
||||
pv_error(state, "%s: %s: %s",
|
||||
_("failed to read file"),
|
||||
state->input_files[filenum],
|
||||
strerror(errno));
|
||||
_("failed to read file"), state->input_files[filenum], strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fstat64(fd, &isb)) {
|
||||
pv_error(state, "%s: %s: %s",
|
||||
_("failed to stat file"),
|
||||
state->input_files[filenum], strerror(errno));
|
||||
close(fd);
|
||||
if (0 != fstat(fd, &isb)) {
|
||||
pv_error(state, "%s: %s: %s", _("failed to stat file"),
|
||||
NULL == state->input_files ? "-" : state->input_files[filenum], strerror(errno));
|
||||
(void) close(fd);
|
||||
state->exit_status |= 2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstat64(STDOUT_FILENO, &osb)) {
|
||||
pv_error(state, "%s: %s",
|
||||
_("failed to stat output file"), strerror(errno));
|
||||
close(fd);
|
||||
if (0 != fstat(STDOUT_FILENO, &osb)) {
|
||||
pv_error(state, "%s: %s", _("failed to stat output file"), strerror(errno));
|
||||
(void) close(fd);
|
||||
state->exit_status |= 2;
|
||||
return -1;
|
||||
}
|
||||
@@ -265,30 +339,112 @@ int pv_next_file(pvstate_t state, int filenum, int oldfd)
|
||||
* destination. This restriction is ignored for anything other
|
||||
* than a regular file or block device.
|
||||
*/
|
||||
input_file_is_stdout = 1;
|
||||
input_file_is_stdout = true;
|
||||
if (isb.st_dev != osb.st_dev)
|
||||
input_file_is_stdout = 0;
|
||||
input_file_is_stdout = false;
|
||||
if (isb.st_ino != osb.st_ino)
|
||||
input_file_is_stdout = 0;
|
||||
if (isatty(fd))
|
||||
input_file_is_stdout = 0;
|
||||
input_file_is_stdout = false;
|
||||
if (0 != isatty(fd))
|
||||
input_file_is_stdout = false;
|
||||
if ((!S_ISREG(isb.st_mode)) && (!S_ISBLK(isb.st_mode)))
|
||||
input_file_is_stdout = 0;
|
||||
input_file_is_stdout = false;
|
||||
|
||||
if (input_file_is_stdout) {
|
||||
pv_error(state, "%s: %s",
|
||||
_("input file is output file"),
|
||||
state->input_files[filenum]);
|
||||
close(fd);
|
||||
pv_error(state, "%s: %s", _("input file is output file"),
|
||||
NULL == state->input_files ? "-" : state->input_files[filenum]);
|
||||
(void) close(fd);
|
||||
state->exit_status |= 4;
|
||||
return -1;
|
||||
}
|
||||
|
||||
state->current_file = state->input_files[filenum];
|
||||
if (0 == strcmp(state->input_files[filenum], "-")) {
|
||||
state->current_file = "(stdin)";
|
||||
state->current_input_file = filenum;
|
||||
#ifdef O_DIRECT
|
||||
/*
|
||||
* Set or clear O_DIRECT on the file descriptor.
|
||||
*/
|
||||
if (0 != fcntl(fd, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) {
|
||||
/*@-compdef@ */
|
||||
/*
|
||||
* splint - passed or returned storage is undefined - but at
|
||||
* this point we know the input file list is been populated,
|
||||
* so that's OK.
|
||||
*/
|
||||
debug("%s: %s: %s", pv_current_file_name(state), "fcntl", strerror(errno));
|
||||
/*@+compdef@ */
|
||||
}
|
||||
/*
|
||||
* We don't clear direct_io_changed here, to avoid race conditions
|
||||
* that could cause the input and output settings to differ.
|
||||
*/
|
||||
#endif /* O_DIRECT */
|
||||
|
||||
debug("%s: %d: %s: fd=%d", "next file opened", filenum, pv_current_file_name(state), fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the name of the current file. The returned buffer may point to
|
||||
* internal state and must not be passed to free() or used after "state" is
|
||||
* freed.
|
||||
*/
|
||||
/*@out@*/ const char *pv_current_file_name(pvstate_t state)
|
||||
{
|
||||
static char *str_none = NULL;
|
||||
static char *str_stdin = NULL;
|
||||
const char *input_file_name = NULL;
|
||||
|
||||
/*@-observertrans@ */
|
||||
/*@-onlytrans@ */
|
||||
/*@-statictrans@ */
|
||||
/*
|
||||
* Here we are doing bad things with regards to whether the returned
|
||||
* string is an allocated string from the state->input_files array,
|
||||
* a constant string, or a returned string from gettext(), but it
|
||||
* has no impact. We explicitly document, above, that the returned
|
||||
* string expires with the state, and hence switch off the
|
||||
* associated splint warnings.
|
||||
*/
|
||||
|
||||
if (NULL == str_none)
|
||||
str_none = _("(none)");
|
||||
if (NULL == str_stdin)
|
||||
str_stdin = _("(stdin)");
|
||||
|
||||
/* Fallback in case of translation failure. */
|
||||
if (NULL == str_none)
|
||||
str_none = "(none)";
|
||||
if (NULL == str_stdin)
|
||||
str_stdin = "(stdin)";
|
||||
|
||||
if (state->current_input_file < 0)
|
||||
return str_none;
|
||||
if ((unsigned int) (state->current_input_file) >= state->input_file_count)
|
||||
return str_none;
|
||||
|
||||
if (NULL == state->input_files) {
|
||||
input_file_name = NULL;
|
||||
} else {
|
||||
input_file_name = state->input_files[state->current_input_file];
|
||||
}
|
||||
if (NULL == input_file_name)
|
||||
return str_none;
|
||||
if (0 == strcmp(input_file_name, "-"))
|
||||
return str_stdin;
|
||||
|
||||
/*@-compdef@ */
|
||||
return input_file_name;
|
||||
/*@+compdef@ */
|
||||
/*
|
||||
* splint warns about state->input_files being undefined, but we
|
||||
* know it's been populated fully by the time this function is
|
||||
* called.
|
||||
*/
|
||||
|
||||
/*@+statictrans@ */
|
||||
/*@+onlytrans@ */
|
||||
/*@+observertrans@ */
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+301
-314
@@ -1,8 +1,13 @@
|
||||
/*
|
||||
* Main program entry point - read the command line options, then perform
|
||||
* the appropriate actions.
|
||||
* Functions providing the main transfer or file descriptor watching loop.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -20,24 +25,6 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
/*
|
||||
* Add the given number of microseconds (which may be negative) to the given
|
||||
* timeval.
|
||||
*/
|
||||
static void pv_timeval_add_usec(struct timeval *val, long usec)
|
||||
{
|
||||
val->tv_usec += usec;
|
||||
while (val->tv_usec < 0) {
|
||||
val->tv_sec--;
|
||||
val->tv_usec += 1000000;
|
||||
}
|
||||
while (val->tv_usec >= 1000000) {
|
||||
val->tv_sec++;
|
||||
val->tv_usec -= 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pipe data from a list of files to standard output, giving information
|
||||
* about the transfer on standard error according to the given options.
|
||||
@@ -46,15 +33,17 @@ static void pv_timeval_add_usec(struct timeval *val, long usec)
|
||||
*/
|
||||
int pv_main_loop(pvstate_t state)
|
||||
{
|
||||
long written, lineswritten;
|
||||
long long total_written, since_last, cansend;
|
||||
long lineswritten;
|
||||
off_t total_written, transferred_since_last, cansend;
|
||||
ssize_t written;
|
||||
long double target;
|
||||
int eof_in, eof_out, final_update;
|
||||
struct timeval start_time, next_update, next_ratecheck, cur_time;
|
||||
struct timeval init_time, next_remotecheck;
|
||||
long double elapsed;
|
||||
struct stat64 sb;
|
||||
int fd, n;
|
||||
bool eof_in, eof_out, final_update;
|
||||
struct timespec start_time, next_update, next_ratecheck, cur_time;
|
||||
struct timespec init_time, next_remotecheck, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
struct stat sb;
|
||||
int fd;
|
||||
unsigned int file_idx;
|
||||
|
||||
/*
|
||||
* "written" is ALWAYS bytes written by the last transfer.
|
||||
@@ -65,8 +54,9 @@ int pv_main_loop(pvstate_t state)
|
||||
* "total_written" is the total bytes written since the start,
|
||||
* or in line mode, the total lines written since the start.
|
||||
*
|
||||
* "since_last" is the bytes written since the last display,
|
||||
* or in line mode, the lines written since the last display.
|
||||
* "transferred_since_last" is the bytes written since the last
|
||||
* display, or in line mode, the lines written since the last
|
||||
* display.
|
||||
*
|
||||
* The remaining variables are all unchanged by linemode.
|
||||
*/
|
||||
@@ -75,54 +65,83 @@ int pv_main_loop(pvstate_t state)
|
||||
|
||||
pv_crs_init(state);
|
||||
|
||||
eof_in = 0;
|
||||
eof_out = 0;
|
||||
eof_in = false;
|
||||
eof_out = false;
|
||||
total_written = 0;
|
||||
since_last = 0;
|
||||
lineswritten = 0;
|
||||
transferred_since_last = 0;
|
||||
state->initial_offset = 0;
|
||||
|
||||
gettimeofday(&start_time, NULL);
|
||||
gettimeofday(&cur_time, NULL);
|
||||
memset(&cur_time, 0, sizeof(cur_time));
|
||||
memset(&start_time, 0, sizeof(start_time));
|
||||
|
||||
next_update.tv_sec = start_time.tv_sec;
|
||||
next_update.tv_usec = start_time.tv_usec;
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_copy(&start_time, &cur_time);
|
||||
|
||||
memset(&next_ratecheck, 0, sizeof(next_ratecheck));
|
||||
memset(&next_remotecheck, 0, sizeof(next_remotecheck));
|
||||
memset(&next_update, 0, sizeof(next_update));
|
||||
|
||||
pv_elapsedtime_copy(&next_ratecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_remotecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
if ((state->delay_start > 0)
|
||||
&& (state->delay_start > state->interval)) {
|
||||
pv_timeval_add_usec(&next_update,
|
||||
(long) (1000000.0 *
|
||||
state->delay_start));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->delay_start));
|
||||
} else {
|
||||
pv_timeval_add_usec(&next_update,
|
||||
(long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
}
|
||||
|
||||
next_ratecheck.tv_sec = start_time.tv_sec;
|
||||
next_ratecheck.tv_usec = start_time.tv_usec;
|
||||
next_remotecheck.tv_sec = start_time.tv_sec;
|
||||
next_remotecheck.tv_usec = start_time.tv_usec;
|
||||
|
||||
target = 0;
|
||||
final_update = 0;
|
||||
n = 0;
|
||||
final_update = false;
|
||||
file_idx = 0;
|
||||
|
||||
fd = pv_next_file(state, n, -1);
|
||||
/*
|
||||
* Open the first readable input file.
|
||||
*/
|
||||
fd = -1;
|
||||
while (fd < 0 && file_idx < state->input_file_count) {
|
||||
fd = pv_next_file(state, file_idx, -1);
|
||||
if (fd < 0)
|
||||
file_idx++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit early if there was no readable input file.
|
||||
*/
|
||||
if (fd < 0) {
|
||||
if (state->cursor)
|
||||
pv_crs_fini(state);
|
||||
return state->exit_status;
|
||||
}
|
||||
#if HAVE_POSIX_FADVISE
|
||||
/* Advise the OS that we will only be reading sequentially. */
|
||||
(void) posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
#ifdef O_DIRECT
|
||||
/*
|
||||
* Set or clear O_DIRECT on the output.
|
||||
*/
|
||||
if (0 != fcntl(STDOUT_FILENO, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) {
|
||||
debug("%s: %s", "fcntl", strerror(errno));
|
||||
}
|
||||
state->direct_io_changed = false;
|
||||
#endif /* O_DIRECT */
|
||||
|
||||
#if HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
/*
|
||||
* Set target buffer size if the initial file's block size can be
|
||||
* read and we weren't given a target buffer size.
|
||||
*/
|
||||
if ((0 == fstat64(fd, &sb)) && (0 == state->target_buffer_size)) {
|
||||
unsigned long long sz;
|
||||
sz = sb.st_blksize * 32;
|
||||
if ((0 == fstat(fd, &sb)) && (0 == state->target_buffer_size)) {
|
||||
size_t sz;
|
||||
sz = (size_t) (sb.st_blksize * 32);
|
||||
if (sz > BUFFER_SIZE_MAX)
|
||||
sz = BUFFER_SIZE_MAX;
|
||||
state->target_buffer_size = sz;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (0 == state->target_buffer_size)
|
||||
state->target_buffer_size = BUFFER_SIZE;
|
||||
@@ -132,33 +151,30 @@ int pv_main_loop(pvstate_t state)
|
||||
cansend = 0;
|
||||
|
||||
/*
|
||||
* Check for remote messages from -R every short while
|
||||
* Check for remote messages from -R every short while.
|
||||
*/
|
||||
if ((cur_time.tv_sec > next_remotecheck.tv_sec)
|
||||
|| (cur_time.tv_sec == next_remotecheck.tv_sec
|
||||
&& cur_time.tv_usec >= next_remotecheck.tv_usec)) {
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_remotecheck) > 0) {
|
||||
pv_remote_check(state);
|
||||
pv_timeval_add_usec(&next_remotecheck,
|
||||
REMOTE_INTERVAL);
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
}
|
||||
|
||||
if (state->pv_sig_abort)
|
||||
if (1 == state->pv_sig_abort)
|
||||
break;
|
||||
|
||||
if (state->rate_limit > 0) {
|
||||
gettimeofday(&cur_time, NULL);
|
||||
if ((cur_time.tv_sec > next_ratecheck.tv_sec)
|
||||
|| (cur_time.tv_sec == next_ratecheck.tv_sec
|
||||
&& cur_time.tv_usec >=
|
||||
next_ratecheck.tv_usec)) {
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_ratecheck) > 0) {
|
||||
target +=
|
||||
((long double) (state->rate_limit)) /
|
||||
(long double) (1000000 /
|
||||
RATE_GRANULARITY);
|
||||
pv_timeval_add_usec(&next_ratecheck,
|
||||
RATE_GRANULARITY);
|
||||
((long double) (state->rate_limit)) / (long double) (1000000000.0 /
|
||||
(long
|
||||
double) (RATE_GRANULARITY));
|
||||
long double burst_max = ((long double) (state->rate_limit * RATE_BURST_WINDOW));
|
||||
if (target > burst_max) {
|
||||
target = burst_max;
|
||||
}
|
||||
pv_elapsedtime_add_nsec(&next_ratecheck, RATE_GRANULARITY);
|
||||
}
|
||||
cansend = target;
|
||||
cansend = (off_t) target;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -166,14 +182,13 @@ int pv_main_loop(pvstate_t state)
|
||||
* try to write more than we're allowed to.
|
||||
*/
|
||||
if ((0 < state->size) && (state->stop_at_size)) {
|
||||
if (((long) (state->size) <
|
||||
(total_written + cansend))
|
||||
if ((state->size < (total_written + cansend))
|
||||
|| ((0 == cansend)
|
||||
&& (0 == state->rate_limit))) {
|
||||
cansend = state->size - total_written;
|
||||
if (0 >= cansend) {
|
||||
eof_in = 1;
|
||||
eof_out = 1;
|
||||
eof_in = true;
|
||||
eof_out = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,11 +197,10 @@ int pv_main_loop(pvstate_t state)
|
||||
&& (0 >= cansend) && eof_in && eof_out) {
|
||||
written = 0;
|
||||
} else {
|
||||
written =
|
||||
pv_transfer(state, fd, &eof_in, &eof_out,
|
||||
cansend, &lineswritten);
|
||||
written = pv_transfer(state, fd, &eof_in, &eof_out, cansend, &lineswritten);
|
||||
}
|
||||
|
||||
/* End on write error. */
|
||||
if (written < 0) {
|
||||
if (state->cursor)
|
||||
pv_crs_fini(state);
|
||||
@@ -194,39 +208,43 @@ int pv_main_loop(pvstate_t state)
|
||||
}
|
||||
|
||||
if (state->linemode) {
|
||||
since_last += lineswritten;
|
||||
transferred_since_last += lineswritten;
|
||||
total_written += lineswritten;
|
||||
if (state->rate_limit > 0)
|
||||
target -= lineswritten;
|
||||
} else {
|
||||
since_last += written;
|
||||
transferred_since_last += written;
|
||||
total_written += written;
|
||||
if (state->rate_limit > 0)
|
||||
target -= written;
|
||||
}
|
||||
|
||||
if (eof_in && eof_out && n < (state->input_file_count - 1)) {
|
||||
n++;
|
||||
fd = pv_next_file(state, n, fd);
|
||||
if (fd < 0) {
|
||||
if (state->cursor)
|
||||
pv_crs_fini(state);
|
||||
return state->exit_status;
|
||||
/*
|
||||
* EOF, and files remain - advance to the next file.
|
||||
*/
|
||||
while (eof_in && eof_out && file_idx < (state->input_file_count - 1)) {
|
||||
file_idx++;
|
||||
fd = pv_next_file(state, file_idx, fd);
|
||||
if (fd >= 0) {
|
||||
eof_in = false;
|
||||
eof_out = false;
|
||||
}
|
||||
eof_in = 0;
|
||||
eof_out = 0;
|
||||
}
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
/* Now check the current time. */
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
/* If full EOF, final update, and force a display updaate. */
|
||||
if (eof_in && eof_out) {
|
||||
final_update = 1;
|
||||
final_update = true;
|
||||
if ((state->display_visible)
|
||||
|| (0 == state->delay_start))
|
||||
next_update.tv_sec = cur_time.tv_sec - 1;
|
||||
|| (state->delay_start < 0.001)) {
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
}
|
||||
}
|
||||
|
||||
if (state->no_op)
|
||||
/* Just go round the loop again if there's no display. */
|
||||
if (state->no_display)
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -236,6 +254,7 @@ int pv_main_loop(pvstate_t state)
|
||||
* was received.
|
||||
*/
|
||||
if (state->wait) {
|
||||
/* Restart the loop if nothing written yet. */
|
||||
if (state->linemode) {
|
||||
if (lineswritten < 1)
|
||||
continue;
|
||||
@@ -257,78 +276,82 @@ int pv_main_loop(pvstate_t state)
|
||||
* SIGTSTOP so things don't mess up.
|
||||
*/
|
||||
pv_sig_nopause();
|
||||
gettimeofday(&start_time, NULL);
|
||||
state->pv_sig_toffset.tv_sec = 0;
|
||||
state->pv_sig_toffset.tv_usec = 0;
|
||||
pv_elapsedtime_read(&start_time);
|
||||
pv_elapsedtime_zero(&(state->pv_sig_toffset));
|
||||
pv_sig_allowpause();
|
||||
|
||||
next_update.tv_sec = start_time.tv_sec;
|
||||
next_update.tv_usec = start_time.tv_usec;
|
||||
pv_timeval_add_usec(&next_update,
|
||||
(long) (1000000.0 *
|
||||
state->interval));
|
||||
/*
|
||||
* Start the display, but only at the next interval,
|
||||
* not immediately.
|
||||
*/
|
||||
pv_elapsedtime_copy(&next_update, &start_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
}
|
||||
|
||||
if ((cur_time.tv_sec < next_update.tv_sec)
|
||||
|| (cur_time.tv_sec == next_update.tv_sec
|
||||
&& cur_time.tv_usec < next_update.tv_usec)) {
|
||||
/* Restart the loop if it's not time to update the display. */
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_timeval_add_usec(&next_update,
|
||||
(long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
if (next_update.tv_sec < cur_time.tv_sec) {
|
||||
next_update.tv_sec = cur_time.tv_sec;
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
} else if (next_update.tv_sec == cur_time.tv_sec
|
||||
&& next_update.tv_usec < cur_time.tv_usec) {
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
}
|
||||
/* Set the "next update" time to now, if it's in the past. */
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
init_time.tv_sec =
|
||||
start_time.tv_sec + state->pv_sig_toffset.tv_sec;
|
||||
init_time.tv_usec =
|
||||
start_time.tv_usec + state->pv_sig_toffset.tv_usec;
|
||||
if (init_time.tv_usec >= 1000000) {
|
||||
init_time.tv_sec++;
|
||||
init_time.tv_usec -= 1000000;
|
||||
}
|
||||
if (init_time.tv_usec < 0) {
|
||||
init_time.tv_sec--;
|
||||
init_time.tv_usec += 1000000;
|
||||
}
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
memset(&init_time, 0, sizeof(init_time));
|
||||
pv_elapsedtime_add(&init_time, &start_time, &(state->pv_sig_toffset));
|
||||
|
||||
elapsed = cur_time.tv_sec - init_time.tv_sec;
|
||||
elapsed +=
|
||||
(cur_time.tv_usec - init_time.tv_usec) / 1000000.0;
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
* time minus effective start time.
|
||||
*/
|
||||
memset(&transfer_elapsed, 0, sizeof(transfer_elapsed));
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &init_time);
|
||||
|
||||
elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (final_update)
|
||||
since_last = -1;
|
||||
transferred_since_last = -1;
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (1 == state->pv_sig_newsize) {
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
if (state->pv_sig_newsize) {
|
||||
state->pv_sig_newsize = 0;
|
||||
pv_screensize(&(state->width), &(state->height));
|
||||
|
||||
new_width = state->width;
|
||||
new_height = state->height;
|
||||
pv_screensize(&new_width, &new_height);
|
||||
|
||||
if (!state->width_set_manually)
|
||||
state->width = new_width;
|
||||
if (!state->height_set_manually)
|
||||
state->height = new_height;
|
||||
}
|
||||
|
||||
pv_display(state, elapsed, since_last, total_written);
|
||||
pv_display(state, elapsed_seconds, transferred_since_last, total_written);
|
||||
|
||||
since_last = 0;
|
||||
transferred_since_last = 0;
|
||||
}
|
||||
|
||||
if (state->cursor) {
|
||||
pv_crs_fini(state);
|
||||
} else {
|
||||
if ((!state->numeric) && (!state->no_op)
|
||||
if ((!state->numeric) && (!state->no_display)
|
||||
&& (state->display_visible))
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
if (state->pv_sig_abort)
|
||||
if (1 == state->pv_sig_abort)
|
||||
state->exit_status |= 32;
|
||||
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
(void) close(fd);
|
||||
|
||||
return state->exit_status;
|
||||
}
|
||||
@@ -344,17 +367,17 @@ int pv_main_loop(pvstate_t state)
|
||||
int pv_watchfd_loop(pvstate_t state)
|
||||
{
|
||||
struct pvwatchfd_s info;
|
||||
long long position_now, total_written, since_last;
|
||||
struct timeval next_update, cur_time;
|
||||
struct timeval init_time, next_remotecheck;
|
||||
long double elapsed;
|
||||
int ended;
|
||||
int first_check;
|
||||
off_t position_now, total_written, transferred_since_last;
|
||||
struct timespec next_update, cur_time;
|
||||
struct timespec init_time, next_remotecheck, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
bool ended, first_check;
|
||||
int rc;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.watch_pid = state->watch_pid;
|
||||
info.watch_fd = state->watch_fd;
|
||||
rc = pv_watchfd_info(state, &info, 0);
|
||||
rc = pv_watchfd_info(state, &info, false);
|
||||
if (0 != rc) {
|
||||
state->exit_status |= 2;
|
||||
return state->exit_status;
|
||||
@@ -377,113 +400,112 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&(info.start_time), NULL);
|
||||
gettimeofday(&cur_time, NULL);
|
||||
memset(&cur_time, 0, sizeof(cur_time));
|
||||
memset(&next_remotecheck, 0, sizeof(next_remotecheck));
|
||||
memset(&next_update, 0, sizeof(next_update));
|
||||
memset(&init_time, 0, sizeof(init_time));
|
||||
memset(&transfer_elapsed, 0, sizeof(transfer_elapsed));
|
||||
|
||||
next_update.tv_sec = info.start_time.tv_sec;
|
||||
next_update.tv_usec = info.start_time.tv_usec;
|
||||
pv_timeval_add_usec(&next_update,
|
||||
(long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_copy(&(info.start_time), &cur_time);
|
||||
pv_elapsedtime_copy(&next_remotecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
next_remotecheck.tv_sec = info.start_time.tv_sec;
|
||||
next_remotecheck.tv_usec = info.start_time.tv_usec;
|
||||
|
||||
ended = 0;
|
||||
ended = false;
|
||||
total_written = 0;
|
||||
since_last = 0;
|
||||
first_check = 1;
|
||||
transferred_since_last = 0;
|
||||
first_check = true;
|
||||
|
||||
while (!ended) {
|
||||
/*
|
||||
* Check for remote messages from -R every short while
|
||||
* Check for remote messages from -R every short while.
|
||||
*/
|
||||
if ((cur_time.tv_sec > next_remotecheck.tv_sec)
|
||||
|| (cur_time.tv_sec == next_remotecheck.tv_sec
|
||||
&& cur_time.tv_usec >= next_remotecheck.tv_usec)) {
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_remotecheck) > 0) {
|
||||
pv_remote_check(state);
|
||||
pv_timeval_add_usec(&next_remotecheck,
|
||||
REMOTE_INTERVAL);
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
}
|
||||
|
||||
if (state->pv_sig_abort)
|
||||
if (1 == state->pv_sig_abort)
|
||||
break;
|
||||
|
||||
position_now = pv_watchfd_position(&info);
|
||||
|
||||
if (position_now < 0) {
|
||||
ended = 1;
|
||||
ended = true;
|
||||
} else {
|
||||
since_last += position_now - total_written;
|
||||
transferred_since_last += position_now - total_written;
|
||||
total_written = position_now;
|
||||
if (first_check) {
|
||||
state->initial_offset = position_now;
|
||||
first_check = 0;
|
||||
first_check = false;
|
||||
}
|
||||
}
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
/* Ended - force a display update. */
|
||||
if (ended) {
|
||||
ended = 1;
|
||||
next_update.tv_sec = cur_time.tv_sec - 1;
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
}
|
||||
|
||||
if ((cur_time.tv_sec < next_update.tv_sec)
|
||||
|| (cur_time.tv_sec == next_update.tv_sec
|
||||
&& cur_time.tv_usec < next_update.tv_usec)) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 50000;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
/*
|
||||
* Restart the loop after a brief delay, if it's not time to
|
||||
* update the display.
|
||||
*/
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) {
|
||||
pv_nanosleep(50000000);
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_timeval_add_usec(&next_update,
|
||||
(long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
if (next_update.tv_sec < cur_time.tv_sec) {
|
||||
next_update.tv_sec = cur_time.tv_sec;
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
} else if (next_update.tv_sec == cur_time.tv_sec
|
||||
&& next_update.tv_usec < cur_time.tv_usec) {
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
}
|
||||
/* Set the "next update" time to now, if it's in the past. */
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
init_time.tv_sec =
|
||||
info.start_time.tv_sec + state->pv_sig_toffset.tv_sec;
|
||||
init_time.tv_usec =
|
||||
info.start_time.tv_usec +
|
||||
state->pv_sig_toffset.tv_usec;
|
||||
if (init_time.tv_usec >= 1000000) {
|
||||
init_time.tv_sec++;
|
||||
init_time.tv_usec -= 1000000;
|
||||
}
|
||||
if (init_time.tv_usec < 0) {
|
||||
init_time.tv_sec--;
|
||||
init_time.tv_usec += 1000000;
|
||||
}
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&init_time, &(info.start_time), &(state->pv_sig_toffset));
|
||||
|
||||
elapsed = cur_time.tv_sec - init_time.tv_sec;
|
||||
elapsed +=
|
||||
(cur_time.tv_usec - init_time.tv_usec) / 1000000.0;
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
* time minus effective start time.
|
||||
*/
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &init_time);
|
||||
|
||||
elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (ended)
|
||||
since_last = -1;
|
||||
transferred_since_last = -1;
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (1 == state->pv_sig_newsize) {
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
if (state->pv_sig_newsize) {
|
||||
state->pv_sig_newsize = 0;
|
||||
pv_screensize(&(state->width), &(state->height));
|
||||
|
||||
new_width = state->width;
|
||||
new_height = state->height;
|
||||
pv_screensize(&new_width, &new_height);
|
||||
|
||||
if (!state->width_set_manually)
|
||||
state->width = new_width;
|
||||
if (!state->height_set_manually)
|
||||
state->height = new_height;
|
||||
}
|
||||
|
||||
pv_display(state, elapsed, since_last, total_written);
|
||||
pv_display(state, elapsed_seconds, transferred_since_last, total_written);
|
||||
|
||||
since_last = 0;
|
||||
transferred_since_last = 0;
|
||||
}
|
||||
|
||||
if (!state->numeric)
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
|
||||
if (state->pv_sig_abort)
|
||||
if (1 == state->pv_sig_abort)
|
||||
state->exit_status |= 32;
|
||||
|
||||
return state->exit_status;
|
||||
@@ -501,23 +523,22 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
{
|
||||
struct pvstate_s state_copy;
|
||||
const char *original_format_string;
|
||||
char new_format_string[512] = { 0, };
|
||||
char new_format_string[512];
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
struct pvstate_s *state_array = NULL;
|
||||
int array_length = 0;
|
||||
int fd_to_idx[FD_SETSIZE] = { 0, };
|
||||
struct timeval next_update, cur_time;
|
||||
int fd_to_idx[FD_SETSIZE];
|
||||
struct timespec next_update, cur_time;
|
||||
int idx;
|
||||
int prev_displayed_lines, blank_lines;
|
||||
int first_pass = 1;
|
||||
bool first_pass = true;
|
||||
|
||||
/*
|
||||
* Make sure the process exists first, so we can give an error if
|
||||
* it's not there at the start.
|
||||
*/
|
||||
if (kill(state->watch_pid, 0) != 0) {
|
||||
pv_error(state, "%s %u: %s",
|
||||
_("pid"), state->watch_pid, strerror(errno));
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
return 2;
|
||||
}
|
||||
@@ -532,43 +553,28 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
* Make sure there's a format string, and then insert %N into it if
|
||||
* it's not present.
|
||||
*/
|
||||
original_format_string =
|
||||
state->format_string ? state->format_string : state->
|
||||
default_format;
|
||||
original_format_string = state->format_string ? state->format_string : state->default_format;
|
||||
memset(new_format_string, 0, sizeof(new_format_string));
|
||||
if (NULL == strstr(original_format_string, "%N")) {
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(new_format_string, sizeof(new_format_string) - 1,
|
||||
#else
|
||||
sprintf(new_format_string,
|
||||
#endif
|
||||
"%%N %s", original_format_string);
|
||||
(void) pv_snprintf(new_format_string, sizeof(new_format_string), "%%N %s", original_format_string);
|
||||
} else {
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(new_format_string, sizeof(new_format_string) - 1,
|
||||
#else
|
||||
sprintf(new_format_string,
|
||||
#endif
|
||||
"%s", original_format_string);
|
||||
(void) pv_snprintf(new_format_string, sizeof(new_format_string), "%s", original_format_string);
|
||||
}
|
||||
new_format_string[sizeof(new_format_string) - 1] = '\0';
|
||||
state_copy.format_string = NULL;
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(state_copy.default_format,
|
||||
sizeof(state_copy.default_format) - 1,
|
||||
#else
|
||||
sprintf(state_copy.default_format,
|
||||
#endif
|
||||
"%.510s", new_format_string);
|
||||
(void) pv_snprintf(state_copy.default_format, PV_SIZEOF_DEFAULT_FORMAT, "%.510s", new_format_string);
|
||||
state_copy.default_format[PV_SIZEOF_DEFAULT_FORMAT - 1] = '\0';
|
||||
|
||||
/*
|
||||
* Get things ready for the main loop.
|
||||
*/
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
memset(&cur_time, 0, sizeof(cur_time));
|
||||
memset(&next_update, 0, sizeof(next_update));
|
||||
|
||||
next_update.tv_sec = cur_time.tv_sec;
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
pv_timeval_add_usec(&next_update,
|
||||
(long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
for (idx = 0; idx < FD_SETSIZE; idx++) {
|
||||
fd_to_idx[idx] = -1;
|
||||
@@ -576,19 +582,17 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
|
||||
prev_displayed_lines = 0;
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
int rc, fd, displayed_lines;
|
||||
|
||||
if (state->pv_sig_abort)
|
||||
if (1 == state->pv_sig_abort)
|
||||
break;
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
if (kill(state->watch_pid, 0) != 0) {
|
||||
if (first_pass) {
|
||||
pv_error(state, "%s %u: %s",
|
||||
_("pid"), state->watch_pid,
|
||||
strerror(errno));
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
if (NULL != info_array)
|
||||
free(info_array);
|
||||
@@ -599,48 +603,38 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
break;
|
||||
}
|
||||
|
||||
if ((cur_time.tv_sec < next_update.tv_sec)
|
||||
|| (cur_time.tv_sec == next_update.tv_sec
|
||||
&& cur_time.tv_usec < next_update.tv_usec)) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 50000;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
/*
|
||||
* Restart the loop after a brief delay, if it's not time to
|
||||
* update the display.
|
||||
*/
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) {
|
||||
pv_nanosleep(50000000);
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_timeval_add_usec(&next_update,
|
||||
(long) (1000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
|
||||
if (next_update.tv_sec < cur_time.tv_sec) {
|
||||
next_update.tv_sec = cur_time.tv_sec;
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
} else if (next_update.tv_sec == cur_time.tv_sec
|
||||
&& next_update.tv_usec < cur_time.tv_usec) {
|
||||
next_update.tv_usec = cur_time.tv_usec;
|
||||
}
|
||||
/* Set the "next update" time to now, if it's in the past. */
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
if (state->pv_sig_newsize) {
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (1 == state->pv_sig_newsize) {
|
||||
state->pv_sig_newsize = 0;
|
||||
pv_screensize(&(state->width), &(state->height));
|
||||
for (idx = 0; idx < array_length; idx++) {
|
||||
state_array[idx].width = state->width;
|
||||
state_array[idx].height = state->height;
|
||||
pv_watchpid_setname(state,
|
||||
&(info_array[idx]));
|
||||
pv_watchpid_setname(state, &(info_array[idx]));
|
||||
state_array[idx].reparse_display = 1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = pv_watchpid_scanfds(state, &state_copy,
|
||||
state->watch_pid, &array_length,
|
||||
&info_array, &state_array,
|
||||
fd_to_idx);
|
||||
state->watch_pid, &array_length, &info_array, &state_array, fd_to_idx);
|
||||
if (rc != 0) {
|
||||
if (first_pass) {
|
||||
pv_error(state, "%s %u: %s",
|
||||
_("pid"), state->watch_pid,
|
||||
strerror(errno));
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
if (NULL != info_array)
|
||||
free(info_array);
|
||||
@@ -651,13 +645,13 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
break;
|
||||
}
|
||||
|
||||
first_pass = 0;
|
||||
first_pass = false;
|
||||
displayed_lines = 0;
|
||||
|
||||
for (fd = 0; fd < FD_SETSIZE; fd++) {
|
||||
long long position_now, since_last;
|
||||
struct timeval init_time;
|
||||
long double elapsed;
|
||||
off_t position_now, transferred_since_last;
|
||||
struct timespec init_time, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
|
||||
if (displayed_lines >= (int) (state->height))
|
||||
break;
|
||||
@@ -675,8 +669,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
if (pv_watchfd_changed(&(info_array[idx]))) {
|
||||
fd_to_idx[fd] = -1;
|
||||
info_array[idx].watch_pid = 0;
|
||||
debug("%s %d: %s", "fd", fd,
|
||||
"removing");
|
||||
debug("%s %d: %s", "fd", fd, "removing");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -685,8 +678,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
* Displayable fd - display, or remove if changed
|
||||
*/
|
||||
|
||||
position_now =
|
||||
pv_watchfd_position(&(info_array[idx]));
|
||||
position_now = pv_watchfd_position(&(info_array[idx]));
|
||||
|
||||
if (position_now < 0) {
|
||||
fd_to_idx[fd] = -1;
|
||||
@@ -695,40 +687,35 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
since_last =
|
||||
position_now - info_array[idx].position;
|
||||
transferred_since_last = position_now - info_array[idx].position;
|
||||
info_array[idx].position = position_now;
|
||||
|
||||
init_time.tv_sec =
|
||||
info_array[idx].start_time.tv_sec +
|
||||
state->pv_sig_toffset.tv_sec;
|
||||
init_time.tv_usec =
|
||||
info_array[idx].start_time.tv_usec +
|
||||
state->pv_sig_toffset.tv_usec;
|
||||
if (init_time.tv_usec >= 1000000) {
|
||||
init_time.tv_sec++;
|
||||
init_time.tv_usec -= 1000000;
|
||||
}
|
||||
if (init_time.tv_usec < 0) {
|
||||
init_time.tv_sec--;
|
||||
init_time.tv_usec += 1000000;
|
||||
}
|
||||
memset(&init_time, 0, sizeof(init_time));
|
||||
memset(&transfer_elapsed, 0, sizeof(transfer_elapsed));
|
||||
|
||||
elapsed = cur_time.tv_sec - init_time.tv_sec;
|
||||
elapsed +=
|
||||
(cur_time.tv_usec -
|
||||
init_time.tv_usec) / 1000000.0;
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&init_time, &(info_array[idx].start_time), &(state->pv_sig_toffset));
|
||||
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
* time minus effective start time.
|
||||
*/
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &init_time);
|
||||
|
||||
elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (displayed_lines > 0) {
|
||||
debug("%s", "adding newline");
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
debug("%s %d [%d]: %Lf / %Ld / %Ld", "fd", fd, idx,
|
||||
elapsed, since_last, position_now);
|
||||
debug("%s %d [%d]: %Lf / %Ld / %Ld", "fd", fd, idx, elapsed_seconds, transferred_since_last,
|
||||
position_now);
|
||||
|
||||
pv_display(&(state_array[idx]), elapsed,
|
||||
since_last, position_now);
|
||||
pv_display(&(state_array[idx]), elapsed_seconds, transferred_since_last, position_now);
|
||||
displayed_lines++;
|
||||
}
|
||||
|
||||
@@ -745,10 +732,10 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
while (blank_lines > 0) {
|
||||
unsigned int x;
|
||||
if (displayed_lines > 0)
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
for (x = 0; x < state->width; x++)
|
||||
write(STDERR_FILENO, " ", 1);
|
||||
write(STDERR_FILENO, "\r", 1);
|
||||
pv_write_retry(STDERR_FILENO, " ", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\r", 1);
|
||||
blank_lines--;
|
||||
displayed_lines++;
|
||||
}
|
||||
@@ -756,7 +743,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
debug("%s: %d", "displayed lines", displayed_lines);
|
||||
|
||||
while (displayed_lines > 1) {
|
||||
write(STDERR_FILENO, "\033[A", 3);
|
||||
pv_write_retry(STDERR_FILENO, "\033[A", 3);
|
||||
displayed_lines--;
|
||||
}
|
||||
}
|
||||
@@ -768,14 +755,14 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
while (blank_lines > 0) {
|
||||
unsigned int x;
|
||||
for (x = 0; x < state->width; x++)
|
||||
write(STDERR_FILENO, " ", 1);
|
||||
write(STDERR_FILENO, "\r", 1);
|
||||
pv_write_retry(STDERR_FILENO, " ", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\r", 1);
|
||||
blank_lines--;
|
||||
if (blank_lines > 0)
|
||||
write(STDERR_FILENO, "\n", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
while (prev_displayed_lines > 1) {
|
||||
write(STDERR_FILENO, "\033[A", 3);
|
||||
pv_write_retry(STDERR_FILENO, "\033[A", 3);
|
||||
prev_displayed_lines--;
|
||||
}
|
||||
|
||||
|
||||
+96
-49
@@ -1,12 +1,16 @@
|
||||
/*
|
||||
* Functions for converting strings to numbers.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include "pv.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
/*
|
||||
* This function is used instead of the macro from <ctype.h> because
|
||||
@@ -20,37 +24,50 @@ static bool pv__isdigit(char c)
|
||||
|
||||
|
||||
/*
|
||||
* Return the numeric value of "str", as an unsigned long long.
|
||||
* Return the numeric value of "str", as an off_t, where "str" is expected
|
||||
* to be a sequence of digits (without a thousands separator), possibly with
|
||||
* a fractional part, optionally followed by a units suffix such as "K" for
|
||||
* kibibytes.
|
||||
*/
|
||||
unsigned long long pv_getnum_ull(const char *str)
|
||||
off_t pv_getnum_size(const char *str)
|
||||
{
|
||||
unsigned long long n = 0;
|
||||
unsigned long long decimal = 0;
|
||||
unsigned int decdivisor = 1;
|
||||
off_t integral_part = 0;
|
||||
off_t fractional_part = 0;
|
||||
unsigned int fractional_divisor = 1;
|
||||
unsigned int shift = 0;
|
||||
|
||||
if (NULL == str)
|
||||
return n;
|
||||
return (off_t) 0;
|
||||
|
||||
/* Skip any non-numeric leading characters. */
|
||||
while (str[0] != '\0' && (!pv__isdigit(str[0])))
|
||||
str++;
|
||||
|
||||
/*
|
||||
* Parse the integral part of the number - the digits before the
|
||||
* decimal mark or units.
|
||||
*/
|
||||
for (; pv__isdigit(str[0]); str++) {
|
||||
n = n * 10;
|
||||
n += (unsigned long long) (str[0] - '0');
|
||||
integral_part = integral_part * 10;
|
||||
integral_part += (off_t) (str[0] - '0');
|
||||
}
|
||||
|
||||
/*
|
||||
* If a decimal value was given, skip the decimal part.
|
||||
* If the next character is a decimal mark, skip over it and parse
|
||||
* the following digits as the fractional part of the number.
|
||||
*
|
||||
* Note that we hard-code the decimal mark as '.' or ',' so this
|
||||
* will fail if there are any locales whose decimal mark is not one
|
||||
* of those two characters.
|
||||
*/
|
||||
if (('.' == str[0]) || (',' == str[0])) {
|
||||
str++;
|
||||
for (; pv__isdigit(str[0]); str++) {
|
||||
if (decdivisor < 10000) {
|
||||
decimal = decimal * 10;
|
||||
decimal +=
|
||||
(unsigned long long) (str[0] - '0');
|
||||
decdivisor = decdivisor * 10;
|
||||
/* Stop counting below 0.0001. */
|
||||
if (fractional_divisor < 10000) {
|
||||
fractional_part = fractional_part * 10;
|
||||
fractional_part += (off_t) (str[0] - '0');
|
||||
fractional_divisor = fractional_divisor * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,6 +77,7 @@ unsigned long long pv_getnum_ull(const char *str)
|
||||
* T=TiB=1024GiB).
|
||||
*/
|
||||
if (str[0] != '\0') {
|
||||
/* Skip any spaces or tabs after the digits. */
|
||||
while ((' ' == str[0]) || ('\t' == str[0]))
|
||||
str++;
|
||||
switch (str[0]) {
|
||||
@@ -96,98 +114,126 @@ unsigned long long pv_getnum_ull(const char *str)
|
||||
if (shiftby > 30)
|
||||
shiftby = 30;
|
||||
|
||||
n = n << shiftby;
|
||||
decimal = decimal << shiftby;
|
||||
/*@-shiftimplementation@ */
|
||||
/*
|
||||
* splint note: ignore the fact that the types we are
|
||||
* shifting are signed, because we know they are definitely
|
||||
* not negative.
|
||||
*/
|
||||
integral_part = (off_t) (integral_part << shiftby);
|
||||
fractional_part = (off_t) (fractional_part << shiftby);
|
||||
/*@+shiftimplementation@ */
|
||||
|
||||
shift -= shiftby;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add any decimal component.
|
||||
* Add the fractional part, divided by its divisor, to the integral
|
||||
* part, now that we've multiplied everything by the appropriate
|
||||
* units.
|
||||
*/
|
||||
decimal = decimal / decdivisor;
|
||||
n += decimal;
|
||||
fractional_part = fractional_part / fractional_divisor;
|
||||
integral_part += fractional_part;
|
||||
|
||||
return n;
|
||||
return integral_part;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the numeric value of "str", as a double.
|
||||
* Return the numeric value of "str", as a double, where "str" is expected
|
||||
* to be a positive decimal number expressing a time interval.
|
||||
*/
|
||||
double pv_getnum_d(const char *str)
|
||||
double pv_getnum_interval(const char *str)
|
||||
{
|
||||
double n = 0.0;
|
||||
double result = 0.0;
|
||||
double step = 1;
|
||||
|
||||
if (NULL == str)
|
||||
return n;
|
||||
return 0.0;
|
||||
|
||||
/* Skip any non-digit characters at the start. */
|
||||
while (str[0] != '\0' && (!pv__isdigit(str[0])))
|
||||
str++;
|
||||
|
||||
/* Parse the digits before the decimal mark. */
|
||||
for (; pv__isdigit(str[0]); str++) {
|
||||
n = n * 10;
|
||||
n += (double) (str[0] - '0');
|
||||
result = result * 10;
|
||||
result += (double) (str[0] - '0');
|
||||
}
|
||||
|
||||
/* If there is no decimal mark, return the value as-is. */
|
||||
if ((str[0] != '.') && (str[0] != ','))
|
||||
return n;
|
||||
return result;
|
||||
|
||||
/* Move past the decimal mark. */
|
||||
str++;
|
||||
|
||||
/* Parse the digits after the decimal mark, up to 0.0000001. */
|
||||
for (; pv__isdigit(str[0]) && step < 1000000; str++) {
|
||||
step = step * 10;
|
||||
n += ((double) (str[0] - '0')) / step;
|
||||
result += ((double) (str[0] - '0')) / step;
|
||||
}
|
||||
|
||||
return n;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the numeric value of "str", as an unsigned int.
|
||||
* Return the numeric value of "str", as an unsigned int, following the same
|
||||
* rules as pv_getnum_size(), expecting "str" to express a value to be used
|
||||
* as a count (such as number of screen columns, or size of a buffer).
|
||||
*/
|
||||
unsigned int pv_getnum_ui(const char *str)
|
||||
unsigned int pv_getnum_count(const char *str)
|
||||
{
|
||||
return (unsigned int) pv_getnum_ull(str);
|
||||
return (unsigned int) pv_getnum_size(str);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return nonzero if the given string is not a valid number of the given
|
||||
* type.
|
||||
* Return true if the given string is a valid number of the given type.
|
||||
*/
|
||||
int pv_getnum_check(const char *str, pv_numtype_t type)
|
||||
bool pv_getnum_check(const char *str, pv_numtype type)
|
||||
{
|
||||
if (0 == str)
|
||||
return 1;
|
||||
if (NULL == str)
|
||||
return false;
|
||||
|
||||
/* Skip leading spaces and tabs. */
|
||||
while ((' ' == str[0]) || ('\t' == str[0]))
|
||||
str++;
|
||||
|
||||
/* If the next character isn't a digit, this isn't a number. */
|
||||
if (!pv__isdigit(str[0]))
|
||||
return 1;
|
||||
return false;
|
||||
|
||||
/* Skip over the digits. */
|
||||
for (; pv__isdigit(str[0]); str++);
|
||||
|
||||
/*
|
||||
* If there's a decimal mark (see note in pv_getnum_size() above),
|
||||
* check that too.
|
||||
*/
|
||||
if (('.' == str[0]) || (',' == str[0])) {
|
||||
/* Integers should have no decimal mark. */
|
||||
if (type == PV_NUMTYPE_INTEGER)
|
||||
return 1;
|
||||
return false;
|
||||
/* Skip the decimal mark, then all digits. */
|
||||
str++;
|
||||
for (; pv__isdigit(str[0]); str++);
|
||||
}
|
||||
|
||||
/* If the string ends here, this is a valid number. */
|
||||
if ('\0' == str[0])
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Suffixes are not allowed for doubles, only for integers.
|
||||
*/
|
||||
/* A units suffix is not allowed for doubles, only for integers. */
|
||||
if (type == PV_NUMTYPE_DOUBLE)
|
||||
return 1;
|
||||
return false;
|
||||
|
||||
/* Skip trailing spaces or tabs. */
|
||||
while ((' ' == str[0]) || ('\t' == str[0]))
|
||||
str++;
|
||||
|
||||
/* Check the units suffix is one we know about. */
|
||||
switch (str[0]) {
|
||||
case 'k':
|
||||
case 'K':
|
||||
@@ -200,13 +246,14 @@ int pv_getnum_check(const char *str, pv_numtype_t type)
|
||||
str++;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the string has trailing text, it's not a valid number. */
|
||||
if (str[0] != '\0')
|
||||
return 1;
|
||||
return false;
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+254
-94
@@ -1,12 +1,19 @@
|
||||
/*
|
||||
* Signal handling functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -15,9 +22,46 @@
|
||||
void pv_crs_needreinit(pvstate_t);
|
||||
#endif
|
||||
|
||||
static pvstate_t pv_sig_state = NULL;
|
||||
/*@null@*/ static pvstate_t pv_sig_state = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Ensure that terminal attribute TOSTOP is set. If we have to set it,
|
||||
* record that fact by setting the state boolean "pv_tty_tostop_added" to
|
||||
* true, so that in pv_sig_fini() we can turn it back off again.
|
||||
*/
|
||||
static void pv_sig_ensure_tty_tostop()
|
||||
{
|
||||
struct termios terminal_attributes;
|
||||
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
|
||||
if (0 != tcgetattr(STDERR_FILENO, &terminal_attributes)) {
|
||||
debug("%s: %s", "failed to read terminal attributes", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == (terminal_attributes.c_lflag & TOSTOP)) {
|
||||
terminal_attributes.c_lflag |= TOSTOP;
|
||||
if (0 == tcsetattr(STDERR_FILENO, TCSANOW, &terminal_attributes)) {
|
||||
pv_sig_state->pv_tty_tostop_added = true;
|
||||
debug("%s", "set terminal TOSTOP attribute");
|
||||
} else {
|
||||
debug("%s: %s", "failed to set terminal TOSTOP attribute", strerror(errno));
|
||||
}
|
||||
#if HAVE_IPC
|
||||
/*
|
||||
* In "-c" mode with IPC, make all "pv -c" instances aware
|
||||
* that we set TOSTOP, so the last one can clear it on exit.
|
||||
*/
|
||||
if (pv_sig_state->cursor && (NULL != pv_sig_state->crs_shared) && (!pv_sig_state->crs_noipc)) {
|
||||
pv_sig_state->crs_shared->tty_tostop_added = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle SIGTTOU (tty output for background process) by redirecting stderr
|
||||
* to /dev/null, so that we can be stopped and backgrounded without messing
|
||||
@@ -25,20 +69,39 @@ static pvstate_t pv_sig_state = NULL;
|
||||
* subsequent SIGCONT we can try writing to the terminal again, in case we
|
||||
* get backgrounded and later get foregrounded again.
|
||||
*/
|
||||
static void pv_sig_ttou( __attribute__ ((unused))
|
||||
static void pv_sig_ttou( /*@unused@ */ __attribute__((unused))
|
||||
int s)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open("/dev/null", O_RDWR);
|
||||
if (fd < 0)
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
|
||||
fd = open("/dev/null", O_RDWR); /* flawfinder: ignore */
|
||||
if (fd < 0) {
|
||||
debug("%s: %s", "failed to open /dev/null", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* flawfinder rationale: not checking for symlinks because this is
|
||||
* explicitly a device file under /dev so we assume it is safe to
|
||||
* open.
|
||||
*
|
||||
* TODO: look at just preventing stderr output instead of writing to
|
||||
* stderr while backgrounded.
|
||||
*/
|
||||
|
||||
if (-1 == pv_sig_state->pv_sig_old_stderr)
|
||||
pv_sig_state->pv_sig_old_stderr = dup(STDERR_FILENO);
|
||||
|
||||
dup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
if (dup2(fd, STDERR_FILENO) < 0) {
|
||||
debug("%s: %s", "failed to replace stderr", strerror(errno));
|
||||
}
|
||||
|
||||
if (0 != close(fd)) {
|
||||
debug("%s: %s", "failed to close /dev/null", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,11 +109,15 @@ static void pv_sig_ttou( __attribute__ ((unused))
|
||||
* Handle SIGTSTP (stop typed at tty) by storing the time the signal
|
||||
* happened for later use by pv_sig_cont(), and then stopping the process.
|
||||
*/
|
||||
static void pv_sig_tstp( __attribute__ ((unused))
|
||||
static void pv_sig_tstp( /*@unused@ */ __attribute__((unused))
|
||||
int s)
|
||||
{
|
||||
gettimeofday(&(pv_sig_state->pv_sig_tstp_time), NULL);
|
||||
raise(SIGSTOP);
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
pv_elapsedtime_read(&(pv_sig_state->pv_sig_tstp_time));
|
||||
if (0 != raise(SIGSTOP)) {
|
||||
debug("%s: %s", "raise", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,51 +126,53 @@ static void pv_sig_tstp( __attribute__ ((unused))
|
||||
* last SIGTSTP to the elapsed time offset, and by trying to write to the
|
||||
* terminal again (by replacing the /dev/null stderr with the old stderr).
|
||||
*/
|
||||
static void pv_sig_cont( __attribute__ ((unused))
|
||||
static void pv_sig_cont( /*@unused@ */ __attribute__((unused))
|
||||
int s)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct termios t;
|
||||
struct timespec current_time;
|
||||
struct timespec time_spent_stopped;
|
||||
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
|
||||
pv_sig_state->pv_sig_newsize = 1;
|
||||
|
||||
if (0 == pv_sig_state->pv_sig_tstp_time.tv_sec) {
|
||||
tcgetattr(STDERR_FILENO, &t);
|
||||
t.c_lflag |= TOSTOP;
|
||||
tcsetattr(STDERR_FILENO, TCSANOW, &t);
|
||||
#ifdef HAVE_IPC
|
||||
pv_crs_needreinit(pv_sig_state);
|
||||
#endif
|
||||
return;
|
||||
/*
|
||||
* We can only make the time adjustments if this SIGCONT followed a
|
||||
* SIGTSTP such that we have a stop time.
|
||||
*/
|
||||
if (0 != pv_sig_state->pv_sig_tstp_time.tv_sec) {
|
||||
|
||||
memset(¤t_time, 0, sizeof(current_time));
|
||||
memset(&time_spent_stopped, 0, sizeof(time_spent_stopped));
|
||||
|
||||
pv_elapsedtime_read(¤t_time);
|
||||
|
||||
/* time spent stopped = current time - time SIGTSTP received */
|
||||
pv_elapsedtime_subtract(&time_spent_stopped, ¤t_time, &(pv_sig_state->pv_sig_tstp_time));
|
||||
|
||||
/* add time spent stopped the total stopped-time count */
|
||||
pv_elapsedtime_add(&(pv_sig_state->pv_sig_toffset), &(pv_sig_state->pv_sig_toffset),
|
||||
&time_spent_stopped);
|
||||
|
||||
/* reset the SIGTSTP receipt time */
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_tstp_time));
|
||||
}
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
pv_sig_state->pv_sig_toffset.tv_sec +=
|
||||
(tv.tv_sec - pv_sig_state->pv_sig_tstp_time.tv_sec);
|
||||
pv_sig_state->pv_sig_toffset.tv_usec +=
|
||||
(tv.tv_usec - pv_sig_state->pv_sig_tstp_time.tv_usec);
|
||||
if (pv_sig_state->pv_sig_toffset.tv_usec >= 1000000) {
|
||||
pv_sig_state->pv_sig_toffset.tv_sec++;
|
||||
pv_sig_state->pv_sig_toffset.tv_usec -= 1000000;
|
||||
}
|
||||
if (pv_sig_state->pv_sig_toffset.tv_usec < 0) {
|
||||
pv_sig_state->pv_sig_toffset.tv_sec--;
|
||||
pv_sig_state->pv_sig_toffset.tv_usec += 1000000;
|
||||
}
|
||||
|
||||
pv_sig_state->pv_sig_tstp_time.tv_sec = 0;
|
||||
pv_sig_state->pv_sig_tstp_time.tv_usec = 0;
|
||||
|
||||
/*
|
||||
* Restore the old stderr, if we had replaced it.
|
||||
*/
|
||||
if (pv_sig_state->pv_sig_old_stderr != -1) {
|
||||
dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO);
|
||||
close(pv_sig_state->pv_sig_old_stderr);
|
||||
if (dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO) < 0) {
|
||||
debug("%s: %s", "failed to restore old stderr", strerror(errno));
|
||||
}
|
||||
if (0 != close(pv_sig_state->pv_sig_old_stderr)) {
|
||||
debug("%s: %s", "failed to close duplicate old stderr", strerror(errno));
|
||||
}
|
||||
pv_sig_state->pv_sig_old_stderr = -1;
|
||||
}
|
||||
|
||||
tcgetattr(STDERR_FILENO, &t);
|
||||
t.c_lflag |= TOSTOP;
|
||||
tcsetattr(STDERR_FILENO, TCSANOW, &t);
|
||||
pv_sig_ensure_tty_tostop();
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
pv_crs_needreinit(pv_sig_state);
|
||||
@@ -111,22 +180,28 @@ static void pv_sig_cont( __attribute__ ((unused))
|
||||
}
|
||||
|
||||
|
||||
#ifdef SIGWINCH
|
||||
/*
|
||||
* Handle SIGWINCH (window size changed) by setting a flag.
|
||||
*/
|
||||
static void pv_sig_winch( __attribute__ ((unused))
|
||||
static void pv_sig_winch( /*@unused@ */ __attribute__((unused))
|
||||
int s)
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
pv_sig_state->pv_sig_newsize = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Handle termination signals by setting the abort flag.
|
||||
*/
|
||||
static void pv_sig_term( __attribute__ ((unused))
|
||||
static void pv_sig_term( /*@unused@ */ __attribute__((unused))
|
||||
int s)
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
pv_sig_state->pv_sig_abort = 1;
|
||||
}
|
||||
|
||||
@@ -136,42 +211,55 @@ static void pv_sig_term( __attribute__ ((unused))
|
||||
*/
|
||||
void pv_sig_init(pvstate_t state)
|
||||
{
|
||||
struct sigaction sa;
|
||||
static struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
/*
|
||||
* Note that wherever we use a "struct sigaction", we declare it
|
||||
* static and explicitly zero it before use, because it may contain
|
||||
* deeper structures (e.g. "sigset_t") which trigger splint
|
||||
* warnings about potential memory leaks.
|
||||
*/
|
||||
|
||||
pv_sig_state = state;
|
||||
|
||||
pv_sig_state->pv_sig_old_stderr = -1;
|
||||
pv_sig_state->pv_sig_tstp_time.tv_sec = 0;
|
||||
pv_sig_state->pv_sig_tstp_time.tv_usec = 0;
|
||||
pv_sig_state->pv_sig_toffset.tv_sec = 0;
|
||||
pv_sig_state->pv_sig_toffset.tv_usec = 0;
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_tstp_time));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_toffset));
|
||||
|
||||
/*
|
||||
* Note that we cast all sigemptyset() and sigaction() return values
|
||||
* to void, because there's nothing we can reasonably do about any
|
||||
* conceivable error they may return.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ignore SIGPIPE, so we don't die if stdout is a pipe and the other
|
||||
* end closes unexpectedly.
|
||||
*/
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGPIPE, &sa, &(pv_sig_state->pv_sig_old_sigpipe));
|
||||
(void) sigaction(SIGPIPE, &sa, &(pv_sig_state->pv_sig_old_sigpipe));
|
||||
|
||||
/*
|
||||
* Handle SIGTTOU by continuing with output switched off, so that we
|
||||
* can be stopped and backgrounded without messing up the terminal.
|
||||
*/
|
||||
sa.sa_handler = pv_sig_ttou;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGTTOU, &sa, &(pv_sig_state->pv_sig_old_sigttou));
|
||||
(void) sigaction(SIGTTOU, &sa, &(pv_sig_state->pv_sig_old_sigttou));
|
||||
|
||||
/*
|
||||
* Handle SIGTSTP by storing the time the signal happened for later
|
||||
* use by pv_sig_cont(), and then stopping the process.
|
||||
*/
|
||||
sa.sa_handler = pv_sig_tstp;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGTSTP, &sa, &(pv_sig_state->pv_sig_old_sigtstp));
|
||||
(void) sigaction(SIGTSTP, &sa, &(pv_sig_state->pv_sig_old_sigtstp));
|
||||
|
||||
/*
|
||||
* Handle SIGCONT by adding the elapsed time since the last SIGTSTP
|
||||
@@ -179,53 +267,116 @@ void pv_sig_init(pvstate_t state)
|
||||
* terminal again.
|
||||
*/
|
||||
sa.sa_handler = pv_sig_cont;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGCONT, &sa, &(pv_sig_state->pv_sig_old_sigcont));
|
||||
(void) sigaction(SIGCONT, &sa, &(pv_sig_state->pv_sig_old_sigcont));
|
||||
|
||||
/*
|
||||
* Handle SIGWINCH by setting a flag to let the main loop know it
|
||||
* has to reread the terminal size.
|
||||
*/
|
||||
#ifdef SIGWINCH
|
||||
sa.sa_handler = pv_sig_winch;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGWINCH, &sa, &(pv_sig_state->pv_sig_old_sigwinch));
|
||||
(void) sigaction(SIGWINCH, &sa, &(pv_sig_state->pv_sig_old_sigwinch));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle SIGINT, SIGHUP, SIGTERM by setting a flag to let the
|
||||
* main loop know it should quit now.
|
||||
*/
|
||||
sa.sa_handler = pv_sig_term;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGINT, &sa, &(pv_sig_state->pv_sig_old_sigint));
|
||||
(void) sigaction(SIGINT, &sa, &(pv_sig_state->pv_sig_old_sigint));
|
||||
|
||||
sa.sa_handler = pv_sig_term;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGHUP, &sa, &(pv_sig_state->pv_sig_old_sighup));
|
||||
(void) sigaction(SIGHUP, &sa, &(pv_sig_state->pv_sig_old_sighup));
|
||||
|
||||
sa.sa_handler = pv_sig_term;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGTERM, &sa, &(pv_sig_state->pv_sig_old_sigterm));
|
||||
(void) sigaction(SIGTERM, &sa, &(pv_sig_state->pv_sig_old_sigterm));
|
||||
|
||||
/*
|
||||
* Ensure that the TOSTOP terminal attribute is set, so that a
|
||||
* SIGTTOU signal will be raised if we try to write to the terminal
|
||||
* while backgrounded (see the SIGTTOU handler above).
|
||||
*/
|
||||
pv_sig_ensure_tty_tostop();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Shut down signal handling.
|
||||
* Shut down signal handling. If we had set the TOSTOP terminal attribute,
|
||||
* and we're in the foreground, also turn that off (though if we're in
|
||||
* cursor "-c" mode, only do that if we're the last PV instance, otherwise
|
||||
* leave the terminal alone).
|
||||
*/
|
||||
void pv_sig_fini( __attribute__ ((unused)) pvstate_t state)
|
||||
void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
{
|
||||
sigaction(SIGPIPE, &(pv_sig_state->pv_sig_old_sigpipe), NULL);
|
||||
sigaction(SIGTTOU, &(pv_sig_state->pv_sig_old_sigttou), NULL);
|
||||
sigaction(SIGTSTP, &(pv_sig_state->pv_sig_old_sigtstp), NULL);
|
||||
sigaction(SIGCONT, &(pv_sig_state->pv_sig_old_sigcont), NULL);
|
||||
sigaction(SIGWINCH, &(pv_sig_state->pv_sig_old_sigwinch), NULL);
|
||||
sigaction(SIGINT, &(pv_sig_state->pv_sig_old_sigint), NULL);
|
||||
sigaction(SIGHUP, &(pv_sig_state->pv_sig_old_sighup), NULL);
|
||||
sigaction(SIGTERM, &(pv_sig_state->pv_sig_old_sigterm), NULL);
|
||||
bool need_to_clear_tostop = false;
|
||||
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
|
||||
(void) sigaction(SIGPIPE, &(pv_sig_state->pv_sig_old_sigpipe), NULL);
|
||||
(void) sigaction(SIGTTOU, &(pv_sig_state->pv_sig_old_sigttou), NULL);
|
||||
(void) sigaction(SIGTSTP, &(pv_sig_state->pv_sig_old_sigtstp), NULL);
|
||||
(void) sigaction(SIGCONT, &(pv_sig_state->pv_sig_old_sigcont), NULL);
|
||||
#ifdef SIGWINCH
|
||||
(void) sigaction(SIGWINCH, &(pv_sig_state->pv_sig_old_sigwinch), NULL);
|
||||
#endif
|
||||
(void) sigaction(SIGINT, &(pv_sig_state->pv_sig_old_sigint), NULL);
|
||||
(void) sigaction(SIGHUP, &(pv_sig_state->pv_sig_old_sighup), NULL);
|
||||
(void) sigaction(SIGTERM, &(pv_sig_state->pv_sig_old_sigterm), NULL);
|
||||
|
||||
need_to_clear_tostop = pv_sig_state->pv_tty_tostop_added;
|
||||
|
||||
if (pv_sig_state->cursor) {
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
* We won't clear TOSTOP if other "pv -c" instances
|
||||
* were still running when pv_crs_fini() ran.
|
||||
*
|
||||
* TODO: we need a better way to determine if we're the last
|
||||
* "pv" left.
|
||||
*/
|
||||
if (pv_sig_state->cursor && pv_sig_state->crs_pvcount > 1) {
|
||||
need_to_clear_tostop = false;
|
||||
}
|
||||
#else /* !HAVE_IPC */
|
||||
/*
|
||||
* Without IPC we can't tell whether the other "pv -c"
|
||||
* instances in the pipeline have finished so we will just
|
||||
* have to clear TOSTOP anyway.
|
||||
*/
|
||||
#endif /* !HAVE_IPC */
|
||||
}
|
||||
|
||||
debug("%s=%s", "need_to_clear_tostop", need_to_clear_tostop ? "true" : "false");
|
||||
|
||||
if (need_to_clear_tostop && pv_in_foreground()) {
|
||||
struct termios terminal_attributes;
|
||||
|
||||
debug("%s", "about to to clear TOSTOP terminal attribute if it is set");
|
||||
|
||||
if (0 != tcgetattr(STDERR_FILENO, &terminal_attributes)) {
|
||||
debug("%s: %s", "tcgetattr", strerror(errno));
|
||||
} else if (0 != (terminal_attributes.c_lflag & TOSTOP)) {
|
||||
terminal_attributes.c_lflag -= TOSTOP;
|
||||
if (0 == tcsetattr(STDERR_FILENO, TCSANOW, &terminal_attributes)) {
|
||||
debug("%s", "cleared TOSTOP terminal attribute");
|
||||
} else {
|
||||
debug("%s: %s", "failed to clear TOSTOP terminal attribute", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
pv_sig_state->pv_tty_tostop_added = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -234,17 +385,19 @@ void pv_sig_fini( __attribute__ ((unused)) pvstate_t state)
|
||||
*/
|
||||
void pv_sig_nopause(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
static struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGTSTP, &sa, NULL);
|
||||
(void) sigaction(SIGTSTP, &sa, NULL);
|
||||
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGCONT, &sa, NULL);
|
||||
(void) sigaction(SIGCONT, &sa, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -253,17 +406,19 @@ void pv_sig_nopause(void)
|
||||
*/
|
||||
void pv_sig_allowpause(void)
|
||||
{
|
||||
struct sigaction sa;
|
||||
static struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
sa.sa_handler = pv_sig_tstp;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGTSTP, &sa, NULL);
|
||||
(void) sigaction(SIGTSTP, &sa, NULL);
|
||||
|
||||
sa.sa_handler = pv_sig_cont;
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGCONT, &sa, NULL);
|
||||
(void) sigaction(SIGCONT, &sa, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -276,7 +431,9 @@ void pv_sig_allowpause(void)
|
||||
void pv_sig_checkbg(void)
|
||||
{
|
||||
static time_t next_check = 0;
|
||||
struct termios t;
|
||||
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
|
||||
if (time(NULL) < next_check)
|
||||
return;
|
||||
@@ -286,14 +443,17 @@ void pv_sig_checkbg(void)
|
||||
if (-1 == pv_sig_state->pv_sig_old_stderr)
|
||||
return;
|
||||
|
||||
dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO);
|
||||
close(pv_sig_state->pv_sig_old_stderr);
|
||||
if (dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO) < 0) {
|
||||
debug("%s: %s", "failed to restore old stderr", strerror(errno));
|
||||
}
|
||||
|
||||
if (0 != close(pv_sig_state->pv_sig_old_stderr)) {
|
||||
debug("%s: %s", "failed to close duplicate old stderr", strerror(errno));
|
||||
}
|
||||
|
||||
pv_sig_state->pv_sig_old_stderr = -1;
|
||||
|
||||
tcgetattr(STDERR_FILENO, &t);
|
||||
t.c_lflag |= TOSTOP;
|
||||
tcsetattr(STDERR_FILENO, TCSANOW, &t);
|
||||
|
||||
pv_sig_ensure_tty_tostop();
|
||||
#ifdef HAVE_IPC
|
||||
pv_crs_needreinit(pv_sig_state);
|
||||
#endif
|
||||
|
||||
+239
-58
@@ -1,14 +1,47 @@
|
||||
/*
|
||||
* State management functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/* alloc / realloc history buffer */
|
||||
static void pv_alloc_history(pvstate_t state)
|
||||
{
|
||||
if (NULL != state->history)
|
||||
free(state->history);
|
||||
state->history = NULL;
|
||||
|
||||
state->history = calloc((size_t) (state->history_len), sizeof(state->history[0]));
|
||||
if (NULL == state->history) {
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory
|
||||
* leak warnings, but in this case it's unavoidable, and
|
||||
* mitigated by the fact we only translate each string once.
|
||||
*/
|
||||
fprintf(stderr, "%s: %s: %s\n", state->program_name,
|
||||
_("history structure allocation failed"), strerror(errno));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
|
||||
state->history_first = state->history_last = 0;
|
||||
state->history[0].elapsed_sec = 0.0; /* to be safe, memset() not recommended for doubles */
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new state structure, and return it, or 0 (NULL) on error.
|
||||
*/
|
||||
@@ -19,8 +52,19 @@ pvstate_t pv_state_alloc(const char *program_name)
|
||||
state = calloc(1, sizeof(*state));
|
||||
if (NULL == state)
|
||||
return NULL;
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
/* splint 3.1.2 thinks this is required for some reason. */
|
||||
if (NULL != state->program_name) {
|
||||
free(state->program_name);
|
||||
}
|
||||
|
||||
state->program_name = pv_strdup(program_name);
|
||||
if (NULL == state->program_name) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->program_name = program_name;
|
||||
state->watch_pid = 0;
|
||||
state->watch_fd = -1;
|
||||
#ifdef HAVE_IPC
|
||||
@@ -30,12 +74,26 @@ pvstate_t pv_state_alloc(const char *program_name)
|
||||
state->crs_lock_fd = -1;
|
||||
|
||||
state->reparse_display = 1;
|
||||
state->current_file = _("none");
|
||||
state->current_input_file = -1;
|
||||
#ifdef HAVE_SPLICE
|
||||
state->splice_failed_fd = -1;
|
||||
#endif /* HAVE_SPLICE */
|
||||
state->display_visible = false;
|
||||
|
||||
/*
|
||||
* Get the current working directory, if possible, as a base for
|
||||
* showing relative filenames with --watchfd.
|
||||
*/
|
||||
if (NULL == getcwd(state->cwd, PV_SIZEOF_CWD - 1)) {
|
||||
/* failed - will always show full path */
|
||||
state->cwd[0] = '\0';
|
||||
}
|
||||
if ('\0' == state->cwd[1]) {
|
||||
/* CWD is root directory - always show full path */
|
||||
state->cwd[0] = '\0';
|
||||
}
|
||||
state->cwd[PV_SIZEOF_CWD - 1] = '\0';
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -48,13 +106,46 @@ void pv_state_free(pvstate_t state)
|
||||
if (0 == state)
|
||||
return;
|
||||
|
||||
if (state->display_buffer)
|
||||
if (NULL != state->program_name)
|
||||
free(state->program_name);
|
||||
state->program_name = NULL;
|
||||
|
||||
if (NULL != state->display_buffer)
|
||||
free(state->display_buffer);
|
||||
state->display_buffer = NULL;
|
||||
|
||||
if (state->transfer_buffer)
|
||||
if (NULL != state->name) {
|
||||
free(state->name);
|
||||
state->name = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->format_string) {
|
||||
free(state->format_string);
|
||||
state->format_string = NULL;
|
||||
}
|
||||
|
||||
/*@-keeptrans@ */
|
||||
if (NULL != state->transfer_buffer)
|
||||
free(state->transfer_buffer);
|
||||
state->transfer_buffer = NULL;
|
||||
/*@+keeptrans@ */
|
||||
/* splint - explicitly freeing this structure, so free() here is OK. */
|
||||
|
||||
if (NULL != state->history)
|
||||
free(state->history);
|
||||
state->history = NULL;
|
||||
|
||||
if (NULL != state->input_files) {
|
||||
unsigned int file_idx;
|
||||
for (file_idx = 0; file_idx < state->input_file_count; file_idx++) {
|
||||
/*@-unqualifiedtrans@ */
|
||||
free(state->input_files[file_idx]);
|
||||
/*@+unqualifiedtrans@ */
|
||||
/* splint: see similar code below. */
|
||||
}
|
||||
free(state->input_files);
|
||||
state->input_files = NULL;
|
||||
}
|
||||
|
||||
free(state);
|
||||
|
||||
@@ -65,17 +156,13 @@ void pv_state_free(pvstate_t state)
|
||||
/*
|
||||
* Set the formatting string, given a set of old-style formatting options.
|
||||
*/
|
||||
void pv_state_set_format(pvstate_t state, bool progress,
|
||||
bool timer, bool eta,
|
||||
bool fineta, bool rate,
|
||||
bool average_rate, bool bytes,
|
||||
bool bufpercent,
|
||||
unsigned int lastwritten, const char *name)
|
||||
void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, bool fineta, bool rate, bool average_rate, bool bytes, bool bufpercent, size_t lastwritten, /*@null@ */
|
||||
const char *name)
|
||||
{
|
||||
#define PV_ADDFORMAT(x,y) if (x) { \
|
||||
if (state->default_format[0] != '\0') \
|
||||
strcat(state->default_format, " "); \
|
||||
strcat(state->default_format, y); \
|
||||
(void) pv_strlcat(state->default_format, " ", sizeof(state->default_format)); \
|
||||
(void) pv_strlcat(state->default_format, y, sizeof(state->default_format)); \
|
||||
}
|
||||
|
||||
state->default_format[0] = '\0';
|
||||
@@ -89,18 +176,25 @@ void pv_state_set_format(pvstate_t state, bool progress,
|
||||
PV_ADDFORMAT(eta, "%e");
|
||||
PV_ADDFORMAT(fineta, "%I");
|
||||
if (lastwritten > 0) {
|
||||
char buf[16];
|
||||
char buf[16]; /* flawfinder: ignore */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
#ifdef HAVE_SNPRINTF
|
||||
(void) snprintf(buf, sizeof(buf) - 1, "%%%uA",
|
||||
lastwritten);
|
||||
#else
|
||||
(void) sprintf(buf, "%%%uA", lastwritten);
|
||||
#endif
|
||||
(void) pv_snprintf(buf, sizeof(buf), "%%%uA", (unsigned int) lastwritten);
|
||||
PV_ADDFORMAT(lastwritten > 0, buf);
|
||||
/*
|
||||
* flawfinder rationale: large enough for string, zeroed
|
||||
* before use, only written to by pv_snprintf() with the
|
||||
* right buffer length.
|
||||
*/
|
||||
}
|
||||
|
||||
state->name = name;
|
||||
if (NULL != state->name) {
|
||||
free(state->name);
|
||||
state->name = NULL;
|
||||
}
|
||||
|
||||
if (NULL != name)
|
||||
state->name = pv_strdup(name);
|
||||
|
||||
state->reparse_display = 1;
|
||||
}
|
||||
|
||||
@@ -113,113 +207,200 @@ void pv_state_force_set(pvstate_t state, bool val)
|
||||
void pv_state_cursor_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->cursor = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_numeric_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->numeric = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_wait_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->wait = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_delay_start_set(pvstate_t state, double val)
|
||||
{
|
||||
state->delay_start = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_linemode_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->linemode = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_null_set(pvstate_t state, bool val)
|
||||
void pv_state_bits_set(pvstate_t state, bool bits)
|
||||
{
|
||||
state->null = val;
|
||||
};
|
||||
state->bits = bits;
|
||||
}
|
||||
|
||||
void pv_state_no_op_set(pvstate_t state, bool val)
|
||||
void pv_state_null_terminated_lines_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->no_op = val;
|
||||
};
|
||||
state->null_terminated_lines = val;
|
||||
}
|
||||
|
||||
void pv_state_no_display_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->no_display = val;
|
||||
}
|
||||
|
||||
void pv_state_skip_errors_set(pvstate_t state, unsigned int val)
|
||||
{
|
||||
state->skip_errors = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_error_skip_block_set(pvstate_t state, off_t val)
|
||||
{
|
||||
state->error_skip_block = val;
|
||||
}
|
||||
|
||||
void pv_state_stop_at_size_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->stop_at_size = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_rate_limit_set(pvstate_t state, unsigned long long val)
|
||||
void pv_state_sync_after_write_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->sync_after_write = val;
|
||||
}
|
||||
|
||||
void pv_state_direct_io_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->direct_io = val;
|
||||
state->direct_io_changed = true;
|
||||
}
|
||||
|
||||
void pv_state_discard_input_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->discard_input = val;
|
||||
}
|
||||
|
||||
void pv_state_rate_limit_set(pvstate_t state, off_t val)
|
||||
{
|
||||
state->rate_limit = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_target_buffer_size_set(pvstate_t state,
|
||||
unsigned long long val)
|
||||
void pv_state_target_buffer_size_set(pvstate_t state, size_t val)
|
||||
{
|
||||
state->target_buffer_size = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_no_splice_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->no_splice = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_size_set(pvstate_t state, unsigned long long val)
|
||||
void pv_state_size_set(pvstate_t state, off_t val)
|
||||
{
|
||||
state->size = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_interval_set(pvstate_t state, double val)
|
||||
{
|
||||
state->interval = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_width_set(pvstate_t state, unsigned int val)
|
||||
void pv_state_width_set(pvstate_t state, unsigned int val, bool was_set_manually)
|
||||
{
|
||||
state->width = val;
|
||||
};
|
||||
state->width_set_manually = was_set_manually;
|
||||
}
|
||||
|
||||
void pv_state_height_set(pvstate_t state, unsigned int val)
|
||||
void pv_state_height_set(pvstate_t state, unsigned int val, bool was_set_manually)
|
||||
{
|
||||
state->height = val;
|
||||
};
|
||||
state->height_set_manually = was_set_manually;
|
||||
}
|
||||
|
||||
void pv_state_name_set(pvstate_t state, const char *val)
|
||||
void pv_state_name_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
{
|
||||
state->name = val;
|
||||
};
|
||||
if (NULL != state->name) {
|
||||
free(state->name);
|
||||
state->name = NULL;
|
||||
}
|
||||
if (NULL != val)
|
||||
state->name = pv_strdup(val);
|
||||
}
|
||||
|
||||
void pv_state_format_string_set(pvstate_t state, const char *val)
|
||||
void pv_state_format_string_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
{
|
||||
state->format_string = val;
|
||||
};
|
||||
if (NULL != state->format_string) {
|
||||
free(state->format_string);
|
||||
state->format_string = NULL;
|
||||
}
|
||||
if (NULL != val)
|
||||
state->format_string = pv_strdup(val);
|
||||
}
|
||||
|
||||
void pv_state_watch_pid_set(pvstate_t state, unsigned int val)
|
||||
void pv_state_watch_pid_set(pvstate_t state, pid_t val)
|
||||
{
|
||||
state->watch_pid = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_watch_fd_set(pvstate_t state, int val)
|
||||
{
|
||||
state->watch_fd = val;
|
||||
};
|
||||
}
|
||||
|
||||
void pv_state_average_rate_window_set(pvstate_t state, unsigned int val)
|
||||
{
|
||||
if (val < 1)
|
||||
val = 1;
|
||||
if (val >= 20) {
|
||||
state->history_len = val / 5 + 1;
|
||||
state->history_interval = 5;
|
||||
} else {
|
||||
state->history_len = val + 1;
|
||||
state->history_interval = 1;
|
||||
}
|
||||
pv_alloc_history(state);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the array of input files.
|
||||
*/
|
||||
void pv_state_inputfiles(pvstate_t state, int input_file_count,
|
||||
const char **input_files)
|
||||
void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const char **input_files)
|
||||
{
|
||||
unsigned int file_idx;
|
||||
|
||||
if (NULL != state->input_files) {
|
||||
for (file_idx = 0; file_idx < state->input_file_count; file_idx++) {
|
||||
/*@-unqualifiedtrans@ */
|
||||
free(state->input_files[file_idx]);
|
||||
/*@+unqualifiedtrans@ */
|
||||
/*
|
||||
* TODO: find a way to tell splint the array
|
||||
* contents are "only" and "null" as well as the
|
||||
* array itself.
|
||||
*/
|
||||
}
|
||||
free(state->input_files);
|
||||
state->input_files = NULL;
|
||||
state->input_file_count = 0;
|
||||
}
|
||||
state->input_files = calloc((size_t) (input_file_count + 1), sizeof(char *));
|
||||
if (NULL == state->input_files) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
fprintf(stderr, "%s: %s: %s\n", state->program_name, _("file list allocation failed"), strerror(errno));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
for (file_idx = 0; file_idx < input_file_count; file_idx++) {
|
||||
/*@-nullstate@ */
|
||||
state->input_files[file_idx] = pv_strdup(input_files[file_idx]);
|
||||
if (NULL == state->input_files[file_idx]) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
fprintf(stderr, "%s: %s: %s\n", state->program_name,
|
||||
_("file list allocation failed"), strerror(errno));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
}
|
||||
state->input_file_count = input_file_count;
|
||||
state->input_files = input_files;
|
||||
}
|
||||
|
||||
/*@+nullstate@*/
|
||||
/* splint: see unqualifiedtrans note by free() above. */
|
||||
|
||||
/* EOF */
|
||||
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Functions for portably managing strings.
|
||||
*
|
||||
* Copyright 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/*
|
||||
* Wrapper for sprintf(), falling back to sprintf() on systems without that
|
||||
* function.
|
||||
*
|
||||
* Returns -1 if "str" or "format" are NULL or if "size" is 0.
|
||||
*
|
||||
* Otherwise, ensures that the buffer "str" is always terminated with a '\0'
|
||||
* byte, before returning whatever the system's vsnprintf() or vsprintf()
|
||||
* returned.
|
||||
*/
|
||||
int pv_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
if (NULL == str)
|
||||
return -1;
|
||||
if (0 == size)
|
||||
return -1;
|
||||
if (NULL == format)
|
||||
return -1;
|
||||
|
||||
str[0] = '\0';
|
||||
|
||||
va_start(ap, format);
|
||||
#ifdef HAVE_VSNPRINTF
|
||||
ret = vsnprintf(str, size, format, ap); /* flawfinder: ignore */
|
||||
#else /* ! HAVE_VSNPRINTF */
|
||||
ret = vsprintf(str, format, ap); /* flawfinder: ignore */
|
||||
#endif /* HAVE_VSNPRINTF */
|
||||
va_end(ap);
|
||||
|
||||
str[size - 1] = '\0';
|
||||
|
||||
/*
|
||||
* flawfinder rationale: this function replaces snprintf so
|
||||
* explicitly takes a non-constant format; also it explicitly
|
||||
* \0-terminates the output buffer, as flawfinder warns that some
|
||||
* sprintf() variants do not.
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of strlcat() where it is unavailable: append a string to a
|
||||
* buffer, constraining the buffer to a particular size and ensuring
|
||||
* termination with '\0'.
|
||||
*
|
||||
* Appends the string "src" to the buffer "dst", assuming "dst" is "dstsize"
|
||||
* bytes long, and ensuring that "dst" is always terminated with a '\0'
|
||||
* byte.
|
||||
*
|
||||
* Returns the intended length of the string, not including the terminating
|
||||
* '\0', i.e. strlen(src)+strlen(dst), regardless of whether truncation
|
||||
* occurred.
|
||||
*
|
||||
* Note that this implementation has the side effect that "dst" will always
|
||||
* be terminated with a '\0' even if "src" was zero bytes long.
|
||||
*/
|
||||
size_t pv_strlcat(char *dst, const char *src, size_t dstsize)
|
||||
{
|
||||
#ifdef HAVE_STRLCAT
|
||||
size_t result;
|
||||
|
||||
result = strlcat(dst, src, dstsize);
|
||||
|
||||
if ((NULL != dst) && (dstsize > 0))
|
||||
dst[dstsize - 1] = '\0';
|
||||
|
||||
return result;
|
||||
#else
|
||||
size_t dstlen, srclen, available;
|
||||
|
||||
if (NULL == dst)
|
||||
return 0;
|
||||
if (NULL == src)
|
||||
return 0;
|
||||
if (0 == dstsize)
|
||||
return 0;
|
||||
|
||||
dst[dstsize - 1] = '\0';
|
||||
dstlen = strlen(dst); /* flawfinder: ignore */
|
||||
srclen = strlen(src); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: src must explicitly be \0 terminated, so
|
||||
* this is up to the caller; with dst, we enforce \0 termination
|
||||
* before calling strlen().
|
||||
*/
|
||||
|
||||
available = dstsize - dstlen;
|
||||
if (available > 1)
|
||||
(void) pv_snprintf(dst + dstlen, available, "%.*s", available - 1, src);
|
||||
|
||||
return dstlen + srclen;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate and return a duplicate of a \0-terminated string, ensuring that
|
||||
* the duplicate is also \0-terminated. Returns NULL on error.
|
||||
*/
|
||||
/*@null@ */
|
||||
/*@only@ */
|
||||
char *pv_strdup(const char *original)
|
||||
{
|
||||
size_t length;
|
||||
char *duplicate;
|
||||
|
||||
if (NULL == original) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length = strlen(original); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: the original string is explicitly required
|
||||
* to be \0 terminated.
|
||||
*/
|
||||
duplicate = calloc(1, 1 + length);
|
||||
if (NULL == duplicate)
|
||||
return NULL;
|
||||
|
||||
memcpy(duplicate, original, length); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: the buffer is explicitly allocated to be
|
||||
* large enough.
|
||||
*/
|
||||
|
||||
duplicate[length] = '\0';
|
||||
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
+472
-263
File diff suppressed because it is too large
Load Diff
+233
-128
@@ -1,7 +1,13 @@
|
||||
/*
|
||||
* Functions for watching file descriptors in other processes.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -20,6 +26,89 @@
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <libproc.h>
|
||||
#include <sys/proc_info.h>
|
||||
#endif
|
||||
|
||||
int filesize(pvwatchfd_t info)
|
||||
{
|
||||
if (S_ISBLK(info->sb_fd.st_mode)) {
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Get the size of block devices by opening
|
||||
* them and seeking to the end.
|
||||
*/
|
||||
fd = open(info->file_fdpath, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
info->size = lseek(fd, 0, SEEK_END);
|
||||
close(fd);
|
||||
} else {
|
||||
info->size = 0;
|
||||
}
|
||||
} else if (S_ISREG(info->sb_fd.st_mode)) {
|
||||
if ((info->sb_fd_link.st_mode & S_IWUSR) == 0) {
|
||||
info->size = info->sb_fd.st_size;
|
||||
}
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
{
|
||||
struct vnode_fdinfowithpath vnodeInfo = { };
|
||||
|
||||
if (NULL == state)
|
||||
return -1;
|
||||
if (NULL == info)
|
||||
return -1;
|
||||
|
||||
if (kill(info->watch_pid, 0) != 0) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s", _("pid"), info->watch_pid, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t proc_fd = (int32_t) info->watch_fd;
|
||||
int size = proc_pidfdinfo(info->watch_pid, proc_fd,
|
||||
PROC_PIDFDVNODEPATHINFO, &vnodeInfo,
|
||||
PROC_PIDFDVNODEPATHINFO_SIZE);
|
||||
if (size != PROC_PIDFDVNODEPATHINFO_SIZE) {
|
||||
pv_error(state, "%s %u: %s %d: %s",
|
||||
_("pid"), info->watch_pid, _("fd"), info->watch_fd, strerror(errno));
|
||||
return 3;
|
||||
}
|
||||
|
||||
strlcpy(info->file_fdpath, vnodeInfo.pvip.vip_path, PV_SIZEOF_FILE_FDPATH);
|
||||
|
||||
info->size = 0;
|
||||
|
||||
if (!(0 == stat(info->file_fdpath, &(info->sb_fd)))) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s %d: %s: %s",
|
||||
_("pid"),
|
||||
info->watch_pid, _("fd"), info->watch_fd, info->file_fdpath, strerror(errno));
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (filesize(info) != 0) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s %d: %s: %s",
|
||||
_("pid"),
|
||||
info->watch_pid,
|
||||
_("fd"), info->watch_fd, info->file_fdpath, _("not a regular file or block device"));
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Fill in the given information structure with the file paths and stat
|
||||
@@ -34,11 +123,11 @@
|
||||
* 3 - stat or lstat on /proc/pid/fd/N failed
|
||||
* 4 - file descriptor is not opened on a regular file
|
||||
*
|
||||
* If "automatic" is nonzero, then this fd was picked automatically, and so
|
||||
* if it's not readable or not a regular file, no error is displayed and the
|
||||
* If "automatic" is true, then this fd was picked automatically, and so if
|
||||
* it's not readable or not a regular file, no error is displayed and the
|
||||
* function just returns an error code.
|
||||
*/
|
||||
int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, int automatic)
|
||||
int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
{
|
||||
if (NULL == state)
|
||||
return -1;
|
||||
@@ -47,94 +136,62 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, int automatic)
|
||||
|
||||
if (kill(info->watch_pid, 0) != 0) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s",
|
||||
_("pid"),
|
||||
info->watch_pid, strerror(errno));
|
||||
pv_error(state, "%s %u: %s", _("pid"), info->watch_pid, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(info->file_fdinfo, sizeof(info->file_fdinfo) - 1,
|
||||
#else
|
||||
sprintf(info->file_fdinfo,
|
||||
#endif
|
||||
"/proc/%u/fdinfo/%d", info->watch_pid, info->watch_fd);
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(info->file_fd, sizeof(info->file_fd) - 1,
|
||||
#else
|
||||
sprintf(info->file_fd,
|
||||
#endif
|
||||
"/proc/%u/fd/%d", info->watch_pid, info->watch_fd);
|
||||
(void) pv_snprintf(info->file_fdinfo, PV_SIZEOF_FILE_FDINFO,
|
||||
"/proc/%u/fdinfo/%d", info->watch_pid, info->watch_fd);
|
||||
(void) pv_snprintf(info->file_fd, PV_SIZEOF_FILE_FD, "/proc/%u/fd/%d", info->watch_pid, info->watch_fd);
|
||||
|
||||
memset(info->file_fdpath, 0, sizeof(info->file_fdpath));
|
||||
if (readlink
|
||||
(info->file_fd, info->file_fdpath,
|
||||
sizeof(info->file_fdpath) - 1) < 0) {
|
||||
memset(info->file_fdpath, 0, PV_SIZEOF_FILE_FDPATH);
|
||||
if (readlink(info->file_fd, info->file_fdpath, PV_SIZEOF_FILE_FDPATH - 1) < 0) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s %d: %s",
|
||||
_("pid"),
|
||||
info->watch_pid,
|
||||
_("fd"), info->watch_fd, strerror(errno));
|
||||
_("pid"), info->watch_pid, _("fd"), info->watch_fd, strerror(errno));
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!((0 == stat64(info->file_fd, &(info->sb_fd)))
|
||||
&& (0 == lstat64(info->file_fd, &(info->sb_fd_link))))) {
|
||||
if (!((0 == stat(info->file_fd, &(info->sb_fd)))
|
||||
&& (0 == lstat(info->file_fd, &(info->sb_fd_link))))) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s %d: %s: %s",
|
||||
_("pid"),
|
||||
info->watch_pid,
|
||||
_("fd"),
|
||||
info->watch_fd, info->file_fdpath,
|
||||
strerror(errno));
|
||||
info->watch_pid, _("fd"), info->watch_fd, info->file_fdpath, strerror(errno));
|
||||
return 3;
|
||||
}
|
||||
|
||||
info->size = 0;
|
||||
|
||||
if (S_ISBLK(info->sb_fd.st_mode)) {
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Get the size of block devices by opening
|
||||
* them and seeking to the end.
|
||||
*/
|
||||
fd = open64(info->file_fdpath, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
info->size = lseek64(fd, 0, SEEK_END);
|
||||
close(fd);
|
||||
} else {
|
||||
info->size = 0;
|
||||
}
|
||||
} else if (S_ISREG(info->sb_fd.st_mode)) {
|
||||
if ((info->sb_fd_link.st_mode & S_IWUSR) == 0) {
|
||||
info->size = info->sb_fd.st_size;
|
||||
}
|
||||
} else {
|
||||
int ret = filesize(info);
|
||||
if (ret != 0) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s %d: %s: %s",
|
||||
_("pid"),
|
||||
info->watch_pid,
|
||||
_("fd"),
|
||||
info->watch_fd,
|
||||
info->file_fdpath,
|
||||
_("not a regular file or block device"));
|
||||
return 4;
|
||||
_("fd"), info->watch_fd, info->file_fdpath, _("not a regular file or block device"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
int pv_watchfd_changed(pvwatchfd_t info)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Return nonzero if the given file descriptor has changed in some way since
|
||||
* we started looking at it (i.e. changed destination or permissions).
|
||||
*/
|
||||
int pv_watchfd_changed(pvwatchfd_t info)
|
||||
{
|
||||
struct stat64 sb_fd, sb_fd_link;
|
||||
struct stat sb_fd, sb_fd_link;
|
||||
|
||||
if ((0 == stat64(info->file_fd, &sb_fd))
|
||||
&& (0 == lstat64(info->file_fd, &sb_fd_link))) {
|
||||
if ((0 == stat(info->file_fd, &sb_fd))
|
||||
&& (0 == lstat(info->file_fd, &sb_fd_link))) {
|
||||
if ((sb_fd.st_dev != info->sb_fd.st_dev)
|
||||
|| (sb_fd.st_ino != info->sb_fd.st_ino)
|
||||
|| (sb_fd_link.st_mode != info->sb_fd_link.st_mode)
|
||||
@@ -147,15 +204,30 @@ int pv_watchfd_changed(pvwatchfd_t info)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Return the current file position of the given file descriptor, or -1 if
|
||||
* the fd has closed or has changed in some way.
|
||||
*/
|
||||
long long pv_watchfd_position(pvwatchfd_t info)
|
||||
off_t pv_watchfd_position(pvwatchfd_t info)
|
||||
{
|
||||
long long position;
|
||||
off_t position;
|
||||
unsigned long long pos_long;
|
||||
#ifdef __APPLE__
|
||||
struct vnode_fdinfowithpath vnodeInfo = { };
|
||||
int32_t proc_fd = (int32_t) info->watch_fd;
|
||||
|
||||
int size = proc_pidfdinfo(info->watch_pid, proc_fd,
|
||||
PROC_PIDFDVNODEPATHINFO, &vnodeInfo,
|
||||
PROC_PIDFDVNODEPATHINFO_SIZE);
|
||||
if (size != PROC_PIDFDVNODEPATHINFO_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
position = (off_t) vnodeInfo.pfi.fi_offset;
|
||||
#else
|
||||
FILE *fptr;
|
||||
|
||||
if (pv_watchfd_changed(info))
|
||||
@@ -164,14 +236,40 @@ long long pv_watchfd_position(pvwatchfd_t info)
|
||||
fptr = fopen(info->file_fdinfo, "r");
|
||||
if (NULL == fptr)
|
||||
return -1;
|
||||
pos_long = -1;
|
||||
position = -1;
|
||||
fscanf(fptr, "pos: %llu", &position);
|
||||
if (1 == fscanf(fptr, "pos: %llu", &pos_long))
|
||||
position = (off_t) pos_long;
|
||||
fclose(fptr);
|
||||
#endif
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
static int pidfds(pvstate_t state, unsigned int pid, struct proc_fdinfo **fds, int *count)
|
||||
{
|
||||
int size_needed = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, 0, 0);
|
||||
if (size_needed == -1) {
|
||||
pv_error(state, "%s: unable to list pid fds: %s", _("pid"), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
*count = size_needed / PROC_PIDLISTFD_SIZE;
|
||||
|
||||
*fds = (struct proc_fdinfo *) malloc(size_needed);
|
||||
if (*fds == NULL) {
|
||||
pv_error(state, "%s: alloc failed: %s", _("pid"), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
proc_pidinfo(pid, PROC_PIDLISTFDS, 0, *fds, size_needed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Scan the given process and update the arrays with any new file
|
||||
* descriptors.
|
||||
@@ -181,39 +279,57 @@ long long pv_watchfd_position(pvwatchfd_t info)
|
||||
*/
|
||||
int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
unsigned int watch_pid, int *array_length_ptr,
|
||||
pvwatchfd_t * info_array_ptr,
|
||||
pvstate_t * state_array_ptr, int *fd_to_idx)
|
||||
pvwatchfd_t * info_array_ptr, pvstate_t * state_array_ptr, int *fd_to_idx)
|
||||
{
|
||||
char fd_dir[512] = { 0, };
|
||||
DIR *dptr;
|
||||
struct dirent *d;
|
||||
int array_length = 0;
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
struct pvstate_s *state_array = NULL;
|
||||
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(fd_dir, sizeof(fd_dir) - 1, "/proc/%u/fd", watch_pid);
|
||||
#ifdef __APPLE__
|
||||
struct proc_fdinfo *fd_infos = NULL;
|
||||
int fd_infos_count = 0;
|
||||
|
||||
if (pidfds(state, watch_pid, &fd_infos, &fd_infos_count) != 0) {
|
||||
pv_error(state, "%s: pidfds failed", _("pid"));
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
sprintf(fd_dir, "/proc/%u/fd", watch_pid);
|
||||
#endif
|
||||
DIR *dptr;
|
||||
struct dirent *d;
|
||||
|
||||
(void) pv_snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", watch_pid);
|
||||
|
||||
dptr = opendir(fd_dir);
|
||||
if (NULL == dptr)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
array_length = *array_length_ptr;
|
||||
info_array = *info_array_ptr;
|
||||
state_array = *state_array_ptr;
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (fd_infos_count < 1) {
|
||||
pv_error(state, "%s: no fds found", _("pid"));
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < fd_infos_count; i++) {
|
||||
#else
|
||||
while ((d = readdir(dptr)) != NULL) {
|
||||
#endif
|
||||
int fd, check_idx, use_idx, rc;
|
||||
long long position_now;
|
||||
off_t position_now;
|
||||
|
||||
fd = -1;
|
||||
#ifdef __APPLE__
|
||||
fd = fd_infos[i].proc_fd;
|
||||
#else
|
||||
if (sscanf(d->d_name, "%d", &fd) != 1)
|
||||
continue;
|
||||
if ((fd < 0) || (fd >= FD_SETSIZE))
|
||||
continue;
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Skip if this fd is already known to us.
|
||||
*/
|
||||
@@ -244,14 +360,9 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
use_idx = array_length - 1;
|
||||
|
||||
if (NULL == info_array) {
|
||||
new_info_array =
|
||||
malloc(array_length *
|
||||
sizeof(*info_array));
|
||||
new_info_array = malloc(array_length * sizeof(*info_array));
|
||||
} else {
|
||||
new_info_array =
|
||||
realloc(info_array,
|
||||
array_length *
|
||||
sizeof(*info_array));
|
||||
new_info_array = realloc(info_array, array_length * sizeof(*info_array));
|
||||
}
|
||||
if (NULL == new_info_array)
|
||||
return 2;
|
||||
@@ -260,14 +371,9 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
info_array[use_idx].watch_pid = 0;
|
||||
|
||||
if (NULL == state_array) {
|
||||
new_state_array =
|
||||
malloc(array_length *
|
||||
sizeof(*state_array));
|
||||
new_state_array = malloc(array_length * sizeof(*state_array));
|
||||
} else {
|
||||
new_state_array =
|
||||
realloc(state_array,
|
||||
array_length *
|
||||
sizeof(*state_array));
|
||||
new_state_array = realloc(state_array, array_length * sizeof(*state_array));
|
||||
}
|
||||
if (NULL == new_state_array)
|
||||
return 2;
|
||||
@@ -276,10 +382,8 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
|
||||
*array_length_ptr = array_length;
|
||||
|
||||
for (check_idx = 0; check_idx < array_length;
|
||||
check_idx++) {
|
||||
state_array[check_idx].name =
|
||||
info_array[check_idx].display_name;
|
||||
for (check_idx = 0; check_idx < array_length; check_idx++) {
|
||||
state_array[check_idx].name = info_array[check_idx].display_name;
|
||||
state_array[check_idx].reparse_display = 1;
|
||||
}
|
||||
}
|
||||
@@ -289,23 +393,24 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
/*
|
||||
* Initialise the details of this new entry.
|
||||
*/
|
||||
memcpy(&(state_array[use_idx]), pristine,
|
||||
sizeof(*pristine));
|
||||
memset(&(info_array[use_idx]), 0,
|
||||
sizeof(info_array[use_idx]));
|
||||
memcpy(&(state_array[use_idx]), pristine, sizeof(*pristine));
|
||||
memset(&(info_array[use_idx]), 0, sizeof(info_array[use_idx]));
|
||||
|
||||
info_array[use_idx].watch_pid = watch_pid;
|
||||
info_array[use_idx].watch_fd = fd;
|
||||
rc = pv_watchfd_info(state, &(info_array[use_idx]), 1);
|
||||
#ifdef __APPLE__
|
||||
if (fd_infos[i].proc_fdtype != PROX_FDTYPE_VNODE) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
rc = pv_watchfd_info(state, &(info_array[use_idx]), true);
|
||||
|
||||
/*
|
||||
* Lookup failed - mark this slot as being free for re-use.
|
||||
*/
|
||||
if ((rc != 0) && (rc != 4)) {
|
||||
info_array[use_idx].watch_pid = 0;
|
||||
debug("%s %d: %s: %d", "fd", fd,
|
||||
"lookup failed - marking slot for re-use",
|
||||
use_idx);
|
||||
debug("%s %d: %s: %d", "fd", fd, "lookup failed - marking slot for re-use", use_idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -316,18 +421,14 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
* show it.
|
||||
*/
|
||||
if (rc != 0) {
|
||||
debug("%s %d: %s", "fd", fd,
|
||||
"marking as not displayable");
|
||||
debug("%s %d: %s", "fd", fd, "marking as not displayable");
|
||||
info_array[use_idx].watch_fd = -1;
|
||||
}
|
||||
|
||||
state_array[use_idx].size = info_array[use_idx].size;
|
||||
if (state_array[use_idx].size < 1) {
|
||||
char *fmt;
|
||||
while (NULL !=
|
||||
(fmt =
|
||||
strstr(state_array[use_idx].default_format,
|
||||
"%e"))) {
|
||||
while (NULL != (fmt = strstr(state_array[use_idx].default_format, "%e"))) {
|
||||
debug("%s", "zero size - removing ETA");
|
||||
/* strlen-1 here to include trailing NUL */
|
||||
memmove(fmt, fmt + 2, strlen(fmt) - 1);
|
||||
@@ -335,14 +436,13 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
}
|
||||
}
|
||||
|
||||
state_array[use_idx].name =
|
||||
info_array[use_idx].display_name;
|
||||
state_array[use_idx].name = info_array[use_idx].display_name;
|
||||
|
||||
pv_watchpid_setname(state, &(info_array[use_idx]));
|
||||
|
||||
state_array[use_idx].reparse_display = 1;
|
||||
|
||||
gettimeofday(&(info_array[use_idx].start_time), NULL);
|
||||
pv_elapsedtime_read(&(info_array[use_idx].start_time));
|
||||
|
||||
state_array[use_idx].initial_offset = 0;
|
||||
info_array[use_idx].position = 0;
|
||||
@@ -354,7 +454,12 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
free(fd_infos);
|
||||
#else
|
||||
closedir(dptr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -363,44 +468,44 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
/*
|
||||
* Set the display name for the given watched file descriptor, truncating at
|
||||
* the relevant places according to the current screen width.
|
||||
*
|
||||
* If the file descriptor is pointing to a file under the current working
|
||||
* directory, show its relative path, not the full path.
|
||||
*/
|
||||
void pv_watchpid_setname(pvstate_t state, pvwatchfd_t info)
|
||||
{
|
||||
int path_length, max_display_length;
|
||||
int path_length, cwd_length, max_display_length;
|
||||
char *file_fdpath = info->file_fdpath;
|
||||
|
||||
memset(info->display_name, 0, sizeof(info->display_name));
|
||||
memset(info->display_name, 0, PV_SIZEOF_DISPLAY_NAME);
|
||||
|
||||
path_length = strlen(info->file_fdpath);
|
||||
cwd_length = strlen(state->cwd);
|
||||
if (cwd_length > 0 && path_length > cwd_length) {
|
||||
if (0 == strncmp(info->file_fdpath, state->cwd, cwd_length)) {
|
||||
file_fdpath += cwd_length + 1;
|
||||
path_length -= cwd_length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
max_display_length = (state->width / 2) - 6;
|
||||
if (max_display_length >= path_length) {
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(info->display_name,
|
||||
sizeof(info->display_name) - 1,
|
||||
#else
|
||||
sprintf(info->display_name,
|
||||
#endif
|
||||
"%4d:%.498s", info->watch_fd, info->file_fdpath);
|
||||
(void) pv_snprintf(info->display_name,
|
||||
PV_SIZEOF_DISPLAY_NAME, "%4d:%.498s", info->watch_fd, file_fdpath);
|
||||
} else {
|
||||
int prefix_length, suffix_length;
|
||||
|
||||
prefix_length = max_display_length / 4;
|
||||
suffix_length = max_display_length - prefix_length - 3;
|
||||
|
||||
#ifdef HAVE_SNPRINTF
|
||||
snprintf(info->display_name,
|
||||
sizeof(info->display_name) - 1,
|
||||
#else
|
||||
sprintf(info->display_name,
|
||||
#endif
|
||||
"%4d:%.*s...%.*s",
|
||||
info->watch_fd, prefix_length, info->file_fdpath,
|
||||
suffix_length,
|
||||
info->file_fdpath + path_length - suffix_length);
|
||||
(void) pv_snprintf(info->display_name,
|
||||
PV_SIZEOF_DISPLAY_NAME,
|
||||
"%4d:%.*s...%.*s",
|
||||
info->watch_fd, prefix_length,
|
||||
file_fdpath, suffix_length, file_fdpath + path_length - suffix_length);
|
||||
}
|
||||
|
||||
debug("%s: %d: [%s]", "set name for fd", info->watch_fd,
|
||||
info->display_name);
|
||||
debug("%s: %d: [%s]", "set name for fd", info->watch_fd, info->display_name);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that data can be just passed straight through.
|
||||
|
||||
VALUE=`echo TESTING | $PROG 2>/dev/null` || exit 1
|
||||
test "$VALUE" = "TESTING"
|
||||
|
||||
# EOF
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that the update interval can be set.
|
||||
|
||||
sleep 1 | $PROG -f -i 0.1 >/dev/null 2>$TMP1
|
||||
|
||||
# There should be more than 6 lines of output.
|
||||
#
|
||||
NUM=`tr '\r' '\n' < $TMP1 | wc -l | tr -d ' '`
|
||||
test $NUM -gt 6
|
||||
|
||||
# EOF
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# A simple test of rate limiting.
|
||||
|
||||
# Transfer 102 bytes at 100 bytes/sec. It should take at least 1 second.
|
||||
#
|
||||
START=`date +%S`
|
||||
dd if=/dev/zero bs=102 count=1 2>/dev/null | $PROG -L 100 2>/dev/null | cat >/dev/null
|
||||
END=`date +%S`
|
||||
|
||||
test $START -ne $END
|
||||
|
||||
# EOF
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that the progress bar moves when data is coming in.
|
||||
|
||||
dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
| $PROG -f -p -i 0.1 -L 500 >/dev/null 2>$TMP1
|
||||
|
||||
# There should be more than 2 different lines of output.
|
||||
#
|
||||
NUM=`tr '\r' '\n' < $TMP1 | sort | uniq -u | wc -l | tr -d ' '`
|
||||
test $NUM -gt 2
|
||||
|
||||
# EOF
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that the elapsed time counter does count up.
|
||||
|
||||
# Transfer a zero amount of data, but take 3 seconds to do it.
|
||||
#
|
||||
(sleep 3 | $PROG -f -t >/dev/null) 2>&1 | tr '\r' '\n' > $TMP1
|
||||
|
||||
# Count the number of different timer values; it should be >1.
|
||||
#
|
||||
NUM=`sort < $TMP1 | uniq -u | wc -l | tr -d ' '`
|
||||
test $NUM -gt 1
|
||||
|
||||
# EOF
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that the estimated time counter counts.
|
||||
|
||||
dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
| $PROG -f -e -s 100 -i 0.1 -L 25 >/dev/null 2>$TMP1
|
||||
|
||||
# Count the number of different ETA values there have been.
|
||||
#
|
||||
NUM=`tr '\r' '\n' < $TMP1 | tr -d ' ' | sed '/^$/d' | sort | uniq | wc -l | tr -d ' '`
|
||||
|
||||
# 3 or less - not OK, since it should have taken 4 seconds.
|
||||
#
|
||||
test $NUM -gt 3 || exit 1
|
||||
|
||||
# 8 or more - not OK, since even on a heavily loaded system that's too long.
|
||||
#
|
||||
test $NUM -lt 8
|
||||
|
||||
# EOF
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that the estimated time counter can show the end time of day.
|
||||
|
||||
dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
| $PROG -f -I -s 100 -i 0.1 -L 25 >/dev/null 2>$TMP1
|
||||
|
||||
# Count the number of different ETA values there have been.
|
||||
#
|
||||
NUM=`tr '\r' '\n' < $TMP1 | tr -d ' ' | sed '/^$/d' | sort | uniq | wc -l | tr -d ' '`
|
||||
|
||||
# There should be at least 1 line of output.
|
||||
#
|
||||
test $NUM -gt 0 || exit 1
|
||||
|
||||
# 8 or more different values - not OK.
|
||||
#
|
||||
test $NUM -lt 8
|
||||
|
||||
# EOF
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that the byte counter counts.
|
||||
|
||||
dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
| LANG=C $PROG -f -b >/dev/null 2>$TMP1
|
||||
NUM=`tr '\r' '\n' < $TMP1 | tr -d ' '`
|
||||
test "$NUM" = "100B"
|
||||
|
||||
# EOF
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that numeric output outputs some percentages.
|
||||
|
||||
# Process 100 bytes at 100 bytes per second, updating every 0.1 seconds for
|
||||
# around 10 output lines.
|
||||
#
|
||||
dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
| $PROG -s 100 -n -i 0.1 -L 100 >/dev/null 2>$TMP1
|
||||
|
||||
# The number of output lines should be >8 and <13, and the final percentage
|
||||
# should be 100.
|
||||
#
|
||||
test `wc -l < $TMP1` -gt 8
|
||||
test `wc -l < $TMP1` -lt 13
|
||||
test `sed -n '$p' < $TMP1` -eq 100
|
||||
|
||||
# EOF
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that the -q option shuts everything up.
|
||||
|
||||
dd if=/dev/zero bs=1000 count=5 2>/dev/null \
|
||||
| $PROG -f -q -i 0.1 -L 5000 >/dev/null 2>$TMP1
|
||||
test ! -s $TMP1
|
||||
|
||||
# EOF
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that there is no SIGPIPE or dropped data on bigger data transfers.
|
||||
|
||||
# We nead GNU head. On some platforms it is named ghead instead of head.
|
||||
HEAD=head
|
||||
for p in `echo $PATH | tr ':' '\n'`
|
||||
do
|
||||
if test -x $p/ghead
|
||||
then
|
||||
HEAD=$p/ghead
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Don't use dd. See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=324308
|
||||
COUNT1=100000000
|
||||
#COUNT2=`$PROG -B 100000 -q /dev/zero | $HEAD -c $COUNT1 | wc -c | tr -d ' '`
|
||||
# Remove \n to fix the test on AIX
|
||||
COUNT2=`$PROG -B 100000 -q /dev/zero | $HEAD -c $COUNT1 | tr -d '\n' | wc -c | tr -d ' '`
|
||||
|
||||
#echo "[$COUNT1] [$COUNT2]"
|
||||
|
||||
test "x$COUNT1" = "x$COUNT2"
|
||||
|
||||
# EOF
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Transfer a large chunk of data through pv and check data correctness
|
||||
# afterwards.
|
||||
|
||||
rm -f $TMP1 $TMP2 2>/dev/null
|
||||
|
||||
# exit on non-zero return codes
|
||||
set -e
|
||||
|
||||
# generate some data
|
||||
dd if=/dev/urandom of=$TMP1 bs=1024 count=10240 2>/dev/null
|
||||
|
||||
CKSUM1=`cksum $TMP1 | awk '{print $1}'`
|
||||
|
||||
# read through pv and test afterwards
|
||||
$PROG -B 100000 -q $TMP1 > $TMP2
|
||||
|
||||
CKSUM2=`cksum $TMP2 | awk '{print $1}'`
|
||||
|
||||
test "x$CKSUM1" = "x$CKSUM2"
|
||||
|
||||
# clean up
|
||||
rm -f $TMP1 $TMP2 2>/dev/null
|
||||
|
||||
# EOF
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Same as test 13 (1mboundary) but for rate, not bytes transferred.
|
||||
|
||||
# Transfer 1500kB of data in a bursty fashion.
|
||||
#
|
||||
(dd if=/dev/zero bs=1k count=999;
|
||||
sleep 1;
|
||||
dd if=/dev/zero bs=1k count=1;
|
||||
sleep 1;
|
||||
dd if=/dev/zero bs=3 count=1;
|
||||
sleep 1;
|
||||
dd if=/dev/zero bs=1k count=500;
|
||||
sleep 1;
|
||||
) 2>/dev/null | ($PROG -rtef -s 1500k >/dev/null) 2>$TMP1
|
||||
|
||||
# Count how many different line lengths we've seen.
|
||||
#
|
||||
NUM=`tr '\r' '\n' < $TMP1 | awk '{x=length($0);if(x>0)print length($0)}' | sort | uniq | wc -l`
|
||||
|
||||
# There should only be one length (not counting 0).
|
||||
#
|
||||
test $NUM -eq 1 || { echo; tr '\r' '\n' < $TMP1; exit 1; }
|
||||
|
||||
# EOF
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Transfer a large chunk of data through pv using pipes, sending it in a
|
||||
# bursty fashion, and check data correctness afterwards.
|
||||
|
||||
rm -f $TMP1 $TMP2 2>/dev/null
|
||||
|
||||
# exit on non-zero return codes
|
||||
set -e
|
||||
|
||||
# generate some data
|
||||
dd if=/dev/urandom of=$TMP1 bs=1024 count=10240 2>/dev/null
|
||||
|
||||
CKSUM1=`cksum $TMP1 | awk '{print $1}'`
|
||||
|
||||
# read through pv and test afterwards
|
||||
(
|
||||
dd if=$TMP1 bs=1 count=9000
|
||||
sleep 1
|
||||
dd if=$TMP1 bs=1 skip=9000 count=1240
|
||||
sleep 1
|
||||
dd if=$TMP1 bs=1024 skip=10 count=1014
|
||||
sleep 1
|
||||
dd if=$TMP1 bs=1024 skip=1024 count=1024
|
||||
sleep 1
|
||||
dd if=$TMP1 bs=1024 skip=2048
|
||||
) 2>/dev/null | $PROG -q -L 2M | cat > $TMP2
|
||||
|
||||
CKSUM2=`cksum $TMP2 | awk '{print $1}'`
|
||||
|
||||
test "x$CKSUM1" = "x$CKSUM2"
|
||||
|
||||
# same again but with one less pipe
|
||||
(
|
||||
dd if=$TMP1 bs=1 count=9000
|
||||
sleep 1
|
||||
dd if=$TMP1 bs=1 skip=9000 count=1240
|
||||
sleep 1
|
||||
dd if=$TMP1 bs=1024 skip=10 count=1014
|
||||
sleep 1
|
||||
dd if=$TMP1 bs=1024 skip=1024 count=1024
|
||||
sleep 1
|
||||
dd if=$TMP1 bs=1024 skip=2048
|
||||
) 2>/dev/null | $PROG -q -L 2M > $TMP2
|
||||
|
||||
CKSUM2=`cksum $TMP2 | awk '{print $1}'`
|
||||
|
||||
test "x$CKSUM1" = "x$CKSUM2"
|
||||
|
||||
# clean up
|
||||
rm -f $TMP1 $TMP2 2>/dev/null
|
||||
|
||||
# EOF
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that numeric output gives a timer when used with -t.
|
||||
|
||||
# Process 100 bytes at 100 bytes per second, updating every 0.1 seconds for
|
||||
# around 10 output lines.
|
||||
#
|
||||
dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
| $PROG -s 100 -n -t -i 0.1 -L 100 >/dev/null 2>$TMP1
|
||||
|
||||
# The number of output lines should be >8 and <13, and the number of
|
||||
# different elapsed times should be at least 7. The last percentage should
|
||||
# be 100.
|
||||
#
|
||||
test `wc -l < $TMP1` -gt 8
|
||||
test `wc -l < $TMP1` -lt 13
|
||||
test `tr , . < "$TMP1" | awk '{print int(10*$1)}' | sort -n | uniq | wc -l` -gt 7
|
||||
test `sed -n '$p' < $TMP1 | awk '{print $2}'` -eq 100
|
||||
|
||||
# EOF
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that numeric output gives a byte count instead of a percentage when
|
||||
# used with -b.
|
||||
|
||||
# Process 500 bytes at 500 bytes per second, updating every 0.1 seconds for
|
||||
# around 10 output lines.
|
||||
#
|
||||
dd if=/dev/zero bs=500 count=1 2>/dev/null \
|
||||
| $PROG -s 500 -n -b -i 0.1 -L 500 >/dev/null 2>$TMP1
|
||||
|
||||
# The number of output lines should be >8 and <13, and the final byte count
|
||||
# should be 500.
|
||||
#
|
||||
test `wc -l < $TMP1` -gt 8
|
||||
test `wc -l < $TMP1` -lt 13
|
||||
test `sed -n '$p' < $TMP1` -eq 500
|
||||
|
||||
# EOF
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Try changing the format of a transfer remotely.
|
||||
|
||||
# Do nothing if IPC is not supported.
|
||||
if ! $PROG -h | grep -Eq "^ -R,"; then
|
||||
echo "SKIPPED" | tr "\n" ' '
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rm -f $TMP1 $TMP2 $TMP3 $TMP4 2>/dev/null
|
||||
|
||||
# Exit on non-zero return codes.
|
||||
set -e
|
||||
|
||||
# Generate an empty test file.
|
||||
dd if=/dev/zero of=$TMP1 bs=1024 count=10240 2>/dev/null
|
||||
|
||||
(
|
||||
sleep 1
|
||||
$PROG -R `cat $TMP4` -a
|
||||
sleep 2
|
||||
$PROG -R `cat $TMP4` -L 10M
|
||||
) &
|
||||
|
||||
$PROG -L 2M -f -P $TMP4 $TMP1 > $TMP2 2>$TMP3
|
||||
|
||||
# Make sure there is more than one length of line (excluding blank lines).
|
||||
line_lengths=`tr '\r' '\n' < "$TMP3" | awk '{print length($0)}' | grep -Fvx 0 | sort -n | uniq | wc -l`
|
||||
test $line_lengths -gt 1
|
||||
|
||||
# EOF
|
||||
@@ -1,54 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Try repeatedly messaging a transfer process, and make sure the data stays
|
||||
# intact.
|
||||
|
||||
# Do nothing if IPC is not supported.
|
||||
if ! $PROG -h | grep -Eq "^ -R,"; then
|
||||
echo "SKIPPED" | tr "\n" ' '
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rm -f $TMP1 $TMP2 $TMP3 $TMP4 2>/dev/null
|
||||
|
||||
# Exit on non-zero return codes.
|
||||
set -e
|
||||
|
||||
# Generate some data.
|
||||
dd if=/dev/urandom of=$TMP1 bs=1024 count=10240 2>/dev/null
|
||||
|
||||
# Run a few remote control commands in the background.
|
||||
#
|
||||
echo FAIL > $TMP3
|
||||
(
|
||||
set +e
|
||||
sleep 2
|
||||
for x in 1 2 3; do
|
||||
$PROG -R `cat $TMP4` -apterb || exit 1
|
||||
(usleep 200000 || sleep 1) 2>/dev/null
|
||||
$PROG -R `cat $TMP4` -p || exit 1
|
||||
(usleep 200000 || sleep 1) 2>/dev/null
|
||||
$PROG -R `cat $TMP4` -N "test" || exit 1
|
||||
(usleep 200000 || sleep 1) 2>/dev/null
|
||||
$PROG -R `cat $TMP4` -F "%e" || exit 1
|
||||
(usleep 200000 || sleep 1) 2>/dev/null
|
||||
$PROG -R `cat $TMP4` -N "." || exit 1
|
||||
(usleep 200000 || sleep 1) 2>/dev/null
|
||||
done
|
||||
$PROG -R `cat $TMP4` -L 10M
|
||||
echo OK > $TMP3
|
||||
) &
|
||||
|
||||
# Run our data transfer.
|
||||
$PROG -L 100k -i 0.1 -f -P $TMP4 $TMP1 > $TMP2 2>/dev/null
|
||||
|
||||
# Check our remote control calls ran OK.
|
||||
BGSTATUS=`cat $TMP3`
|
||||
test "x$BGSTATUS" = "xOK"
|
||||
|
||||
# Check data integrity.
|
||||
CKSUM1=`cksum $TMP1 | awk '{print $1}'`
|
||||
CKSUM2=`cksum $TMP2 | awk '{print $1}'`
|
||||
test "x$CKSUM1" = "x$CKSUM2"
|
||||
|
||||
# EOF
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Make sure -S stops at the given size.
|
||||
|
||||
rm -f $TMP1 $TMP2 2>/dev/null
|
||||
|
||||
# exit on non-zero return codes
|
||||
set -e
|
||||
|
||||
# generate some data
|
||||
dd if=/dev/urandom of=$TMP1 bs=1024 count=10 2>/dev/null
|
||||
|
||||
# read through pv and test afterwards
|
||||
$PROG -S -s 5120 -q $TMP1 > $TMP2
|
||||
|
||||
CKSUM2=`cksum $TMP2 | awk '{print $1}'`
|
||||
|
||||
# take the first 5120 bytes of TMP1 and cksum them
|
||||
rm -f $TMP2
|
||||
dd if=$TMP1 of=$TMP2 bs=1024 count=5 2>/dev/null
|
||||
CKSUM1=`cksum $TMP2 | awk '{print $1}'`
|
||||
|
||||
test "x$CKSUM1" = "x$CKSUM2"
|
||||
|
||||
# clean up
|
||||
rm -f $TMP1 $TMP2 2>/dev/null
|
||||
|
||||
# EOF
|
||||
Regular → Executable
+10
-3
@@ -4,6 +4,9 @@
|
||||
# 1MiB, described here:
|
||||
# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=586763
|
||||
|
||||
# Dummy assignments for "shellcheck".
|
||||
testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"
|
||||
|
||||
# Transfer 1500kB of data in a bursty fashion.
|
||||
#
|
||||
(dd if=/dev/zero bs=1k count=999;
|
||||
@@ -12,14 +15,18 @@
|
||||
sleep 1;
|
||||
dd if=/dev/zero bs=1k count=500;
|
||||
sleep 1;
|
||||
) 2>/dev/null | ($PROG -btef -s 1500k >/dev/null) 2>$TMP1
|
||||
) 2>/dev/null | ("${testSubject}" -btIf -s 1500k >/dev/null) 2>"${workFile1}"
|
||||
|
||||
# Count how many different line lengths we've seen.
|
||||
#
|
||||
NUM=`tr '\r' '\n' < $TMP1 | awk '{x=length($0);if(x>0)print length($0)}' | sort | uniq | wc -l`
|
||||
lineLengthCount=$(tr '\r' '\n' < "${workFile1}" | sed 's/ *$//' | awk '{x=length($0);if(x>0)print length($0)}' | sort | uniq | wc -l | tr -dc '0-9')
|
||||
|
||||
# There should only be one length (not counting 0).
|
||||
#
|
||||
test $NUM -eq 1 || { echo; tr '\r' '\n' < $TMP1; exit 1; }
|
||||
test "${lineLengthCount}" = "1" && exit 0
|
||||
|
||||
echo "variable line lengths detected"
|
||||
tr '\r' '\n' < "${workFile1}"
|
||||
exit 1
|
||||
|
||||
# EOF
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This is the same as the other display length at magnitude boundary check,
|
||||
# but for rate, not bytes transferred.
|
||||
|
||||
# Dummy assignments for "shellcheck".
|
||||
testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"
|
||||
|
||||
# Transfer 1500kB of data in a bursty fashion.
|
||||
#
|
||||
(dd if=/dev/zero bs=1k count=999;
|
||||
sleep 1;
|
||||
dd if=/dev/zero bs=1k count=1;
|
||||
sleep 1;
|
||||
dd if=/dev/zero bs=3 count=1;
|
||||
sleep 1;
|
||||
dd if=/dev/zero bs=1k count=500;
|
||||
sleep 1;
|
||||
) 2>/dev/null | ("${testSubject}" -rtIf -s 1500k >/dev/null) 2>"${workFile1}"
|
||||
|
||||
# Count how many different line lengths we've seen.
|
||||
#
|
||||
lineLengthCount=$(tr '\r' '\n' < "${workFile1}" | sed 's/ *$//' | awk '{x=length($0);if(x>0)print length($0)}' | sort | uniq | wc -l | tr -dc '0-9')
|
||||
|
||||
# There should only be one length (not counting 0).
|
||||
#
|
||||
test "${lineLengthCount}" = "1" && exit 0
|
||||
|
||||
echo "variable line lengths detected"
|
||||
tr '\r' '\n' < "${workFile1}"
|
||||
exit 1
|
||||
|
||||
# EOF
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Test that "make install" installs the expected minimum set of files.
|
||||
|
||||
# Dummy assignments for "shellcheck".
|
||||
testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"
|
||||
|
||||
makeDir="${testSubject%/*}"
|
||||
if ! test -d "${makeDir}"; then
|
||||
echo "could not find the directory to run \`make' in"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
makeCommand=$(command -v gmake 2>/dev/null)
|
||||
test -z "${makeCommand}" && makeCommand="make"
|
||||
|
||||
testInstallDir=$(mktemp -d)
|
||||
if ! test -n "${testInstallDir}"; then
|
||||
echo "failed to create temporary installation directory"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
export DESTDIR="${testInstallDir}"
|
||||
if ! ${makeCommand} -C "${makeDir}" install DESTDIR="${testInstallDir}" >"${workFile1}" 2>&1; then
|
||||
echo "\`make install' exited $?"
|
||||
rm -rf "${testInstallDir}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exitStatus=0
|
||||
if ! find "${testInstallDir}" -type f -name "pv.1*" | grep -Fq "pv.1"; then
|
||||
echo "installation of man page failed"
|
||||
exitStatus=1
|
||||
fi
|
||||
if ! find "${testInstallDir}" -type f -name "pv*" | grep -Fv "pv.1" | grep -Fq "pv"; then
|
||||
echo "installation of binary failed"
|
||||
exitStatus=1
|
||||
fi
|
||||
|
||||
rm -rf "${testInstallDir}"
|
||||
exit "${exitStatus}"
|
||||
|
||||
# EOF
|
||||
Regular → Executable
+10
-3
@@ -3,6 +3,9 @@
|
||||
# Check that the average transfer rate counter changes, but not more than it
|
||||
# should.
|
||||
|
||||
# Dummy assignments for "shellcheck".
|
||||
testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"
|
||||
|
||||
# Transfer 210 bytes as 100 bytes, a 1 second gap, 110 bytes, and another 1
|
||||
# second gap.
|
||||
#
|
||||
@@ -10,15 +13,19 @@
|
||||
sleep 1;
|
||||
dd if=/dev/zero bs=110 count=1 2>/dev/null;
|
||||
sleep 1;
|
||||
) | $PROG -f -i 0.5 -a >/dev/null 2>$TMP1
|
||||
) | "${testSubject}" -f -i 0.5 -a >/dev/null 2>"${workFile1}"
|
||||
|
||||
# Count the number of rates output that are below 80.
|
||||
#
|
||||
NUM=`tr '\r' '\n' < $TMP1 | tr -dc '0-9.\n' | sed '/^$/d' | awk '$1<80{print}' | wc -l | tr -d ' '`
|
||||
lineCount=$(tr '\r' '\n' < "${workFile1}" | tr -dc '0-9.\n' | sed '/^$/d' | awk '$1<80{print}' | wc -l | tr -dc '0-9')
|
||||
|
||||
# Nearly all of the output rates should be above 80 since the average rate
|
||||
# will always be around 100 bytes per second, except for pauses.
|
||||
#
|
||||
test $NUM -lt 2
|
||||
test "${lineCount}" -lt 2 && exit 0
|
||||
|
||||
echo "average rate varied more than expected"
|
||||
tr '\r' '\n' < "${workFile1}"
|
||||
exit 1
|
||||
|
||||
# EOF
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that the byte counter counts in bits when --bits is selected.
|
||||
|
||||
# Dummy assignments for "shellcheck".
|
||||
testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"
|
||||
|
||||
dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
| "${testSubject}" -f -b -8 >/dev/null 2>"${workFile1}"
|
||||
|
||||
counterValue=$(tr '\r' '\n' < "${workFile1}" | tr -d ' ')
|
||||
test "${counterValue}" = "800b" && exit 0
|
||||
|
||||
echo "unexpected bit counter value: ${counterValue}"
|
||||
exit 1
|
||||
|
||||
# EOF
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that "--buffer-percent" displays correctly.
|
||||
|
||||
# Dummy assignments for "shellcheck".
|
||||
testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"
|
||||
|
||||
# The output should show 100% and 0% as the buffer initially fills up due to
|
||||
# there being nowhere to write it to, and then empties.
|
||||
( dd if=/dev/zero bs=1024 count=1024; sleep 2; ) 2>/dev/null \
|
||||
| "${testSubject}" -f -T -i 0.5 -B 1024 2>"${workFile1}" \
|
||||
| (sleep 1; dd bs=1024 count=512; sleep 1; cat; ) >/dev/null 2>&1
|
||||
|
||||
differentLines=$(tr '\r' '\n' < "${workFile1}" | sed '/^ *$/d' | sort | uniq | wc -l | tr -dc '0-9')
|
||||
test "${differentLines}" -gt 1 && exit 0
|
||||
|
||||
echo "expected output changes not seen"
|
||||
tr '\r' '\n' < "${workFile1}" | sed 's/^ *$/d' | sort | uniq
|
||||
exit 1
|
||||
|
||||
# EOF
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user